[at http://mikadomethod.wordpress.com/ we will put more information on the Mikado Method]
A couple of years ago, Ola Ellnestam and I was working on a project where the code was a big ball of mud, or at least well on the way there. Global variables and singletons all across the code base, circular dependencies, deep and fragile inheritance hierarchies etc. The Technical Debt was everywhere.
All of a sudden we were supposed to deliver to a new client and the interest on our loan went through the roof. The reptile response from several developers on the team was to copy most parts of the code base to a new project and modify the code there. This would double our debt, but decrease the interest temporarily, until the next client would drop in. We fought with all we got to avoid doubling our debt and in the end we had convinced everybody that we could re-factor the code-base, just give us a week or two…
Our approach was that we should do what we needed to do, fix all the compiler errors, run all the tests, check-in, done. Yeah, right…
We did what we wanted to do, got about 20 compiler errors and started fixing them. When we were just about done, the compiler could move a step forward and showed us yet another bunch of errors. When trying to fix them we had to make new re-factorings, that in turn created new errors. So we went on, and every day on the daily stand-up we said that “We just have a couple more errors to fix, but we will probably be done today or tomorrow”. Yeah, right…
After more than two weeks of working like this, with 1200+ files checked out, 200+ compiler errors we had to face it. We would never make it. We were trying to behead the Software Hydra, but for every head we cut off two more grew out. We had to make the tough decision to revert everything we had done. But, as Tom Poppendieck always say: There is no failure but the failure to learn. And did we ever.
Go with the flow
We had realized that we had been walking with the refactoring dependencies, i.e. we tried to re-factor a part of the code that was depending on that another refactoring already had been done, which it hadn’t. If we could just walk with those dependencies, or prerequisites, until we reached a re-factoring that had no prerequisites, a leaf in the dependency graph, then we could just do that refactoring without any hassle. And by doing that, we would have fulfilled the prerequisites of another re-factoring that now had become a leaf, ready for execution. By doing so with all prerequisites, eventually our goal would be met!
The Mikado Graph and the Mikado Method
When we presented this method at SDC2009, Laurent Bossavit suggested that this dependency graph and dependent refactorings had great similarities with how the Mikado Game is played. In order to get to “The Emperor”, you cannot just pick-up that stick. First you have to pick up all the sticks that in some way is above that stick. We thought it was an excellent observation and we now call it The Mikado Method and the dependency graph is called The Mikado Graph, as suggested by Laurent.
The Naive Approach
In our real-world case, we drew the Mikado Graph on a whiteboard, step by step. To do that, you naively start with the thing you want to achieve and draw that on your Mikado Graph, typically a business goal. Try to implement that change. If that goes all well, you are done. Check-in. Congratulations!
In most cases, however, you end up with compiler errors or tests that don’t run. Examine the errors and failed test and come up with measures that would have prevented those errors or test failures. This is often other refactorings in the application. Those measures become sub-goals to you business goal. Draw them on the graph as well, with arrows pointing from the business goal to the sub-goals. Revert the code to the previous working version.
Now, for each of the sub-goals repeat the process by naively trying to achieve them. Draw the solutions to the new issues as new sub-goals, revert the code, attack new sub-goals and so on. In the end, you can actually implement a leaf sub-goal while the application still works. Great! You just got one step closer to achieve your business goal.
By doing the refactorings from the leaves and in the opposite direction of the dependency arrows, you will eventually achieve your set out business goal.