Archive for July, 2008

Tools: ReSharper 4.0

We just finished our trial period for ReSharper from JetBrains. We’re buying licenses right now. It’s become indispensable to us. It’s that good.

ReSharper is like pair programming for introverts. It’s like a real-time FxCop, offering refactorings and best practices advice while you type.

Gordon had used ReSharper in its 2.0 days. I’d heard many positive things about ReSharper, but hadn’t tried it myself. The recently released 4.0 version offers support for C# 3.5, including the var keyword, object and collection initializers, and lambda expressions. Check out the in-depth review by Simon Hart if you want more details. Or just try it yourself.

How to avoid Visual Studio Help

For what seems like the thirteen-thousandth time, I just accidentally pushed the F1 key while I was writing some code. It’s pretty close to the escape key. I didn’t mean to push it. I guess I just have fat fingers.

I really, really hate pressing F1 in Visual Studio. Usually, it takes about a minute to display Microsoft’s help documentation thingy, which is impossible to navigate, frequently wrong and and generally not very helpful. This afternoon, the document explorer decided it had to go and update itself, which took about five minutes before it could take it’s usual minute to load the non-relevant, non-help, that I didn’t even want in the first place!

During this time, Visual Studio was COMPLETELY Unusable. The help dialog blocks the main visual studio  thread - and all attempts to get back to work were greeted with a friendly, informative “This may take several minutes” dialog.

Time Passes…
Time Passes…
Time Passes…

Arggh! Gord Mad!… And it turns out it’s not just me. This annoys other folks, too!

Right. That’s it Visual Studio. You’ve made me go through this song and dance for THE LAST TIME!

For starters, where do we all go for help? To Google, that’s where. So, I added an external tool using the Tools>External Tools Method:

Adding an External Tool

I set up my command to point to Firefox, and passed as the arguments:

http://www.google.com/search?site=&hl=en&q=$(CurText)+c%23&

(The +c%23& part of the command appends “C#” to whatever is highlighted in the IDE. If you’re not using C#, you could leave it out, or substitute it with whatever else you usually search for)

Then, I flipped over to the Keyboard bindings screen (Tools > Options > Keyboard:)

VS 2008 Keybinding

VS 2008 Keyboard Binding Screen

And I re-mapped the F1 key to my new ExternalCommand1.

There! Now, whenever I press F1, Visual Studio opens a new tab on my web browser, and searches Google for whatever I have highlighted in the IDE.

Purposefully punishing developers with a minute or two wait everytime they press a certain key is just plain unforgivable. They get really distracted trying to work around the “functionality”, and then further distracted writing ranty blog posts about it…

Enums are Ints that Ain’t

Enumerations are incredibly useful in Microsoft .NET, but they can be odd to work with at times. While researching something to do with the new System.Addin namespace in C# 3.5, I was reminded of some enum craziness I’d forgotten.

Enumerations are implemented as collection of integer constants. You can cast any integer to an enum type, regardless of whether it’s been defined in the collection. That makes the code below legal, despite the fact that no item in our enum has a value of 55.

  1. public enum Color
  2. {
  3.     Black = 0,    
  4.     Red = 1,
  5.     Green = 2,
  6.     Blue = 3
  7. }
  8.  
  9. Brush.Color = (Color)55;

You can’t rely on the compiler to enforce legal enum values. This means if you’re using enums in case statements, you ought to include a default statement to catch those cases where an unexpected value gets passed. It’s always a good defensive coding measure, but I’d mistakenly assumed I could skip it in the case of enums. Not anymore.

[Edit: See this old post from Greg Vaughn for some other examples of Enum wackiness. Weird.]

ISO Date Validation RegEx

I needed a regular expression to correctly parse ISO 8601 format dates and times. The standard includes many alternative representations, but I was particularly concerned about the subset of ISO 8601 formats allowed in XML.

Paul Ward had posted a date parsing expression on the RegExLib site. I extended it a bit to handle times and time zones. I’m pretty sure they work, though it can be hard to tell sometimes. (See Jeff Atwood’s Now You Have Two Problems.)

ISO date
^(\d{4})\D?(0[1-9]|1[0-2])\D?([12]\d|0[1-9]|3[01])$

ISO time
^([01]\d|2[0-3])\D?([0-5]\d)\D?([0-5]\d)?\D?(\d{3})?$

ISO offset
^([zZ]|([\+-])([01]\d|2[0-3])\D?([0-5]\d)?)?$

ISO date and time
^(\d{4})\D?(0[1-9]|1[0-2])\D?([12]\d|0[1-9]|3[01])(\D?([01]\d|2[0-3])\D?([0-5]\d)\D?([0-5]\d)?\D?(\d{3})?)?$

ISO date, time, and offset (the works)
^(\d{4})\D?(0[1-9]|1[0-2])\D?([12]\d|0[1-9]|3[01])(\D?([01]\d|2[0-3])\D?([0-5]\d)\D?([0-5]\d)?\D?(\d{3})?([zZ]|([\+-])([01]\d|2[0-3])\D?([0-5]\d)?)?)?$

If you find it useful — or find a bug — let me know.

256 Character Filenames Should be Enough for Anybody

One of the key components of Infovark is a file crawler. We monitor specified folders for additions, updates and deletes, so that we can let users know what changes have occurred. I figured that making a recursive descent through files and folders in Windows would be a snap. And it would be, if not for the details.

Walking a file hierarchy is one of those basic examples included in just about every programming book, just like “Hello World!”. You can find sample code everywhere, but here’s the MSDN article on Iterating Through a Directory Tree. Notice how it recommends that you read about how NTFS works, at the end of the article? That’s where the important details hide.

Inconstant Constants

Implement the naive version of file recursion, and you’ll likely get a System.IO.PathTooLongException in fairly short order. This is because Windows filenames have a maximum limit of 260 characters. Most of the time. There are a few gotchas. Check out the Naming a File article. After reading it, you’ll probably have similar reactions to the folks on this Joel on Software forum thread about Windows MAX_PATH.

Here’s the gist: The Windows shell has a 260 character limit on its filenames. This is the MAX_PATH constant. However, the OS Kernel itself supports filenames with up to 32,000 characters (for compatibility with UNIX systems). So it’s trivially easy to work around this “constant” using a variety of hacks. For example:

  1. Sometimes you can squeeze in a few extra characters by using the DOS 8.3 short name format. This gives your files bizarre names like C:\PROGRA~1\DOCUME~1\LongName.txt.
  2. You can drop down into Win32 API calls and unmanaged code. Certain file-handling functions accept the “\\?\” prefix, which lets you use the UNIX-style names. Naturally, this comes with additional baggage that I can’t even begin to describe.
  3. You can map a drive to a folder deep in your tree. This effectively fakes out the Windows shell into thinking the path is much shorter than it really is.
  4. You can create a shared folder and bypass the length restriction. This works for the same reason that mapping a drive does.

The most common case where these hacks crop up is when a Windows server administrator maps network drives. While end users can create file hierarchies nested right up to the 260 character limit on their H: drives, the administrator of the file server can’t actually navigate that deeply. That’s right: The file server administrator can’t actually reach the deepest files on the machine because he sees C:\File Shares\Shared Drives\ where end users see H:. As you can imagine, this makes backing up network drives no fun at all.

But there’s a fix, right?

Not really. You’ll have to figure out how to deal with all these exceptions and hacks yourself. The Base Class Library (BCL) Team at Microsoft is working on both temporary and long-term solutions for the .NET Framework. You can read Part 1, Part 2 and Part 3 on the BCL Team Blog for all the gory details.

The core issue is the trade-off between consistency and backward compatibility. It’s a challenge that becomes tougher every year, both for Microsoft itself and for developers using the MS platform. It’s amazing how backward-compatible Microsoft is, given its quarter century accumulation of legacy code. It’s great for businesses and consumers, but from a developer’s perspective, all those gotchas add up over time. I don’t want to have the institutional memory of Raymond Chen just to navigate the filesystem. And is 256 characters a reasonable limit for filenames in a modern OS?

Oh, in case you were wondering, the maximum URL length is 2,083 characters in Internet Explorer.

Swapping NUnit for xUnit?

In our previous programming jobs, neither Gordon nor I had to do much testing. We tended to focus on architecture and development issues. Just prior to forming Infovark, we were acting as consultants for an ECM vendor that has since been snapped up by HP. So while we were aware of things like unit testing and test-driven development, we’d never had to do much of it ourselves.

We knew it was important, though. We’d seen too many things go wrong in software projects that didn’t make testing a core part of their standard operating procedures. So we incorporated testing into our product development and we’ve been learning about this testing stuff as we go. (It always happens that way, doesn’t it?)

We began with NUnit, the gold standard for unit testing on the .NET Platform, and quickly discovered some things that everyone else already knew:

  1. Good unit tests are essential for refactoring. It’s the only way you can make big OO changes with confidence that you haven’t broken anything that used to work.
  2. Good unit tests are are essential for troubleshooting. It makes it much easier to pinpoint the source of the errors when things go wrong.
  3. Good unit tests are essential for making your product fail gracefully. Every program will fail at some point. It’s how a program reacts to a failure condition that counts.
  4. You can’t write good test suites without good specifications. You’ll forget to test key assumptions and dependencies. You won’t confirm error conditions. You’ll couple your tests to your current object model, rather than to program requirements.
  5. If you’re doing it right, you’ll write far more code for testing than for the product itself. It’s much harder to verify correctness than it is to write correct code.
  6. Unit testing is different from integration testing. Integration testing is different from system testing. All three are important.

In addition to these common nuggets of TDD wisdom, we also discovered something else: It’s dreadfully easy to shoot yourself in the foot with NUnit tests. It’s easy to write tests that aren’t atomic, for example, or tests that expect errors to occur in one line of code that pass because another line of code throws a similar error.

To address some of these quibbles, a splinter group has launched xUnit on CodePlex. It aims to simplify testing syntax, incorporate more .NET 3.5 constructs, and prevent some of the more common NUnit anti-patterns that testing neophytes (like us) regularly develop.

We’ve messed around with XUnit a bit, and so far we like what we see. It’s not enough yet to make us abandon NUnit though, especially with NUnit 2.5 on the horizon. Besides, the NUnit framework is integrated with a variety of other development tools we’ve found indispensable. (I.e., everything made by JetBrains.)

But that’s just our opinion. What do you think? How do these things stack up? And what about the testing framework built in to Visual Studio Team System? We’d love to hear your experiences with these tools.