A couple of years ago I (somewhat inadvertently) got involved in learning more about software design patterns than I really wanted to. It sounded like fun in the beginning, in a geeky kind of way, but soon – like so many of my “I wonder” ideas – spiralled out of control.
I was daft enough to propose a session about design patterns to several conference organizers, and to my surprise they actually went for it. In a big way. So I ended up having to keep doing it, even though I soon realized that I was digging myself into the proverbial hole. Best way to get flamed at a conference or when writing articles? Do security or design patterns. And, since I suffered first degree burns with the first topic some years ago, I can’t imagine how I drifted so aimlessly into the second one.
Mind you, people seemed to like the story about when you are all sitting in a design meeting for a new product, figuring out the architecture and development plan, and some guy at the back with a pony tail, beard, and sandals suggests using the Atkinson-Miller Reverse Osmosis pattern for the business layer. Everyone smiles and nods knowingly; then they sneak back to their desk to search for it on the Web and see what this guy was talking about. And, of course, discover that there is no such pattern. Thing is, you never know. There are so many out there, and they even seem to keep creating new ones. Besides which, design patterns are scary things to many people (including me). Especially if UML seems to be just an Unfathomable Mixture of Lines.
Of course, design patterns are at the core of best practice software development, and part of most things we do at p&p. So I now find myself on a project that involves documenting architectural best practice. And, since somebody accidently tripped over one of my online articles, they decided I should get the job of documenting the most common and useful software patterns. No problem, I know most of the names and there is plenty of material out there I can use for research. And we have a team of incredibly bright dev and architect guys to advise me, so it’s just a matter of applying the usual documentation engineering process to the problem. Gather the material, cross reference it, analyze it, review it, and document the outcome.
Ha! Would that it were that easy. I mean, take a simple pattern like Singleton. GOF (the Gang of Four in their book Design Patterns: Elements of Reusable Object-Oriented Software) define the definition of the pattern and the intended outcome. To quote: “Ensure a class only has one instance, and provide a global point of access to it.” So documenting the intentions of the pattern is easy. The problem comes when you try and document the implementation.
It starts with the simple approach of making the constructor private and exposing a method that creates an instance on the first call, then returns it every time afterwards. But what about thread safety when creating the instance? No problem; put a lock around the bit that checks for an instance and creates one if there is no existing instance. But then you lock the thread every time you access the method. So start with the test for existence, and only lock if you need to create the instance. But then you need to check for an existing instance again after you lock the thread in case you weren’t quick enough and another thread snuck in while you weren’t looking. OK so far, but some compilers (including C# but not Visual Basic) optimise the code and will remove the second lock as there is nothing in the routine that can change the value of the instance variable between the two lock statements. So you need to mark the variable as volatile.
Now that you’ve actually got the “best” implementation of the pattern, you discover that the recommended approach in .NET is to allow the framework to create the instance as a shared variable automatically, which they say is guaranteed to be safe in a multi-user environment. However, this means that you don’t get lazy initialization – the framework creates it when the program starts. But you can create it as a child class and let .NET create the instance only on demand. So which is best? What should I recommend? I guess the trick is to document both (as several Web sites already do). Problem solved? Not quite. Now you need to explain where and when use of the pattern is most appropriate.
At this point, I discovered I’d proverbially put my head into a hornet’s nest. Out there in the real world, there seems to be a 50:50 split between people saying using Singleton is a worse sin than GOTO, and those who swear by it as a useful tool in the programmer’s arsenal. In fact, I spent a hour reading more than 100 posts in one thread that (between flamings) never did provide any useful resolution. Instead of Singleton, they say, use a shared or global variable. As much of the online stuff seems to describe Singleton only as an ideal way to implement a global counter, I can see that reasoning. However, I’ve used it for things like exposing read-only data from an XML disk file, and it worked fine. The application only instantiates it on the few occasions that the data is required, but it’s available quickly and repeatedly afterwards to all the code that needs it. I suppose that’s one of the joys of the lazy initialization approach.
And then, having fought my way through all this stuff, I remembered the last project I worked on. If you use a dependency injection framework or container (such as the Unity Application Block) you have a built-in mechanism for creating and managing singletons. It even allows you to manage singletons using weak references where another process originally generated the instance. And you automatically get lazy initialization for your own classes as well as singleton behavior – even if you didn’t originally define the class to include singleton capabilities. So I guess I need to document that approach as well.
And then there are sixty or so other patterns to tackle. And some of them might actually be complicated…