Gang of Four Anti-Patterns

Tuesday, July 21, 2009 1:26 PM

These is basically patterns where you're better off avoiding them.  Seriously, just skip those parts of the book:

Singleton

All patterns are a trade-off.  The trade-off with singleton is reducing the number of parameters certain functions take and trading them for more static methods.  From the perspective of code agility, a every method on singleton might as well be a static method.  Not only that, but everything the singleton touches might as well be a static method.  The testing implications of the Singleton pattern are horrendous.  Steve Yegge has written far more than I intend to on the subject, so I'm really not going to spend any more time on telling you what a stupid, stupid idea it is.  Singletons, static methods and global variables all expose the same problem.  In fact, they're pretty much effectively the same thing most of the time. 

So, what should you do instead of a singleton?  Well, let's say, for instance, that you have a network connection (call it X) wrapped as an XConnection object.  There's only one physical connection, and that needs to be accessed from various parts of the system.  Well, actually, the answer is very simple: you pass the object into the contructor of the objects that need it.  If some of those objects get created before the network connection gets called, you could pass in an object that creates the connection on the first call, or you .  Basically, take the static methods you were thinking of, and turn them into instance methods.

Now, the technique that we've just described is called Dependency Injection (DI), and is made easier by using a DI container.  Ironically, you tend to tell the container that the connection object has a "Singleton" lifecycle.  But all that means is that there's one connection referenced by the container, not one connection usable in the whole of your memory space.  The distinction may appear small, but it's the difference between a flexible design and a brittle nightmare.  Much as certain extremely talented people may use the technique, don't make your container a singleton.  That way lies madness.

Singletons are, of course, a special case of the concept of shared state.  In general terms, state and especially shared state, is problematic.  Designs that share very little state or, even better, have no state at all tend to be less prone to hard to analyze bugs and easier to repurpose when requirements change.

Prototype

This one basically says you shouldn't create your objects, you should copy them.  We already know this concept in .NET, it's called ICloneable.  There's all sorts of problems with cloning objects, number one of which is that it's not that well defined.  If X has Y as a property, when you clone X, do you clone Y?  Seriously, semantically, the prototype pattern is a mess.

The BCL team were talking about demising ICloneable five years ago

The thing with prototype is: you can see how it might look sensible if you're a C++ programmer.  Copy means something quite specific: a memory-based clone.  Any good C++ developer would know exactly what that would do.  It'd copy things declared as values and re-use things declared as pointers.  Let's just think about that for a second: what happens when your data structure changes a value to a reference?  Well, the semantics of your copy change.  And, of course, you can't copy anything that uses an external resource.

Now, JavaScript is based around the idea of prototypes instead of classes.  These are not the same thing as the prototype pattern. 

On the other hand, it's important to note that sometimes context is everything. 

Summary

The Singleton and Prototype pattern have no place in the arsenal of the educated C# developer.  Prototype just makes no real sense, Singleton will positively ruin your code.  Most people know that singleton is a bad idea, but are still enamoured with the concept of shared state.  On the other hand, I don't think anyone is seriously attempting to use the prototype pattern in C# in the first place.

Comments
No comments posted yet.
Something to add?

Talking sense? Talking rubbish? Something I'm missing? Let me know!

Fields denoted with a "*" are required.

 (will not be displayed)

 
Please add 8 and 7 and type the answer here:

Preview Your Comment