It’s not knitting

I was at a user group meeting the other day where the speaker was giving a brief introduction to design patterns. The first pattern, as always, was the classic Singleton. After talking about the bad points of the Singleton pattern itself, in particular the problems it causes for unit testing and the lack of scalability, the presenter talked though the double check locking implementation.
 
        private static Class2 m_Singleton = null;
        private static object m_Lock = new object();
        public static Class2 Instance()
        {
            if (m_Singleton == null)
            {
                lock (m_Lock)
                {
                    if (m_Singleton == null)
                    {
                        m_Singleton = new Class2();
                    }
                }
            }
            return m_Singleton;
        }
 
He then pointed out that this was old school and that there was better way in C# to do the Singleton.
 
        static Class1 m_Singleton = new Class1();
        static Class1()
        {
        }
        public static Class1 Instance()
        {
            return m_Singleton;
        }
 
Note that the empty static constructor is there to prevent the C# code compiling to IL with the field marked as beforefieldinit which would allow the CLR to run the initializer at any time. With the static constructor the first time that m_Singleton can be initialised is on access to the class.
 
What he didn’t point out was that there’s a very obvious case where the "old" implementation is far better. If the field initialization throws an exception, then the "old" pattern will keep trying to make the Singleton when the Instance method is executed. The "new" style implementation will keep throwing the exception from the first failure.
 
    public class Class1
    {
        … new style code above …
        static int m_Count = 0;
        Class1()
        {
            Console.WriteLine("Making instance");
            if (m_Count == 0)
            {
                Console.WriteLine("Throw");
                m_Count++;
                throw new Exception();
            }
        }
    }
 
    public class Class2
    {
        … old style code above ….
        static int m_Count = 0;
        Class2()
        {
            Console.WriteLine("Making instance");
            if (m_Count == 0)
            {
                Console.WriteLine("Throw");
                m_Count++;
                throw new Exception();
            }
        }
    }
 
Trying the following harness code, first for Class1 and then with all instances of Class1 replaced by Class2,
 
        static void Main(string[] args)
        {
            Exception caught = null;
            try
            {
                Class1 a = Class1.Instance();
            }
            catch (Exception x)
            {
                Console.WriteLine("Exception");
                caught = x;
            }
            try
            {
                Class1 b = Class1.Instance();
            }
            catch (Exception x)
            {
                Console.WriteLine("Exception 2 – {0}", x == caught);
            }
        }
 
We see that the "old" style keeps trying to make a Singleton and snapshots it on success, whereas the "new" style has one go at making it and then returns the same exception object thereafter.
 
This point brought home to me just how subtle code can be and how often "equivalent" code is only equivalent from one perspective but behaves completely differently in other dimensions. In the "new" style, the mechanics of the locking has been pushed into the virtual machine making the code cleaner, but this has also resulted in a slight loss of control for the programmer.
 
The GOF patterns are great but are not universal across all languages. The talk caused me to have another look at Greg Sullivan’s survey of the standard patterns and how they are implemented in dynamic languages, better patterns through reflection, which is a good read.
 
Advertisements
This entry was posted in Computers and Internet. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s