I used to work on a legacy project that was about ten years old. Let's say it's a common age for a legacy project. The team consisted of about eight to ten developers and due to the vast majority of them being contract workers the turnover was of less than 2 years. In this French company, to avoid troubles with labor laws, the maximum time a contract worker could be under contract is 2 years. This means that at least forty developers worked on this project. I haven't checked the versioning history, but there could have been probably sixty different developers on the project.
As you can probably guess, the project has, as most legacy project do, an issue with technical debt. Or to put it in the words of Arnaud Lemaire :
There have been some attempts as to clean code. Clean code was only a concern after an incident of some kind, whether it be a critical bug, a production deployment gone wrong, you name it, anything that spawns white hair on management.
To name a few, it started with a Sonar server, to statically analyze the quality of code. That worked really well. Critical bugs were fixed, security flaws were avoided, developers were sensitized on the matter. After a while, and the habit of plucking out bugs with Sonar, instead of solving minor bugs, we were introducing functional regressions. It happened several times until Sonar was blamed for it. Yes someone actually blamed the tool. Imagine a black-smith cursing on his hammer! After that, no-one really cared about fixing Sonar bugs any more.
There were some unit tests on the project, but only on critical parts. And on those critical parts, functionalities were not thoroughly tested. I can't really blame the developers on that part. Tests were not really encouraged as they were seen as a waste of time. Indeed, the functionality was coded and it was QA's job to actually assert that it was working as expected.
Since the team was not really convinced with keeping a clean code base, preferring quick wins and small patches, I convinced the team manager to have a one-day training with an external consultant on good practices. After all, as a member of the team, I had but little belief from the team on the subject. We found that Johan Martinsson did exactly that. The team loved the concept of TDD that he showed us. We then each sought out to refactor a complex part of the code using a Golden Master (remember how the project is poorly tested ?). It was interesting as some parts started to be less complicated and code disappeared too. But by the end of the day, the refactoring was far from being complete and got abandoned the next day.
Refactoring seemed in reach to many in the team, but the code being so rotten, even a small refactoring revealed of a challenge. An the Golden Master technique added a lot of overhead before actually refactoring. So we took shortcuts and with a smug and confident smirk did some bold refactorings. Needless to say that after a while, our card castle started to fall.
Our Product Owner was not getting the new stories and we were breaking existing behavior. As any other manager would, he dealt with the matter by making a decision and had everyone stick to it :
no more refactoring
Some developers on the team felt relieved to go back to the old way of working, back in their safe zone.
I tried to find out what refactoring really was to management. Is changing the name of a variable refactoring ? Yes. Is removing a line of existing code refactoring ? Yes. Is adding a new file refactoring ? No.
Some people in management were developers in a former life, which meant that they were able to make statements on things they sort of remembered from the days. This was going to be a tricky task! I tried as much as I could to avoid this definition of refactoring, but sometimes, the pragmatist in me though that this was nonsense and that we were focusing more on following a dumb rule and less on understanding the business value of our work.
How it ended
As I had no real power to change mentalities (remember, I'm an external consultant), after a while, I got the chance to work on a greenfield project and drive it technically. Those who stayed seemed contempt about it at first then eventually left.
So what did we do wrong ?
Let's take a step back. Fixing Sonar bugs is important as it reduces obvious bugs. But it's important not to introduce new bugs. This should be relatively safe in a unit-tested environment. Fixing Sonar bugs should be done automatically on trivial bugs, but only on tested code for less trivial bugs.
The same goes for refactoring. Martin Fowler recommends refactoring only on tested code. This is simple precept we did not follow.
Management interfered with how developers should do their job. That should not happen. Everyone on the team has its domain of expertise. If an expert is told by someone with another position/job on the team how to do his job, then he's not really an expert and should be replaced with this person. Let the experts do their job and be confident that they will do their best.