Eric Gunnerson's Compendium

Posts

Bellevue is a hilly place. It's perched (roughly) between two large bodies of fresh water. Lake Washington, to the west, is something around 10 or 15' above sea level, and Lake Sammamish, to the east, is about 40' about sea level.

What that means for me is that if I'm going riding, I'm going to be riding up and down some hills. Some are steep hills, of the "I'd really like to stop now, but if I do I fear I will merely fall across the road and lie there until some vehicle approaches" variety. Others are less steep. As I was suffering going up one of these hills, I thought it might be fun to know exactly how steep it is (cyclists have weird senses of humor, and love/hate relationships with hills). A few web searches led me to this inclinometer, but being the techie that I am, it didn't seem cool enough, so I did a bit more research.

Hills are measured in terms of gradient, which is merely the rise of the hill over the run. If you're going up 2 feet for every 100 feet you travel, you're on a 2% hill. As an aside, it turns out that humans are great at overestimating the steepness of hills. It's easy to think that some streets are nearly 45 degrees (100% gradient), but it turns out that the steepest streets around Seattle (and we have some steep ones) are a 21% gradient, a mere 11 degrees. Take out a piece of graph paper, and draw a triangle that's 10 units long and 2 units high. Take a look at that, and then try to reconcile it with the streets you've been on. Doesn't make much sense.

Anyway, what I was looking for was a way to measure the gradient of the streets I was on. To do that, I needed a way to set a reference point, move forward, and then figure out the delta in distance and altitude. If you're thinking GPS, you're right on the button. This finally gave me an excuse to order a data cable for my Garmin Etrex, and yesterday afternoon I did a little drive on some hills with the GPS on, came home, and used a gps utility program to download the data, extracted it to a text file, imported to excel, it did some graphing.

The result was fairly good, actually, except for the fact that the Etrex only saves data every once in a while (to save memory space), so in a car, the samples are too far apart to get a good reading. This wouldn't be a problem climbing on the bike, but might be when descending. I can get around that by taking the laptop with me and saving the location every second, which should give me more than enough resolution to get some good data. GPS isn't great on absolute position, and is even less good on absolute altitude, but it's quite good on relative measurements of both of those.

I'll have to write a C# utility to run on the laptop, of course, so that I don't have to do all the ugly massaging and export. I might eventually buy a GPS for my pocket PC, as there are some small ones that fit in the compact flash slot.

• Q: Compiler compatibility vs. comformance

I got an email from a customer today, in which he noted that the C# compiler allows you to write:

bool b = ...

switch (b)
{
case true:
...
break;

case false:
....
break;
}

despite the fact that the spec does not list bool as one of the types that you can switch on.

Unfortunately, we've shipped the current behavior, and one of our high-order goals is not to break existing code by changing the compiler. In most cases, that's a really good goal, as your customers are justifiably upset when the new compiler breaks their code.

In this case, however, I think we may be going to far in not fixing a bug because there's a chance somebody might have written code that used it. I'm therefore looking for your opinion (noting, for the record, that it seems that I could sometimes be replaced by an auto-blogger question-asking piece of software) on what makes the most sense.

Question:

How would you have us trade off language conformance (and perhaps language innovation) vs language stability?

More specifically, when is it acceptable for the compiler to give an error on code that used to work?

• Deterministic Finalization

C++ has deterministic finalization. When you declare a stack-based object, at the end of the scope, the destructor is called before other work is done.

I just finished writing a response on this topic for a customer, and thought I'd share my favorite reference on the subject with you:

• Comcast makes me happy...

Hope it happens in my neck of the woods...

• Exception class, return codes, and messages

I've had a couple of questions recently about how to architecture libraries with respect to exception handling, specifically related to exception granualarity. Questions like:

• Is is okay to define an exception with a return code inside of it?
• How many exception classes should I have?

The first place to start is the Error Raising and Handling Guidelines from the Design Guidelines for Class Libraries. There is lots of useful information in the design guidelines even if you aren't writing libraries. The guidelines do mention something like "don't use return codes", but that's about it.

One of the high-value design points when designing exceptions is robustness. The robustness of the customer's code depends directly on the way you structure your exception hierarchy. Here's some code that I've seen. Assume that ApplicationException is the actual type I'm catching, not the base type of a hierarchy:

```try
{
// code here...
}
catch (ApplicationException e)
{
if (e.Message.IndexOf("Database Connection Error"))
{
// recovery code here
}
}
```

There are at least two problems with the code, one major, and one a bit more subtle. Do you see them?

I'll start with the more subtle one first. If your exception messages are localized, it's likely that the string matching will fail. This is a bad bug, because it only shows up in the localized version in an error case, and your tests aren't very likely to catch it.

The second bug is a whopper. If the exception that comes in isn't a database connection error, it is swallowed by the catch block, never to be heard from again. That's pretty much the worst thing that exception handling code can do.

The problem is that the exception design has forced the user to look inside the exception to decide what to do. This is bad, whether it be the message text, a return code, or the type of an inner exception that the user is looking for.

To prevent this, I'd recommend the following guideline:

• Make sure that your user doesn't have to grovel inside of your exception classes to find out whether to handle the exception or not.

One way to determine this is to ask yourself, "Self, would a user ever care about the different cases where ApplicationException is thrown?" In some cases this is obvious, but in other cases, it's not quite so clear. My recommendation is that you err on the side of more granularity rather than less granularity.

• Cluetrain

Apparently, I'm "on the Cluetrain", though strangely, I don't recall boarding, or even buying a ticket.

There are some interesting points here, and I do think that VS has focused mostly on the "edit and build" side of software development, without taking a larger view.

Will that change in Whidbey? I think you'll have to wait and see.

• PM: Renaming Windows Formsh

On Tuesday, I asked a question about whether people keep their form class names and form filenames in sync. I'd like to thank all who responded, and provide a little background on the issue. To do that, I'll have to explain a bit about our internal development a process.

Many of you have probably encountered the problem of "feature creep", where new features keep showing up during development. Feature creep is bad because it throws of your completion estimates, makes it hard for your test team to know what you're planning on building, and generally annoys people. It's especially bad when you have a lot of interdependent teams, and the new feature isn't something you want but rather something somebody else wants, and it gets worse if there are multiple teams depending on you.

One way to deal with this is to say, "No new features", after you reach a certain point in your release cycle. That would work great if planning was perfect, but it's fairly common to find out that a planned architecture has technical problems, or a new customer need comes to light, or somebody has a great idea, or a usability study shows that your current approach flat-out sucks. Not to mention the "we didn't think of that" factor, which we try to minimize but cannot eliminate.

Our approach is to provide a standard process known as a DCR (Development Change Request). In a DCR, the PM who owns the feature gets to produce a document that describes:

• What the issue is
• Why it's important that we fix it
• What the customer scenarios are
• What options there are to fix it
• The amount of schedule time (for dev, QA, and PM) that it will take to address
• How we'll get that time (by cutting other features, or, if it's important enough, slipping the schedule to fit it in)

This usually involves a considerable amount of research by the team, as it's really important to understand the subject deeply, and the research often involves more than one team.

Once the DCR is written up, the PM (and usually other involved parties) meet with the management team of their product (in our case, it's our PUM, our dev manager, our qa manager, and our group program manager) to present the DCR. The management team will either approve the DCR, reject the DCR, or ask for more data.

In this specific situation, the problem that we're trying to address has to do with the build system. If you've looked at the PDC session abstracts, you may have come across mention of something called MSBuild. MSBuild is a new build system that isn't coupled to the VS project system, which means you'll be able to build your Whidbey projects from the command line without loading VS.

If you've gone spelunking in your windows forms files, you may have come across a line that says:

System.Resources.ResourceManager resources = new System.Resources.ResourceManager (typeof(Form1));

Behind the scenes, the Windows Forms designer has put some form resources in a .RESX file. These resources will get converted to a binary format by resgen.exe, and then put into the assembly as part of compilation. Since there may be multiple forms in one assembly, there needs to be a way to find the right resources for a form. For Windows Forms, the full name of the class was chosen as a key. The project system finds this out by talking to the Code Model, a sort of "mini in-process compiler" that also parses code for intellisense and other IDE features (if you read the PDC session abstracts closely, you'll find a new feature...). The code model tells the project system what the name of the form is, and this is passed to the compiler and used to name the binary resource blob in the assembly.

The resource manager constructor gets that same name from the type passed into the constructor, uses it to find the correct blob, and things are hunky and hopefully, dory as well.

Enter MSBuild. It seems like a good idea to be able to build windows forms projects in MSBuild, but there is a problem.

There is no code model for MSBuild to ask for the form name, and no facility to find that information, so it's DCR time. We've spend the last few weeks talking about different options to solve this, but none of them are great, and we don't have a single candidate that we all like.

One of the front runners has the bad characteristic of requiring a project file checkout whenever the form class name is changed, which could be a problem if the project file is already checked out exclusively.

If our users typically rename the form file when they change the class name, then the issue is largely moot, as that rename would also require a project file checkout, and that's why I asked for your feedback.

Several of the comments talked about the poor state of rename in VS (ie, you can't do a VSS rename from inside VS). I talked with the VSS PM, and he said that they are planning to do rename for Whidbey. Please read that as, "It's likely to show up, but don't get mad at Eric if it doesn't, as it's not his call". I did convey the feedback I got about the quality of the current solution.

• Question: Renaming windows forms?

I'm working on resolving an issue, and the way that we decide depends upon the prevalence of a specific scenario. I'd like to know your opinion on the following Windows Forms scenario.

How often do you rename the form class without renaming the file that holds the form class? ie how often do you change "class EmployeeForm" to "class AddressForm" without also renaming the form file?

Thanks

• Creating a great presentation

With PDC coming up, there have been lots of Microsoft entries about what makes a good presentation, and I'd like to throw my 35 cents into the discussion. Here are three things I like to keep in mind.

Why is always more important than what

Technical people are smart and used to figuring out things on their own. They can figure out the C# property syntax in their sleep. What they can't figure out is what was going on in your mind when you wrote a feature, and knowing that is the most important part.

This is also critical for connecting with your audience. Showing some code and saying, "have you ever had to write ugly code like this?", and then showing the improvement will always garner a good response (assuming that the feature is actually useful). It's your job to provide the connection between the feature and the problem it solves.

What you don't talk about is more important than what you do talk about

Technical topics always have lots of subtle and interesting points that you could talk about. Understand the difference between what you could talk about and what the audience needs to know, and stick with the simplest scenario to start with. I've seen lots of presentations where the speaker throws in "interesting" asides that merely confuse the attendee.

To put it another way, your job as a speaker is to filter the important information out of all the possible information. If you don't filter out the irrelevant details, your attendees won't know whether they should understand that information. That will 1) leave them thinking about your previous aside when you want them thinking about the topic you're now discussion and 2) make them feel stupid.

Your job is not to display your technical mastery of the subject. I don't, for example, talk about the advanced events syntax when I talk about C# events. It's not relevant information.

Get concrete fast

Real world examples always beat abstract ones. Don't spend time on introductions when you could explain it as part of a real-world example, or show as part of a demo

Iterate and embellish

Most topics have several layers to them, either layers of complexity or ordered layers of discussion. In properties, for example, I would first show the world without properties, discuss the problems, and then show the world with properties. A building-block approach is easier for people to understand, and it builds the progression into the presentation so you can't forget it.

I once came across a presentation guide that suggested not using revelation in presentations (revelation is when points are gradually revealed). If you're going to present effectively, you need to be able to focus the discussion on a specific point, and you do this through revelation. If you have three main points on a slide, and you show them all at once, your audience will be reading the second and third points while you're talking about the first. You want them listening to you instead.

Revelation combined with diagrams can be a tremendous learning aid. A good diagram is worth at least 2^10 words. Consider whether you can express points graphically.

Finally, I have a personal reason for liking revelation. One of the reason I emjoy presentating is the comedic potential, and an essential element of humor is timing. The funny part of the slide usually isn't the first part, and if you don't use revelation, everybody gets to it at different points - if they notice it at all. You want the impact to hit them all at once, and that's why you use revelation.

Final Thoughts

You should also read Conference Presentation Judo by Mark-Jason Dominus. If you presented before, this is a phenomenally useful presentation. Make sure you read the notes along with the slides.

And if you're a Microsoft person who wants somebody to comment on your slides, I might be amenable.

• C# Pro Magazine

C# Pro is coming soon from Informat
• Signs you've been playing too much MechAssault...

You drive into work in the morning, and as you drive around the garage, you see some green objects blocking a stall at the other end of a row of cars. Your first thought is, "Cool! Health!"

(They were egg crates, but the color match was pretty close)

• Splash Screens and non-rectangular windows

I needed a splash screen for my music player app. I tried a couple of ideas that didn't work very well, but then I hit on the idea of using the image of a CD as the background of the splash screen - and doing a non-rectangular window. I'll start with the splash screen...

Conceptually, a splash screen is pretty simple - it's just a form that you bring up at the start of the program. The code is something like this:

SplashForm splashForm;
public MyForm()
{
splashForm = new SplashForm();
splashForm.Show();
}

and we'll hook the Activated event to hide the form.

private void Form1_Activated(object sender, System.EventArgs e)
{
splashForm.Close();
}

When we run this, however, something strange happens. The form comes up, but it never renders - there's just a black background. This is because we need the windows messages to be processed to get the form to paint. There are several ways to do this, but my choice is to simply call Application.DoEvents() after the form is shown. This processes any messages that have yet to be processed, showing the form.

Next, we need to make a non-rectangular form. This is done by setting the region on the form. This is surprisingly easy to do. Here's the code I used for the CD:

public SplashForm()
{
GraphicsPath p = new GraphicsPath();
this.Region = new Region(p);

...
}

The first ellipse defines the outside of the picture, and then the second one this inside. This gives me a round window with a hole in the center.

Pretty cool!

• If you want to buy a used car...

I have a couple of recommendations to make, from my experience buying a used BMW 328i

The first is for my broker, Darrel Kempf. Darrel ended up owning a very small car lot (4 cars) when he bought some property a number of years ago, and that somehow turned into a business selling, renting, and brokering cars.

Darrel was recommended to us by a friend that bought a 530 though him. For a flat rate (\$600 in my case, IIRC), he will find a used car for you and transport it back to his lot, where you pick it up. In my case, he ended up travelling to a BMW auction in California and then talking to me about the cars that were available on his cell phone as he walked through the car lot. Overall, a very pleasurable experience, and I figure we saved at least \$4000 on the car over what it would have cost in Bellevue. He deals in all makes and models of cars.

My second recommendation is for Carfax. After Darrel had bought the car and before I paid for it, I ordered a Carfax vehicle history report for \$19.99. It told me that there had been no severe accidents reported, that the odomenter was likely correct, and that it had only had one owner. It also gives the history of when it entered the US, when it was licensed and emission tested, etc. Easily worth the money for the peace of mind.

• Versioning, Virtual, and Override

Part IV of Anders' interview is up.
• Part II: The solution explorer and windows forms

Thanks for all your comments. On the basis of those comments, we've decided not to change the current behavior. There are two things I'd like to bring out.

First, thanks to Jacob for mentioning that you can set the default behavior. One of the problems we have with VS is that there is lots of functionality that people don't know about. I've added this to my "Things that people don't know about list". So, if you want to change the default, right click and choose "open with". This works for both Windows forms and ASP projects.

The second concerns options. There were several comments that say, "make it an option, so people can choose", and then Monte Hansen said, "I think there needs to be a gatekeeper for project-level options and if it were me, this one wouldn't make it".

I agree with that sentiment. In some cases, you have to provide flexibility - for example, if you had a feature that said "braces must go on the line after the if statement", you would make lots of people unhappy. That would be a Bad Thing.

But there are other cases where adding an option is is the simple way out - either because a team can't agree on what should or shouldn't be there, or because the team hasn't worked hard enough on what the customer wants (these may really be the same thing - not knowing your customers well enough). It's easy to say "let's make it an option", but in a product like Visual Studio, there are already too many opaque options. There may be some interesting ways of fixing this - like making the options that pertain to a window actually be accessible from that window - but in the category of options, fewer is already better.

I was looking through the options in VS2003 for one where I could say, "Does anybody ever set this option". I had just read Mark's comment:

One feature that disappeared between 2002 and 2003 that really drives me nuts, was that when you changed between document tabs the project tree view would update to select the current page you are viewing

and what do I find? Under "Projects and Solutions", there's an option named "Track active item in solution explorer" that I think does what Mark wants. We didn't take the feature away, but we did do a good enough job of hiding it that it appeared that it was missing. That's a good indication of why "make it an option" can be a bad choice - we put effort both into coding something, making it an option, and then testing it, but we hide it so that our users get little benefit from it. Many times the effort to do this just isn't worth the return, as an unfound option is no different than a feature that doesn't exist.

We had a similar situation back when I was on the C++ compiler team. User asked us for more information to help them find problems in their code, and there were a number of situations that the compiler could identify. Unfortunately, in many cases, the compiler would warn on perfectly reasonable code, and since many people compile with "warn as error" on, we couldn't make them level 2 warnings, as it would break lots of existing code.

So we made them level 4 warnings, but the result was that since the default was level 2, almost nobody got any benefit out of the work that we did, so we stopped adding new ones.

• Shiver me timbers!

I've been home sick today, so I didn't get to post this until now.

Today is "Talk like a Pirate" day

• XBox tip of the day...

Today, I accidentally figured out that the "off" button on my XBox isn't just an off button. It's also an on button, and it's one that doesn't eject the disc first, so you don't have to wait for the tray to come out and push it back in.

• I'm in need of ideas

I've been cleaning my office today, and I need some help on a problem I have.

Back when I wrote my C# book (A Programmer's Introduction to C# (still available at better booksellers everywhere (Eric needs to pay for his season's pass at Stevens Pass (where it snowed this week (view the webcam))))), I was lucky enough to have the first edition translated into a number of different languages. Whenever a publisher would finish a translation, my publisher (Apress, new owner of most of the Wrox titles) would send me a box of books. I always put one on the bookshelf, and when I had one that I thought somebody would be interested in, I'd give it to them. For example, I gave my Czech mother-in-law a copy of Začínáme programovat v C# , and Anders got a copy of

 But after a while, I exhausted the humorous potential of giving relatives copies of books that not only covered topics they didn't understand, but were written in languages they didn't speak, and I'm left with a number of copies that I don't know what to do with. Most are the first edition of the book, which is nowhere near as good as the second edition. So I'm looking for ideas of what to do. I currently have: 7 Danish 1 Italian 4 Dutch 4 Korean 2 Korean (2nd edition) 2 Chinese 2 Polish 4 Czech

• The solution explorer and windows forms

I have a design question for you. Yes, I don't own the project system anymore, but I started this particular issue, and I want to follow up on it:

In VS 2002, whenever you double-click on a form file in solution explorer, the project system always opens the form designer on that file.

We are considering modifying the behavior in Whidbey so that the project system will track the most-recently-viewed state for the file. If you had most recently looked at the code view, double-clicking would take you to the code view. If you had most recently looked at the design view, double-clicking would take you to the design view. This state would not be persisted across closing and reopening the project.

What do you think? Should we stick with the current behavior, or should we change to the new behavior? And why?

• Going to PDC...

The C# team has finally decided who is going to PDC, and I'm going to California, though I am not going to make a new start, nor do I current have an "achin'" in my heart. (1)

(1) Too lazy to do a google search, huh? Too young to know better. Okay, just this once: Answer.

• C# Design Principle: Know what you're trying to build

(The opinions expressed herein reflect my opinion about the principles we used in designing C#, and do not necessarily reflect the opinions of the C# design team).

Know what you're trying to build

Over the past few years, I've answered a lot of questions about language design rationale. Most questions have straightforward answers. For example, if somebody asks "Why doesn't C# have macros?", that's easy to answer.

Other questions require a bit more work, and/or may be religious discussions. "Why are methods non-virtual by default?" takes more time to answer.

The toughest ones to answer aren't tough because they're technically hard - they're tough because it's hard to give a nice answer to. This is usually because doing what the person requests would require changing one of the basic tenets of the language.

Our goal in C# was to create a modern, real-world managed language that would be comfortable to developers used to the C family of languages (C, C++, Java, etc.). So, when I get questions like, "Why is C# case-sensitive?", they're really hard to answer. The real answer is that our target users would think we were crazy if we made a language that wasn't case-sensitive. You can say this in a polite way, but the person who asked the question is usually confused by your response. Their perspective is often "of course a language should be case-insensitive", which is diametricly opposed to the C# view.

Similarly, I've been asked why C# doesn't allow you to define your own operators. There are some languages that allow you to do that, but that's very much not what we're after.

Re-reading this, I'm not sure it's terribly insightful, so I'll try to summarize. When you're designing a language, you need to be clear up front what you're trying to build, and who is going to want to use that. Those early decisions are going to have a huge impact on the design of the language, and once you've made them, you can't really go back.

• What PMs do for fun...

Last week, I made a bad joke (I'm the owner of bad jokes for the Visual C# PM team), related to the the concept of arity in generics. I regret that I don't remember the exact joke I made, but we riffed a bit on different permutations (popul-arity, singul-arity, disp-arity). That went on for a few minutes, but we realized that it ws a tough joke to communicate.

Then Julian (one of our IDE PMs) suggested that we could communicate it better through code. Here's what he suggested:

class Hil<T>
{
// Implementation
}

class Jocul<T>
{

}

Once you've done this, then people can discuss the Hil-arity and Jocul-arity of this implementation.

You may have noticed that we often don't aspire to particularly high standards of comedic expression.

If you ever want to find words that contain a certain string of letters, I suggest OneLook.

• Very interesting.

Roy Osherove writes of some very interesting research in his blog.