I’m Adam, and i’m a recovering Singleton addict.
adamschepis.com
adamschepis.com
1- Take a programmer who's tied to an IoC container and DI as a way of life, along with anti-singleton, and interface everything.
2- Introduce him or her to a dynamic language. Specifically focusing on testability without DI, interfaces and fear of singletons and statics.
3- Watch as he or she either:
a - accepts the fundamental truth that all that crap in a static language doesn't add value outside of freeing you from the language
b - refuses to believe that what you are doing can even be classified as programming
This is equally entertaining to do to either a very "experienced" (doing the same thing for the last 10 years) programmer, or someone who's just discovered mocking and mocks everything.
You can tell a lot about a Java or C# programmer by how readily he or she accepts this shift (which isn't to say they magically switch over to a dynamic language, but they should recognize that all that stuff a static language demands of us is really a limitation of said languages).
I tend to think about it the other way around, as "These are things I can do in a static type system but not in a dynamic one," but never let it be said that arguing about type systems on the internet was a good use of my time.
I will admit that I need the hacks from time to time, though. Recently, I wrote an overly large method that calls a callback when the command completes. For my test, I needed to run a bit of code right before the callback was called.
Runtime role application to the rescue! In my test, I wrote:
my $done = AnyEvent->condvar;
$done->begin;
my $called_callback = 0;
{ pacakge FixupCallback;
requires 'update_table';
around 'update_table' => sub {
my ($orig, $self, @args) = @_;
my $cb = pop @args;
# this is like "super"
$self->$orig( @args, sub {
$called_callback = 1;
$cb->(@_); # call the original callback
$done->end; # then return control flow back to us
});
};
}
Then, I just find the instance of the class that I need to tweak: my $view = $app->latency_publisher->view;
FixupCallback->meta->apply($view);
And now I've fixed up the code enough to write a sane test. While cool, this doesn't negate the need for dependency injection. I want my app code to be 99% clean, and use the hacks for that 1% case where the hacks result in cleaner code than "the right way".Also, I've never programmed Java or C#, so don't say that I have inherited bad habits from those languages :)
It seems your argument is basically: "HA HA look at the static language developers, aren't they stupid! They need to accept some fundamental truths and find their freedom!".
I'm interested in what you have to say but I'd like to actually hear some technical reasons to support your argument.
class SystemTime
{
public Func<DateTime> Now => () = DateTime.Now;
}
Ultimately though, you're having to work around the fact that Java and C# are class-oriented, rather than object-oriented. Classes are useful - they serve as a template for your object, but in most (all?) dynamic languages, the class itself is a living, breathing, modifiable, runtime object.What does all this mean? How do you get the current time in a testable manner in Ruby? Use Time.now. You don't implement patterns or change your code. You don't fear the evil static..because really, it isn't a static - we don't even call it a static. It's just another method on another class, which we can rewrite at runtime as need be.
How do you stub it? Well, using a mocking framework:
Time.stub!(:now).and_return(Time.local(2011, 5, 3, 0, 1, 22))
The mechanics of how this is internally done isn't too complicated once you know about Ruby's metaprogramming (which probably takes around the same amount of time as getting familiar with C# or Java's reflection capabilities).
I know, it's a simple example. But it's surprisingly common. And I find it a little ridiculous that to get the time, we need to start creating interfaces and injecting parameters. While C#'s lambda's largely solve this problem, move to something just slightly more complicated, and you're back at square one.
I dunno, not sure if that explained it without being condescending. I'm tired...that stub is actually returning a pretty accurate time for me.
Essentially the benefit we're pushing here is cheap decoupling where in static languages you're having to set this kind of arduous plumbing up yourself, aye?
I'm not going to say that it's as big a leap as automatic garbage collection (because, I don't think it is), but I see similarities between a C++ developer who doesn't understand why Java/C# don't have a malloc and delete method, and a Java/C# developer who doesn't understand why XYZ don't have interfaces nor use DI.
We spend so much time doing something a certain way, that it's hard to see how, given a different context (a new language) what we were trying so hard to avoid in the first place, just works.
1) Singletons do make sense when they represent a true physical singleton - for example, you only want one piece of code drawing directly to the screen, the Window Manager, which should indeed be a singleton.
2) Most of your problems stem from the us of GetInstance() not from the use of the Singleton pattern in and of itself. For example, without GetInstance(), the other way to get a reference to the Singleton object is to pass it in to the object that is going to use it. This indicates the dependency in the client class's interface, and also makes mocking out the Singleton for test purposes a real possibility.
Any thoughts on that?
As a PHP guy, setting up optional params are easy, so I like the solution.
Fact of the matter is: canonical implementation of singleton is with getInstance(), so when people rail against Singleton, the getInstance() implementation is implied.
therein lies the problem: most of us are, in general, terrible at predicting the future. By the time I notice I now want more than one piece of code drawing directly to the screen, my code is already full of wrong assumptions.
One way of easing this is -- as you point out -- to make dependencies explicit and abandon GetInstance. Better yet if realizing that, as a design guideline, "needing only one of something" trumps "something being a singleton" any day. This is the kind of future-proofing that generally doesn't hurt the schedule.
That's a false dichotomy. Trying to understand the world as global or local data doesn't make sense; It's contextual. What may be global to you may be local to the next guy and vice versa.
What does make sense, is for a programmer to make a judgement call as to whether something could meaningfully be considered global for the particular case he's working on.
I used to like the concept of dependency injection, but I have come to find it mostly just adds noise. If you use a dynamic language anyway. I don't know about statically, compiled languages, since I don't do much work in those.
Err, firstly I didn't present a dichotomy,false or otherwise. http://en.wikipedia.org/wiki/Dichotomy
Secondly, I have no idea what you're talking about. I'm not talking about whether data is global or local, I'm saying that when you have a single physical asset, it doesn't make sense (and sometimes is even flat out wrong) to have more than one object talking to it. You will get into a big mess if you have two NetworkManagers trying to set up the one ethernet port at the same time, as a simple example. Whether that representation is local or global is orthogonal to the problem.
Certainly, for a given program it may (or may not) make sense to have a restriction which prevents one type of resource to be assigned more than once. My point being that there is no need to treat this restriction as "special" somehow.
1. There should be one instance of the data and
2. The data needs to be lazily initialized.
Otherwise, you might as well drop the facade and use globals.
I’m Adam, and i’m a recovering Singleton addict.
Posted by aschepis on May 2, 2011
My name is Adam, and i’m a recovering Singleton addict. There, i’ve said it. I used to use singletons all the time because they make doing some things, like sharing state globally, incredibly convenient. My code was littered with XYZManager classes. The defining trait of these classes was the static GetInstance() method that magically enabled me to get access to that object and its state wherever I wanted!! What a great idea, right?
What a mess! I learned over time that the cost of changing one of these things, or the cost of doing a major refactor was really high in terms of code change. And to make things worse, because my classes’ dependencies were hidden in implementation and weren’t transparent in the interfaces it was impossible to write real unit tests. This made doing a big refactor even less attractive.
So over the years, through work in the industry and coding on my own I’ve come to the conclusion that the singleton sucks, and that there are very few places where they are actually appropriate (logging comes to mind as one acceptable place). The fact of the matter is that most of the places I see singletons used in software they are actually just an enable for developer laziness.
So here is my off the cuff list of why singletons suck. Feel free to comment and add your own reasons (or counterpoints)
Singletons hide your dependencies. This makes code harder to understand Singletons make unit testing difficult. It’s hard to mock out a global object that you can’t inject into a class Singletons reduce reusability. If i’m writing a class that utilizes a singleton because my application will only ever use one then i’m limiting myself because I can’t use that library to write test tools that may want to simulate how many of these object (for instance, many users) interact with a system. Singletons reduce scalability. A single, global object? Sounds like a source of contention to me. Singletons are not good object oriented design, they are lazy!
The most beautiful Singleton code I've seen in C++ is:
class GrSubsys
{
public:
GrSubsys();
~GrSubsys();
};
extern GrSubsys* gGrSubsys;
... then the constructor and destructor are written such that you can startup/shutdown the singleton as follows: //-------------------------------------------------------
void
App_Startup()
{
// initialize graphics subsystem.
new GrSubsys;
}
//-------------------------------------------------------
void
App_Shutdown()
{
// shutdown the graphics subsystem.
delete gGrSubsys;
}
//-------------------------------------------------------
int
main()
{
// startup the engine.
AppStartup();
// enter the per-frame application loop.
while ( AppFrame() )
{
}
// shutdown the engine.
AppShutdown();
return 0;
}
Shrug. A friend introduced it to me, and I liked it a lot. The same concept can be easily applied to C, too.Let's say the module Foo depends on the Graphics subsystem. That is, Foo.cpp has the code:
#include "GrSubsys.h"
//-------------------------------------------------------
Foo::Foo( const string& name )
{
// fetch a handle to our model (loading it if necessary).
_model = gGrSubsys->GetModel( "models/" + name );
}
//-------------------------------------------------------
bool
Foo::IsValid()
{
return ( _model != NULL );
}
In order to write a unit test that takes into account the aforementioned Singleton pattern, you might write: //-------------------------------------------------------
void
Test_EngineComponents()
{
// prepare for science.
AppStartup();
//==========================
// Test #1 - Foo
//==========================
{
// load a Foo entity.
Foo* sunTzu = new Foo( "test/warlord" );
// verify the entity loaded successfully.
assert( sunTzu->IsValid() );
// shutdown.
delete sunTzu;
}
// conclude our science.
AppShutdown();
}
and AppStartup() is the function which initializes the subsystem singletons (and those will initialize their manager singletons).It's about discipline. Any fool can butcher with any tool.
Why would you want to simulate the graphics subsystem (and therefore the video card)?
The goal here isn't performance testing. It's to check whether the engine works.
What you are talking about is a regression or functional test. Same genus different species, still very useful but not the same tool.
Edit: Going to bed, if someone would like to explain by morning why this needed to be down voted so brutally I would be much obliged!
Thus you'll never be able to unit-test a video game completely. Or even fulfill other forms of testing with the same breadth as is possible in other software, unless you have every possible configuration to test on, or stick with consoles. Games are among the buggiest of all software, but it's not for want of trying!
I'm certainly not saying this is bad. I am saying that, from my experience, video game programming is very different than other sorts of programming.
We have an analogue in enterprise/web programming. Code that interacts against the database. Do you, or don't you, stub/mock out the data layer code? Traditionally people did mock this out. Then Rails came along with ActiveRecord...and now hitting the DB isn't only common, I think a lot of people agree that, at a point, it's the right approach. Because, after all, what are you really testing if you don't hit an actual DB?
But, that's specific to code that has dependencies on outside systems (like the DB, or your graphic subsystem). When I look at your Foo class and the IsValid method, I see a pretty specific unit that really can and should be tested separately from an actual GrSubsys implementation. I mean, you've given it a dependency on GrSubsys, but I'm not sure that's right.
Should the test read:
"it is invalid when the model is null"
or
"it is invalid when the graphic subsystem returned null"
?
The difference is subtle, but important. The first is decoupled from the implementation. Foo is invalid when it's model is null. The second is coupled to the depedency: Foo is only invalid when the graphic subsytem returned null.
What value does that extra coupling, within your test, get you? What should IsValid (either the test, or the implementation) care that why the model is null? Why add that extra complexity which makes your test more likely to break due to changes to the implementation of the dependency?
If you test Foo independently, and then you test that gGrSubsys returns null on an invalid model separately, the two unit tests end up working together in isolation from changes you might make to the other.
some_system::get_instance()->MemberFunc(), instead of sys->MemberFunc()
Problem came apparent when somebody had made the Camera singleton, and it was singleton...
Nowadays we have one keyboard, one mouse, one printer... We used to have one DISPLAY, even one WINDOW (fullscreen), and one JOYSTICK. Just to get the point...
For example, we use at work DEJA Insight Profiler, and you can directly put profile probes (C++) with DEJA_CONTEXT("SomeFunction") - it's using RAII to mark start/end of the probe. But the point is there is no explicit call to DEJA_INIT, or DEJA_CLOSE, etc. But this only works if the DEJA main application is loaded.
http://zmotula.tumblr.com/post/1390385240
There’s also a blog post called Singletons Are Pathological Liars by Miško Hevery, which is very well thought-out and contains links to other related topic:
http://misko.hevery.com/2008/08/17/singletons-are-pathologic...
Hope that helps somebody, reading Hevery’s articles was a huge eye-opener for me.
Hmm, so perhaps that says something more about OO than "singleton style"?