A developer joining a project, unless the project is starting a completely new application, will be working with dreaded “legacy code.” The process of becoming productive in a legacy codebase can be a nightmare. Legacy code has earned its reputation for being poorly structured, hard to work with, undocumented, and obscure. You’ll see evidence in the code of the different programming styles of all the developers who ever worked on that legacy codebase.
Complicating this reality is the fact that legacy code is live. Any improvements you want to make need to be incremental because, by definition, legacy code already has users. Users expect zero downtime, fast response times, and a consistent look and feel. Users expect a seamless surface and experience, and they have no idea how messy things can be underneath the interface they use.
Often legacy code is dependent on languages or hardware that is now obsolete. The code has probably been written poorly and is difficult to understand. The previous programmers are unlikely to be available to answer any questions. You’ll have a hard time understanding what they were thinking and why they chose to write their code the way they did.
When developers are programming under the usual time and budget pressures, they tend to build up technical debt. This debt may be caused by poor coding practices or by the desire to get things done quickly, but even the most careful developers can’t predict how their code will be used and extended in the future. It’s hard to develop a single feature or fix one bug while still considering the overall design of the application, especially when you’re new to the project. Over time the code gets inconsistent. Different components are developed in different ways.
But imagine if that wasn’t the case. Imagine joining a project with a codebase where you can’t see the tracks of the many different developers who built it. Imagine if, for example, all the text or date-handling routines were neatly isolated into one utility file used consistently throughout the application. Imagine if legacy code was like other legacies in our lives—like the antiques, heirlooms, and stories that are cherished and lovingly passed down from one generation to the next. What if legacy code was something we took pride in?
We usually think about legacies when we’re on the receiving end, but how would our code change if we remembered that at every step in our programming career we are creating a legacy for the developers who follow us?
An example is a recent project here at 8th Light that has treated its code this way. Every person on our team sticks to the same conventions so the architecture and naming are as consistent and predictable as possible throughout the application. Because we’re all doing things the same way we can more easily understand, modify, and extend our codebase as the customer’s requirements change.
Recently a developer new to the project submitted a pull request for a new feature. It worked well and the code was quite good but we asked him to change half a dozen things to follow conventions more closely anyway. The feature took a bit more time to complete because of this extra development step but the code is now more consistent and easier for us and future developers on the project to understand and extend.
This particular project has had many different developers contribute to the codebase in the year since we started work. Since we have been careful throughout to build the code in a consistent and well-structured way, our code is more intuitive and coherent and we can be sure that developers who join the team later will have an easier time onboarding. Every developer who has joined the team has left behind legacy code for those who follow.