It really comes done to if you want to do any testing
I’m not sure I agree with that. It’s generally the case that unit testing is the first place you will identify problems caused by things like static methods but the flexibility issues caused by hardcoded dependencies and global state often cause problems as a project grows and code is re-used in a manner it may not have originally been intended or with other components it wasn’t expecting.
Once you realise that the object can’t be re-used without some hacky code because it’s tied to global state or you can’t use it with a substituted dependency then the problems become painfully apparent.
What Tom is saying about Singletons is very subtle. The single state is not the problem it is that a class decides for itself that it can be the only one. Separating the singleton creation and management to another class achieves the same result as a singleton and allows injection of a mock into the instance wrapper or allows it to be overriden at the configuration stage. Using dependency containers they can manage all single instances, the consumer does not require any knowledge that they are using a single state object, in fact the symfony service container that sort of design choice is done by configuration.
Yep! Thanks, you worded it far more eloquently than I did. I should have made it clearer I was talking about the client code using the singleton that’s problematic rather than the singleton itself.
I do agree that testing singleton’s is difficult, but if you work with a third party element that really “only” works properly if things are called in specific manners, and it can only be a single instance, it is difficult to utilize anything but a singleton, but I do give you a valid argument there.
There is plenty of discussion around the web about why singletons are bad practice, this isn’t a new concept either, that initial post I linked to was from 2004. Bringing edge-cases into a discussion really is a red-herring because even here there’s no real reason to use a singleton. The same thing can be easily achieved without littering your codebase with foo::getInstance(). I’m only arguing this point so heavily because people
I’ve seen plenty of times where someone is building a utility class and are not making their methods static even though it serves no purpose as an instantiated class. It doesn’t have internal properties, it doesn’t need to track any information, each method is self contained and not reliant on other properties. They do it because some one told them static is bad. So you see $utility = new Utility(); $utility->GetRootFolder();, instead of Utility::GetRootFolder(); (the latter being faster and consuming less resources).
This is a perfect example of a bad example. In reality, $utility; would be injected rather than created. “new” is static, after all. Those two examples are almost the same, as you say, the benefit is minimal because it’s still making a static call. $utility cannot be substituted in this code so it’s pointless not using static. This highlights the reason object creation should be separate from the utilisation of that object and is not an argument to use static methods. Your example code is tied to a specific implementation of “utility” either way which is far from ideal.