Problems with the Singleton Design Pattern

Introduction

The design pattern Singleton first came to the attention of the software development community at large as a result of its documentation in the book Design Patterns: Elements of Reusable Object-Oriented Software” by Erich Gamma, Richard Helm, Ralph Johnson  and John Vlissides, which I mentioned in my “A Brief Introduction to Software Patterns” article. Unfortunately, Singleton has become one of the most – if not the most – popular patterns when it is actually best avoided.

I have implemented Singleton many times (although not for some years now!). While it is just possible that there might be in existence a favourable problem/context/forces combination, I now can’t think of one occasion where my use of Singleton was a good solution to the problem I was trying to solve. Singleton is, after all, nothing more than a global variable dressed up as an object. Unfortunately, its appearance in the book by Erich Gamma et. al. – nicknamed the “Gang of Four (GoF)” – has given it an undeserved respectability. Further, looking back at the GoF’s examples of where Singleton is supposed to be a good solution, frankly I don’t think they stand up to scrutiny.

For some time now I have held the view that Singleton causes more problems than it solves. It is just unfortunate that often developers use Singleton and find workarounds for the problems it causes, without realising that the presence of these problems is really an indication that they should seek an alternative approach.

Roles and Responsibilities in Design

Having taken the swipe at Singleton, I will spend the rest of this article explaining the assertions made above. To this end I think we need to step back and ask two fundamental questions about the design of objects and their interfaces:

  • How much knowledge should an object have of the outside world in which it is being used?
  • How much responsibility should be captured within a single interface?

In answer to the first of these: an object’s knowledge of the outside world should extend to what it is told via its interface. An object’s purpose is to provide certain functionality to its clients, and to this end an object should provide the minimum useful interface that makes this functionality accessible. As a matter of design principle an object should stick to providing functionality via its interface, and not assume any knowledge of how the outside world – i.e. client code – is using it. Therefore it follows that an interface can’t make any assumptions about how many objects that support that interface are needed, because that issue is resolvable only in the context of the client code.

The matter of how much responsibility an interface should assume is somewhat less concrete. An interface should capture a single role, but it is not always easy to define what constitutes a single (cohesive) role. An interface supporting a simple Factory Method has its role is extended to incorporate the responsibility of serving up other objects with related roles. However, in the case of Singleton, the interface/semantics must assume three kinds of responsibilities: (i) the objects functionality, (ii) the serving up of the single instance, and (iii) the management of that object. Further, the whole premise of Singleton is that there can be only one instance, but the logic is flawed for one simple reason: knowledge of how many instances to create is in the client code, not the type being instantiated. A Singleton object is therefore presuming to know something it cannot reasonably know.

Encapsulation

Encapsulation - cordoning off implementation detail and making it available via a public interface - is a friend to the software designer. Encapsulation is one of the features of well designed software that brings various benefits with it: clarity in the communication of how it is intended to be used, and ease of testing, to name just two. Singleton is essentially just a global variable wrapped up as an object - and global variables are well known to be the enemy of encapsulation. It is just unfortunate that its appearance in the Design Patterns book by Erich Gamma et. al. has lead to so many software developers failing to notice the global variable in disguise aspect of Singleton.

If a function makes use of a global variable, then its inner workings can be influenced via the global variable; that is to say, the inner workings can be influenced from outside the function while bypassing the public/published interface. The same thing applies to a function that uses a Singleton object! Because the public interface can be bypassed in this manner, it is much more difficult to specify pre/post conditions for calls to such a function.

Initialisation

There is only one instance of a Singleton, so it much be initialised only once – but how can this be achieved? All the text book examples seems to dodge this question by using examples that require only default initialisation, that is to say, initialisation that does not require any arguments to be passed to the object on its construction. However, real world examples are not so simple, more often than not.

One approach is to initialise on first use. However this is only practical if the control flow to the point of first use can be predicted, and that the path through the code passes through this point only once. Alternatively, initialisation arguments can be passed to the class method that returns the Singleton’s instance everywhere this method is called; in this case the arguments would have to be ignored except on the first call to this method. Note that this approach is clearly weak, if not flawed: how do you ensure that the same argument values are passed in each case (and if you can’t the result is chaos)? Neither of these methods is pretty, and the indication is very much that Singleton is causing more problems than it is solving!

A Parameter Passing Alternative

Having made a case for Singleton being a bad idea I now need to come up with an alternative. The approach I suggest is simply the following: client code (of the functions/objects that need the single instance) should create and maintain ownership of the single instance, and pass it as an argument to the components that need it. This approach is known as Parameterise From Above. Unfortunately Parameterise From Above is a design pattern that is “out there” and has been discussed in several places (I’m not citing references here, just try Googling it) but which seems to have no formal write up - or at least no definitive write-up. Anyway, using the Parameterise From Above approach, the following are true:

  • Initialisation problems go away because the control flow on which the instance should be initialised is completely clear
  • Encapsulation is in good shape because there is no longer a “back door” that bypasses the interfaces of the functions/objects that use the single instance. Note that it is now straightforward, in a unit test, to substitute a Mock Object implementation for single instance
  • The single instance class now does not assume any responsibility for managing its single instance. That is to say, it can concentrate on providing (via its interface) the functionality that fulfils its design role, and it does not need to concern itself with responsibilities that rightfully belong in the client code that uses it - such as managing class instances!
  • The interface of the single instance class can be designed such that it assumes responsibilities that add up to it fulfilling a single role in the overall software system design
  • Although there is a downside in that the client code must maintain the single instance, believe I have shown that Singleton incurs sufficient problems that having the client code maintain one more instance (and being able to pass the instance around in a natural manner) makes this more than worthwhile
  • If the design changes so that more than once instance is needed, refactoring is far easier

Finally

The problems I have described in this article point to the Singleton design pattern being dysfunctional. That is to say, although it may solve a problem, the consequences of deploying it as a solution results in more problems than are solved, and that the approach involving Parameterise From Above offers are far more preferable set of tradeoffs.

The Anti Patterns Misconception

I kicked off this Software Patterns category with A Brief Introduction to Software Patterns. The following is a short quote from that post which sums up, in a nutshell, what that post had to say:

A pattern is basically a capturing of a problem (in context) together with a solution to that problem

Another pattern related term that is in common use in software development is “anti-pattern”. The concept of the anti-pattern is something of a misconception, so here I’d like to take a look at why it’s a misconception.

It is very convenient to talk about “good” and “bad” practices, but this is problematic in itself because it oversimplifies the world far too much! Please take the following points into account:

  • One of the important things a pattern captures is the context in which a problem is occurring, and hence the context in which the solution is applied
  • In addition, a pattern also captures the tradeoffs accepted in applying the solution

What constitutes “good” and “bad” practice depends largely on what one is trying to do in the first place, and on the surrounding circumstances. Further, a solution which is a good one subject to certain context/tradeoffs might be a bad one subject to different context/tradeoffs.

The anti-pattern misconception starts with another misconception - that a pattern captures a best practice solution to a problem in context, which is not correct. Certainly many known patterns do capture best practice solutions, but the best practice part of it is not part of the definition of what a pattern is. It just so happens that what people are usually interested in is the best way to do things, and hence enthusiasts have documented many patterns capturing best practice solutions.

Just suppose for a minute that the commonly believed myth about patterns capturing best practice was true. That leaves a reason - a need in fact - to capture wrong/bad/worst practices, to help developers recognise them and understand why they are wrong/bad. This is where the term anti-pattern comes in. In reality anti-patterns are just patterns - that is, patterns in which the solution captured is a bad one. In fact, the anti-pattern captures a solution that does not satisfy the acceptable tradeoffs, does not work in the context, or both. A pattern captures a solution to a problem - be it a good, bad, or indifferent one, hence the anti-pattern concept is actually meaningless. Unfortunately, in my experience, write-ups and discussions of anti-patterns either do not take into account that the world is not so clear cut, just choose to ignore it, or both.

Double Dispatch Pattern

The Double Dispatch pattern is a design pattern used to leave a class hierarchy open to having extra operations added to it. Further, double dispatch allows the implementations of such added operations to be different according to the actual, or “concrete”, type of the class.

In this article I will start with an example of C# double dispatch. Although the example uses C# as its language, both Java double dispatch and C++ double dispatch could be implemented in a very similar way.

Example

Consider a drawing program (yes I know you’ve heard this one a thousand times before, but it serves well as an example!). This program will have a shape class hierarchy that will be headed up by an interface called IShape. Let’s say we have two concrete classes: Circle and Rectangle.

The role of the shape hierarchy is to encapsulate information about the properties of the shapes in our drawing program, such as their positions and sizes. That is to say, its role is to contain application logic, and it does not want to have code in it that interacts with the GUI. In typical GUI tradition, we will want to put up dialog boxes for each shape to allow the user to update its properties, and this dialog box will be different depending on whether the IShape object is a Rectangle or Circle. Here is a fragment (in C#) of the shape hierarchy:

    interface IShape
    {
        ...

        void move(int newX, int newY);

        ...

        void process(IProperties props);
    }

    class Circle : IShape
    {
        ...

        void IShape.move(int newX, int newY) { ... }

        ...

        void IShape.process(IProperties props)
        {
            props.show(this);
        }
    }

    class Rectangle : IShape
    {
        ...

        void IShape.move(int newX, int newY) { ... }

        ...

        void IShape.process(IProperties props)
        {
            props.show(this);
        }
    }

I have left in the move() method simply to give the hierarchy some sense of realism, but process() is the method we’re really interested in here. Code that uses our shape hierarchy will only be doing so through references to IShape. However, when methods are called, the methods invoked are those of the concrete classes - therefore, in method calls the actual concrete class is known.

Further, in the implementation of process() in a concrete class, the this reference has the type of the concrete class - this allows us to take advantage of overloading.

This brings me to the classes that will actually display the properties dialogs - i.e. the classes that will actually contain the GUI code. They will be headed up by an interface that I am going to call IProperties, and that looks like this:

    interface IProperties
    {
        void show(IShape s);
        void show(Circle c);
        void show(Rectangle r);
    }

IProperties declares a show() method overload for each class in the IShape hierarchy. Because (in the implementation of the process() method) this refers to the concrete class of the object in the IShape hierarchy, the correct overload of IProperties.show() will be called.

If the IProperties interface has only one implementation - i.e. presumably called Properties - then it is possible to get away without the interface. However, this is something I do not recommend as it makes IShape and its subclasses just a little to tightly coupled to its properties for comfort. Further, IProperties may have more than one concrete class. For example, imagine that our drawing program is quite sophisticated and can distinguish between regular users and administrator level users. Let’s say that administrators have extra properties available to them. This would require more than one implementation of IProperties - say, UserProperties and AdminProperties. Then all that is needed is for an instance of the correct concrete properties class to be passed to IShape.show(). To keep the article’s size down a bit, I haven’t shown any of the code for IProperties‘ concrete classes, but I assume readers will have no problem mentally filling these in.

Now, the following example code shows how an IShape object’s properties can be invoked:

    void example(IShape sh, IProperties props)
    {
        sh.process(props);
    }

The Double Dispatch Pattern

So far I’ve just given a code example - now to show double dispatch as a pattern. I’m going to do this using a very simple description.

  • We are doing object oriented software development using a language such as C#/Java/C++. We want to add methods to a class hierarchy [the shape hierarchy], but (a) we want to keep code for these operations decoupled from the hierarchy and/or (b) we want to avoid modification of the hierarchy’s own code. Further, we want these operations to be polymorphic - that is to say, we want each concrete (derived) class in the hierarchy to have its own implementation of the method servicing the operation.
  • Therefore… First, invoke the operation on an object in the hierarchy [that is, via the process() method, in the example], and let the object (which knows what its own concrete class is) forward the operation on to another “handler” object containing the method that services the operation [the IProperties object that has the show() method]. This solves the problem but at the expense of having more class hierarchies to manage and maintain. Also, if a class is added to the original hierarchy, then each handler object class will need a method adding to it

This is a standalone write-up of the double dispatch pattern - as opposed to the informal illustration given by the above example. In passing, I hope to add further examples in the (near) future.

Finally

While I’ve seen a few examples of the double dispatch pattern in text books, I haven’t seen any literature describing it as such, that is, as a pattern (but note I’m saying I haven’t seen any, not that there aren’t any). Normally, double dispatch is mentioned as a technique used within the Visitor pattern, a more specific design pattern (see Gamma et al - the “Gang of Four Book”, mentioned in my previous article A Brief Introduction to Software Patterns). In fact I think developers often confuse the Double Dispatch pattern with the Visitor pattern. I think that is a shame, and that the former needs to be understood in its own right.

A Brief Introduction to Software Patterns

I’m pretty sure that the first contact most software developers at large have with patterns is through the well known book "Design Patterns: Elements of Reusable Object-Oriented Software" by Erich Gamma, Richard Helm, Ralph Johnson  and John Vlissides - the "Gang of Four" (GoF) as they became known. This book - containing twenty-four object oriented design level patterns - is just one of many books on the subject, and the twenty-four patterns it describes are just a small number of the documented patterns that are out there. Further, the patterns it describes are all pitched at the level of object oriented design, whereas there are many patterns documented at all stages and levels of software development: for example, see "Pattern-oriented Software Architecture Volume 1: A System of Patterns" by Frank Buschmann, Regine Meunier, Hans Rohnert, and Peter Sommerlad, which looks at patterns for system architecture, design patterns and programming idioms.

In order to start off the Software Patterns category, I thought I’d write a short introduction to the topic. In it, I aim to give an "in a nutshell" explanation of both what a pattern is, and what patterns contribute to software development.

What is a Pattern?

A pattern is basically a capturing of a problem (in context) together with a solution to that problem. As so often happens, though, things are just not that simple. To understand what a pattern is, I think it is worth stepping back and looking more generally at problems and their solutions. With this in mind, consider the following:

  • There is very rarely any such thing as the solution to a problem. That is to say, any problem will usually have more than one solution, each solution offering its own set of tradeoffs. Finding a solution is not a matter of finding the right solution, rather it is a case of deciding on the most acceptable set of tradeoffs.
  • Deploying a solution to a problem entails risk. If the solution turns out to be the wrong one, resources have been wasted. This risk can be mitigated by understanding the tradeoffs a solution offers, and the tradeoffs are best understood by drawing on the available experience.

The purpose of capturing a solution as a pattern is to help users choose the solution that will work best in their particular situation. Therefore, the most useful patterns are those harvested from existing practice/experience.

A pattern is made up - be it explicitly or implicitly - of the following elements:

  1. Name. The name by which the pattern is known. This may also give alternative names, if there are any
  2. Context. Problems occurs in context, and the context influences the suitability of a solution
  3. Problem. Self explanatory. This is usually quite a short statement, and a popular choice is to phrase it as a short question
  4. Forces. Factors that limit the choice of solution. The term forces is a metaphor from physics (forces influence the direction of the solution)
  5. Solution. Self explanatory
  6. Consequences. The pros and cons associated with the choice of solution. Sometimes the more general term Resulting Context (emphasising that the solution/consequences have changed the context from that in which the problem occurred) is used instead of consequences

These are the essential elements, but they are non-limiting in that they may be supported with other material. In particular, a pattern write-up often begins with an abstract or overview of the pattern, and of course examples are always good to include. Also, very importantly, examples of known uses should be included.

Example Pattern

  • Name: Proxy
  • Context: An object oriented software development where access to an object (the Subject) is non-trivial, in that it is necessary to assert some control over such access, or intercept the access in some way. For example, we may need to insert code to write log entries when operations are invoked on the object
  • Problem: How can control be asserted over access to the Subject?
  • Forces: The control asserted must be transparent from the client code perspective
  • Solution: Let client code address a representative of - that is, a Proxy for - the Subject. The client code addresses the Proxy, and the Proxy forwards requests to the Subject (as well as forwarding the Subject’s responses to the client). In order to address the transparency requirement, the Proxy object should have the same interface as its target object; ideally it should be possible to interchange the Subject and Proxy in the client code
  • Consequences: The above solution implements the ability to transparently assert control over access to the Subject. However, this transparency also hides any extra work done to access the Subject from clients. Therefore, it must be kept in mind that their is potential for performance problems to subtly creep into the system

Notation

There are various approaches to writing up patterns. The above example is also an example of the most disciplined. However, this approach does suffer from being quite formal and not particularly accessible for the reader. This is probably why pattern authors generally have a leaning towards less formal notations. Two popular forms are:

  • Simply stating the pattern as a problem/solution pair. In this case, usually the context and forces are rolled in with the problem, while the consequences are included in the solution
  • Describing the pattern from the perspective of intent and motivation. This is the approach used in the popular GoF "Design Patterns" book alluded to above in the introduction

Finally

I think patterns are a very important tool in the software development toolbox. I also think that the tendency towards more relaxed notational styles is a good thing in general because it makes for easier and more accessible reading. However, the more relaxed styles make it easy to overlook a fundamental point: a pattern is motivated by the need to understand the solution to a problem, together with its consequences. This must be kept in mind, otherwise there is a risk of this particular tool loosing its value.

The Difference Between Encapsulation and Abstraction

The difference between encapsulation and abstraction seems to trouble some people, which is something I find rather odd. While both are concepts important to object oriented design, and while both are complementary to one another, they are two different concepts. In this article I will explain briefly what encapsulation and abstraction are, and how they interact with, and complement, each other.

First, a few words about each of abstraction and encapsulation:

  • The use of abstraction in software design is similar to its use in maths. It involves representing a physical thing or a concept in terms of its essential properties and behaviour. This way, such a thing, be it a concept or something that has physical existence, can be dealt with in a way suitable for modelling the way the real world behaves.
  • Encapsulation is a tool - that is, a tool in the intellectual sense - for drawing boundaries around implementations. One reason for this is to allow implementations to change without affecting the outside world. Another reason, perhaps more important, is its usefulness in structuring the design of a system. To further emphasise the organisational usefulness of encapsulation, consider that it allows the implementation to be tested in isolation, without integration with the rest of the system. A simple function is one example of a unit of encapsulation - that is, as long as it does not use any global variables or any other kind of globally accessible resource. In passing note that this is why global variables are such a bad idea - they compromise the boundaries of encapsulation.

In my articles Accessing Object Properties While Respecting Encapsulation and Updating Object Properties While Respecting Encapsulation, I used a Circle class to illustrate the querying and updating of object properties. The class implements a Circle abstraction, in that Circle is manifested in a computer model by being represented as a combination of state and behaviour. Encapsulation is the instrument that permits the Circle to expose its state to the outside world in a way that keeps the public perception of its state separate from the way its state is implemented. For example, the Circle exposes a public radius property, but the implementation could be in terms of the diameter - requiring a calculation in the background when the radius is queried.

Abstraction and encapsulation are each complex topics in their own right, far more so than might be apparent when these concepts are first encountered. I hope this short article has helped to shed some light on the difference between encapsulation and abstraction.

?>iMaleSpectrumPass Mobile Milf Videos diflucan online All Girl Mobile Flomax online iMuscleMen Asian Parade Milf Seeker cartoonreality His First Huge Cock Rookie Guys justcartoondicks kamagra portugal Pure Anime hot muscle dudes Tranny Seducers Gay College Sex Parties Ebony Shemale Mobile Shes My Ex PV Trannies Housewife Porn Videos PV Strips 3DS Max 8 OEM3Q 3GP Video Converterdownload acdsee manager 2009 oemred eye remover pro 1.2cheapest windows vistacheapest windows vista ultimatecheap AutoCAD 2009Vision Backup Enterprisecheap Macromedia ColdFusionnero photoshow 5 downloadadobe photoshop cs oemcoldfusion mx 7 downloadkamagra sildenafil citratekamagra generic viagraorder caverta onlinecaverta 100buy cavertatadaliscasodex 50 mg tablet