Page 1 of 1

pure static vs. traditional class

Posted: Sat Sep 25, 2010 6:38 pm
by raccer
Are there a few simple tests, or questions one can asses, that determines whether a class should be static or not?
Here is one I found:
I.E.
If your class does not need a __construct() method, the singleton pattern is not appropriate.
In that case, you should use a purely static class.
-Kevin McArthur, ProPHP
I have a specific class, that is responsible for incoming input to my webapp (http post), this class parses input, does other stuff, calls other classes, etcetera.

Conceptually, I can make this class work either way, (purely static or like a singleton) so what else can I consider that would highlight the pros /cons ?

Thanks!

Re: pure static vs. traditional class

Posted: Sat Sep 25, 2010 9:06 pm
by josh
What horrible advice. Static classes should almost never be used. First understand the difference between class & object. A class is a definition, like a blue print. An object is what is built from that blueprint.

Differences in State
When you store some static data (use a static class with static variables), those variables are stored with the class itself. Since the class is the blue print (the class you type into your IDE itself), there can only be one set of state.

However there can be unlimited number of objects per each given class, each time you instantiate the class it creates a brand new object with new state. A static class may seem to make sense when you want "one" (for example "one logged in user") - however when you suddenly need to re-use the same logic for more than one user you've got a lot of backtracking

Coupling
Another difference is in coupling, this difference is slightly harder to understand (maybe). When you refer to a static class you refer to the name of the class, the name of that class then gets repeated into your code which introduces "coupling" (places that must be changed if you want to change that behavior). This breaks a design principle called 'dont repeat yourself' (one place to make a given change, one reason to change something)...

Objects on the other hand, can be passed as arguments, through the constructor of a collaborating object. Therefore collaborating objects don't need to know what kind of objects are being passed in. One day it could be a User object (representing a logged in user) - the next day they could start receiving instead a Registrant object (representing a user that is in the middle of registration process). This is where interfaces come in. If you program by interface and you avoid static classes, your software becomes more cohesive and less coupled.

A big example with coupling is what if you want to take some code and use it in another system - how much work is that going to take? A lot more if your code is static. You can prove this to yourself with unit tests. Static code is incredibly hard to exercise under unit test, which means its hard to take that code and exercise it outside of it's original environment. If code is easy to unit test (dependency injection) that means its easy to "trick" our object into collaborating with new objects, or "trick" it into running inside some new system, almost like a kidney transplant.

Dependency Injection
This just means, when you want to call a method on another class, DONT refer to that class from within a method's definition. Instead of "calling" that class, "ask". This is the holywood principle. Don't call us we'll call you (stupid saying to help you remember). In other words, don't instantiate classes, or call static methods all over the place. Instead accept collaborating objects as constructor arguments. For example maybe you have a Newletter class that operates on a User class. You don't want to couple that Newsletter class to some given User class - but the two classes do need to work together -thats where you use dependency injection http://martinfowler.com/articles/injection.html

Re: pure static vs. traditional class

Posted: Sun Sep 26, 2010 12:04 pm
by merek
With php 5.3.0 you can do the following, I tested on my wamp that has 5.3.2.

Code: Select all

<?php
class static_class {
	public static $property = "Static Class Property";
}

class other_class {
	public static function get_static_class_property($static_class_name) {
	    return $static_class_name::$property;
	}
}
$other_class = new other_class();
echo $other_class->get_static_class_property("static_class");
?>

Re: pure static vs. traditional class

Posted: Wed Sep 29, 2010 4:27 pm
by Christopher
raccer wrote:Conceptually, I can make this class work either way, (purely static or like a singleton) so what else can I consider that would highlight the pros /cons ?
The main reason to use static classes and Singletons is so you can learn first hand what bad choices they are -- when you recode them later to objects. It really makes their downsides quite vivid.

PS - agree with Josh and the excellent information he provided.

Re: pure static vs. traditional class

Posted: Thu Sep 30, 2010 1:31 pm
by josh
I think a static registry is ok, as long as it can be overridden with dependency injection and is unit tested. In Zend, a lot of stuff tries to grab database adapters, or translation objects straight from a global, static registry. This is ok because I can create an instance of the registry object instead, and pass it into any of these components - then those components will use the registry I pass to them, instead of the global static one. This way when using your class, people can decide whether they want to be lazy, or follow best practices. After all, if you're hammering out simple contact forms all day, its not going to matter; but if you're making a real application it will matter.

I would say if your script is dead simple, its "ok" to have a global database adapter. Just don't go making the Form class itself global (static) or something.

Also some people say its ok to have a static method/class where there is no "state". Its a matter of preference

In a more OOP language you can do
5.multiply(5).subtract(4); // 21

In a more static way you can do:
Math.subtract(Math.multiply(5,5),4); // 21

I prefer the former from a usability point of view. A static method is not easy to use in real situations.

Re: pure static vs. traditional class

Posted: Thu Sep 30, 2010 6:47 pm
by Christopher
josh wrote:I think a static registry is ok, as long as it can be overridden with dependency injection and is unit tested. In Zend, a lot of stuff tries to grab database adapters, or translation objects straight from a global, static registry. This is ok because I can create an instance of the registry object instead, and pass it into any of these components - then those components will use the registry I pass to them, instead of the global static one. This way when using your class, people can decide whether they want to be lazy, or follow best practices. After all, if you're hammering out simple contact forms all day, its not going to matter; but if you're making a real application it will matter.
Zend is removing most of this from 2.0. They finally saw the problems are worse than the benefits.
josh wrote:I would say if your script is dead simple, its "ok" to have a global database adapter. Just don't go making the Form class itself global (static) or something.

Also some people say its ok to have a static method/class where there is no "state". Its a matter of preference

In a more OOP language you can do
5.multiply(5).subtract(4); // 21

In a more static way you can do:
Math.subtract(Math.multiply(5,5),4); // 21
I think it is almost always better to create an object. It is just one more line and is not only better design-wise, but I think usually reads better:

$cartTotal = new Math;
$cartTotal.subtract($cartTotal.multiply(5,5),4); // 21

Re: pure static vs. traditional class

Posted: Fri Oct 01, 2010 3:11 am
by josh
Christopher wrote:Zend is removing most of this from 2.0. They finally saw the problems are worse than the benefits.
They are specifically keeping things like database adapters, the user's locale, translation objects, etc.. in the static registry and keeping a static registry.
Elimination of most singletons. ZF has often been accused of "singletonitis." While we're not sure if we completely agree, we will note that in most cases, the singletons we have have presented a number of problems and led to difficult test cases. Additionally, in most cases, the singleton is unwarranted. We will be refactoring to eliminate these, including in Zend_Controller_Front. In exceptional cases, we will keep them; these include global operations such as autoloading and database connections
http://webcache.googleusercontent.com/s ... =firefox-a

In the places where you would really get yourself into trouble, the singletons are opt in. For things that are trivial like a database adapter, the singleton is opt out (way it works now)

$cartTotal = new Math;
$cartTotal.subtract($cartTotal.multiply(5,5),4); // 21
I'd prefer to see

$cartTtotal = new Math(5).
$cartTotal.mulitply(5).subtract(4); // 21

By the way, singletons are not static methods, they just use them. They have tons of static methods like factory methods or Zend_Validate that are not singletons. I don't prefer for it but they did in a way that doesn't cause me huge problems.

Re: pure static vs. traditional class

Posted: Fri Oct 01, 2010 10:27 am
by alex.barylski
By the way, singletons are not static methods, they just use them.
Perhaps, but you can't have singletons without static methods, so in this case, using one effectively forces the use of the other, does it not?

Cheers,
Alex

Re: pure static vs. traditional class

Posted: Sat Oct 02, 2010 2:04 am
by josh
Christopher wrote "Zend is removing 'them'". Zend is removing *some* of their singletons - far from removing all singletons or even all static methods.

I agree though, a static method provides hardly any benefit aside from the exceptional situation of getting a database adapter around. Even that is better handled by dependency injection but thats subjective.

Re: pure static vs. traditional class

Posted: Sat Oct 09, 2010 5:04 pm
by raccer
Josh!

Thank you for the awesome response! I'm reading about patterns now, and hope to loosen up coupling I have in my classes. I'll be back soon if I have any questions regarding suitability of specific patterns for various purposes. LMK if you're ever in the silicon valley, I'll buy you a drink!

Side question relating to frameworks: I started building my web app/service from scratch, and later heard that frameworks are the magic when developing web app/services; is it madness to continue w/o a framework? or does it not matter so long as I build it with object oriented design principals?

Re: pure static vs. traditional class

Posted: Sat Oct 09, 2010 8:07 pm
by josh
Frameworks are not a silver bullet, but the design methodologies themselves like TDD almost are. Writing your own framework would delay a major project by at least 6 months in my opinion. If you have the budget to sit around for 6 months and not produce a working application, then it doesn't matter. For example on Friday I had to make a "contact form"/"shopping cart" hybrid. I was able to code with SEO URLs, all data inputs validated, demo it to the client, incorporate their changes while they were on the phone and have the project over with in less than an hour. But it took me a year to get that proficient with the framework.

Asking about working without a framework is the same as asking about working on punch cards or something. Its just going to be a lot more work, and there aren't very many people who will argue that its a bright idea.