Archive for November, 2008

Programmers who write tests get more time to program

I became a programmer so that I could spend time creating software by programming. I don’t want to waste my time managing low-quality code.

Does your code work the first time your test it out? Mine certainly never does. So if I hand over the code to someone else, I’m sure to get a bug report back that will take up my valuable programming time. This much is obvious to most developers. However, it also means that I don’t want to have to go thought a long manual test myself to verify my code.

The first thing I do when I’m starting on a programming task is ask myself: “How am I going to test that this actually works?” I know it has to be done, I know it will take up a lot of my time if I do a poor job of it, so I want to get it right.

A good way to start is by writing tests before you write the code. The tests will specify the required behavior of the code. If you write the tests with the question: “How will I know when my task is complete?” The chances are that not only will your tests will be better for it, your design will also have improved.

I’ve come to code bases that were otherwise good, but that required me to write a lot of code to support my tests. In other words: The code was overly complex to use.

For example, a system that is built with an asynchronous chain of services connected via a message bus might require you to deploy your code before you can test it. I’ve redesigned such code in a couple of steps that progressively reduced the coupling, improved the cohesion, and simplified the testing of the code:

  1. Allow the code to be run synchronously and in-process by a configuration change. The messaging infrastructure is no longer coupled to the business logic. The resulting design is both easier to follow and more flexible, in addition to being easier to test. However, testing still requires setting up a long chain of services.
  2. Refactoring my services to calculate the result they send to the next service by using a transformation function made the responsibilities of different parts of the code clearer. And I could test almost all the logic by just calling this transformation function and checking the return value.

When encountering a programming task, ask yourself: “How can I test this?” If the answer is “Not very easily” try to write a test anyway. The test will probably require a lot of setup and it may be hard to verify the results. These are design problems, not test problems. Use the information from the testing process to refactor your system to a better design.

May you achieve fewer bugs and spend all your days programming happily in a well-designed system!

Improvements to this text are very welcome.

Comments

Er smidige målprisprosjekter mulig?

The Norwegian computing association has released guidelines for contracts regarding agile projects. Wednesday, November 26th I will be part of a panel debating this work and the combination of agile and contracts. This Norwegian language blog post contains my introductory remarks for the debate.

Kom på debatten på Oslo Lean Meetup på onsdag og delta på debatten!

Jeg er ikke en prosjektleder, en advokat eller en politikker, så jeg kan ikke si så mye om hva som må være med i en slik kontrakt. Jeg er bare en programmerer. Jeg er en programmerer som ønsker å jobbe på gode prosjekter. Jeg håper at det er mulig for meg å jobbe på gode prosjekter som også advokatene og politikerne vil være fornøyde med.

Hva er et godt prosjekt? Den enkle definisjonen er at et godt prosjekt er et prosjekt som både leverandøren og kunden, både utviklerne og brukerne er fornøyde med. For meg som programmerer er dette viktig. Og jeg tror det er viktig for mange andre programmerer. Hva er det som gjør at enkelte mennesker synes programmering er spennende? Jeg tror svaret er enkelt: Programmerer er mennesker som brenner for å skape ting som noen har bruk for.

Jeg ønsker å skape verdi, og for meg er smidige metoder en god rettesnor. Jeg tror ikke smidige metoder er et magisk ord man kan bruke for å få til vellykkede prosjekter, men jeg tror at verdiene smidige metoder beskriver forbedrer sjansene mine for å delta på gode prosjekter. Men bare dersom man forstår verdiene og ikke bare utfører tomme ritualer som man kaller “smidig”.

Jeg har jobbet noen år som programmerer. Og jeg har deltatt både på prosjekter jeg var fornøyd med og på prosjekter som jeg ikke var fornøyd med. Den triste sannheten er at de fleste prosjektene jeg har sett eller deltatt på var ikke gode prosjekter.

Derfor var det veldig spennende for meg når jeg først fikk høre om veillederen. Spørsmålet jeg håper veilederen kan svare på: Er det mulig å forbedre sjansen for at leveranseprosjekter blir gode leveranseprosjekter? Kan veilederen forbedre sjansen for at prosjektene våre blir gode prosjekter?

Jeg har lest gjennom det som har blitt skrevet med en blanding av håp og skrekk. Mitt svar er “jeg vet ikke”.

Men jeg er skeptisk. Det virker som om smidige metoder, som mye annet, er i ferd meg å bli et offer for sin egen suksess. Kan vi risikere å falle i fella at vi tror at fordi vi bruker ord som Product Owner og ScrumMaster og Sprint og Product Backlog så vil alt bli bedre av seg selv?

Det er lett å si “smidig”, men det er ikke alltid lett å gjøre smidig. Så for å forstå hva smidige metoder dreier seg om, gikk jeg tilbake til kilden.

Jeg bladde opp på http://agilemanifesto.org. De smidige verdiene er kjent for de fleste nå. De står på forsiden. Men det ser ut som om mange overser den første linken herfra. Den går til de tolv smidige prinsippene. Jeg har valgt ut tre for dere:

“Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.”

“Simplicity–the art of maximizing the amount of work not done–is essential.”

“Welcome changing requirements, even late in development. Agile processes harness change for the customer’s competitive advantage.”

Det jeg har fått ut av smidighet, er erkjennelsen om at vi ikke kan anta perfekt informasjon. Vi er nødt til å få feedback på det vi tror og det vi gjør, og vi er nødt til å endre planene basert på denne feedbacken. Denne grunnleggende verdien ligger bak ønsket om hyppige leveranser og mye annet.

Så jeg står igjen med et siste spørsmål: Er det mulig å lage en leveransekontrakt som verdsetter denne dype verdien om feedback? Det håper jeg å få svar på i denne debatten.

Comments

An informative workplace

Agile software development has learned about informative workplaces and stop-the-line quality management from lean manufacturing systems. Here are my implementations of it at my last project:

All is well

This video shows how our project looked when all is well.

The large green light in the front shows the status of our build server. The green flashing lights show the status of our staging and production server.

For the production server, the frequency of green blinks indicates the load of the system for the last 10 minutes relative in % to highest load ever observed. The occasional yellow blink shows the frequency of user errors. In our case, this usually means that a user has submitted an invalid file. The frequency is also calibrated to the highest load ever observed. This means that the relative frequency of yellow and green blinks is correct.

The staging server gets a copy of the production traffic, but delayed by a few minutes. It runs the next version to be released of the software.

If the light blinks red, there is a bug or operations problem. I think. The thing is: The red light for the production and even staging servers hardly ever has a red light. Why? Because we weed out all the problems earlier in the process.

Fixing errors at the earliest possible time

The build light is key. When we check in code, it tries to build the code and run tests for it:

If an error was introduced, the light turns red within 20 minutes.

This process was good enough to catch the large majority of the defects the team ever introduced. To catch the next batch, we introduced an automated test that ran real production data over a fully installed system after every build. Sadly, we didn’t find a good way to monitor this.

The technical details

The lamps were purchased from Delcom Products Inc. At $90 a pop, they are pretty expensive, but they are the only option we’ve found that will let you control lights directly using the USB port.

Delcom ships the lights with a driver as a DLL (an open source Linux driver is available, but I’ve never tried it). We wrote a wrapper in Ruby using the Win32API Ruby package. We added a nice set of classes that let us write things like visual_indicators[2].red.blink(12, 24) to have the 3rd lamp’s red led stay on for 12/100 second and off for 24/100 second.

The status polling was done over http. We had dedicated rules in the frontend web server to let the polling probe into the staging and production servers. These servers implemented the status as a servlet that would return something like red flash 10%; yellow off; green solid. The most challenging part on the Ruby-side was converting 10% frequency flashes into meaningful on and off values for the blinks. The server would look at it’s work queue items (it was a batch server) for the last ten minutes to determine the status.

The build server was originally implemented using hudson. We found it difficult to distinguish building from error (red blinks) from building from ok (green blinks). This eventually led me to implement a 100-line Ruby script as our build server. The script would be triggered from cron every minute and if there was no other build going on (determined by a lock file) and the Subversion repository had been changed since the last build, but more than 3 minutes ago, it would start a build.

The lamp would get the build status by polling static files exposed over HTTP with Apache httpd.

An eye towards excellence

Seeing the status of the testing, staging and production environments gave us confidence that the systems were working. It also gave us a greater understanding of the problems of the operations people who have to take over responsibility for the solution at some time.

Towards the end of the project, putting new software into production each iteration after one week in staging seemed more and more feasible from a technical point of view. We didn’t quite get there before I had to leave the project, but it was a goal worth striving for.


Comments

Making FitNesse Maven friendly (now with Slim)

Regular readers of my blog may remember that I’ve researched how to get the classpath from the FitNesse-process inherited by the Fit process that FitNesse spawns when it runs a test. This trick is an easy way to get around having to specify classpath variables in your FitNesse tests. This blogposts provides an easier way, plus compatibility with the new Slim testrunner in FitNesse.

This is the basic process:

  1. Create a Maven project with a dependency on your System Under Test in addition to FitNesse.
  2. Insert a few bootstrap files and classes into the project (to be explained)
  3. Start fitnesse.FitNesse as a main class in the project
  4. All classes in the project and its dependencies will now be available in Fixture classes

This article uses the 20081115 version of FitNesse, which is not yet in the Maven repository. To get it yourself, download it from the FitNesse website.

The problem

Fixing the classpath is exceedingly simple. But you need to understand a bit of the inner workings of FitNesse to get it to work. When you press the “test” button on a test, or the suite button on a test suite, FitNesse instantiates a class based on the registered “responder”. Our first order of business is to override this, but in order to do that, we need to take control over FitNesse.

You can do this by adding fitnesse.jar and fitlibrary.jar to your classpath, either manually in Eclipse, or by using a Maven dependency on org.fitnesse:fitnesse and org.fitnesse:fitlibrary.

Once FitNesse is in you IDE’s classpath, you can run the Java class “fitnesse.FitNesse”. This starts FitNesse on port 80. Navigate to, say “http://localhost/MyFirstTest”, and you’re ready to add a test.

In order to get it to work, though, you will have to do something like the following:


!path target/classes
!path /.m2/repository/org/fitnesse/fitnesse/20060719/fitnesse-20060719.jar
!path /.m2/repository/org/fitnesse/fitlibrary/20060719/fitlibrary-20060719.jar

!|my.test.ExampleFixture|
|first|second|sum?|product?|
|10|10|20|100|
|1|0|1|0|
|10000|1|10001|10000|

Ugh! Bad FitNesse!

The solution

What actually happens when you press “test” is that FitNesse creates and executes a Responder class. You can override a responder by adding a file called plugins.properties to the current working directory. Here is an example of such a file:


Responders = test:com.brodwall.fitnesse.InheritClasspathTestResponder

As you can see, I replace the test-responder with my own subclass. Here is the code of the InheritClasspathTestResponder for the very latest version of FitNesse:

public class InheritClasspathTestResponder extends TestResponder {
 
    private static final String PATH_SEPARATOR = System.getProperty("path.separator");
 
    /** For FitNesse 20081115 and later */
    @Override
    protected String buildClassPath() throws Exception {
        return super.buildClassPath() + PATH_SEPARATOR + getInheritedClassPath();
    }
 
    protected String getInheritedClassPath() {
        String inheritedClasspath = "";
        String parentClassPath = System.getProperty("java.class.path");
        String[] classPathElements = parentClassPath.split(PATH_SEPARATOR);
        for (String element : classPathElements) {
            inheritedClasspath += PATH_SEPARATOR + "\"" + element + "\"";
        }
        return inheritedClasspath;
    }
}

For older versions of FitNesse, you can instead override the buildCommand method as follows:

/** For FitNesse 20080812 and earlier */
protected String buildCommand(PageData data, String program,
                String classPath) throws Exception {
    return super.buildCommand(data, program, classPath + getInheritedClassPath());
}

This works both with both the original Fit test runner and the new Slim test runner. To try it out with a Slim runner, insert the following into a test page:


!define TEST_SYSTEM {slim}

(Notice that Uncle Bob’s article introducting Slim mistakenly !defines TEST_RUNNER. The correct variable is TEST_SYSTEM)

Debugging

In my original experiment, I also managed to get debugging support for FitNesse. This is how it works:

  1. After running a test, replace the part ?test in the URL with ?debug. The page will look like it’s hanging while the server is waiting for the debugger.
  2. In your IDE, attach a remote debugger to the Fit-process.
  3. You can now debug your code just as normal

This turned out to be a lot harder with the newest version of FitNesse. To support Slim, this version introduces the concept of TestSystem classes, of which there are two implementations, FitTestSystem and SlimTestSystem. These classes build up the (Java) command line to execute the test runner.

As of the current version of FitNesse, there is no plugin point to put new implementations of TestSystem, so I had to change TestResponder implementation of performExecution quite a bit. The original has some caching and other freaky stuff which I finally gave up trying to override. Sadly, my implementation only works for Slim. For some reason, overriding FitTestSystem#buildCommand causes FitNesse to hang. So: Use at your own risk.

To install the code, you have to modify the plugins.properties file described above:


Responders = test:com.brodwall.fitnesse.InheritClasspathTestResponder, \
debug:com.brodwall.fitnesse.DebugTestResponder

Here is the awful implementation of DebugTestResponder. I’ll see if I can get changes implemented in FitNesse to make it easier.

public class DebugTestResponder extends InheritClasspathTestResponder {
    private static final String PATH_SEPARATOR = System.getProperty("path.separator");
 
    private static final int DEBUG_PORT = 1044;
 
    @Override
    protected void performExecution() throws Exception {
        TestSystem testSystem = createTestSystem();
 
        // The following line is the correct behavior,
        //  but TestResponder.fastTest is private :-(
        //testSystem.setFastTest(fastTest);
        testSystem.setFastTest(false);
        testSystem.getExecutionLog(classPath, TestSystem.getTestRunner(data));
        testSystem.start();
 
        if (testSystem.isSuccessfullyStarted()) {
            addToResponse(HtmlUtil.getHtmlOfInheritedPage("PageHeader", page));
            SetupTeardownIncluder.includeInto(data, true);
            if (data.getContent().length() == 0)
                response.add(formatter.messageForBlankHtml());
            testSystem.sendPageData(data);
            testSystemGroup.bye();
        }
    }
 
    private TestSystem createTestSystem() throws Exception {
        String testSystemName = TestSystem.getTestSystemName(data);
        if ("slim".equalsIgnoreCase(TestSystem.getTestSystemType(testSystemName))) {
            return new SlimTestSystem(page, this) {
                @Override
                protected String buildCommand(String program, String classPath) throws Exception {
                    return DebugTestResponder.this.buildCommand(program, classPath);
                }
            };
        } else {
            // For some reason, overriding FitTestSystem.buildCommand causes FitNesse to hang
            return new FitTestSystem(context, page, this);
        }
    }
 
 
    protected String buildCommand(String program, String classPath) throws Exception {
        String debugOptions = "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address="
                        + DEBUG_PORT;
        return "java " + debugOptions + " " + "-cp " + classPath + PATH_SEPARATOR
                        + getInheritedClassPath() + " " + program;
    }
 
 
}

In conclusion

It is possibly, you could even say easy, to make Maven and FitNesse play nice. The trick with InheritClasspathTestResponder shows how you can stop maintaining the FitNesse classpath separate from the Maven classpath, which makes FitNesse into just another main-class in your system.

Sadly, the structure around the new TestSystem classes needs a little improvement to support debugging.

Comments

What you didn’t think you needed to know about hashCode and equals

This article is a repost of my comments to the question on how to implement hashCode and equals on stackoverflow

There are some issues worth noticing if you’re implementing hashCode and equals for classes that are persisted using an Object-Relationship Mapper (ORM) like Hibernate. If you didn’t think this topic is stupidly overcomplicated already!

Lazy loaded objects are subclasses

If your objects are persisted using an ORM, in many cases you will be dealing with dynamic proxies to avoid loading object too early from the data store. These proxies are implemented as subclasses of your own class. This means that the commonly recommended this.getClass() == o.getClass() will return false. For example:

Person saved = new Person("John Doe");
Long key = dao.save(saved);
dao.flush();
Person retrieved = dao.retrieve(key);
saved.getClass().equals(retrieved.getClass());
    // Will return false if Person is loaded lazy

If you’re dealing with an ORM using o instanceof Person is the only thing that will behave correctly.

Lazy loaded objects have null-fields

ORMs usually use the getters to force loading of lazy loaded objects. This means that person.name will be null if person is lazy loaded, even after person.getName() forces loading and returns “John Doe”. In my experience, this crops up often in hashCode and equals.

If you’re dealing with an ORM, make sure to always use getters, and never field references in hashCode and equals.

Saving an object will change it’s state

Persistent objects often use a id field to hold the key of the object. This field will be automatically updated when an object is first saved. Don’t use an id field in hashCode. But you can use it in equals.

A pattern I often use is

if (this.getId() == null) {
    return this == other;
} else {
    return this.getId() == other.getId();
}

But: You cannot include getId() in hashCode(). If you do, when an object is persisted, it’s hashCode changes. If the object is in a HashSet, you’ll “never” find it again.

In my Person example, I probably would use getName() for hashCode and getId() plus getName() (just for paranoia) for equals. It’s okay if there are some risk of “collisions” for hashCode, but never okay for equals.

hashCode should use the non-changing subset of properties from equals

Comments

Toyota Kyushu - En produksjonsballett

This is a rough Norwegian language translation of the article JKE Day 1: Toyota Kyushu - The Manufacturing Ballet by Kevin Meyer (improvements on the language are very welcome, comments on the contents should go to Kevin). The reproduction has been authorized by the author. Unlike the rest of my site, this article is not available under creative commons license.

Jeg kom over en artikkel som demonstrerte hvor bemerkelsesverdig lean production system kan være. Den var så spennende at jeg bestemte meg for å oversette den til norsk:

Read the rest of this entry »

Comments

Creative Commons Attribution 3.0 Unported
Creative Commons Attribution 3.0 Unported