Awesome: Local Transit on Google Maps for iPhone

I didn’t notice exactly when it happened, but Google Maps has been updated with information about the public transit routes and fares here in town. It’s pretty awesome. Instead of fighting with paper maps or the local transit authority’s own trip finder implementation, I can just pull up Google Maps on my iPhone and plot a trip from my location to wherever I need to go.

Not only is it pretty sweet that I get information like bus routes, total fare required, and scheduled departures, but if I keep monitoring the app while on the bus, it’ll also tell me how far away I am from my stop:

I’ll have to keep an eye on it to see if it goes by traffic or published schedules to adjust the time, but either way it’s pretty sweet. It’s good to live in the future.

How to create an infinite loop

Obvious in retrospect, but took me a minute to catch on to what’s going on here:

public void DoStuff(byte maximum)
{
    for(byte i = 1; i <= maximum; i++)
    {
      // whatever
    }
}

This works like a trooper until someone passes in a byte.MaxValue in a unit test and i becomes 0 after reaching maximum and getting incremented again.

Are Comments Evil?

I’m a bit late to this party, with the majority of the opinions on the subject having been weighed in last week and the week before it, but after reading Jesse Liberty’s Coding Without a Net post and then Davy Brion’s response to it, I’ve been noodling on my own usage of comments in code and what I think about them.

In the end, I think I have to side with Davy and answer the question of “are code comments evil?” with “it depends”. The biggest argument I’ve read against code comments is that they can easily go out of sync with the code. While I agree and have certainly seen it happen many times, I don’t think that’s a reason to avoid comments. I think that’s a reason to hire developers with better discipline. After all, when a comment is replaced with an extra lengthy and specific method name, who’s to say that some developer won’t come along at a later date and change the guts of the method without updating its name? It really is still the same problem — the developer wasn’t diligent enough.

Don’t get me wrong – I don’t think extensive comments are a viable alternative to good naming conventions or proper designs, but I still believe comments can be very valuable when expressing the motivation behind code being written a certain way (e.g. to work around a bug or to address some design considerations). Properly written comments that detail the “how” behind the “what” can save time that’d otherwise be spent looking up a wiki page or some other document that explained the design. And that’s assuming that there even is such a document.

Used in combination with good naming practices, these comments can make reading and understanding code a lot easier. Where this scheme is pretty much guaranteed to go pear-shaped is if the comments are required. For example, I’ve seen projects configured to fail to build if there is a non-private method that’s missing its XML documentation. The result is not unexpected — every public method is decorated with an auto-generated XML comment that is absolutely obvious and sometimes a bit weird – GhostDoc is pretty good at parsing method and property names into English sentences, but it’s not perfect and produces its share of “Validations the handler” on a method called “ValidationHandler”.

The worst kind of comment in my mind, though, is the “angry and lazy developer” comment. Have you ever come across a section of code where someone took the type to type in something along the lines of “This is horrible. Does this even work?”? If yes, then you know what I’m talking about. It’s when a developer came across some code and instead of figuring out what’s wrong with it and fixing it (thereby leaving the campsite cleaner than he found it, as it were) or asking the original developer, he instead chose to leave a passive-aggressive comment in the code and check it in. The odds of someone looking at that piece of code may be relatively low and the comment will survive days, then weeks, then months. It’s even more fun when an aforementioned undisciplined developer comes along and fixes the code without altering the passive-aggressive comment.

So in the end… “it depends”. As with many programming paradigms, there’s a lot of ways to misuse code comments, but I think there also are ways to use them for good rather than evil and that they should not be abandoned completely. The truth is in the middle, not in the “comment everything” or “comment nothing” extremes.

New desktop specs

I have used a laptop as my main machine for a couple years now. I guess calling it a laptop would be a bit of a misnomer — it is an Alienware m9750, a relative powerhouse for its time, weighing in at 10 lbs and making my car think I’m a bad driver who lets her front seat passengers ride without a seatbelt if I were to put it beside me in the car. It has served me well, but the time has come to move on.

I opted to return to the desktop this time, in part for financial reasons and in part because I would’ve much preferred to just do a few spot upgrades on my laptop… which unfortunately wasn’t much of an option. I haven’t paid attention to hardware in a while, so I enlisted the help of a friend in sourcing out good parts to put together. Here’s what we ended up with:

ASRock H55M Pro Micro ATX motherboard
Intel Core i3-530 2.93Ghz Dual Core CPU
4GB DDR3 1333 RAM
Western Digital Caviar Black 640GB SATA HDD (7200 RPM, 32MB Cache)
MSI N250GTS Twin Frozr 1GB video card

With a couple other bits (such as power supply and a DVD burner, all this lives inside an In Win Griffin case and is hooked up to my existing monitor — a 24″ Samsung SyncMaster 2443BW.

For completeness’ sake, my keyboard and mouse are both Logitechs — a Wave and an MX400, respectively.

It is by no means an ultimate machine, but for just over $800 after taxes and shipping, it’s not too shabby at all.

Here’s a comparison of the Windows Experience Index scores. Old laptop:
WEI of my old laptop

New desktop:
WEI of my new desktop

I look forward to upgrading the hard drive at some point (maybe with some solid state goodness) to bump that score up a point.

Why Excel thinks your CSV is a SYLK

Just a quick post to share a tip I discovered this morning. I was generating a CSV file and for some reason when I went to open it in Excel, I got a message saying the file’s extension was CSV, but the file format was SYLK. Clicking through a couple message boxes opened the file up just fine anyway.

A bit of digging turned up the Wikipedia page linked above, and within it the format syntax description:

”’ID”’ record:
Use:
A header to identify spreadsheet type and creator.
Must be first record in the file.

Yep. If the first record of your CSV file is “ID”, Excel will attempt to intepret the file as SYLK. Changing “ID” to anything else (including “Id” or “id”) fixes the issue.

On Importance of Good Method Names and Paying Attention

I spent a somewhat frustrating hour at work today trying to plot a straight line on a chart using a framework that shall remain nameless. I quickly had the slope and the y-intercept worked out and all I needed were two x values to plug into the equation to calculate some points. I already had another series plotted on the same chart and just picking the minimum and maximum x values from it was sufficient for my causes.

Naturally, I could do the legwork of figuring the min and max myself, but why do the work when the framework can do it for you? I poked around and found a couple useful methods: FindMinValue() and FindMaxValue(). I had assumed (based on Intellisense and lack of code docs) that they would return the values I needed. Then a couple things taught me that wasn’t so at all:
1. I used var to declare my variables, so I didn’t notice that the functions in question are returning integers.
2. I was wrong in my original assumption. Those methods aren’t finding and returning the min and max values. Instead, they’re returning indices into the array of points in the series, pointing me to the location of the min and max values.

I guess technically the method names didn’t lie: they are “finding” the location of the values for me. I still found that to be counterintuitive. In my opinion, FindMinValueIndex() would’ve been better.

So, the lesson is: pay attention, don’t assume anything, and if you ever release an API framework, try to be as clear as possible about the intent of your methods when you name them.

ComboBox SelectedItem vs SelectedValue Question

Annoying discovery of the day:

The following code works as you’d expect — MyProperty on the model is updated when the user picks a new item in the dropdown.

comboBox1.DataBindings.Add("SelectedValue", myModel, "MyProperty", true, DataSourceUpdateMode.OnPropertyChanged);

The following, however, doesn’t work the same way and the model update isn’t triggered until the input focus moves to another control on the form:

comboBox1.DataBindings.Add("SelectedItem", myModel, "MyProperty", true, DataSourceUpdateMode.OnPropertyChanged);

Does anybody know why? I’d investigate myself, but I don’t even know where to start. Pointers in the right direction to start the investigation or an outright explanation are both welcome.

Update: Some explanations are up on StackOverflow. In the end, I ended up binding to both SelectedValue and SelectedItem, which ensures instant model updates based on UI changes (through the SelectedValue binding), and UI updates based on programmatic model changes (through the SelectedItem binding).

Another thing to note is that when binding to SelectedValue without setting the DisplayMember/ValueMember properties, it helps to pass in “true” for the formattingEnabled binding parameter.

Replace Paper with Unit Tests: Code Snippets Edition

In my previous post about making mental notes about condition tests or new features through unit tests I offered an example of making a live template in ReSharper to automate some of the process.

This post is about achieving a similar thing in plain Visual Studio with the help of the Code Snippets feature.

Introduction to Code Snippets

In a nutshell, a code snippet in Visual Studio is either a template or a static chunk of code that is stored in a specific location and is available through IntelliSense. Visual Studio comes with some snippets pre-configured, such as “ctor“, which creates a default constructor for a class.

To use a snippet, start typing out its shortcut – either type the whole thing or wait for IntelliSense to pop up and complete it for you – and then press TAB key twice to expand the snippet into code.

There’s a detailed guide to using and creating snippets available on MSDN. For the rest of this post, I will just show what I did for my purposes.

Snippet Location and Creating New Snippets

Snippets are located in a specific folder under your installation of Visual Studio, so you’ll have a snippet collection per VS version. On my machine, where I used default installation paths, C# snippets for VS 2008 and 2010 are in the following folders:

C:\Program Files\Microsoft Visual Studio 9.0\VC#\Snippets\1033\Visual C#

C:\Program Files\Microsoft Visual Studio 10.0\VC#\Snippets\1033\Visual C#

You can use the Code Snippet Manager (available through Tools->Code Snippets Manager… menu item) to explore currently installed snippets for various languages.

To create a new snippet, you can simply write its XML definition (see below for my example or read the MSDN guide for more info), save the file with the .snippet extension and drop it in the appropriate folder. Visual Studio will see it without needing to restart.

You can also use a visual editor such as the open source Snippet Editor, which now includes support for Visual Studio 2010.

Unimplemented Unit Test Snippet

Here’s my code snippet in its entirety:

<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Unimplemented Unit Test</Title>
<Shortcut>test</Shortcut>
<Description>Code snippet for a failing test placeholder</Description>
<Author>Anna Lear (http://annalear.ca)</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>testName</ID>
<ToolTip>Descriptive test name</ToolTip>
<Default>NewTest</Default>
</Literal>
<Literal>
<ID>testBody</ID>
<ToolTip>Test contents</ToolTip>
<Default>Assert.Fail("Implement me!");</Default>
</Literal>
</Declarations>
<Code Language="CSharp">
<![CDATA[
[Test]
public void $testName$()
{
$testBody$
}
]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>

I wrote it within Visual Studio 2010 and it helpfully provided IntelliSense support and guidance, which made writing the XML really easy.

Now when I type in “test” in a class and press TAB twice, the code within the CDATA portion of the snippet gets pasted into my code. “NewTest” and “Assert.Fail(“Implement me!”);” lines will be highlighted and I can navigate between then with TAB and Shift-TAB if I need to edit them. I typically always edit the name of the test, and only edit the body when I intend to implement the test at the same time.

Couple things to keep in mind:

1. When you add literals to a snippet, their IDs are case-sensitive.

2. If you want to preserve your formatting (multiple lines, etc.), make sure that you’re code is within a single CDATA element. Otherwise you’ll end up with all your code on the same line, which probably isn’t what you want.

Download

You can either copy the snippet above and do the legwork of placing it in a file and the correct location, or download the .snippet file or the .vsi installer, the latter of which will allow you to easily install the above snippet into any version of Visual Studio (2005 or newer) that you have on your machine.

Toronto Code Camp 2010: Lessons Learned

This weekend I had the great opportunity to attend Toronto Code Camp 2010. It was my first code camp and my first major dev-related event, so I was pretty excited all around. I’m happy to say it didn’t disappoint. Over the next few days I’ll post some of the notes I’ve made and/or links to slides if I can find them, but for this point I’d like to just list some of the lessons I learned.

In no particular order…

1. Having business cards on hand is important.

Every conversation I had in-between sessions ended with an exchange of business cards. The ones I had with me were employer-branded, which is better than nothing, but I think I will be making some of my own soon.

2. Talks that look irrelevant may turn out to be very enjoyable.

I’m primarily a desktop application developer just starting to poke my nose outside .NET 2.0. I was worried for a bit that the event was very focused on technologies I don’t work with. Well, lesson learned: that doesn’t matter. Learning something outside my normal work was perhaps one of the most valuable things I took home with me.

I would almost go as far as to say “go to talks on subjects you know nothing about”.

3. Bring food.

The code camp’s organizers, volunteers, and sponsors do an excellent job of bringing a free event out to the developer community and provide a free (!) lunch to the majority of the attendees. Alas, for a day full of thinking, it would be helpful to have some “brain food” on hand throughout the day.

I didn’t bring anything along this time and my afternoon sustenance was comprised of a Coke and a Bounty bar out of the vending machine. This is not a mistake I plan on repeating.

4. Even though they may work with different programming languages or technologies, all developers speak code.

I don’t think there’s anything else I need (or have to) say about this one. When in doubt, sketch out some code on a napkin. Maybe clarify the syntax. And suddenly you’ve explained a concept to someone even though you’re working in drastically different areas.

5. Don’t be shy.

I only recently began coming out to user groups and other dev-related events and I gotta say that writing code in isolation, no matter what you’re working on, isn’t nearly as fun as coming out and meeting other people with the same interests. So don’t be shy. Say hello to the person next to you, ask about them and tell them about yourself.

Conclusion

I came home from the camp both incredibly inspired and incredibly worn out. “Information overload” didn’t quite cover it. Now that I’ve had time to process, I can safely say that the event, for me, has been a blast. I regret being unable to stay for the afterparty and meet more people, but that’s something to fix for next year as well.

For now, I’m excited about the Microsoft Web Camp coming up on May 7 and 8. And after that… who knows?

Replace paper with unit tests

TDD, or Something Like It

When I write new code, I often start out following the TDD principles: write a test, make it pass, refactor. But often, as I’m doing the refactoring or even the initial implementation, I find myself thinking of other tests I should do or features I should add. Instead of jotting things down on a piece of paper, I’ve started creating method stubs for my future tests that effectively document my development path for me:

[Test]
public void CreateItemThrowsExceptionWhenNameIsDuplicate()
{
}

This is nice and I can go in and fill in the details of those tests as I work through my code. However, it’s still easy to forget or miss a test, since these will automatically show up as passing. So we can add an Assert.Fail() call:

[Test]
public void CreateItemThrowsExceptionWhenNameIsDuplicate()
{
    Assert.Fail("Implement me!");
}

This will now remind you to implement tests as you run them locally. Great!

Why bother?

The benefits are pretty clear:

  1. Even if you’re the type of developer to write tests after you write the actual code, this will help you make sure you’re not forgetting anything. It can save you from either trying to find that piece of paper where you wrote down your thoughts three days ago or from staring at your just-written code to identify parts that need testing.
  2. This promotes clear and meaningful test method names, since you have to be able to remember what you were going to test when you wrote the stub.
  3. As you fill in your tests, you will use your own code. If you’re writing an API or just a new set of public methods, you will see pretty quickly if they’re easy to use or if the consumers of your methods will come after you with torches and pitchforks.

My, that’s a lot of code to type in every time…

Typing all that out every time can, indeed, be quite tedious. That’s where Live Templates from ReSharper come in to save the day. I have a template set up that when I start typing in the word “test”, Intellisense picks it up and expands it to create a skeleton method that looks like the ones above, prompting me to fill in the method name and contents (with the Assert.Fail() call filled in by default).

Creating a Live Template with ReSharper

  1. Go to ReSharper->Live Templates… in Visual Studio to bring up the Templates Explorer dialog.
  2. Go under “User Templates” in the Live Templates tab and click the “New Template” button.
  3. In the window that comes up, pick your shortcut (mine is just “test”) and paste the following in the template’s code window:
    [Test]
    public void $TESTNAME$()
    {
         $ACTION$
    }

$TESTNAME$ and $ACTION$ are variables that can be pre-defined (as I will explain below) or be left undefined to let you type them in as needed. I leave $TESTNAME$ undefined and set $ACTION$ as follows:

  1. Click on “choose macro” in the Value column on the right.
  2. Select “Constant Value” and click OK.
  3. Paste “Assert.Fail(“Implement me!”);” in the dialog box that comes up and click OK again.

That’s it! Save your template and it becomes available to you in all your projects. Whenever you need a new test, just start typing “test” (or whatever shortcut you picked) and press TAB to expand it when Intellisense figures out what you’re doing.

The final result should look something like this:

Live Template Example

Live Template Example

For more information on ReSharper templates see their site.

No ReSharper?

I have tried to produce something similar with just plain recorded macros, but I’m doing something wrong there and my attempts haven’t worked at all. I’ll post again about it if/when I figure that part out.