Smaller Steps

I always thought that I was doing my unit testing, programming and refactoring in small steps. But during the last year or so I learned that I was wrong. Dead wrong.

I have been interested in code quality and craftsmanship for some time now. The books I read and the people I talked to gave me the first hints that I should do my work in smaller steps. Then, at SoCraTes Conference 2012, I learned about the Taking Baby Steps exercise by Adrian Bolboaca. This showed me how small your steps could really be.

I still don't use the "Baby Steps" technique in my projects - I only use it as an exercise. But since I learned about it, I am trying to take smaller and smaller steps in my projects too.

An example would be handy right now

Today I was refactoring some code I wrote earlier. I had a class that did two things, and I wanted to pull some methods out into a new class. Then both classes would only do one thing and better adhere to the Single Responsibility Principle.

I have simplified the example a little bit. Anyway, the code was something like this:

public class FooService {
    public List listAll() {
        ...
    }
    public List listBy(Name name) {
        ...
    }

    //Other methods that have a different responsibility
}

Step 1: Create a new class FooLists and make it accessible through FooService

public class FooService {
    public FooLists lists() {
        return fooLists;
    }

    public List listAll() {
        ...
    }
    public List listBy(Name name) {
        ...
    }

    //Other methods that have a different responsibility
}

All tests are still green. Of course they are: I only added a new method.
Commit.

Step 2: Copy the two list... methods to FooLists.
All tests are still green. Of course, I only added new methods in a class that is not used yet.
Commit.

Step 3: Change listAll so it delegates to FooLists:

public class FooService {
    public FooLists lists() {
        return fooLists;
    }

    public List listAll() {
        return fooLists.listAll();
    }
    public List listBy(Name name) {
        ...
    }

    //Other methods that have a different responsibility
}

This was the first "real" change. All tests are still green. Phew.
Commit.

Step 4: Find all references of listAll(). Change the first to lists().listAll()
Run all the tests. They are still green.
Commit.

Step 5: Change all other references of listAll()
Run all the tests. They are still green.
Commit.

Step 6: Remove the method listAll() from FooService
Run all the tests. They are still green.
Commit.

Steps 7-n: Do the same for listBy(name). Run the tests after each step.

This was easy

This was really easy. I never had the feeling that I am on thin ice. I always could run "hg revert && hg purge" and only lose the work of a couple of minutes.

I am not yet sure if the end result is what I want. It is definitely better than before. But now there is this train wreck code like "fooService.lists().listAll()" in other parts of the system.

I think I know what I'll do next ;)

You might also be interested in...

Posting Type: 

My name is David Tanzer and I have been working as an independent software consultant since 2006. I help my clients to develop software right and to develop the right software by providing training, coaching and consultanting for teams and individuals.

Learn more...