Always Add Value as a Software Engineer
Recently I had an engineer spend an entire day swapping out our unit test framework, all of our mocking code, and the test setup. At the end of the day, the code does the exact same thing, and it takes the same amount of code to setup and execute tests using the new framework.
My question: did the change add any value?
I would argue it didn’t.
What is adding value in software engineering?
- Refactoring code so that it’s easier to maintain.
- Adding code for new features.
- Fixing bugs by either adding or changing code.
- Building tools that make the rest of the team more productive – i.e. automating the release process.
You could argue that my developer fell into the first category: refactoring code so it’s easier to maintain.
But here’s the thing: it took the exact same number of lines of code to write tests as it did before. The setup for the new framework was the same level of complexity as the old one, and debugging new tests was just as difficult as before.
So what was the difference between the two? The new framework was “cooler” because it was new, the documentation was slightly better, and most importantly, that was the way my developer did things at his old job, and that way was “better”.
I see this a lot. Engineers who
- Want to swap part of the system with a Cool New Tool™ (I’m guilty of this sometimes).
- Want to rewrite an entire subsystem to force it to match a paradigm that engineer is more familiar with. Because he or she is more familiar with it, that paradigm is automatically superior.
I urge you to avoid both cases. We all have the urge to rewrite everything when we get into a new codebase. Invariably there are 1,000 things that are broken, and dozens of hacks and duct tape that were written with the future intention of cleaning them up. But then the engineer moved on, and the refactor never happened.
When we begin work on a new software project, we all need to remember “if it ain’t broke, don’t fix it.”
Because even if that code looks terrible and broken, as Joel Spolsky says, rewriting from scratch is something you should never do.
That old, broken, ugly code deals with 10 edge cases you would have never thought of, and it’s accumulated thousands of hours of soak time in the wild, dealing with real user input.
I think some engineers have a better intuitive sense about adding value than others. Some people “just get it.” They dive into a new project and immediately tackle something the team has been avoiding for months. Nobody told them to do it. They just saw the opportunity and got after it.
Other engineers get hung up on the most trivial of details. They become consumed by how “broken” the code is, and they can’t resist the urge to rewrite everything.
They think they’re making the code prettier, but in reality it’s only prettier to them. The next engineer who looks at the codebase automatically thinks everything is broken again, and the process repeats. It’s a miracle we ever get anything done.
Next time you have the urge to redo everything, try to resist. Sometimes, a complete rewrite is warranted, but it should only come after your current implementation has caused you considerable pain. If this is the 3rd feature you’re trying to hack into the current design, then okay, maybe it’s time to rewrite this submodule so it’s more extensible.
Rewrites should never be triggered because some tool is newer, sexier, Better™, more familiar, or mentioned more times on Hacker News.
There need to be legitimate advantages to trigger a rewrite. Some examples:
- Will save the team a bunch of time.
- Will allow the team to write less code from now on.
- Will allow the code to support the next 5 features.
- Will make debugging easier.
Unfortunately a lot of this is subjective. If you avoid rewrites too often, you might wind up with a mountain of technical debt that nobody will touch. A fuzzy line exists between the point when you shouldn’t rewrite versus when you should.
I believe it’s the sign of a good engineer to be able to tell when you should or when you shouldn’t redo everything.