Singletons Give You Pimples: Why to Avoid the Singleton Pattern in ActionScript 3.0 Programming
At the 2006 OOPSLA Conference in Portland, Oregon one of the people who came into our session was pounding on the Singleton Design Pattern. He even brought in a PowerPoint presentation quoting Erich Gamma as saying he wished he’d never included the Singleton in the GoF book. This wasn’t a mild rebuff of the Singleton; it was a wholesale condemnation.
The Singleton in ActionScript 3.0
A quick online search reveals a good deal of discussion about the Singleton in ActionScript 3. However, much of that discussion is based on how to improve it given AS3’s lack of private class constructors. Both Grant Skinner and Tink have provided brilliant workarounds that seem to solve the problem of multiple instantiations of a Singleton. Darron Schall has written a nice summary of the ActionScript 3.0 Singleton discussions and reached a similar conclusion as I originally did. Namely, most of the problems envisioned by ActionScript 3.0’s lack of private class constructors never caused the problems that AS3’s shortcomings were supposed to have caused. In our book, we provide a brief cautionary tale about using the Singleton, but it was not very strong or substantive. (I wrote the Singleton chapter; so I can say that.)
Any attempt to improve the Singleton is like making the black mamba more deadly. The point is not to improve it but to avoid it. However, in understanding the problems using the Singleton, we can better understand what the focus of OOP programming should be and the reason that using design patterns is important for achieving the dual goals of change and re-usability. A lot of the criticisms of the Singleton have been summarized by Scott Densmore and on the Flash-Focus blog, and my intention is not to improve on their comments. Rather, I’d like to use the general comments by them and others to focus on good practices and re-focus the discussion of design patterns to the key issues important to OOP and design patterns. That focus, I believe, is the relationship between objects.
Dependencies Hamper Change
A core principle in design patterns is to reduce dependencies. A primary culprit in creating dependencies is the global variable. Global variables can run through a program like a skin-eating virus. One little change requires unzipping the whole package and changing all of the parts—rewriting the program. That’s why private variables and functions are so important. The little buggers are encapsulated and won’t run amok and change or get changed by unwanted operations in the program. Global variables, while making life simpler in the short run, cause headaches when even little changes have to be made. The extent to which Singletons provide a global access point, they serve many of the same functions and generate the same kind of problems as global variables. However, they often hide their global character and untangling unwanted dependencies because of Singletons is often more troublesome than the same process with global variables. You don’t expect Singletons to create dependencies and so they may be overlooked as the source of the problem. Creating global variables, on the other hand, is an act that programmers actually have to think about and so should be well known when dependency problems arise. As such they are (or should be) the immediate suspects. Not so with Singletons. After all, the Singleton structure is a design pattern and we all expect design patterns to have the opposite effect and automatically reduce dependencies. However, Singletons may have been denizens of the Dark Side all along, and we just never noticed. (Miško Hevery’s blog post, Singletons are Pathological Liars is another interesting take on why Singletons are nothing more than global variables.)
The Single Responsibility Rule
A fundamental principle in OOP is that each class (or element) should have a single responsibility. Chandima lays it out nicely in the MVC chapter in our book (p.443),
…each element in the MVC adheres to the single responsibility principle. Each element has a well-defined role. The model manages state, the view represents state, and the controller handles user input. This allows each element to be swapped out without affecting other elements.
Now you may be thinking—That’s exactly what a Singleton does! Its single purpose is to provide a single entry point. Well, not according to Scott Densmore. The Singleton provides both a single entry point, and it also insures only a single instance of the class will be created. Count ‘em. That’s two responsibilities. Well maybe so, and maybe not. According to the Freemans (authors of Head First Design Patterns), a single responsibility refers to a design principle,
A class should have only one reason to change.
Okay, but does the Singleton have any reason to change? A responsibility is a reason to change, and so yes, as a matter of fact, it does. Unfortunately, it has more than one.
The Chain of Responsibility pattern discussed on this blog is one of the best examples of the rule of Single Responsibility. Each element in the chain has one and only one responsibility. Figure 1 illustrates how the chain works. A request is passed to the first element in the chain, and if can handle the request, it does. If not it passes it on to the next element or until it runs out of options or is handled by a residual class.
Figure 1: Each element has a single responsibility.
In some respects the Chain of Responsibility pattern represents a microcosm of the Single Responsibility rule. You can see clearly what each element’s responsibility is and whether it can handle the request or not. Likewise, you can change the elements without having to change the rest of the program. All programs should have the feature of Single Responsibility.
No Tight Coupling Please
The principle of Loose Coupling is so ubiquitous in both design pattern and OOP architecture that to mention it may seem to be an overstatement. However, I’ve seen too many instances where a perfectly good design pattern is ruined because the developer willy-nilly tightly coupled objects without really thinking through the consequences. During testing, especially unit testing, these tightly coupled structures make testing alternative implementations virtually impossible without re-writing all the code. That defeats the purpose of OOP and the whole concept of encapsulation.
Singletons type to the exact type of the Singleton object. Of course with that you have no loose coupling; just the opposite. If you think this is a minor matter, tools exist for detecting Singletons (in Java) so that they don’t mess up the program. In other words, Singletons are treated like viruses. At Google, in their Guide: Writing Testable Code one of the flaws includes adding or using singletons.
Why So Many Singletons?
Several years ago I was working on a beta for a Web development tool. Like all betas, we had a diverse international group of developers and designers tweaking and testing the application. In the beta forum one of the designer/developers commented that he once had a client who insisted that he use Front Page to develop a site he wanted. When the designer balked, the client explained that Front Page was the most common tool in Web development and so must be the best. It seems that some have applied the same logic to the Singleton. Not only is it common, it is simple to write—even without private class constructors in ActionScript 3.0. In good faith, many developers seem to have concluded that using the Singleton would guarantee that their code was design pattern based and promoted good OOP. Unfortunately, it seems that the opposite may be true. So before plopping another Singleton into your code, keep in mind that you may be inadvertently adding what amounts to an OOP virus to your project.