Author Archives: paulvick

The cat’s out of the bag…

Oh, and yeah, my book is finally available! I’ve actually got a real, printed copy of it sitting here on my desk and Amazon claims that they’re shipping it within 24 hours! (It may not be on the shelves of your local Barnes and Noble for a little while longer, though.)

Overall, I have to admit that I find this kind of frightening, somewhat akin to what it must be like taking your child off to their first day at school. Here’s something that’s been a part of you for quite some time, and now it’s out there at the mercy of the big, bad world. Will it make friends? Will it get beaten up and come home crying? I guess now only time is going to tell….

So, everyone, go out and buy a copy and tell me (and everyone else on Amazon) how wonderful it is! Here’s a handy link to help you get started:

Hope you all like it….

P.S. – There’s already someone selling a used copy of the book on Amazon. I’ve had my own copy something like 48 hours… how does that happen?

Why do hobbyists matter?

After Kathleen worried about losing the hobbyist programmer on .NET, Rory came back with the question “Should the hobbyist programmer matter to Microsoft?” His thesis, in a nutshell, was:

I say that we don’t worry about the hobbyists – don’t dissuade them from coding in .NET, but don’t cater to them either.

I understand where he’s coming from, but I think that the terminology is confusing the issue. When we talk about “hobbyist programmer,” it evokes images of guys tinkering in their garages or in their basements on the weekend. And, yeah, maybe if it was just the equivalent of a bunch of guys (or gals) building model trains or making furniture or rebuilding old cars, it wouldn’t matter so much. But the reality is that the hobbyist programmer doesn’t just program on the weekends – they’re also programming during the week at their “real” jobs.

Before I started working on VB, I worked on Access. And I cannot count the number of times that customer testimonials started along the lines of “I was fooling around with Access one day and managed to write this small app to help manage my group. Once my department found out about it, they started using it to manage the department. Now my whole company uses it!” One of the key aspects of Access’s success was this kind of “viral adoption” where some tinkerer used it to solve some local problem that ended up solving a company-wide problem. The same holds for VB – lots of VB applications in corporations started life as someone’s side project. As I put it in a recent presentation, “Throwaway applications have a way of becoming mission critical applications.” And where do those throwaway applications come from? Hobbyist programmers.

With the spread of computing into more and more industries, the people who don’t consider themselves programmers become more and more important because they’re the beachhead for “real programming” to make its way in. For example, the throwaway applications that hobbyists write ultimately helps drive demand for professional programmers to come in and “professionalize” the applications so that they scale correctly for the corporation. Also, as hobbyist applications make companies more open to the benefits of technology, they open the door to commercial software that can augment or replace the homegrown applications and maybe do a better job. And, of course, hobbyist programmers usually need lots of help, which drives demand for websites, magazines, books, consultants, etc.

So, in much the same way that small businesses serve a vital function in keeping the economy going so that large corporations can thrive, hobbyists play a vital role in sustaining the ecosystem that supports the professional programmers. Even if the professional programmers don’t always appreciate that…

TryCast (aka. the ‘as’ operator)

About 8 months ago, I promised to explain why the C# ‘as’ operator was worth adding to VB and then never got back to it. While trying to figure out what comments I missed, I came across the promise again and figured I’d take the opportunity to rectify the situation.

In Whidbey, we’re going to introduce YACO (Yet Another Conversion Operator) called TryCast that’s equivalent to the C# ‘as’ operator. Why? It turns out that it’s useful in some specific, but not uncommon, situations. Let’s say that you want to write a method that accepts an object and, if it implements a particular interface, do something with it. For example:

Sub Print(ByVal o As Object)
Dim PrintableObject As IPrintable

If TypeOf o Is IPrintable Then
PrintableObject = DirectCast(o, IPrintable)
PrintableObject.Print()
End If
...
End Sub

Ok, great, this works fine. The problem is, though, that we’re doing redundant work here. You see, when the CLR executes the If statement, it does a type check for the TypeOf expression. If o does implement IPrintable, it then goes ahead and casts o to IPrintable, which does another type check to ensure that the value really does implement IPrintable. So you’re doing two type checks, and type checks can be expensive. (When I say “expensive” here, I don’t mean expensive like “$760,000 for a Ferrari” expensive, I mean more like “$3.50 for a latte twice a day adds up over 365 days” expensive.)

What TryCast does is it allows you to combine the two type checks into one. TryCast, as its name suggests, will try the cast and, if it succeeds, return the value cast to that type. Otherwise, it returns the value Nothing. So you can rewrite the code above as:

Sub Print(ByVal o As Object)
Dim PrintableObject As IPrintable = TryCast(o, IPrintable)

If PrintableObject IsNot Nothing Then
PrintableObject.Print()
End If
...
End Sub

Voila, two type checks becomes one! Even if we hadn’t gotten any feature requests for this, we were planning to do it anyway because we found that several of our language helpers that deal with object values could be sped up ~5% just by eliminating the redundant type checks. So it’s not nothing. (So to speak.)

One question that might come to mind is: why not just optimize the first code into the second code under the covers instead of introducing a new operator? We did consider this at the compiler level, and the CLR could also choose to do it at the JIT level. However, while we could optimize this particular case, it’s easy to construct cases that would be difficult for the compiler or JIT to optimize. Which would mean that you could make a minor tweak to the structure of your code and suddenly lose the optimization without knowing it. In this case we figured explicitness was better…

Update 4/3/04: Made some corrections based on comments below.

Blog software is only as good as its developer…

…and in this case, since I’m the developer, what does that say about me? I just discovered that when I wrote the code to produce the comments feed for my blog, I screwed up. Rather than giving the past x days of comments, my comments RSS feed was giving all the comments for the past x days of entries. So if you commented on an entry that was more than x days (I think it’s something like 10 or 14) old, then it wouldn’t ever show up in the feed. I noticed this by accident when cross-linking to my old IsNot post, and now I think I’ve got it fixed.

So if you’ve submitted some comments and I totally ignored you, it might be because I was relying on a broken comments feed. Then again, it could be because I’m a lazy bastard… You’ll just have to guess!

(I will be going back through all my comments to find ones that I might have missed…)

IsNot and the fall of civilization

Back when I said that Whidbey is going to be introducing an IsNot operator, Karl raised some objections to the operator in the comments, to which I said:

Karl, it seems like your question isn’t so much why we’re adding “IsNot” but why we have “Is” in the first place. It’s a good question, I’ll try to address it in an entry soon.

…and then I never came back to it. Now that Daniel has picked up the thread again, let me return to the subject and elaborate just a little bit.

As I said in the comments, the question that Karl and Daniel raise is not so much “why IsNot?” but instead “why Is?” The fundamental reason for adding IsNot was that it’s irritating to have a comparison operator and not its inverse. For example, it’s entirely feasible to have a language with just Not, =, < and <=, but no language bothers to be “pure” that way because it’s a PITA to have to write “If Not x = 5 Then” or “If Not x <= 5 Then” and so on. Given the existence of the “Is” operator, having its opposite seems like, as Martha would say, “a good thing.” Charges of language pollution seem, on the face of it, to be a stretch.

OK, so let’s leave aside the question of IsNot for a moment. Why bother to have two comparison operators, “Is” and “=“? There’s a historical reason and a modern reason. The historical reason is that, prior to VS 2002, VB allowed classes to define a parameterless default property that represented the “value” of the class. This feature allowed, say, a TextBox object to declare that its Text property was its “value” property and then the user could write “TextBox1 = “foo”” and it would assign the string value “foo” to TextBox1.Text. However, since a class could be both an object and a value, you needed to have two forms of comparison and assignment to distinguish between the two. Assignment was handled by splitting it into “Let” vs “Set” assignment: “Let TextBox1 = “foo”” assigned a value to the default property, while “Set TextBox1 = New TextBox()” assigned a value to TextBox1 itself. Comparison was handled by splitting it into, yes, you guessed it, “=” and “Is”. The code “TextBox1 = “foo”” would do a value comparison between the string value “foo” and the default property TextBox1.Text. The code “TextBox1 Is TextBox2”, on the other hand, would do an object comparison between two TextBox objects.

When we made the leap to .NET, though, we ran up against a bit of a wall. Other languages such as C# and C++ didn’t support the concept of parameterless default properties, two types of assignment, two types of comparison, etc. This wasn’t a big deal for fields, but it was a huge issue for properties – whereas a VB property could define a Get, Let and Set, a C# property could define only a Get and a Set. We spent a lot of time trying to invent ways to map between the two schemes and finally came to the conclusion there was no good mapping. (Even today this is one of the friction points between COM and .NET that can make interop a pain.) So we gave in and dropped parameterless default properties from the language. This meant that we could also drop Let vs. Set assignment from the language. And, if we’d chosen too, we could have dropped “Is”. But we didn’t…. Why is that? Two reasons, one minor, one major.

The minor reason is that we could produce more optimal comparisons between values typed as Object (if someone’s really interested in this, I can explain, but it’s kind of obscure). The major reason was that we were anticipating a feature that didn’t make it into VS 2002 or VS 2003 but will make it into Whidbey: operator overloading. Take the situation where you’ve got a class that overloads the equality operator:

Class ComplexNumber
...

Public Shared Operator = (ByVal c1 As ComplexNumber, ByVal c2 As ComplexNumber) As Integer
...
End Operator
End Class

Now, when you say “c1 = c2“, you’re always going to get value equality between two ComplexNumber instances, not reference equality. But let’s say that you really need to know whether c1 and c2 are the same instance not just the same value. How do you do it? In VB, it’s simple. You say “If c1 Is c2 Then…“. What do you have to do in C#? You have to make sure you cast both values to object and then do the comparison: “if ((object)c1 == (object)c2) {…}“. Forget the cast, and you’ve accidentally slipped back into value comparison.

So that’s why we kept “Is“ and “=“. And, yes, I think this is one of the places where our syntax is clearer than C#’s. Although everyone’s free to disagree…

Can you quit and not even know it?

So my wife’s been working out with a personal trainer at the health club we belong to through work. Yesterday, we get a call from the trainer saying that she can’t meet with Andy because we cancelled Andy’s membership with the health club, which is odd because we hadn’t. So I called the health club this morning and they told me that they cancelled my wife’s membership because Microsoft told me that I was cancelling my membership! So I called the Microsoft benefits line and they informed me that they cancelled my health club membership because the HR system says that I’m resigning from Microsoft this Friday!

Is there some memo I didn’t get?

I’m sure that some wires got crossed somewhere between me and Paul Vijijlkj or whoever is quitting on Friday and it’ll all be straightened out in short order. But it’s just another Brazil-esque reminder of how technology can take on a life of it’s own. Glad I figured this out through the health club ahead of time and not when my next paycheck didn’t show up or my cardkey stopped working…

Background compilation, part 1

Roy points to Philip’s complaint that VB still exhibits problems with multi-language solutions that have been around since the VS 2002 beta. Philip’s completely correct, and the explanation of why this bug still hasn’t been fixed even though we’ve known about it since before VS 2002 shipped bears some explanation. Specifically, the problem is with a mistake we made when designing our background compilation system a very long time ago. Since I’ve been asked more than a few times about how background compilation works, this is an excellent chance to delve into that subject. So let me talk about background compilation for a while and then we’ll get back to Philip’s bug.

“Background compilation” is the feature in VB that gives you a complete set of errors as you type. People who move back and forth between VB and C# notice this, but VB-only developers may not realize that other languages such as C# don’t always give you 100% accurate Intellisense and don’t always give you all of the errors that exist in your code. This is because their Intellisense engines are separate, scaled-down compilers that don’t do full compilation in the background. VB, on the other hand, compiles your entire project from start to finish as Visual Studio sits idle, allowing us to immediately populate the task list with completely accurate errors and allowing us to give you completely accurate Intellisense. As Martha would say, it’s a good thing.

However, doing background compilation is a tricky prospect. The problem is that just as soon as you’ve finished compiling the project in the background, the user is likely to do something annoying like edit their code. Once they do that, the application you just finished compiling is now incorrect – it doesn’t reflect the current state of the user’s code anymore. So, the question is: how do you handle that? The brute force way would be to throw away the entire result of the compilation and start over again. However, since Intellisense depends on compilation being mostly complete, this is impractical – given a reasonably large project, you may never get the chance to give Intellisense because by the time you’re almost done recompiling the whole project, the user has had the chance to type in another line of code, thus invaliding all the work you just did. You’ll never catch up.

To deal with this, we implement a concept we call “partial decompilation.” When a user makes an edit, instead of throwing the entire compilation state away, we figure out the smallest amount of stuff we can throw away and then keep everything else. Since most edits don’t actually affect the project as a whole, this means we can usually throw out minimal information and get back to being fully compiled pretty quickly. Here’s how we do it: each file in the project is considered to be in one of the following states at any one time:

  • NoState: We’ve done nothing with the file.
  • Declared: We’ve built symbols for the declarations in the file, but we haven’t bound references to other types yet.
  • Bound: We’ve bound all references to types.
  • Compiled: We’ve emitted IL for all the properties and methods in the file.

When a project is compiled, all the files in the project are brought up to each successive state. (In other words, we have to have gotten all files to Declared before we can bring any file up to Bound, because we need to have symbols for all the declarations in hand before we can bind type references.) When all the files have reached Compiled, then the project is fully compiled.

Now let’s say that a user walks up to a project that’s reached Compiled state and makes an edit to a file. The first thing that we have to do is classify the kind of edit that the user made. (Keep in mind that “an edit” can actually be an extremely complex one if the user chose to cut and paste one block of code over another block of code.) Edits can generally be broken down into two classifications:

  • Method-level edits, i.e. edits that occurs within a method or a property accessor. These are the most common and also the easiest to deal with because a method-level edit can never affect anything outside of the method itself.
  • Declaration-level edits, i.e. edits that occur in the declaration of a type or type member (method, property, field, etc). These are less common and can affect anyone who references them or might reference them anywhere in the project.

When an edit comes through, it’s first classified. If it’s a method-level edit, then the file that the edit took place in is decompiled to Bound. This involves the relatively small work of throwing away all the IL for the properties and methods defined in the file. Then we can just recompile all the methods and we’re back to being fully compiled. Not a lot of work. Say, though, that the edit is a declaration-level edit. Now, we have to do some more work.

Earlier, when we were bringing files up to Bound state, we kept track of all the intra-file dependencies caused by the binding process. So if a file a.vb contained a reference to a class in b.vb, we recorded a dependency from a.vb to b.vb. When we go to decompile a file that’s had a declaration edit, we call into the dependency manager to determine what files depend on the edited file. We then decompile the edited file all the way down to NoState, because we have to rebuild symbols for the file. Then we go through and decompile all the files that depend on the edited file down to Declared, because those files now have to rebind all their name references in case something changed (for example, maybe the class the file depended on got removed). This is a bit more work, but in most cases the number of files being decompiled is limited and we’re still doing a lot less work than doing a full recompile.

This is kind of the high-level overview of how it works – there are lots of little details that I’ve glossed over, and the process is quite a bit more complex than this, but you get the idea. I’m going to stop here for the moment and pick up the thread again in a few days, because there’s a few more pieces of the puzzle that we have to put into place before we get to explaining the bug.

A requiem for easter eggs…

Tom rebuts Jeremy Mazner’s lament for the disappearance of easter eggs. Ultimately, I think most easter eggs are the equivalent of stories about college exploits: they’re only interesting only to the people who were involved and deathly boring to everyone else. Sure, there is the occasionally clever or humorous easter egg, but most serve no purpose to anybody except as a little ego trip.

I say this knowing full well that I wrote several easter eggs for Access before the prohibition on easter eggs went in. I even wrote one that I thought was somewhat clever: a Magic Eight Ball easter egg. The problem was, I left the team and within several versions the Magic Eight Ball had turned into the Crashing Magic Eight Ball.

I don’t think losing easter eggs is a great loss, personally… (Although those Excel guys were always pretty damn impressive.)

Neither a borrower nor a lender be…

Geek Noise pointed to a tirade against the Cult of Performance that brought to mind a criticism that Jet had of my 10 Rules of Performance entry. The points raised are very well taken – it can actually be more damaging to obsess about performance prematurely than to obsess about it too late. The point that I’m arguing for is moderation. For some reason, developers like to live at extremes – either they’re this way or that, never in the middle. Either they never think about performance or they are completely obsessed with it. Instead, I’m arguing that performance should be a part of the development process and the thought process, but not the only consideration. (If it was, most applications would never ship.)

I suppose this is all human nature, if you look at the way that people tend to polarize in other areas. The title for this entry comes from a speech Polonius gives his son Laertes in Hamlet in which he’s purporting to give him some life advice. Since Polonius is sort of a doddering old windbag, most of the speech boils down to useless platitudes along the lines of be smart, but not too smart; be nice, but not too nice; be rich, but not too rich. However, he does end with a good bit of advice that, nontheless, has got to be the most difficult to follow:

This above all: to thine own self be true,
And it must follow, as the night the day,
Thou canst not then be false to any man.

If you think about it, a lot of my performance advice boils down to a variation on this theme. Most of what I argue for is to stop and take the time to understand the true nature of your application and work with that. Obsessing about the performance of code you haven’t even written yet doesn’t fall into that category…