I was recently watching a documentary that described the engineering and design of bridges. These bridges, some of them 80 years old, have been in constant use from the moment they were built.
There really was no cookie cutter recipe. For the most part, each bridge was a custom design job that resulted from the engineering best practices at the time it was designed, the available materials, and the opinions of the engineers. Sounds a lot like the software development.
One thing that didn’t sound like software at all was the attitude toward maintenance. The bridge engineers all had respect for the original design and applied their skills to maintain it. They would incorporate new techniques and materials where it supported the intent of the original designers, but there was no push to “refactor” the bridge. As a result the bridges keep working, fulfilling their original purpose and providing value every day.
Imagine how this might be different if each new engineer on the project came in and said “This bridge design is crap. I’m surprised it even works. We know so much more about the right way to build a bridge now. We’re going to have to gut this architecture and update it to implement current best practices.”
How long do you think that bridge would remain in service? Even worse, how reliable do you think that bridge would be after a new set of engineers came in and tried to implement a brand new architecture, producing a mish-mash of the old and the new.
It sounds like an obviously bad idea when talking about bridges, but for some reason we don’t give it a second thought in the software world. We have a chronic lack of respect for those who came before us. We’re constantly rewriting code THAT IS WORKING for no better reason than we don’t like the design.
I can look back at my career and see multiple instances where I’ve been the chief refactor offender, rewriting code that was working, even entire application architectures because I thought they were written poorly. It’s easy to do. There’s no shortage of legitimately bad code or developers who rush to implement the latest tools and ideas without really understanding what they’re doing.
These days I’m a little older and a little wiser. I try to keep 2 important principles in mind
1. Software is not an end unto itself.
Our end customers don’t really care if our services are perfectly RESTful, or if we’ve properly implemented dependency injection throughout our app. They care if it works.
2. There’s always a reason the developer who came before me did things the way they did.
Here’s a cycle I’ve gone through countless times. I see code that works but it’s stupidly implemented, what was this idiot thinking. It’s going to take me an extra hour but let me fix this nonsense. Ok I’m pretty much finished and wait, this key use case doesn’t work. I can fix it, but now the rest of my refactor is broken. Well if I do this and this it will work, but…. oh… it pretty much works the same way it did to start with.