Friday, January 30, 2009

Fact about Pizza.

I find this test as amusing as it's silly:
#light

open Pencil.Unit

Fact "Pizza should have cheese."
    ("Pizza" |> Should (Contain "Cheese"))
And the output:
Pizza should have cheese. Failed with "Pizza" doesn't contain "Cheese".

Craftmanship over Crap

Uncle Bob makes a compelling case for adding one more value to the Agile Manifesto, initially and for effect it was "Craftmanship over Crap" he later changed it to the less dramatic "Craftmanship over Execution" and asked others if they could find an even better phrasing and many good points were raised, for the full story look here. I've been mulling over this a bit, looking at the proposals and in the meantime hoping that my green wristband will guide me, but then it struck me. The original formulation is from a clean code perspective absolutley perfect, with one minor detail. It's not Crap the word, it's CRAP the acronym, and that's a honest misstake. Let's look a bit closer CRAP is Coupled Redundant Arbitrary Duplication and in essence that's exectly the anti-thesis of clean code. The marvelous thing about it is that even the acronym in itself exhibits a distinctly CRAP quality. Coupled because it doesn't make sense without the other parts. Redundant because it duplicates what crap is. Arbitrary since it could be something else. Duplication is redundant.

Tuesday, January 27, 2009

Minimal Unit Tests in F#

It's easy to get caught up in always building bigger, cooler more complex thingmajigs. Sometimes we forget our roots, take Unit Testing for exmaple, there's numerous frameworks and doodahs to facilitate that, but how slim and still provide value could it be. Over a cup of hot cacao I decided to find out. Here's the result:
#light

namespace Pencil.Unit

open System
open System.Diagnostics
open System.Collections.Generic

type IMatcher =
    abstract Match<'a> : 'a -> 'a -> bool
    abstract Format<'a> : 'a -> 'a -> string

module Unit =
    let (|>) x f = let r = f x in r |> ignore; r //work-around for broken debug info.
    let mutable Count = 0
    let Errors = List<String>()
    let Should (matcher:IMatcher) = fun e a ->
        Count <- Count + 1
        if matcher.Match e a then
            Console.Write('.')
        else
            let frame = StackTrace(true).GetFrame(1)
            let trace = String.Format(" ({0}({1}))",
                frame.GetFileName(),
                frame.GetFileLineNumber())
            Console.Write('F')
            Errors.Add((matcher.Format e a) + trace)

    let Equal = {
        new IMatcher with
            member x.Match e a = a.Equals(e)
            member x.Format e a =
                String.Format("Expected:{0}, Actual:{1}", e, a)}
open Unit
//Tests goes here
2 * 4 |> Should Equal 8
2 + 1 |> Should Equal 2

//Report the result
Console.WriteLine("{2}{2}{0} tests run, {1} failed.", Count, Errors.Count, Environment.NewLine)
if Errors.Count <> 0 then
    Errors |> Seq.iter
        (fun e -> Console.WriteLine("{0}", e))
And the output from the above:
.F

2 tests run, 1 failed.
(Expected:2, Actual:3 (F:\Pencil.Unit.fs(34))
Less than 40 lines of F# and we're on our way to unit testing goodness.

Monday, January 26, 2009

Why done should be "in use".

Done. Funny word that. When is something done? Is it when it's checked into version control? When is passes all our autmated acceptance tests? When QA says so? Or is it when we got real users deriving value from it? I would say the later based upon this simple observation. As a user theese things are all equal: * Feature not implemented. * Feature not deployed. * Don't know about the feature. * Can't find the feature. The implication is that unless we figure out how to build, deploy and educate users we simply haven't delivered busniess value. Scary isn't it?

Thursday, January 15, 2009

Falling into the pit of success, by design.

Jeff doesn't care about resource cleanups. And I can agree to some part,but the problem is that his solution "forget it and write an article making fun of overzealous disposers" seems a bit, well, short sighted. The thing is that I agree on the point that it's silly that our best mainstream "solution" to disposal thusfar is "using". Now, come on the best we could do was invent sugar so that our try finally blocks looks prettier? Let us have a quick look at the problem using File instead of SqlConnections, the semantics are the same but it's possible to illustrate something that people actually do with fewer lines using it. It seems that Jeff thinks that we should be fine with doing this:
public void JeffIsWingingIt()
{
    var target = File.CreateText("output.file");
    target.WriteLine("Very important stuff.");
}
The sad part here is that code like this often *seems* to be working but in reality quite often you'll end up with truncated output and a long hunt to find the responsible party. So the correct version looks like this:
public void CorrectButNoFun()
{
    using(var target = File.CreateText("output.file2"))
        target.WriteLine("Very important stuff.");
}
Sadly that not at all as appealing, but at least we get all the data written to disk and the file handle reclaimed in an orderly matter. But I would say the API is to blame in this case, it encourages us to do the wrong thing (forgetting to Dispose when done). There's quite easy to fix this and make it like this instead.
public void DesignedForSuccess()
{
    FileUtil.Write("output.file3",
        target => target.WriteLine("Very important stuff."));
}

static class FileUtil
{
    public static void Write(string path,
    Action<TextWriter> action)
    {
        using(var file = File.CreateText(path))
            action(file);
    }
}
Here resource handling and work are cleanly separated and abstracted. Using a similar approach you can easily and safely work with SqlConnection,SqlCommand,SqlDataReader and a huge varaity of other error prone but Disposable classes. Once and only once. Don't repeat yourself. It applies to resource handling to.

Fixing a bug, more than a local hack.

This is the true story of a bug, and the process of solving it. For reasons not relevant to the discussion I had the need to determine if a given 'Type' was part of the "System" namespace and hence could be considred a Framework type, it was deemed enough that just checking that the full name began with "System." was good enough for our purpose. The implementation is obvious and self-explanatory:
static bool IsFrameworkType(Type type)
{
        return type.FullName.StartsWith("System.");
}
Simple elegant and to the point. But since I said this was the story of a bug something went astray. The thing is that under certain quite arcane circumstances "Type.FullName" can return null, the details aren't really important, the problem is that the code above crashes with a NullReferenceException if that happens. And that's important for me since then I won't get to see the result of my program run. The quick, obvious fix is to check for null. As seen below:
static bool IsFrameworkType(Type type)
{
        var name = type.FullName;
        return name != null && name.StartsWith("System.");
}
And that's how the majority of bugs get "fixed", a local fix at the point of failiure, a pat on the back for a now passing test and away we dart to the next challange. And that I think is part of the problem why software takes so long. If we keep our local focus what can we do to both fix this bug and design safety in? We can reengineer our API to handle this gracefully. In languages with open classes we could fix our string API, in C# we have extension methods and if we work in an environment without them utility classes and free functions can aid us. So what's the root cause here? I would say that "StartsWith" is the culprit in this case. Because we know that we will have something to check against "System.", but we're not sure that we have a target for our StartsWith call. For this situation "System.".IsStartOf would make more sense, since that way we know that we have a instance to start with. Using extension methods we arrive at this:
static class StringExtensions
{
    public static bool IsStartOf(this string prefix, string s)
    {
            return s != null && s.StartsWith(prefix);
    }
}

static bool IsFrameworkType(Type type)
{
        return "System.".IsStartOf(type.FullName);
}
Hunting through the code-base I found a couple of other places where this could be used to solve similar problems. How often do you take this extra step to not only fix the problem locally but ponder if you can modify the API or system to prevent it from happening somewhere else? Make it part of your routine, and you're one "why" closer to a clean and productive code base. Further analysis also made it possible to ensure that all types that eventually got sent to this function indeed did have proper FullNames. But that's another story.

Saturday, January 10, 2009

How to write a good commit comment.

When using version control one common problem area are the dreaded commit comments. Most teams and individuals seems to gravitate towards simply not using them, wich is really sad. My best advice to remedy this situation is really really simple. Don't write your commit comment after you done your changes, write it *before* you start working, that way you already have it done when you're done, and you get the added benefit of clearly articulating what you're currently working on. As Stephen Covey puts it "Begin with the end in mind.", it's true for highly successfull people, it ought to be true for highly successfull programmers.

Thursday, January 8, 2009

Clean Code and Mom

If you've ever seen a code rot you know that few substances can so quickly go from shining examples of good to festering bug infested piles that everyone is affraid to touch. Why does this happen and what can we do to combat it?

There's much good advice out there for prevention, "Clean Code" by Robert C Martin is a good starting point and if things have already begun to stink have a look at Micheal Feathers "Working Effectivly Witch Legacy Code". They're well worth your time but since you're reading a blog Im guessing that right now you're searching for a quick snack.

It's quite easy to explain how we manage to get ourselves into this mess and basicly it's one portion human nature and an equal serving of wisdom from mom.

We follow examples.

As humans and developers we're extremly good at following examples, it's what we've evolved and trained to do. We learn to talk and behave by following the examples of our parents and peers, we aquire new skills by copying those who mastered them before us and we invent new ideas most of the time by missunderstanding something we set out to copy. Based on this it's deceptivly simple to conclude that in theory achiving and maintaining high code quality should simply be a matter of establishing a good set of practices and have people learn from and copy them. And as far as theory goes Im quite sure that it does actually hold true, apart from when it doesn't, and in practice that is most of the time.

Why does such a wonderull theory fail so miserably in practice? We could speculate that it's becuase we don't provide the right examples, or that people are ignorant of the wonderful code we've written and therefore doesn't emulate our flawless style. Or could it be that they simply lack the skill and aptitude for it? There's probably truth to be found in all of theese but I find it easier to lean on what mom used to tell me when I was little.

You become what you eat. Now before you dismiss me by saying that this actually reinforces the previous point (wich would be true) the underlying assumption in that dissmissal would be that we on average eat high quality code. If that was the case bad stinking code with wtf/minute ratios approaching positive infinity would not be a problem. Basicly I think the core problem is that most of the code we work with on a daily basis through maintenance and enhancement is the code that didn't work right! In any given codebase changes and work tend to cluster in the worst written, badly designed pockets of crap to ever compile and that's where we send our young and untrained. They come out of it producing sub-par code from the bad examples that have now ingrained their previously healthy minds, the examples they've seen are all terrible examples of what not to do. With experience we can learn to see the differance, we become hardened and learn that the code we see most often are the examples to not follow, we go on expiditions to find the code that have been working and elegantly solving our needs without us even realizing it was there, and we learn to emulate that.

So how does this answer the question how things can go so fast downhill? The answer is that on average people will produce code looking quite much what they last saw. Most of the code people see is horrible that's why they're staring at it. As the amount of bad code increases so does the probability of seeing bad code.

How to break the cycle is left as an exercise for the reader.