Tuesday, April 26, 2005

Long Methods and Classes Are Evil

I've spent a great deal of time in the last week reverse engineering legacy VB6 code, and I'd like to rant a little bit. What's making my life harder is how large and complex the methods are in each class module. The code is very procedural, with little usage of subroutines. The VB functions are several pages long, if/then nesting goes 6 or 7 deep, and case statements span hundreds of lines. Unsurprisingly, the code is hard to maintain and brittle in regression testing. Finding the location of a piece of functionality requires arcane knowledge of the application or some amount of luck with CTRL-F.

If the application you are building or modifying is important or useful, it is a sure bet the code will have to be modified later as requirements change and problems occur. There are some easy steps to take to make your code more understandable. Good naming is obviously important, a variable named "a1" isn't very descriptive, especially when it is an untyped variant. Can you say "Mystery Meat?"

My personal pet peeve is really long methods and classes that do way too much. I'm a terrible slob in most other ways, but I want my code readily organized with each type of code on its proper shelf, err, class. The human brain can only process so much information at a time. Small methods can be seen and understood all at one time. Bugs can hide out in very long methods because there is simply more brush to hide in. Large case statements are veritable camouflage for lurking bugs.

Rules of Thumb for Class and Method Size

  1. Any method should fit into your IDE window so the entire method can be read at one time. I'd take it farther if you can. One of the few code metrics I pay attention to is the average lines of code per method. I strive for an average of not more than 5 lines of code per method.
  2. Too many private members. You know what I mean, if you see a class with an excessive number of private fields (say >10), the class is probably too big. I'm tracing a class with about 75 private fields this morning. Not pleasant. In Fowler's Refactoring book this is described as the code smell "Primitive Obsession."
  3. The size of the code file. Offhand, I'd say any class over 10k in size is getting too large for its britches. A class that is 200k in the file system is certainly too long. TestFixture classes might be an exception.
  4. Exception handling code and instrumentation tend to push methods to be much larger. Invest some thought in how to segregate this type of code away from the main functionality. Aspect Oriented Programming may justify its existence by merely doing this.
  5. Reduce the number of public methods in a class. Just picking a number, I would say less than 10 in most cases. There is a good discussion on this subject at http://c2.com/cgi/wiki?FewShortMethodsPerClass.

I'm not just picking on VB developers, because I've seen (and written) bad examples in other languages, including a C# system that is featured in an early case study on MSDN as a shining example of the wonders of .NET. At a former employer, my teammates and I inherited a large new supply chain system hacked together by a very prominent consultancy. I distinctly remember a coworker printing out a Perl script that contained an if/then branch spanning 18 pages.

As an aside I'm 2-3 years removed from any kind of serious VB6 work. I remember a time when I was a staunch pro-VB guy because of its productivity for building code rapidly and hated being looked down on by Java guys. After becoming quite used to C# coding with ReSharper and other toys, VB6 feels extremely clunky. Combining well-factored C# code with the advanced code navigation features from VS.NET itself and ReSharper, leads to code that is readily traced and reverse-engineered. Oh yeah, I forgot to mention that variants suck and COM sucks more. I do still hate being looked down on by Java guys, though.

Tuesday, April 12, 2005

Bypass VSTS and get yourself a "Poor Man's IntelliJ"

A couple months ago at an agile users group the question was posed, "Do I need Visual Studio Team System to do Test Driven Development?." The answer is an emphatic no. I think it is great that Microsoft has tacitly endorsed TDD and Refactoring by building support into VS.NET, but VSTS is not the only game in town for agile development with .NET.

The painful truth is that the Java community has had far superior IDE support from tools like IntelliJ and Eclipse. IntelliJ is an agile developer's dream IDE. Very good integration with source control, JUnit, and tremendous support for refactoring and code generation. The .Net world got a late start, and Microsoft's emphasis always seems to be on providing more visual drag 'n drop programming for Mort. Lucky for us we don't have to defect to Java or wait and pay (a lot apparently) for VSTS because there are alternatives for .Net today. And don't think for a minute Microsoft hasn't heard "just make it be like IntelliJ/Eclipse" a few too many times for their own comfort.

The VSTS team at Microsoft seems to bristle anytime someone mentions open source alternatives and spit out a comment about "Cobbling together downloaded tools." The reality is that these tools are superior in some respects. Assuming you don't mind assembling the stack yourself, you can use these mostly open source (and free) tools to create what I affectionately call my "Poor Man's IntelliJ."

  1. NUnit - The defacto standard for unit testing in .NET. Arguably better than its Java forebear. I know the NUnit guys are already planning to be compatible with the Whidbey unit testing. I've also heard good things about MbUnit. Supplement NUnit with NMock for dynamic mock objects and NUnitForms and NUnitASP for UI testing.
  2. TestDriven.NET - VS.NET plugin to run NUnit or MbUnit tests in the IDE. I love this tool. It allows you to run tests by clicking on a unit test, testfixture class, or namespace. It also provides the ability to start the debugger using any test method as an entry point. You lose the visual green bar, but the text output includes stack traces that can be clicked on to navigate to the offending test code.
  3. NAnt and NAntContrib - Automated build tool. Right now it looks like MSBuild provides only a subset of the NAnt/NAntContrib tasks, several of which my team depends on in our build process. The MSBuild integration/synchronization with VS2005 is cool, but you can run NAnt from within VS.NET today. Using the solution task, a NAnt script is not too onerous to maintain for moderate sized solutions.
  4. Subversion - We started using Subversion, a free open source version control system built to finally replace CVS. So far I think it is the most problem free source control I've ever used. CVS has a personal animus towards me, but is still a viable and proven tool. VSS is simply unsuitable for serious development needs. Agile development can require more robust source control and VSS just won't deliver.
  5. Ankh - VS.NET plugin for Subversion integration. I'm able to do probably 90% of my source control updating and commits from within the IDE now. It has some contention with ReSharper, but I still enjoy using the tool. I still use TortoiseSVN occasionally.
  6. CruiseControl.NET - Continuous Integration tool. The latest versions seem to be much easier to install and configure, and the website reporting has gotten much easier to use for debugging build failures. Very good integration now with Subversion, NAnt, and NUnit. To the best of my knowledge, VSTS only supports scheduled builds anyway.
  7. ReSharper - The only commercial tool on this list. The best $100 tool anywhere. ReSharper provides refactoring, code navigation, and code generation templates. Since it became stable last year (the beta was flaky), I will not develop on any box that does not have ReSharper. The refactoring support in ReSharper 1.5 is superior to VS 2005 in many respects anyway.
  8. NCover - Code coverage tool. The VSTS equivalent integrated into the IDE does sound really good.
  9. OpenWiki - Use any Wiki engine as a great means of storing and organizing project information and documentation. I've used Jira in the past for project tracking and actually liked it, but a Wiki is good enough for now.

This is not an exhaustive list be any means, but it covers most of the bases. I'm much happier with .NET development now that I can perform most tasks from within the IDE.

To be honest, I have not paid much attention to Visual Studio Team System. My shop probably doesn't have any justifiable need for VSTS and a deep investment in existing tools. Some of the ideas for integrated project tracking and metrics sound pretty cool, but by itself an agile process provides so much more transparency than heavier methods that I'm not sure the formal tracking is important.

Feel free to suggest other tools. I would like to hear from people adopting VSTS, too.