In my previous entry, I described what default instances are but left open the question of why we’re re-introducing them into the language. So let me spend a moment discussing that.
A default instance is, more or less, an instance of the design pattern called a singleton. A singleton is a type that only ever has one instance (hence the “single” part of “singleton”). Forms are often an excellent example of singletons because there is usually only ever going to be one instance of the form (with the exception of less common situations like MDI windows). For example, you only need one instance of the File Open dialog because there will only ever be one File Open dialog on the screen at a time. Rather than having to allocate an instance of the dialog every time you need one, or holding on to the same instance in some random place in your application, a singleton has a central location where the single instance is stored.
In most languages, you have to manage singleton objects yourself. This is usually accomplished by sealing the type (i.e. making it NotInheritable), making it uninstantiable (i.e. making its constructor Private) and exposing a shared property called something like DefaultInstance that returns, well, the default instance. If only the language would do that management for you automatically, how nice would that be? If only…
So now we arrive at the rationale for default instances, aka singletons: we think it’s a more natural way of working with objects that always or almost always have a single instance.
I’ve been using forms as an example up until this point, but let me expand the scope a little bit to illustrate my point. Web services are another example of a natural singleton object. When an application interfaces with a remote web service, there is typically only ever going to be one web service proxy instantiated. In VB 2002 and 2003, it is necessary to create a new instance of a web service proxy and then hold on to that instance for as long as you wish to use the service. If you wanted to share the service across multiple objects, you had to make sure to store the instance somewhere where everyone who needed it could get at it. And, truth be told, all of this management code had nothing to do with your program logic. It was just boilerplate that everyone has to write again and again and again.
In constrast, VB 2005 adds a default instance to web services. When you add a reference to a web service Bob, you automatically get a default instance at My.WebServices.Bob. No need to remember to create an instance of the proxy. No need to sock that proxy away somewhere so that everyone can get at it. It’s just… there. Without you having to do anything to make it so.
This seems like a good thing, but don’t just take my word for it. After all, you can go read about how to implement the singleton pattern in C# and how to implement singleton forms in C#. And then you can come back to VB and find that we already did it for you… (I should add that Justin’s singleton form entry touches on a specific problem having to do with the design of WinForms that I’ll address in the next entry.)
Well, that’s about it for the moment but we’re not done yet… I still need to cover the problems and issues that have been raised around default instances, which I will cover next. That entry, tentatively titled “Default Instances Considered Harmful” is coming soon.]]>
Interesting – the Web Service proxy example actually seems potentially problematic. A web application, for example, might typically have many simulaneous calls to a web service. And especially if they carry state (like SOAP headers), things could get quite confused with multiple clients on multiple threads accessing the same proxy. Obviously they don’t need to use the default instance, but to multi-threading newbies, this might not be that obvious.
Actually I love it. I know it is singleton pattern. But I was afraid that somebody didn’t like it’s syntax and would hate VB…
<![CDATA[You really didn't implement a singleton pattern for anyone, since the developer still has to seal the class and make it uninstantiable in order to truly be a singleton pattern. What's worse you are telling people it's a singleton pattern as-is so they might not think of doing those two steps (and with 1 line of code you've broken the pattern by simply creating a new instance). It also begs the question that if you are using design patterns shouldn't you be analyzing when and how you need them, and if so do you really want a design pattern implemented in every single class? All that wouldn’t be too bad, if your way of providing this half-baked approach wasn’t so ambiguous. As you say, the singleton pattern typically has a property such as DefaultInstance..woudln’t it be clearer if it was done this way as opposed to accessing the default instance via the class name? You still have half-baked idea, but at least it’s clear. myClass.DoSomething() isn’t nearly as clear as: myClass.DefaultInstance.DoSomething() Karl
<![CDATA[Paul: I really think that this whole idea of Default Instances just unnecessarily complicates the language design (and the language interface through which we deal with the VB). Using New on a class isn’t that hard… My biggest worries are that these sorts of changes might prevent you from providing a clean syntax to new language features in the future. Or that you might introduce some kludgy behavior for new features because of the way this feature is being implemented. I, and true lovers of VB I am sure, truly desire for VB to keep a clean, predictable syntax and behavior consistent with true object-orientation. It is sad to have to learn and get used to peculiar hacks in VB that’s inconsistent with good object-orientation. VB got a clean slate with VB.NET and the VB Team has done a darn good job so far – it shows in the VB syntax for Generics constructs, etc. Please let’s not be too quick to mess it up. Anyway, I hope that all the recommendations suggested by Bill at http://msmvps.com/bill/archive/2005/01/24/33679.aspx are taken under *serious* consideration. Best! Taiwo]]>
Thanks Taiwo !!! 🙂
<![CDATA[hey Paul, I find your definition of "why" more like a "how" not a real "why". Why, to me, would include things as why was this made a prioirity, why did this coem before other development enhancements, why was itn’t made optional (originally), why it was felt necessary to confuse the name of the default instance with the name of the type, etc. All these thigns were or shoudl have been part fo the decision as to whether or not implement default isntances, yet they get no coverage ?? Oh, and I find it ironic that you link to Justin’s C# so called singleton forms, which in reality are not true singletons, rather the key concept there was the form being a data storage vessel, something which you know I have been nagging you to address 😉 http://msmvps.com/bill/archive/2005/01/24/33679.aspx ]]>
<![CDATA[Hi Paul... Great information by the way! Will you be updating your recently published VB book for VB2005? Thanks! Leigh]]>
<![CDATA[I think Taiwo has described my thoughts as well. I also understand that *sometimes* having a (nonpure)singleton form may be beneficial…but this is NOT always the case. Exposing forms that would benefit from only having a single instance beside forms that explicitly *need* to be instantiated properly as required will only confuse matters. One thing that may be a possible late change if you really want these default forms in the product is to provide us with two form classes/templates. Form: as it is now, explicit creation required, etc Forms of this type are not exposed in the My namespace. SingletonForm : Forms of this type are exposed in My, and because they explicitly being developed as a single instance form, can have a template that includes the sealed keyword, and a private ctor so the default instance *is* the only one. I’ve not analysed it fully, but I’d imagine that SingletonForm could even be derived from Form, so the code base would be relatively unchanged, as I imagine would your My namespace creation code. Would this help alleviate all our concerns (and be possible within the VS2005 timeframe)? ]]>
Typical..after making my post, I actually read Justins blog entry to see his implementation is similar to what I would like to see as part of the framework (but without the additional benefit of the My namespace being aware of it already, and so being able to filter out the other forms, and the singleton form concept being introduced to VB being available across the board)
detailed on Singletons
<![CDATA[Nice feature .However still i think that i should point out some thing :-
whatever default instance you are providing for webservice is not so imp as i can create a proxy insatnce at any point in my app and the problematic proxy type sharing will be resolved with 2005 courtesy webservice team. sharing a proxy is rare reqd features however sharing between proxy is what quite recommendable. Second type sharing is not recommendable as per soa thus we needn’t have to implement one class in client and share the same across client apps(though u ddin’t have raised it i m mentioning as per the logic i though what may be the situation for using singleton in this scenario). Now coming to the actual requirement of singleton rather i say default instance if you could differentiate the same requirement are winform or an application where we need similar single instance. As per singleton are concerned i had one more topic to be discussed with that is how can you make it sure that only one instance is running in a network?that is let me create a singleton app (let i craeted the exe) and create a shortcut of the same to a different system and if now i try to invoke the same from both app both will run?the process class can only help in a single machine. please send ur comment to:-
Karl’s right. This isn’t a singleton at all. Putting default instance into the language is just going to lead to poorly designed applications which will be difficult to maintain in the long run. It’s just not worth the cost.
How to create Fiveton like Singleton class, with 5 instances.
How to create Fiveton like Singleton class, with 5 instances.