Many codebases suffer from an accumulation of technical debt -- small sub-optimal fixes and tactical decisions. Each of these probably made sense at the time, and we always intend to come back and fix them, but somehow never have time. Ratcheting is one technique that may help to address this problem.
You are on a large codebase in a large team. The codebase hase been around for a while, and as always in these cases, has accumlated some technical debt. These are mostly simple things that would be easy to fix, but there are so may of them that it can be hard to see where to start. And since you are busy releasing new versions and working on new features, it is hard to find the time to just work on these trivial things.
But just leaving them is bad too - since this lead to an acceleration of problems. If there are 100 warnings, then 101 is not so bad, is it? If there are already 30 ignored tests, does it really matter if I ignore this test? These are the sort of simple day to day compromises that lead to a long term deterioration in code.
This is the boiling frog syndrome -- where a small incremental change is not noticeable but over a long period of time there is a significant change.
Another example is build time. Over time our builds tend to get longer, and while today's build may only be a second or two slower than yesterday's, over a year or longer we may be looking at significantly slower builds.
Avoiding this is one problem. Another is fixing it when it has occurred, but you can't take the development process offline to just fix the technical debt.
It is easy to say 'the build should be no longer than 10 minutes' but what do you do if it is currently 20 minutes? What do you do if you have hundreds of build warnings, or FxCop reports thousands of (mostly trivial) problems?
A ratchet is defined as "a ratchet is a device that allows linear or rotary motion in only one direction, while preventing motion in the opposite direction." -- Wikipedia
What we are trying on our project is a software version of the ratchet. The approach is fairly simple, and consists of the following steps:
Identify a problem -- Choose one of the issues that you have, and find a way of reducing it to a number. Examples are build time, the number of ignored tests, the number of enums, switch statements, code coverage or pretty much whatever you can count.
Stop it getting worse -- This is the crucial piece. In every build, check the number, and compare it to the number in the previous build. If it is 'worse', then fail the build. Of course what 'worse' means differs for different metrics. Build time is worse if it goes up. Coverage is worse if it goes down.
Make it better (optional) -- In this step you fail the build if the number doesn't get better. I think of this as tightening the screws. I like to think of it as a reference to literally tightening loose screws on some kind of machine. But done badly it could be a reference to tightening thumbscrews to torture people. A tyrannical 'architect' doing this could kill team morale. On the other hand if the whole team agrees to it and chooses the thing to ratchet then it can be a positive reinforcement.
This means that every time someone checks in, they have to remove one of these items. It may be simple, as in fixing one build warning, or more complex, as in improving code coverage. It will affect productivity a bit, but only a little bit for each checkin. It makes sure that everyone takes responsibility for fixing the problems in the code. Done well, I think this can enhance the team.
Repeat -- There's a lot left to do. Choose another metric. Keep the previous ratchet in place, or you will lose the benefit.
Trying it out
On our current project, we have 85 'TODO' comments in the code. This is classic technical debt. Who knows if these are still valid? We have turned ratcheting of these on in our build to test the idea. With a team of 7 pairs, it should only take us a few days to get that to zero. I'll let you know how it goes...