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 ListlistAll() { ... } public List listBy(Name name) { ... } //Other methods that have a different responsibility } </pre> Step 1: Create a new class FooLists and make it accessible through FooService public class FooService { public FooLists lists() { return fooLists; } public ListlistAll() { ... } public List listBy(Name name) { ... } //Other methods that have a different responsibility } </pre> 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 ListlistAll() { return fooLists.listAll(); }</strong> public List listBy(Name name) { ... } //Other methods that have a different responsibility } </pre> 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...
- Software Quality for Developers Learn about software quality, TDD, ... in this 6-part video course.
- Simplicity: Simplify. Then simplify more. And: Don't let the code become complicated in the first place.
- Developers testing their own code Some considerations about testing code
- It's about courage: About refactoring, and courage as an agile value in general
- Learn more about how I can help you save money and earn money by improving your agile software development process.