2009-10-15

Same old tale (about code quality and technical dept)

Yesterday, we had yet another great Agile Skåne meeting at Green Lion Inn in Malmö.

One of the members is right now experiencing how much bad code can hurt you.

His new employer went to the lowest bidder without any quality control for many years, and have ended up with a total mess, prohibiting them to add features their competitors offer, and hence can’t improve their market share.

How come this serious mistake is made over and over again? After all it’s common knowledge that quality makes you fast and able to respond to change in the long run. (I know, we’re irrational human beings…)

I don’t know if it’s true, but I want it to be:

“Quality is the best business plan.” – Pixar’s John Lasseter

At least, you can’t blame Pixar for not being successful…

More on the subject:

Fowler recently wrote an interesting piece on technical dept: http://martinfowler.com/bliki/TechnicalDebtQuadrant.html

There’s a book on the subject of not acting according to what’s known to work:
”The Knowing-Doing Gap” (ISBN 1422163520), which I haven’t read.

2009-10-07

Decreased changeability when TDD:ing, and a possible solution

Yesterday, we had a great alt.net øresund meeting at BestBrains in København. Sune held a great presentation about TDD, its pros, and cons. Actually, despite being a TDD fan and user, Sune is very insightful and realizes that TDD isn’t a silver bullet. It could actually decrease your changeability if done wrong for example.

I’ve personally experienced some of the pains Sune described and that we discussed during the open space session that followed. Actually, previously the very same day Martin N Jensen and I tried to start attacking some of them by complementing our TDD efforts with a BDD way of defining higher level requirements in the form of stories and scenarios.

During the bicycle/train ride home, i thought some more about these issues. Only two days before I had to fix a lot of tests that utilized mocking/stubbing when an API changed that didn’t affect the system behavior in any way. That got me thinking – what the frak am I doing?!? No business value in that activity…

My not-IRL-tested idea goes something like this:

You have two sets of unit tests.

  • Stable BDD tests that drives the SUT (System Under Test) by only looking at the highest level of state (i.e. the database), performs an action, and then verifies the resulting state/output on the highest possible level. These tests corresponds one-to-one with the requirements if using stories as requirements
  • Instable “classic” TDD tests that drives the design of the inner workings (classes and their interactions, individual methods, etc.) of the SUT

My idea definitely requires UFD (UpFront Design) more according to the lean way of developing software as opposed to some agile start-immediately approaches.

If you start with a set of fairly stable stories, and implement them as BDD tests in one way or another (we’re using StoryQ at the moment), you consider these tests as stable meaning it should require some thinking before changing them.

The much more fragile TDD tests are considered something that could be thrown away (likely in parallel with writing new ones), or rewritten if still needed, when the inner workings are refactored (e.g. when replacing Castle Active Record with Frog.Net Sune, or in my case when removing specialized repositories in favor of one generic the other day).

I feel that if I have my stories implemented as executable acceptance tests, then I would really get

  • true confidence when undertaking big refactorings
  • tests that could actually be read and understood by peers, and possibly some other stakeholders
  • regression test suite that verifies the SUT’s behavior, i.e. that the stakeholders get what’s agreed upon

As a potential benefit I also get extremely readable status reports of every story on e.g. the build server every time an ok commit is made. This is a huge benefit IMHO since it allows you to remove the possible need for a complex task tracking system but still gives your PM (and all others) complete real-time status, allowing you to work with a whiteboard and post-its as a kanban board.

2009-10-02

Programmatically configure Log4net with two rolling file appenders

public static class LogBootstrapper
{
    public static void Bootstrap()
    {
        RootLogger.AddAppender(CreateRollingFileAppender(Level.All));
        RootLogger.AddAppender(CreateRollingFileAppender(Level.Info));
        RootLogger.Repository.Configured = true;
    }

    private static Logger RootLogger
    {
        get { return ((Hierarchy)LogManager.GetRepository()).Root; }
    }

    private static RollingFileAppender CreateRollingFileAppender(Level level)
    {
        var usingFileName = string.Format("logs\\MyProject_{0}-{1}-{2}_{3}.log",
        DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, level.Name);
        var layout = new PatternLayout("[%level] %message%newline");
        var rollingFileAppender = new RollingFileAppender
        {
            Layout = layout,
            AppendToFile = true,
            RollingStyle = RollingFileAppender.RollingMode.Date,
            File = usingFileName,
            ImmediateFlush = true,
            Threshold = level
        };
        rollingFileAppender.ActivateOptions();

        return rollingFileAppender;
    }
}

Beats XML config IMHO.