Default Instance Considered Harmful…?

Way back in the mists of time (better known as January), I wrote two entries on the default instance feature we’re reintroducing in 2005. The first talked about what default instances are and the second talked about why we thought they were a good idea. I promised at the time to talk about the criticisms that have been leveled against the feature “soon,” but that “soon” has turned into “two and a half months or so.” This is partially because my work load suddenly ramped up, but it’s more because my blog entries and the accompanying comments prompted another round of internal discussion over the feature. That, unfortunately, took much longer than I wanted it to, which further delayed this (since I didn’t want to say one thing only to have to take it back later). So I apologize for the delay in getting back to this.

Anyway, now that we’re past that, the objections to default instances seem to tend to boil down to two major issues:

First, although default instances exhibit most of the attributes of singleton objects, they are really only “semi-singletons” because they can still be instantiated. In other words, in addition to saying Form1.Show(), you can also say “x = New Form1()” and then “x.Show()”. When you use New, you’re creating a second (or third or fourth…) instance of Form1 that is totally separate from the default instance. The relationship between the singleton form and the instantiated form can be obscure at best, causing confusion between the singleton nature of the default instance and the multi-instance behavior of the normal type.

Second, a default instance that can be accessed through the type name (at present, only form default instances do this) erases the distinction between instance and shared members. When I say “Form1.x,” I have no way of knowing, without looking at the object browser or MSDN help, whether “x” is a shared member or an instance member.

(There is a third objection that because non-dialog Windows Forms lose state when they close, default instances are not as useful as they were in VB6. This is a limitation of the Windows Forms design, not VB – when a form closes, everything on the form is disposed, including the controls. Bill proposed a workaround that, I’ll confess, I don’t entirely understand, but it’s something we’re talking to the Windows Forms teams about, although I wouldn’t expect anything for VB 2005.)

The bottom line is that both of the major criticisms of default instances are valid. Despite their usefulness, they do create some semantic confusion that did not exist in the language prior to their re-introduction. Why, then, did we do it? In the end, we felt that, on the balance, the semantic confusion created by the feature was greatly outweighed by its usefulness. Working with forms (and, in VB 2005, web services) as default instances is a very natural and understandable way of doing things, regardless of experience level or knowledge of the language. In our continuing quest to make Visual Basic the most approachable and easy to work with language, this seemed like a very natural feature, not just because it happens to be compatible with VB6.

The standard rejoinder to this line of argument is, “well, fine, re-introduce the feature if you must, but why must you make me have to deal with it?” In other words, “why aren’t default instances optional?” This has been the subject of many long-running discussions internally and we’re open to the idea, but found no good way to do so in this release. We considered introducing a single instance/multi-instance mode switch into Windows Forms, but that would mean that changing the instancing mode of a form would cause drastic changes in the way the form was used in code. Thus, it would be vital to choose up-front whether a form was going to be single instance or multi-instance, and woe be unto the developer who chose incorrectly. We just didn’t feel that was a good user model for the feature.

The other major idea we considered was introducing some kind of configurable warning into the product that would allow people to turn the use of a default instance into a warning or error. This seemed much more palatable, but ultimately died because of what it would imply: warnings and errors indicate code that is probably or definitely wrong. They’re intended to ferret out errors, so adding a “warn on use of default instance” warning would imply, well, that using a default instance is an error, which is something that we don’t believe.

So, where does that leave us? One idea that we’ve started to kick around is the idea of integrating the concept of a “programming style” into the product. In other words, if your programming style is to not use default instances, great – you set that style parameter and then the compiler will warn you when you violate that style. Once you start down this path, you can imagine a great number of possible style settings that the compiler could flag – things that are entirely legal and valid, but which someone somewhere might not like. Unfortunately, this kind of feature is well beyond our VB 2005 schedule. However, as we start to think beyond our existing release, we’d love to hear what you think about the idea!

(For the less-aged among my readers, the title of this piece refers in an ironic way to the seminal paper Go To Statement Considered Harmful by Edsger W. Dijkstra, one of the founding luminaries of the computer science field. I would also note in passing that Visual Basic still has a GoTo statement…)

35 thoughts on “Default Instance Considered Harmful…?

  1. Roger Bonine

    Instead of building a full-blown style checker, why not integrate this functionaly into FxCop (or "code analysis", or whatever it’s called in VS 2005)? This seems like the most logical place for it. The "language police" are probably running this tool already, while the "option strict off" crowd almost certainly won’t use it.

    Reply
  2. John Barone

    Thanks for the post.

    I must say that I’m one of the ones that are disappointed with how the default instances are implemented in VB 2005.

    NOTE: I’m not a purist (I have an Access/VB6 background). The 2nd argument you mentioned (confusion b/w shared and default instance methods) is what concerns me the most. I also have some very bad memories of some of the problems that default forms caused; I tended to avoid them like the plague even back then.

    I do appreciate, though, why a default instance would be useful. But why do they have to be joined with the type **so** tightly. Wasn’t something along the lines of adding a shared method (e.g., "Default") which would dish out the default instance possible?

    That way, you could write something like:

    Form1.Default.Show

    ‘ Instead of

    Form1.Show

    It would have been one whole word extra for those that want to use the instances, but would have had the benefit of clarity in the code. You would know right away if it was the default instance that was intended or not.

    Reply
  3. Pingback: Brad McCabe's WebLog

  4. Pingback: Lorenzo Barbieri @ UGIblogs!

  5. Bill McCarthy

    Hey Paul,

    Form1.Show is in fact just an alias for My.Forms.Form1.Show, so what in effect you guys are currently doing is the equivalent of "Imports My.Forms" at project level.

    So the simple way to keep everyone happy is to explicitly include that in standard projects. If the user then chooses to remove the Imports statements, they can still use My.Forms.Form1

    The use of Imports addresses both issues 1 & 2.

    So why not do this ?

    Oh, as to issue 3 I thought I provided some working code as a demo some time back. It basically just used a native window to hook into the wndproc of the default instance, and intercepted the wm_close. A simpler approach could be to use the re-introduced query close event, and simply hide the form instead of closing it.

    Reply
  6. Greg Low

    Hi Paul,

    Sorry, I think it’s sad that the whole shared vs instance thing is getting stuffed up in the language. This completely plays to the worst C# slingshots at VB: Nasty language constructs done to make the language "approachable" and now, worse, not able to be disabled either πŸ™

    Regards,

    Greg

    Reply
  7. Pingback: The Bit Bucket

  8. Anthony D. Green

    As VB programmers I think a lot of us use shortcuts to make our lives easier. I write certain "global" functions to simplify code like my IDispose() method and in 2005 my generic Iif() method. Sometimes I import System.Console in console apps to rewind time to my QBasic days when console IO were a language keywords. And yes I declare in my Global module some form properties when necessary.

    I think we all do it so I’m fine with the VB team reintroducing something we were all doing anyway as long as I have some measure of control over it. I can in VS set my VBProject defaults to Option Strict ON. If the default instances are really just clever overload resolution or shadowing of some generated code in My.Forms then that’s something I’d use and could control. If I can remove the static import of the My.Forms namespace and "turn off" the illusion of default instances then I don’t think any of the arguments can’t be worked around. They wouldn’t fuzz the boundary between instance and Shared (static) members. They’d fuzz the boundary between Types and global properties with abiguous names. People coming from other languages who are confused will just have to learn a little more VB just like they’ll have to recognize my clever uses of Generic type inference (mwahahaha).

    On the otherhand if the VB team is gonna hijack my current code and force frmMain to manditorily return some default instance then the implementation needs to be rethought.

    Reply
  9. Ninputer

    I aggree with that to use Imports My.Forms instead of directly calling the default instances from class names. If anybody doesn’t like it, he can close it by deleting the Imports statements, rather than complains on your blog or the feedback site πŸ˜‰

    Reply
  10. Taiwo Ayedun

    Hello Paul:

    Given all the arguments from a lot of people against the introduction of this feature – or to be provided a way to turn it off or reduce its side effects – and because of the issues that you also admit to in this blog entry, the question must be asked:

    "For whom are you introducing this feature?"

    We all agree that customers drive most of what the product teams do. Which customers are driving the need for this particular feature? The customers that you hope would benefit from this feature are vehemently against it; why is the VB team so adamant about introducing it?

    Thanks,

    Taiwo

    Reply
  11. Taiwo Ayedun

    Paul:

    May I also suggest that you delay the introduction of this feature until you can implement ways for folks to disable or turn off the feature?

    It would seem cruel to satisfy some customers – assuming some customers truly want this feature – at the expense of those for whom the feature would introduce inconveniences.

    Thanks,

    Taiwo

    Reply
  12. Michele Bernardi

    None wants default instances and the rare ones who want them want them to be an option… I can understand this post in a commercial way, but it’s hard for me to think that you agree with what you just wrote.

    Default instances are the dirtiest solution for a problem that doesn’t exists really. Compatibility with "static-old-minded developers" must be broken.

    How many developers use Option Explicit Off? A few, so it’s good to leave to them this option, but would be painfull to force all others. Exactly the same for default instances…

    Reply
  13. Merak

    Can you explain what the difference between :

    "..some kind of configurable warning into the product that would allow people to turn the use of a default instance into a warning or error. "

    and

    "if your programming style is to not use default instances, great – you set that style parameter and then the compiler will warn you when you violate that style."

    Because to me they look identical.

    I can see only 2 "differences":

    1. with a "style", you get to group a whole load of other stuff together to generate the same warning, which you’ve already stated shouldn’t be there as it implies an error…except now it could be any one of a number of "style" issues.

    2. The "style" option is an obvious big change that certainly cannot fit into the VS2005 timeframe, whereas delaying the inclusion of a single warning option (or the feature itself) is much harder to justify.

    (My paranoid side thinks this is the real reason for this idea)

    Whatever mechanism you do though, please remember that it’s infintely harder to turn off (with options or otherwise) the use of a feature once it’s in the product.

    It also stops you being able to use the other suggestions (The static "Default" accessor, etc)

    Style warnings, or actual warnings are one thing..but they mean moving the work to the developers who have to maintain code written in the interim by people who use the feature..and remember that this was one of the bug bears with the VB6 implementation..it was dangerous to remove due to implicit use of shared default instances.

    I’m glad that you are thinking about this, but please delay the inclusion of the feature so ramifications of it’s use can be minimised, and so you have all possible options available when it comes to deciding on it’s permanent inclusion.

    Reply
  14. Owen Pellegrin

    The introduction of this feature is nothing more than an attempt to cater to VB6 programmers that are too lazy/not talented enough to convert to .NET. Visit a .NET forum for any amount of time and you’ll notice that almost 2/3 of the questions revolve around an attempt to use a default instance of a Form with System.NullReferenceException as the result.

    The claim that it is a logical syntax is ridiculous to me. I came to VB .NET from a C++ background and carried with me the hatred of VB6 that all good developers seemed to have. I was pleasantly surprised that .NET fixed everything that my peers had targeted VB6 for.

    I’ve seen the code that is produced by bad VB6 developers. I’ve seen code that is developed by bad VB .NET developers. I find bad .NET code to be many times more readable than bad VB6 code, and I will not condone any actions that make VB .NET more like VB6.

    Perl claims to make easy things easy and hard things possible. This is a good paradigm because you spend time on language constructs to make common tasks very simple. A singleton instance is not a feature required by all applications, so why should we have it incorporated into every application?

    Reply
  15. Scott Thomsen

    I used vb6. I prefer vb.net over c#. I like the "My" namespace. I’m a rarity on the blog scene, I guess.

    "Default instance form accessors", or whatever you call them are a bad, bad, bad, bad idea. One that I believe will sometime in the future make you wish you could go delete the google cache of your articles defending it.

    Other converts from vb6 over the next few years will write code with hard-to-see bugs because of default form / explicit form problems. Add to this that the default form does NOT behave at all like the default form from vb6, and you have a recipie for disaster.

    You also have a legion of vb6 converts that will be (as I did and do) looking at all the examples out there right now. Those examples don’t use default instances… and probably won’t soon in the future either. So I create my code, and Use "Form1.Show()" Then I need to do something that I don’t understand, so I find an example on the web.. It uses "f = new Form1()"…"f.show()". Chaos ensues as we can’t figure out why the example solution works as expected, but not when put into my code!

    Please who is the customer driving this? I’ve yet to talk to or read anyone who thinks this is remotely a good idea except you. So if it’s you driving this, please just create your own language to play with. Don’t take a personal pet feature out on the rest of us. If it’s more people, slap them with a clue stick now, instead of letting them get blasted by hindsight through the rest of vb.net’s lifetime.

    Reply
  16. karl

    Paul, I don’t agree that it should be in there, but damn you rock with respect to coming back to us, explaining it to us and treating us like adults – even when we don’t always deserve it.

    I still think it’s a half-baked idea, but fuck you’re cool! πŸ™‚

    Karl

    Reply
  17. Pingback: Jay Kimble -- The Dev Theologian

  18. Anon - Cause I dont want the fla

    Thanks for the clear and lucid explanation. I’ve been a .NET developer for three years, and have been coding in VB.Net the whole time. I love the Framework, and think it rocks. But this whole VB6-petition-derived language crippling has thoroughly discouraged me.

    The C# people are right. VB coders just don’t get it.

    I’m now going to go switch to C# so I don’t have to deal with this sort of Luddite junk.

    Bye!

    Reply
  19. Darrin

    know full well that it’s much too late for the entire community to change this "feature". In fact, it was never possible for the community to give input on it.

    Good job, vb.net team and feature owner – I’m switching to c# — the land where Andres knows that language productivity does not mean throwing random features into a pot to cater to the 5% crowd (aka morons) that ruins the stew for everyone else.

    It doesn’t matter how many people say this is bad. At microsoft, each "feature" is owned by a person (or perhaps a small team). They feel that it’s thier baby and is the most important thing in the world.

    The owner of this feature must be 1) Extremely persuasive to everyone up the chain. 2) a die-hard vb convert, and 3) too arrogant to realize that if 99% of the people that have discussed this feature outside Microsoft think that it’s not only a waste of time but actually harmful, his "Baby" may be a horrible idea.

    How about this. Be a big person and drop it. Then add a compiler message when you see ‘FormClass.Show()’ that points to a help doc explaining the difference between a class and an instance. Allow vb.net to continue to be great.

    Reply
  20. Duane Roelands

    I really would not like to see this implemented at all. If I have no choice, then I would prefer that developers be forced to explicitly declare that they want to work with forms in this way, i.e. the default setting should be "No Default Instances"

    Dim X As Form = New MyForm is elegant, clear, readable code. Default instances (the VB6) way, is not. It’s another one of those "VB contrivances" that makes developers who work in "real languages" sneer at VB.

    Stop coddling weak developers.

    Reply
  21. Pingback: Richard Clark

  22. Jay Kimble

    Paul,

    I guess I want to chime in a littl further on this. You have a namespace for compatibility. Why aren’t there 2 classes to inherit from? The standard winforms class and the one in the vb compatibility namespace that incudes default instances. That way I can continue to use the syntax I’ve been using for 4 years!

    Jay Kimble

    – the Dev Theologian

    Reply
  23. Pingback: Rob Copeland's Blog

  24. Kevin Welsh

    I sort of agree with Darrin in that there is certainly an underlying reason for the *feature*. VB6 migration is a huge market for selling VS.NET 2005. Tons of VB6 devs have NOT transitioned to .NET. Those of us using VS.NET 2003 sort of ‘have-to’ upgrade to VS.NET 2005, or we lose a competitive edge, so our voice is not so loud.

    <digress>I can certainly relate to ‘Pet Features’. When I leaned how to make a gradient fill in a control, wow, did I go nuts. I even put options forms in apps to let the user pick the colors, then serialize the setting to disk. Sort of a useless thing, really. </digress>

    Another reason for the *feature* could be the sales pitch factor to Brand New Developers. There are new devs graduating from High School and College all the time. I’d like to think that they would know how to implement their own Singletons, but . . . .

    If you want to know what I really think (you do, don’t you?), then read this. MS ACCESS is DEAD! I think the guys at Access were laid off and moved over to VB.NET. Have you seen the new Input Mask Textbox (Access has had that for-EVER, same wizard too), margins in controls (ditto), Drag-N-Drop Databinding (ummm, Access does that).

    Well, you get my point. If you want to get Access devs to move to MSDE and VB.NET AND VB6 devs to move to VB.NET, you gotta speak THIER language.

    Silly us, we thought it was OUR language.

    Reply
  25. Philip

    If this really *has* to go in, fine. I feel that it’s not wise, but then I’m not in charge of Visual Studio, nor do I earn income from selling it – those people make these calls, not me.

    However, 2 points:

    1) You acknowledged the concerns as valid, but then said that usefulness is more important than removing confusion. I disagree strongly on that point.

    I believe that code that is confusing is much, much worse than code that is easier to read and understand but takes two or two hundred extra lines. I thought this was a commonly held viewpoint, but perhaps it’s just me.

    2) I really can’t believe that you’re adding in a huge semantic crutch-hack without the ability to at least opt out (let alone make it opt-in). Simply defaulting Option Strict to off raised hairs – what if there had been no option to turn it on at all? Option Explicit – should we remove that as well?

    I am already writing a FXCop rule to make sure that I can identify this on projects I’m involved in. I’d rather be able to turn "Option UglyHack Off", though.

    Reply
  26. Duane Roelands

    Phillip,

    The FXCop rule is a brilliant idea – I wish I’d thought of it. When you get it crafted, would you mind sharing it? I want it in place before my developers even smell Whidbey.

    Reply
  27. Pingback: Philip Rieck

  28. Pingback: Panopticon Central

  29. Jim

    I think default instances are bad idea. If I had a junior developer on my team that doesn’t understand that forms are classes, I *want* them to get an error so they can ask me or one of the senior developers what they did wrong and we can explain it to them. What I don’t want is them to write poor quality code that, in the long run, will be harder to maintain and debug.

    Now, yes, something like this can and should be caught in a code review, but that’s not the point. The point is that VB.NET should make this easy to do by default. We shouldn’t have to go out of our way to put additional things to check for in our code reviews. Ironically, default instances make VB.NET harder to use, not easier.

    If MS cannot figure out a way to have this turned off by default in time for RTM, then MS should rip this feature from the product until they can get it right.

    Reply
  30. Michael

    Guys, you can’t have a switch to turn this feature on. This feature is designed to make programming easier for the less experienced coders, they won’t know to turn it on. If there is an option then it needs to be ON by default.

    Also, for all those complaining that they are too much of an expert for a feature like this, why aren’t you using C#?

    Reply
  31. Matthew Wills

    I am pretty sure in VB 6 you could effectively disable default instances by creating a module and putting code like:

    Public Form1 as Integer

    Public Form2 as Integer

    This would stop you referencing the default instance of Form2 from within Form1 code.

    Unfortunately, the same trick doesn’t work in VB.NET. Any chance of allowing us to disable it somehow (even by manually declaring variables like in VB 6)? Hell, even a FxCop rule would be helpful…

    Reply
  32. Pingback: Trancecoder's weblog

  33. Kyle Koder

    Well, I’m taking my first compute programming class, and it’s on VB.Net. I’m a few days into the class, and I’ve already run into many, many problems with the default form instances. I didn’t have a clue what was going on until I found this site.

    I can’t find a stable way to target a specific instance other than the default from other form classes.

    It’s causing all kinds of problems.

    If it weren’t there, I’d be done with this project.

    I’m a three-day-old user of this language, and I have this problem.

    Conclusion – Default instances absolutely DO NOT help new users. It’s an unforgivable limitation to the language.

    For now, I’ll have to make more than one identical form class. After this class is over, I’m switching languages.

    I highly suggest an EXTREMELY EASY TO FIND AND WELL-DOCUMENTED off-switch feature for default form instances in future versions of VB, if not a complete removal altogether.

    I simply can’t see any pros here. It wouldn’t be that hard to make the language so that a reference simply to "Form1" would target the first instance (the oldest instance) of the class, and so that "Form1(inst4)" would target the fourth created instance.

    Anyone who can name a pro for default form instances or a (good…as in simple and reliable) workaround, please post. I’ll check back.

    Reply
  34. Paul McMurray

    Old blog, but useful as it came up in a google search for an issue I’m having.

    I have a Windows Mobile Forms application, with upwards of 30+ forms, and rising.

    Each form is orientation/resolution capable and alters its layout to suit each device.

    Problem I have with default instances is this: when the user rotates their device (slide out keyboard an example), they currently have to wait 5 or more seconds for the ui to catch up while each default instance of the 30+ forms fires their Resize events, causing the layout code to fire.

    Now, I’ve coded round this issue to some extent by including a property that gets set when a new instance is created – this allows me to differentiate between a default instance and a new instance, and turn off my layout code in the Resize events accordingly. But it doesn’t stop the Default instances from responding to the resize after the user changes orientation, and the more forms I add to the project, the slower the response to an orientation change becomes.

    I reckon that once the application has its full set of forms finished, there’ll be upwards of 80+ forms – that’s 80+ default instances I don’t want or need, on a device with limited memory and limited CPU.

    If you keep this feature, PLEASE include a way to disable the default instances.

    Reply

Leave a Reply