As previously mentioned in this blog, our team is busy rewriting a complex application from Cobol to Perl.
While studying the old Cobol code, I often discover some areas where the initial design was well-thought and well-organized, but later became blurred and confused over 20 years of maintenance. So part of our analysis task is to do some archeology, trying to understand the historical layers, and to sort out what is still relevant to the current needs of our users.
Unfortunately, the same phenomenon also starts appearing in the Perl code ! Some parts were written two years ago, and then had to evolve for various reasons ... and sometimes the initial design becomes blurred in this process.
One may think that when this happens, it is because the initial design did not have the proper abstraction / parameterization hooks to make it easy to extend. But sometimes when doing the initial design of a component, you don't have a complete picture yet of what is going to surround that component ... or the requirements may have changed because this is a long-term project, and life doesn't stop while we are working on this application. So what is really needed to keep it clean is constant refactoring.
The problem is that maintenance operations do not have the same metrics : maintainers are evaluated by how many tickets they solved and how long it took; so there is a natural tendency to just "get it to work". Spending additional time on refactoring operations brings no immediate reward : users won't see a change, managers won't understand why you need to revisit code that was already written, and there is an additional risk of introducing regressions.
It's easy to understand that on a collective level there would be some rewards on the long-term (better maintainability, cleaner architecture, etc.) ... but on the long-term the maintainer will probably have gone to another project !