Nerdy tidbits from my life as a software engineer

Wednesday, April 29, 2009

The Value of UML

I appear to be a dying breed.  I am one of the few people who really seems to value strong use of UML.  And it perplexes me to death why nobody else cares about drawing things out before they code.

Complex software systems are hard to understand, but they become a thousand percent easier when you can see class relationships with your own two eyes.  Suddenly, a design either make sense or it doesn’t at all.  In either case, visualizing a system in graphical form makes it easy to spot the pros and cons of your design and understand where to make changes.  Without UML, you’re just looking at a lot of loosely connected text files.

And yet, nobody seems to care about drawing things out.  Any argument that up-front design takes more time than none at all is short-sighted as any experienced engineer will tell you.  It will take you longer to skip design altogether because your lack of foresight will cause delays later on.  You know how people tell you to think before you speak?  Well, I say, think before you code.

My suspicion is that the agile movement has somehow convinced everybody that it’s OK to skip drawing UML.  Maybe all those old, out of date UML diagrams sitting on your backup server have convinced you not to bother with it at all.  But when you are starting a brand new project, UML helps you visualize a class hierarchy of your systems foundation before you even start writing it.  So while there may not be much value in staring at an old UML diagram that hasn’t been updated in 3 years, there is a lot of value in staring at a UML diagram for a new system that doesn’t exist yet.  And for new systems, it’s just so critical to get the foundation right.  A system’s effectiveness will stem directly from the basic architecture on which it was founded.  Screw that up, and your software will be screwy.

So here’s where UML fits into my agile process.  During the design phase of my sprint, I spend 2-3 days drawing UML on a whiteboard.  I don’t get it perfect.  I don’t get every property and every method and every parameter right – but I get the basic classes and relationships down.  And this process forces me to think about how everything is going to fit together so that they meet my requirements.  Because it’s on a whiteboard, I can refactor with the stroke of an eraser.  Class names and relationships change every few seconds.  I can visually see the problems with my design, and I can visually find a way to fix it.  Then, once I’m done, I take a picture, save it, and start coding (using TDD of course).

What happens to the picture?  I can hold onto it or not.  Nobody knows how accurate it will be in a few years.  But my opinion is that if the design was right in the first place, it won’t be necessary for people to have an up-to-date picture there all the time.  And if people need to modify the design, it will likely be more useful to redraw the UML as things exist at the time they are being redesigned.  The relationships will be more complex in the future than they are now, which means the UML I draw today will be so out of date for tomorrows redesigns that there’s little point in holding onto it for a long time.

But the point is: UML is still an important part of the process, and it should not be skipped.  You can have UML in an agile process, and in fact, I think they go very well together.

Friday, April 24, 2009

Attributes Can’t Be Generic

This is a bit of a bummer.  Attributes can’t have generic arguments.  IE,

public class InputAttribute<T> : Attribute
{
}
is not legal, and fails to compile with the message, “A generic type cannot derive from 'Attribute' because it is an attribute class.”  What stinks about this is that it means there is no way to add generic type requirements to a generic attribute, such as where T : ISomeInterface.  And that’s a bummer, because I’d like to be able to strongly type a type argument of a generic, instead of leaving it up the consumer to do the right thing.  In other words, change this:
public class InputAttribute : Attribute
{
public InputAttribute(Type inputType)
{
...
}
}
…into this…
public class InputAttribute<T> : Attribute where T : ISomeInterface
{
}
But alas, this is not possible.  Back to the drawing board I guess…there must be a better way.

Tuesday, April 21, 2009

Never Again

One of the coolest things about working at Microsoft is having a chance to work with the latest stuff long before the rest of the world.  Case in point: I’ve been using Visual Studio 2010 on Windows 7 for the last three months – years before anybody else.  It’s an exciting place to be.

But of course, one of the difficulties with using pre-beta software is its propensity for bugs.  And that means, lots of re-imaging.  And re-imaging is a pain.

But not any more.  For whatever reason, I never seemed to bother with the backup and restore functionality that comes with Windows.  Until now, that is.  And I will never again re-install from scratch, knowing how easy it is to restore your machine from a spare disk.

Really, what used to take hours now takes no more than 20 minutes – and it just couldn’t be any easier to do.  I will never, ever re-image from scratch any more.  Why didn’t I try this earlier?

Thursday, April 16, 2009

Designing for Testability

Is it really asking a lot to ask people to make their API’s testable?  It’s so discouraging to me that simple things like service references are 100’s of times harder to test because there is no way to generate them with virtual methods.  So while you can add a command-line flag to svcutil.exe to have it implement INotifyPropertyChanged, you can’t do something simpler like asking it to make all of it’s methods and properties virtual.  And if you can make them virtual, you can test them a lot easier.

And the list of difficult-to-test APIs goes on.  Winforms, the WPF, and my new target of frustration, the Tfs client.  Not only does the VersionControlServer class lack a single virtual method, but it’s also sealed.  Man.  I suppose the problem with not making methods virtual by default (a la Java) is that nobody will do it unless prompted to.  But making your methods virtual is the easiest way to ensure that people can write unit tests that interact with your API.  I’m all for encapsulation, but I also want API’s that I can test against without actually invoking them.

I feel like I’m always fighting against the tide to promote testable APIs, and it’s very frustrating.

Thursday, April 9, 2009

There Has To Be a Better Way

Is there anything more aggravating than writing MSI’s?  There’s simply no easy way to run and test them, and the documentation on MSDN is beyond poor.  For instance, say you want to write a custom action that does something based on the location where your product was installed.  How do you get the installation directory in your installer?  If you check the documentation on MSDN, you’ll spin your wheels for hours and come up empty handed.  And since you can’t debug MSI’s, you’re left to doing horrible things like this to find out which string you need to hard code into your installer in order to find the right property in the Context.Parameters dictionary:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Configuration;
using System.Configuration.Install;

namespace MyInstallers
{
    [RunInstaller(true)]
    public class SetupCustomAction : Installer
    {
        public SetupCustomAction()
        {
        }

        protected override void OnAfterInstall(IDictionary savedState)
        {
            foreach (DictionaryEntry entry in this.Context.Parameters)
            {
                // Can you believe this nonsense?!
                System.Windows.Forms.MessageBox.Show(entry.Key + "=" + entry.Value);
            }

            base.OnAfterInstall(savedState);
        }

    }
}

My Lord is this terrible.  Can you believe this is what I had to find the answer to my simple question?  How else are you supposed to figure out that this.Context.Parameters[“assemblypath”] is what you’re looking for?  If anybody has a better way, please let me know.

Tuesday, April 7, 2009

Overriding / Extending Internal Classes With Reflection.Emit

If you have an internal class:

internal class InternalClass
{
    internal InternalClass()
    {
    }

    protected internal virtual void Test()
    {
    }
}

and you want to override it, the compiler will check to make sure you don’t make the subclasses more accessible than the base class:

public class InternalClassSubclass : InternalClass
{
  // Won't compile!
  // Inconsistent accessibility: base class InternalClass' is less accessible than class 'InternalClassSubclass'
}

But in yet another example of the trickery you can do with Reflection.Emit, you can happily create a subclass of InternalClass and make it public without any problems.  You can also, in fact, override the Test method with a public method and invoke it without any trouble. 

Is this a problem?  I suppose not really.  You can always, for instance, invoke whatever you want using Reflection – so I suppose there’s no harm in being able to do this too.  It certainly makes it a bit easier to generating code since you don’t need to check the visibility of whatever it is you’re overriding.  The only thing you really need to look out for is sealed classes – those you can’t subclass, no matter what.

But it does make you wonder what good visibility checks are if they only happen at compile time.  What good is that if people can come in and invoke whatever they want at runtime?