Monthly Archives: January 2005

Stupid questions…

So Andrea and I were talking on Friday about learning to cook and, in particular, how I used to really drive her nuts with stupid questions when I was taking my first culinary steps in the kitchen. Now, when I say “stupid questions,” I mean really stupid questions not “emperor’s new clothes” kind of stupid questions. The latter kind of stupid questions are understandable and have a certain aura of respectability. For example, while the question “Hey, honey, this recipe says that I need to ‘julienne’ the carrots. What does that mean?” might seem like a stupid question to someone who already knows their way around a kitchen, for the novice it’s a perfectly understandable question. My wife was always more than happy to answer those sorts of questions (provided that she knew the answer, of course…).

No, the stupid questions that drove her nuts were ones along the lines of “Honey, the recipe calls for 2 tablespoons of cooking oil. Where’s the cooking oil?” Questions that, even in my novice state, I should have been able to answer easily if I had just stopped and spent five seconds thinking about it. I mean, it’s not like I hadn’t seen her get the oil out of the cabinet a hundred times. Heck, it’s not like I couldn’t have, through the process of elimination, figured out what cabinet it was in. I was just having a momentary brain lapse, one that occurs less frequently now that: a) I know my way around the kitchen, and b) my wife’s standard answer was something along the lines of “Well, have you looked for the cooking oil?”

The point of the conversation, ultimately, was that no matter how hard one tries it’s sometimes impossible to avoid asking stupid questions like this. The best we can do is draw up a little social contract: I, the undersigned, do solemnly agree to think before I ask a question so as to minimize the chance of asking a stupid question; you, the other undersigned, do solemnly agree to not call me an idiot when I do ask a stupid question, understanding that such things do, occasionally, happen. As long as each of us keeps up our side of the bargain, everyone gets along just fine.

I was reminded of this conversation today when, in response to a technical problem I’m having, I sent out an email to a large email alias describing my problem and asking if anyone was aware of it. About 30 seconds later, I got responses from several people (including Dare) pointing out that my exact problem had been discussed four days ago on the exact same alias. Fortunately, everyone was very nice about it and no one said anything to the effect of “here’s the answer, you moron.” As they say: sometimes you’re the windshield, sometimes you’re the bug…

(As a side note, the one indispensible aid I have found in my quest for culinary mastery is the updated The Joy of Cooking. Besides having lots of good receipes, that thing has saved my rear more times than I care to think. Highly recommended.)

]]>

Singletons and Default Instances

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.

]]>

Vote for Me!

Now I know that you’re all saying to yourselves: “Paul, I read your blog religiously, I’ve bought your book, I’ve gone to all the talks you’ve given, I’ve listened to the .NET Rocks show you were on, I’m even considering getting your name tattooed across my… What else can I possibly do to show my love for you?”

I’m glad you asked!

My friends at Addison-Wesley let me know that my book, The Visual Basic .NET Programming Language, has been nominated for a Sys-Con Reader’s Choice award! I’m up against some pretty stiff competition, so I urge everyone who liked my book and who subscribes (or wants to subscribe) to go to their voting page and vote for the book! And, as an added incentive, every person who votes for me will earn a free gift: my personal and undying gratitude! (Offer void where prohibited. No monetary value. Not available in WA, VA, CT, TX, IA, OK, ND, WV or Puerto Rico. See stores for more details.)

Default Instances

Fresh off of writer’s block, I thought I’d dive straight back into the sea of controversy and talk about a feature called “default instances.” Default instances are a “new” feature in VB 2005 that is really the return of a very old feature, one that’s been around for a long time. Now, the return of default instances has stirred some very passionate debate, but what I’m going to do is address this question in three separate entries. In this entry, I’m going to describe what default instances are at a technical level. In my next entry, I’m going to talk about what I see as the positive case for default instances. Then, in the final entry, I will talk about some limitations of default instances and address the controversy about their reintroduction more directly. You can choose whether or not you want to wait for the last entry before you start throwing brickbats…

So, what are default instances? Well, they’re exactly what their name suggests: a way to provide a default instance of a class that you can use without having to New the class. If you’ve used versions of VB prior to VB 2002 (i.e. pre-.NET), you’ll probably have come across the most common default instance, the form default instance. For example, in VB 6.0, if you created a form named Test, you could say in code:

Test.Show()

And voila! an instance of the form would just magically appear. What was going on behind the scenes was a bit of magic. When you referred to “Test,” the VB runtime would go check and see if it already had a default instance of Test lying around. If it did, then it would hand back that default instance when you called Show(). If there wasn’t a default instance lying around, the runtime would create a new instance of Test and use that as the default instance going forward.

Default instances disappeared in VB 2002 and VB 2003, but are making a comeback in VB 2005. The high-level “why,” I’ll leave to my second entry, so let’s talk about the “how” for the moment. Hopefully, all of you are familiar with the introduction of the My namespace in VB 2005. (If not, go read this MSDN article and then come back.) One part of the My namespace is the Forms object. If you bring up a VB 2005 project with a Form named Test in it, you’ll notice that the My.Forms object has a property called Test. This property returns a default instance of Test. So you can say, sort of like you did in VB 6.0, “My.Forms.Test.Show()” and voila! up pops a new instance of Test. What happens behind the scenes is that the Test property of My.Forms checks to see if it’s already returned an instance of Test and, if it has, it just returns that instance. If it hasn’t returned an instance yet, it just creates a new instance. Pretty simple.

We also extended default instances to work in exactly the same way that VB 6.0 default instances did. Besides saying My.Forms.Test.Show(), you can also just say Test.Show() and it will also access the default instance. Essentially, Test.Show() is a shortcut to saying My.Forms.Test.Show().

There are, however, a couple of differences between the way default instances are implemented in VB6 and the way they are implemented in VB 2005:

  • In VB6, if you tried to use the Is operator to test the default instance to see if it was Nothing, the expression would always evaluate to False. This is because referring to the default instance caused it to be created if it didn’t exist! In VB 2005, we recognize when you are testing the default instance using the Is (or IsNot) operator and won’t auto-create the instance in that case. So you can see if the default instance exists or not.
  • A common source of default instance errors was using the default instance instead of Me within the default instance’s type. For example, if Form1’s load method has the statement “Form1.BackColor = Color.Red”, this will only change the background color of the deafult instance’s form. If you create a new instance of Form1 that is not the default instance, it’s background color will not be red! To assist users in this case, we give an error when you refer to the default instance inside of the type, telling you to use Me instead.

Well, that’s about it for the technical side of things. Now onto the good, the bad and the ugly…

Feedback request on new warning

We’ve been internally discussing a new warning that we’ve added to VB 2005 and how we should treat it for upgrade, and I’d like to get some feedback from those people who have been using the beta or the community previews. A common error that we see is using a reference variable before it’s been assigned a value. For example:

Dim x As Collection
x.Add(10)

This code will throw an exception because I forgot to create a new collection using New. In VB 2005, this code will produce the following warning:

Variable 'x' is used before it has been assigned a value. A null reference exception could result at runtime.

We determine this warning by doing flow of control analysis on the function and determining that you’re using the variable before you gave it a value. This is all well and good, but the warning isn’t perfect. Just because a variable hasn’t been assigned a value doesn’t necessarily mean that there’s going to be a problem. For example:

Dim x As Collection

If Test() Then
x = New Collection()
End If

If x IsNot Nothing Then
x.Add(10)
End If

The test “x IsNot Nothing” will cause a warning that x might be used before it has been assigned a value. This is sort-of true if you look at the code in a simplistic way, but it’s really not a problem, of course, because we’re just testing against Nothing. An ideal solution, and one that we’re considering beyond VB 2005, is to add a more sophisticated level of analysis to the compiler that would allow more fine-grained analysis of null reference problems that would recognize the above situation as safe. But that’s beyond the scope of this release. For now, the level of analysis that we can do is identify places where you used a reference variable without assigning it a value.

Now, to the question: have people found this warning to be annoying on upgrade? New projects don’t seem to have major issues with this warning because you fix the warnings as you go along, by and large. But upgraded projects can be a different story: depending on the coding style used, a project might have a ton of these warnings show up when you first open it in VB 2005. For example, I recently upgraded the VBParser project and spent a little while fixing up 100 or so of these warnings, all of which were what you might call “false positives” – I was using variables before they had been assigned, but always in a safe and courteous manner.

What have people’s experiences been with this warning on upgrade? Was it annoying? Was it helpful? Would it be desirable to not have the warning turned on by default in upgrade? Just to be clear: we’re not planning on changing anything as it stands right now. But now that the beta’s been out in the wild for a while, we thought it might be a good time to validate our assumptions against some cold, hard customer feedback…

Writer’s block

When people haven’t written a while they usually start off with some kind of apology like “sorry I haven’t written in so long, but I’ve been doing xyz.” My feeling is: blogs (with some exceptions) are strictly amateur hour, so no apologies are necessary for life intervening. That’s just the way it is, and people should come to expect that from blogs – you get what you pay for.

That said, I’d really like to say that I haven’t been writing in a while because I’ve been busy, but that’s not really it. The holidays took up a lot of time and I spent a good chunk of the last month or so trying to get the VB Language Specification updated to reflect all the good stuff that we’re doing in VB 2005. Even though, in theory, updating the spec is just a matter of merging individual specifications into the master specification, I tend to do a lot of rewriting to fit things into the general flow and because of the fact that I’m a latent control freak. (Rewriting the spec also helped turn up an interesting number of bugs in our beta compiler. It’s amazing what just trying out what the spec says is supposed to work will produce.) Hopefully the spec will be available generally in the near future (I’m gunning for when Beta2 RTMs, whenever that is), but it’s not like that kept me from writing.

No, I think it’s just plain old writer’s block. There’s always stuff you can write about, but if you’re not interested in or are not inspired, then the writing (and the writing process) is stiff and boring. Until the magic inspiration comes back, I figured the best thing I can do is work on other things and not foist off a bunch of uninteresting junk on everyone. Whatever the reason, it feels kind of like the mojo is coming back, so I’m hopeful that the words will start flowing again. If not, well, I guess this was just a blip…