# Eric Gunnerson's Compendium

Posts
• #### "It's a simple matter of weight ratios..."

This morning I left the cage at home, and decided to come to work using a two-wheeled vehicle. Since I'm only about 2 miles from campus, I took the long way round and rode along beautiful Lake Sammamish Blvd, into Redmond, and then up highway 520 towards Microsoft.

I haven't been riding much the past year or so, and every time I do, I'm reminded why I should do it more. This summer, I sold my ancient Acura Integra, and bought a used BMW 328i. The Integra had reasonable power for a small car, but the 328 is a lot faster, and still fun to drive. But neither accelerate like my motorcycle.

One way to measure performance - a bad way, it turns out - is to look at horsepower to weight ratios. If you do that for the vehicles my wife and I own, you'll find the following:

• Ford Ranger - 27 lb / hp
• Subaru Outback - 23 lb/hp
• BMW 328i - 18 lb/hp
• Honda CBR400RR - 9.6 lb/hp (the wife's bike)
• Honda VFR750 - 7 lb/hp

What does this tell us about the relative acceleration of the vehicles? Well, the answer is "not a lot, really", for a number of reasons:

The first is that torque is the important measure, not horsepower. Torque is what gets you accelerating. Horsepower is only a measure of the work the engine can do. It's a good measure of top speed (assuming equal aerodynamics), but has little bearing otherwise. So why is it the common measure? Beats me - it may be because it has "power" in the title.

The second factor is one of rotational inertia. Big engines have a lot of rotating mass, and when you accelerate the car, you also need to accelerate that mass. Small engines (more correctly, engines with smaller pistons, connecting rods, cranks, etc.) have less rotating mass, and therefore more of the torque can go into accelerating the vehicle. This is one reason engines with more cylinders perform better (but not the only one).

Power curves have a huge difference on acceleration. Race engines are tuned to have lots of torque in a very narrow rev band, and they make lots of power there, but not a lot elsewhere. Their peak power may be higher, but the peakier an engine, the more work it is to extract the power in a useful manner (which, strangely, equates to both "more fun" when you want to work at it, and simply "more work" the rest of the time).

Finally, the rev range of the engine has a huge impact on the amount of acceleration it can produce. If you take two engines, one which makes 30 lb ft of torque at 3000 RPM and one that makes 25 lb ft at 6000 RPM, which one is likely to produce more acceleration? The whole answer lies in gearing - you can take the second engine, gear it down by 50%, and have an engine that produces (ignoring losses) 50 lb ft at 3000 RPM. So, small engines are better because you can spin them faster, which (within reason) gives you a free lunch, so to speak, in the power realm.

So how do you really compare vehicles? Well, one obvious way is "at the dragstrip", which isn't really a bad measurement, delta the differences between dragstrip use and real use, and the launch characteristics. (If you're curious, the BMW does 15.3 sec @ 83MPH, and the VFR does 11.4 sec @ 112 MPH). But a nicer way is to create what's called a thrust graph. For each gear, you take the torque graph, scale it based upon the various gear ratios and the tire size, to finally arrive at a measurement of pounds of thrust at the rear wheel vs road speed. You then overlay the graphs for each gear, and come up with an overall "thrust graph". If you compare the graphs for two vehicles, you'll get a decent idea of how they stack up.

There are only a couple of motorcycle mags that do this, and I've never seen it in a car mag.

Somehow I got from a quick entry about my ride to a dissertation on comparing engines. Not quite sure how that happened...

• #### Call for Votes: comp.std.cli & comp.std.csharp

We are trying to set up newsgroups to discuss the CLI and C# standards.

These groups would live in the comp hierararchy on USENET, and when you want to do that, you need to follow the accepted practices. We are now in the "call for votes" phase.

It's considered a violation of ethics to encourage people to vote one way or the other, so please keep that in mind if you refer to or forward this message.

*****

Voting is now in progress on the proposed newsgroups comp.std.cli & comp.std.csharp. Interested parties should look for the official Call For Votes, which can be found in news.announce.newgroups.

You can also access the posts through Google groups at:

• #### Bike Fit

I've been riding my bicycle a fair bit in past months, and I've been having some comfort problems. The first hour is fine, the second hour elbows hurt and my feet and hands fall asleep (and my butt hurts). The third and fourth hours are more and the same.

I'm planning on doing a metric century (100 KM) in September, which will put me on the bike for 6-7 hours, so I needed to address the comfort issue. I made an appointment with Erik Moen, a physical therapist who works at Seattle's Pro Sports Club (many Microsoft people belong to the Bellevue Pro Sports Club). He came highly recommended as "the great guy" by a friend I have who rides seriously.

So, Tuesday morning I drove into Seattle, and wheeled my bike in for the fit. The nice thing about going to a physical therapist for a bike fit is that he can consider modifications to either the bike or to the body. My expectation was that I would be shopping for a new bike when I was done, or at least some new components. Another big advantage is that it's considered a physical therapy visit, so I didn't have to pay for the session. Ka-Ching!

The session starts with the usual medical history questions, and then a questionaire about my bike-riding tendencies. Except for marking "spinner" instead of "cruiser", I'm pretty much on the lightweight side of all the questions. My session with Erik then began.

Erik is a really nice guy, and he started by doing an evaluation of my body mechanics and flexibility. That took about 15 minutes. We then went to one of the studios and put my bike on a trainer for measurements. This starts with static measurements of the bike (seat highet, difference between bar and saddle height, reach to brake hoods, stem length, seat setback, and crank length). While he did this I watched and generally got in the way.

Next are the rider on bike measurements, which include the trunk angle (37 degrees), distance between elbows and knee, knee angles, and a few others I've forgot). My seat was too far tipped forward (moved it back one notch), and my bars were too low (raised them 1cm and tilted them back). Saddle height was good, as we my cleat placement.

We then worked on position, to see if I could get the handlebar inline with the stem. He adjusted me on the bike to the position he thought I should be in, and found that overall, things were set up pretty well for me.

The problem was that I wasn't actually in that position, due to some inflexibility in my hamstrings and back (there's a note about a "probable ham challenge" on my fit sheet, but I don't think that's about lunch).

His prescription:

1) New shoes to replace my very old Shimano ones

2) Stick with SPD cleats, as they're more practical for my use

3) Insoles (superfeet or biosoft inserts) to make my feet happier

4) A number of trunk and hamstring stretching exercises to stretch my legs and cure me of the "software slouch".

5) A recheck in October

Overall, a very worthwhile hour. Interesting that the bike setup is fine, it's the rider setup that needs some work. I knew I had crappy hamstring flexibility (too much soccer, not enough stretching), but the back part is a new one. I'm going to ask my group to tell me to "sit up straight" if they see me slouching.

I was going to ride this morning but felt to sick, but I'm hoping to get in a few miles tonight. I'll post again with my impressions of the adjustments.

• #### Hangin' with generics

I've been using generics in a project that I'm using on Whidbey. They are tremendously convenient when you want to use collection classes. That wasn't really very surprising.

What was surprising - mostly because I hadn't spent any time reading the generics spec - was how useful generic methods would be. For my app, I sometimes needed to fetch a list of values from a database. I didn't want to write a separate function for each type,  and with generic methods, I could write the following:

```
public List<T> GetValues<T>(string selectStatement)
{
OleDbCommand select = new OleDbCommand (selectStatement, connection);
List<T> list = new List<T> ();
{
}
return list;
} ```

I think that's pretty cool. I wrote several functions like that that perform database operations in a generic (ha ha!) way. So I think generics are going to be cooler than I expected.

I should mention one more thing. If the type you use in the generic method is one of the parameters, the compiler can figure out what generic type you're using, and you don't have to specify it. If I wrote:

```        public T Process<T>(T param) {...}
```

I could call it with:

```        int i = inst.Process(12);
```

and the compiler figures out that I want Procees<int>.

Oh, and before you ask me for the spec, you can't have it... yet... It's still churning due to the ECMA process, and we don't want to release it until it's a bit more concrete.

• #### WMP, album art, and Amazon Web Services

So, I'm working on a music playing application (to be revealed sometime around PDC, or perhaps a bit later if I don't get it working) to play around with Whidbey features. One of the things I want to do is be able to display the album art.

So, I dust off the docs for WMP - which are a bit spotty in places - and go searching for the album art. For a media item in WMP, you can fetch various attributes, and one of them is WM/CoverArt (or something like that). Seems like just the ticket, but none it's not set for any of the items in my collection.

I go searching for another way to get the art. There's a MoreInfo attribute that you can fetch for all the items, but it points to a non-existant page. I play around a bit more and find that I can fix the URL to get to the "More Info" page, which has a link to the album art. A quick Regex, and I pull the cover art url out. I code it up, and run it on a small subset of my album selection (about 20 albums). There is no album art for 5 of the 20 albums.

That's pretty pathetic. It's not like I had a lot of obscure albums there - they were all albums that had certified at least platinum. Now, it may not have had all the albums, but it was really slow, so I had that going for me.

A bit of time on Google led me towards Amazon web services.  The SDK is free, and using it is free, as long as you don't do more than 1 request a second per application (multiple instances can do more). The Details object has a link to the album art, so I just needed to get that object for the album. So, I started up VS, added the WSDL as a web reference, and went to town.

The first attempt was to use keyword searching. That worked well if I as looking for something like "Green Day Dookie", but something like "rush rush" gives you 282 matches, some in artist, some in album. The basic problem is that you're just looking at keywords, and you can't specify album and artist directly. Nor can you find that in the Details object - it just has a single property named ProductName.

The solution was to do an Artist search. This gives me all albums with a specific value in the artist field (once again, a keyword search, not an exact search). You then need to look through all the matches you got back and match against the album you want. This works, but is a bit ungainly, but at least you don't need to do it that often.

Here's some code:

```			ArtistRequest request = new ArtistRequest();
request.artist = albumCoverArt.Artist;
request.devtag = ericsDevtag;
request.mode = "music";
request.type = "lite";
request.page = "1";

AmazonSearchService search = new AmazonSearchService();

ProductInfo productInfo = null;
productInfo = search.ArtistSearchRequest(request);

```

That gets the first chunk of data, and you have to make other calls 1 second apart to get the rest. The devtag is given to you when you register with Amazon, and it identifies who's using the service.

• #### Question of the day

If you put wheat bread into a toaster and take out wheat toast, what happens when you put french bread in a toaster?
• #### Lunch with Bill Venners and Bruce Eckel

Yesterday I had the pleasure of having lunch with Bill Venners and Bruce Eckel. Bill runs Artima.com, a cool site with lots of interesting content. Bruce, of course, is the noted author of Thinking in C++ , and MindView.net. Bruce taught me C++, or at least his book "Using C++" helped a bunch, way back in the early 1990s before I came to Microsoft.

They were here doing interviews, and we (Anders, Dan Fernandez, and I) talked a fair bit about language design and philosophy with them. Anders couldn't be there the whole time, so I fielded questions the rest of the time. One of the best ones that Bruce asked was, "How did the design team know that they were doing the right thing, absent real feedback. How did you avoid creating problems the way the C++ committee did?" (Bruce can say that since he was on the C++ standards committee for a number of years).

The answer is a two-part answer. All of us on the design team were real-world programmers, and Anders has a very practical approach to language design. The second reason is that we had a large group of framework programmers using C# as we developed it, and they were not shy when they found it too hard to do things with our current design.

A very enjoyable hour. Bruce has a blog.

• #### What I Ride, and learning to Ride

I mentioned a day or so ago that I have a motorcycle. A little clarification is in order.

I started riding in 1986 when my 1969 Citroen Safari broke a timing chain at 70 MPH, and embedded a couple of valves in the pistons. It was either a cheap car or a decent motorcycle, and a Honda FT500 made its way to my apartment. After a few months of riding, I got my endorsement, and started riding from time to time. Kim was also interested in riding, but the FT was a bit tall for her, and her attempts were not successful.

Enter the Motorcycle Safety Foundation. MSF was formed in the 1970s to provide, not surprisingly, motorcycle training. I took their Experienced Rider Course, and Kim took the basic course. The basic course is a wonderful way to find out if you really want to ride a motorcycle - the course provides motorcycles, helmets, and a world-class curriculum, all for a few hundred dollars or less. In many states, you walk away from the course having earned a motorcycle endorsement (assuming you pass).

Kim's success led to a 1988 Ninja 250 for her, which was soon followed by a 1989 EX500 for me, followed closely after by an MSF instructor course for me.

MSF takes its instructor training very seriously, and I spent 10 days doing nothing but motorcycle training. After that, I taught a lot of classes, and did a lot of riding, commuting year round by motorcycle for about a decade. The Ninja 250 was replaced by a CBR600F2 for Kim, and a few years later, my EX500, having hit 50K miles, was replaced with a 1997 VFR750, my current bike (though mine is a bit more customized than this one).

Kim liked the power of her CBR, but it's a little too tall for her (she's somewhat height-challenged). So, where do you find front-line sportbikes for people who are a bit on the short side? The answer is obvious. All the Japanese manufacturers make home market bikes that would be perfect. A friend led me to somebody who imports Japanese-spec bikes and registers, and the CBR was soon replaced with a very rare in the states Honda CBR400RR, which is pretty much the perfect wife for Kim

Then, a few years ago I moved near the Microsoft campus and got a lot more busy, so I had to give up teaching motorcycle safety, and I still have a hard time finding time to ride.

I missed a few high points, including an introduction to the pavement, riding a GP spec 125cc bike, and being a passenger around a racetrack at 130MPH, but that's for another entry.

• #### The persistance of nomenclature

Yesteraday, I was struck by the fact that in a technological world, nomenclature outlasts the items it refers to.

When I first joined Microsoft ("The year was 1994. The place was Redmond, Washington..."), we used MS Mail for email, and for scheduling, there was part of it named Schedule+. If you wanted somebody to schedule a time with you, you would ask them to "sched+" a meeting with you.

That usage has persisted over the years, and just yesterday I found myself using it. As I used it, I wondered if the person I was sending that message to had ever actually used Schedule+.

There's a similar situation with our bug tracking software. For years, we used various releases of an internal product named "Raid", and though we moved to Product Studio (the "studio" term shows up a lot...), you still "Raid" a bug, and probably always will.

When new people start and you have to explain this to them, you feel a bit strange (don't worry about uncle Herbert. He does think that he's a plant and insist we water him every day, but other than that, he's perfectly all right).

This morning, I was looking for more examples of this. Record/CD is one, though I always use "album", and I think that's still true if you choose to buy your music. Since IP pays for my motorcycle, my skiing, I buy all my music.

Are there other examples of this?

• #### What does a Program Manager do? (1)

Today, Scoble gave me a field promotion.

After I publicly gave him a hard time for it, I got thinking about what a strange thing it is to be a program manager, and that some people might be interested in what we really do. I'm therefore going to talk about what I do from time to time.

The last few days, I've been trying to create a summary of an SDR the C# team held recently. An SDR (Strategic Design Review, Software Design Review) is when we bring in a group of customers, NDA them, and then show them what our plans are for the next release. They then tell us what they think, and we go back and revise our plans based on that feedback.

To create the summary, I go through the official notes we have, the MP3 recordings we made, and the summaries that other people wrote, and try to pull out the salient points for each session that we want to use to get the right things happening. Whenever possible, I use customer quotes, because if a customer says, "It would be better for customers if you killed <x> and forced your customers to buy <y> instead", it's not *my* opinion, it's the customer's opinion.

An SDR is always a humbling experience, as our attendees a very good at telling us what we're doing wrong (and believe me, we're doing a lot wrong).

The summary will be created as a powerpoint presentation (being good at powerpoint is an important PM skill), which will be forwarded throughout the developer division.

• #### Unit testing and TDD

Back in March, I wrote a column entitled "Unit Testing and Test-First Development".

I've been playing around with unit testing a bit more since then, and have a few tentative conclusions.

1. Unit testing is, overall, a "Good Thing"
2. Unit testing works well for class libraries, especially ones that act fairly statically. If you create one of these, you should be writing unit tests
3. Unit testing is hard with graphical applications and/or dynamic applications. I have an app that I'm writing that uses multiple threads, fires events asynchronously, and is peer to peer. There aren't any unit tests for that section yet.
4. Unit testing is great for tricky code that you wrote but weren't sure that it really worked. I updated my Regex Workbench a while back, and in the process wrote unit tests for all the code that I have that interprets regular expressions to english. I found one feature I hadn't implemented, and two that were implemented incorrectly. I'm now much more confident that it works.

I'e also been playing with Test-driven development. I'm not sure about it yet, though it is true that if you write the tests up front, you're much more likely to write them.

• #### Red vs. Blue

Every week the Visual C# PM team spends a few minutes watching Red vs. Blue, a serial told using the characters in Halo on the XBox. Funny even if you don't play Halo, very funny if you do.

If you like this, pony up the \$10 or \$20 to help defray the costs, and get the hi-res versions.

• #### MC Hawking

Little known fact of the day...

Noted Physicist Stephen Hawking also has a career as a dope MC

• #### NotALegend.com

Eric Sink relates to the "Software Legends" marketing campaign by putting up his own site...
• #### C# Column: Web Services, Remoting, and PocketPC

My most recent C# column has gone live on MSDN. In it, I talk about what I learned in trying to build a remote control application that runs on the PocketPC using the compact framework.

If you have comments on the column, please enter them, and I'll be sure to respond.

• #### Higher Primates Can Program

This came to me from one of the members of the VB team.

• #### Who said this?

I was listening to something a day or so ago, and I came across one of my favorite:

Supreme executive power derives from a mandate of the masses, not from some farcical aquatic ceremony.

Who said this, and who did he say it to?

If you don't know the answer, then I despair at the quality of your education. Look at the comments, where I'm sure somebody will post the answer.

• #### Forms, threading, and frustration

I have a fair amount of windows forms code that uses multiple threads. Because of the way that Windows handles its user interface, you should only be updating the user interface from the main thread. If you try to do it on other threads, bad things happen, and they can be pretty hard to track down.

Windows forms includes some code to detect when that is happening, but it can't do it in all cases. Well, it could, but if it did, the perf would be pretty atrocious.

When you get in this situation, you need to call Invoke() on the form, and pass it a delegate to the function that you want to be called on the main thread. In my case, I need to do an update to my form text when I get an event from the other thread. My code looks something like this:

```                // setup code
object.RemoteUpdate += new UpdateHandler(RemoteUpdateFunc); ```
```        public void RemoteUpdateFunc2(object sender, RemoteUpdateEventArgs args)
{
// use the values here.
}
public void RemoteUpdateFunc(object sender, RemoteUpdateEventArgs args)
{
this.Invoke(new UpdateHandler(RemoteUpdateFunc2), new object[]
{sender, args});
}
```

I have to create a separate function just to do the forwarding, and I have to do that for every event that I want to hook to. That's a lot of boilerplate code that I don't want to write.

So, I set out to try to create a class that could wrap the object. Here's the class that I wrote:

```  	public class Invoker
{
Delegate d;
Form form;

public Invoker(Form form, Delegate d)
{
this.d = d;
this.form = form;
}

public Delegate Handler
{
get
{
return Delegate.CreateDelegate(d.GetType(), this, "Dispatcher");
}
}

public void Dispatcher(object sender, EventArgs args)
{
form.Invoke(d, new object[] { sender, args });
}
}   ```

The goal would be to write code like this:

```           Invoker invoker = new Invoker(this, new UpdateHandler(RemoteUpdateFunc));
object.RemoteUpdate += (UpdateHandler) invoker.Handler;
```

Unfortunately, delegates can only point to methods that are *identical* to the delegate definition. You can't, for example use a delegate that's defined as:

```        public delegate void EventHandler(object sender, EventArgs args);
```

to point to:

```        public delegate void UpdateHandler(object sender, RemoteEventArgs args);
```

even though RemoteEventArgs is derived from EventArgs. So, that means that you can only use this approach to point to delegates that have EventArgs as their second parameter, which doesn't make it very interesting.

So, I had to abandon this approach. The alternative is to modify the class that I'm using so that it can make the call. I didn't want that class to have to have a reference to the Form class, so I created a delegate like:

`        public delegate void InvokeHandler(Delegate d, object[] args);    `

and passed that to my the class that has the events. It can then use the delegate to make the Invoke happen. Not as clean as I had hoped, but it does help a bit.

• #### It's Time for Language Divergence

In It's Time for Language Divergence, Patrick Meader discusses divergence between C# and VB programmers.

I agree that VB and C# users have differences between them, but I think that saying that the languages should diverge is a strange position. It's not about divergence, it's about the making sure that VB and C# serve their customers well. If that means language divergence, then that's fine

• #### Disposing, using, and null

I had an interesting discussion a day or so ago on when you should implement IDisposable on a class. Like many things, it's more complicated when you dig a little. There are three scenarios that are interesting:

1) A class that wraps an unmanaged resource
2) A class that has fields that implement IDisposable
3) A class where no fields implement IDisposable

The first one is the easy one. Since you are directly responsible for that unmanaged object, you will need to implement a finalizer (written using destructor syntax in C#) to do the cleanup. You will also *probably* want to implement IDisposable, so the user can call Dispose() to clean things up. There's a standard idiom in the docs for doing this.

In the second case, there is no direct cleanup you need to do, so you shouldn't write a finalizer (what would it do?). If your users will want to clean up early, you may want to implement IDisposable and call Dispose() on your fields from your Dispose() function.

In the third case, you should do either. If you do implement a finalizer, you will just slow things down.

Another related question is whether setting fields to null will result in quicker recovery of memory. This was important to do in the VB6 world, but in the .NET world, it rarely does anything. The only time it would help is if there was a variable that held a live reference, but wouldn't drop off the stack for a long time. I think I could construct a loop like that, but I think it's pretty rare.

• #### The Tour gets interesting...

Yesterday's stage was the best one I've watched in a long time. Lance Armstrong gets attacked, and doesn't blow away the field. Tyler Hamilton rides with Lance despite having a broken collarbone. Jan Ulrich loses 90 seconds to Lance. Iban Mayo does blow away the field.

All of this in front of thousands of rabid fans.

Lance ends up in the yellow jersey, but not by much. This is going to be much more interesting than last year.

Best moment in the coverage was when they showed 3 cows in a pasture, wearing jerseys yellow, green, and spotted.

• #### Socket programming tip: Localhost != local ip address

I've been writing some socket-based code for an upcoming column, and it worked really nice when I used localhost for the client and server on another machine, but broke when I tried to use the machine name.

Just something else I didn't know about networks. localhost is not the same thing as the local ip address, but is rather a totally separate address.

If you want to create a TcpListener, you should use IPAddress.Any as your parameter for the IP address. That will do what you want.

• #### Le Tour 2003 starts

Le Tour de France 2003 started last weekend. The tour, if you don't know, is a 2000ish-mile, three-week race up and down the mountains in France. It's widely regarded as one of the toughest physical challenges around.

The best coverage in the US is on OLN.

• #### The Brunching Shuttlecocks site closes

The offbeat and often insanely funny Brunching Shuttlecocks website has closed. Well, it hasn't actually closed, but they've stopped updating it. The site is still there, with archived content.

From their wonderful movie reviews, to their offbeat ratings, they've written the kind of comedy I sometimes aspire to write.

I highly recommend the "The Book of Ratings", which is an assembly of ratings from the site, in portable dead tree format.