Have you ever noticed that pretty much anyone, when looking at something for the first time, or joining a project or new effort, seems to always think it is a big mess? And probably needs fixing, perhaps even a complete throwaway and rewrite?
I have a running joke that I frequently use, along these lines. It goes: “I’ve never moved out of a house or apartment without cleaning it very thoroughly, and yet have the next person come in and insist it’s a complete messy disaster. Conversely, I’ve never moved into a new house or apartment without thinking that it’s a complete messy disaster, without the previous person insisting that they cleaned it very thoroughly.”
Taking over a legacy codebase, or joining a new project, can be a big undertaking. But before you prematurely exclaim, “This is all a mess!” and “We need to just redo everything!”, take the time to research and gather some information before you plan your next steps. Here are some ideas to think about.
Read and Study Before You Pass Judgement
“It’s harder to read code than to write it.” – https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/
One thing about projects, whatever the artifact, be it source code, a user story backlog, a set of accounting books, a pile of architecture diagrams, whatever, it’s a lot of information and it takes time to read it all, analyze it, absorb it, and then finally understand how it all connects and fits together. You’re looking at some if-block, wondering why it was there, not realizing it’s because there’s an edge case defect that didn’t come up until later in the test cycle. You’re looking at some user story that makes no sense, not realizing that there’s a potential risk documented in the risk register and this story is there as a mitigation. You’re wondering why the deposits into the account don’t correspond to the invoicing, not realizing that this one external vendor makes lump payments for different invoices and has a monthly dollar limit because of their information system so has to spread out their payments.
I have found that, when joining a new project, it is very easy for that first week to feel like the whole project is a chaotic mess. But as I continue to talk to people, review the artifacts, draw out my own diagrams on a whiteboard, I start to realize that actually, things are fine, there’s a backlog, there’s a plan, things are progressing just fine. The issue was just that I personally didn’t see the whole plan, so it was easier for me to just assume that since I didn’t know the plan, there must not be one.
Instead, give it some time to research and learn all the data. The codebase might be better than you realize, once you understand all the use cases, requirements, and design decisions.
Base Your Decision Upon Data, Not Intuition
Intuition is not bad, that’s your experience talking to you. But also be aware of potential “not invented here”-based bias. Take a look at the actual quantifiable data and factor that into your decision making. For example, try finding the answers to some of these questions:
- Is there a good requirements baseline, or set of user stories? Are they being met?
The true value of solutions and code is the value that it brings to the stakeholders. If the users’ requirements and needs are being met, and the code is accomplishing what it needs to do, then it has value. Yes, there may be technical debt or defects that need addressing, but if the application or product is in use and accomplishing something, then the builders accomplished that fundamental end goal, didn’t they? So be careful about the messaging you send to both the stakeholders and the developers. There are always opportunities to improve quality, but if the user stories are being met and the users are satisfied then if you proclaim things as “broken” you might come across as adversarial, self-serving, or even incompetent.
- Is there a unit/system test suite? Is it passing?
If there are tests written, and the system is passing all (or most) of the tests, then that means there’s a demonstrated level of quality that already exists. The whole point of those tests is to ensure that the code is performing correctly, so it is hard to make the case that the code is “bad” if the tests are passing.
Note that this also means making sure that the tests themselves are good. Do they cover all the use cases? Do they cover edge and bounds cases? Do they cover performance? Do they include quality and security cases, such as linters and static source code analysis tools?
- Are the developers or users experiencing any existing “pain”?
An important metric or data point is qualitatively ascertaining the different stakeholders’ satisfaction. Take the time to talk to both users and developers, and focus on the question, “How are things going right now? Are you satisfied or frustrated?”
If you’re joining a new project and most of the people involved think things are “going fine”, then if you come in and decry that things are not, then they are all going to look at you with some speculation and maybe even suspicion. You need to stop and ask yourself, what is everyone else seeing that I am not? (Fortunately, this question can be answered relatively easily with a conversation.) And also ask yourself, what am I seeing that no one else is? (This one can be harder to answer because it requires you to be self-critical and humble.)
Identify Technical Debt, But Don’t Mistake Style Differences for Defects
I will openly admit, I’m not much of a handyman. I can change my light bulbs and air conditioning air filters, but that’s about it. When my roof needs repairing, or my car’s brakes need to be changed, or my plumbing needs work, I usually just hire someone else to do it for me. And invariably, INVARIABLY, that person comes in, looks at the existing situation, and says the same thing, “Whoever did this before me did this all completely wrong. This is a complete mess.”
Source code is such a similar situation. Almost everyone, myself included, will look at a codebase and almost immediately exclaim, “Look at this mess! This is all just messed up. Who wrote this?” (The running gag is, of course, when it turns out that you wrote it, just a few years ago.)
I did some research into the handyman scenario, and I found some insightful answers from very experienced tradespersons. The answer tended towards, “well, it’s just not the way I would have done it.” And that is a very valid answer but one that requires that aforementioned humility. Identifying defects and quality issues is fine (i.e. “this module could be rewritten to perform faster”, or “these three code blocks are all copy-paste and do the same thing, so let’s make it a shared function”), but just take note and add those to the project backlog. Just because the developer before you used snake case (snake_case) instead of camel case (camelCase) does not mean the whole project is low-quality or needs to be rewritten from scratch.
Taking some time to do some analysis, and being legitimately humble and honest with yourself, can save a lot of time and effort because frequently finding a path to move the existing project forward is more effective than restarting the whole effort. So seek to understand, before you pass judgment.