Reputation: 24061
I'm struggling to know whether I should use a static or instantiated class.
I'm not sure I understand why you would use either apart from, a static class should be used to work on data where as a instantiated class has its own data.
I'm not sure how this apples to my work, for example, I have a model that gets data from a database (a list of products).
If my above assumption is correct then I should instantiate the model, as the class has it's own data.
And for example, if I then had a helper class that converted dates, this should be static, as it just returns data in a different format.
Is all of this correct, can anyone explain to me clearer or any sort of rules I should use when deciding between a static and instantiated class?
Upvotes: 2
Views: 196
Reputation: 522024
I've written about this extensively here: How Not To Kill Your Testability Using Statics. To summarise it:
Choice quote from the linked article:
Obligatory car analogy:
Class Oriented Programming is like buying a car to let it sit in the driveway, opening and closing its doors repeatedly, jumping around on the seats, occasionally turning on the windshield wipers, yet never once turning the ignition key and taking it for a drive. It is missing the point entirely.
Upvotes: 1
Reputation: 77089
A static class isn't really a thing. You may be talking about a class, as distinguished from an instance of that class. A class can have properties and methods that are declared static using the static
keyword. The static
keyword applied to a property means you cannot access that property using an instance.
class Foo {
public static $prop = 123;
}
php > echo Foo::$prop
123
php > $f = new Foo(); $f->prop;
PHP Strict standards: Accessing static property Foo::$prop as non static in php shell code on line 1
However, you can access static methods either way:
class Bar {
public static function meth() { echo "Hello, World\n"; }
}
php > Bar::meth()
Hello, World
php > $b = new Bar();
php > $b->meth();
Hello, World
In spirit, a static method is a good thing. It's a commitment that this method's output doesn't depend on the state of the object. But that's not to say it's guaranteed to be stateless, because there's another use for the static
keyword: Static variables:
class Baz {
public static function m() {
static $callCount = 0;
echo ++$callCount;
}
}
php > Baz::m();
1
php > Baz::m();
2
php > $x = new Baz(); $y = new Baz();
php > $x->m();
3
php > $y->m();
4
…
So statics are a way you can store state in the class itself, independent of the instance. You can even use them for message-passing between instances of the same class. To be honest, the valid uses for that are few and far between, and it is hard to cover stateful statics directly with behavioral tests.
Another use for statics is carrying class-specific information. Let's say you want a whole bunch of classes to have a log
method that always includes some class-specific information in the log message.
trait Xyzzy {
public static function log($msg) {
printf('[%s] %s', static::$_identifier, $msg);
}
}
class Fuzzy {
use Xyzzy;
private static $_identifier = __CLASS__;
}
php > $f = new Fuzzy();
php > $f->log('hello, world');
[Fuzzy] hello, world
So if you feel a static is the right approach, because a method is
Then you should use a static. It can make testing harder, but the tests are here to support you, not get in your way.
By the way, recent versions of PHPUnit can test a subset of static methods using late static bindings.
Upvotes: 2