Software Necromancy - Zombie code, Priority 1 Fires and Crying Babies

Software Necromancy - Zombie code, Priority 1 Fires and Crying Babies

During the course of a software developers career, a lot of code, all of varying qualities come and go; some of which is characterised as clean, some obscene, some ugly and then - some - as "zombie code". This is nothing like the movies, these monsters are real and eat at the very foundations of an organisation.

How does code become "undead"?

Paraphrased from: Zombie code: When maintainability goes out the window

Lack of unit tests!

Code that does not use a testing framework with adequate unit tests sets itself up for failure. This is because, during development (especially in the later stages) - components may be called upon to perform an operation in a way they were not initially designed to. Without testing, you do not know with absolute certainty that your input will function as needed. This leads to assumptions being made which has knock-on implications for every department within the organisation.

No Refactoring

In the days of old an entire project would be scoped, in it's entirety - from end to end. Once the project was signed off, that's what's being built and that's that - The waterfall model. Needless to say, few companies have the time, budget or works in such an inflexible way that could work with this model. Enter AGILE Software Development, a way of accommodating for change with the use of smaller units of work called "sprints".

With this flexibility - things change. Components need rework to accommodate that new decimal point on that number field and thereby all the attached business logic, repository and so forth. When changes like this happen, very little gets taken into account in the way of refactoring - old code is left commented out (for so many all un-funny and all horrible reasons) and the new code just gets put in its place, very little thought gets put into perhaps using another data structure, or a design pattern to implement the changes in a more compatible and future-focused way.

Time and budget concerns sometimes are reasons stated for not refactoring sooner, however, in the long run - refactoring early could be more cost effective than deferring to another time.

All code will need to be refactored at some stage to keep up with the change of technology. Here's a picture that illustrates what happens to an un-refactored code-base over time.


Inflexibile Code

Code that can be changed easily with minimal impact to a system is not impossible to write but requires a little bit of thinking up front. This comes from the idea that you should be able to inject your dependencies as you need them with given contracts for operation rather than creating multiple concrete objects. This is one of the SOLID design principles which is being given increasing prevalence with stable and maintainable code design.

Conclusion

The fight for good code quality is not always an easy one and sometimes leads to horrible things like zombie code - or simply - code that just won't die. It is important to fix these issues the moment they are in view or else it festers within your organisational code base until it is simply "too important/sensitive to replace". Yes, this will mean more money needs to get allocated somewhere and yes it implies some radical thinking will need to be done - but it is possible.

How do you fight existing zombie code?

"Plug the holes, then empty the water from the boat" - this is more about adopting the practices you can now, and taking maintenance time over an extended number of sprints to isolate each component and refactor with unit tests, ideally using Test Driven Development.

"Amputate, cauterize, sterilize" - Target a component and write it's functionality into a new component. Seal off any "holes" in the code and cover edge cases using unit tests. Once the new component is developed and fully tested, swap the component out in the code base using Dependency Injection (Using a framework or custom injector). Clear up any damage caused by the faulty component and repeat for all components requiring refactoring.

How do I stop creating zombie code?

  1. Adopt unit tests (I would recommend TDD) and cover as much of the implemented code within them. It's not wrong to have thousands upon thousands of unit tests.
  2. Whenever an existing component will be impacted by a change, consider if it should still work the way it currently does and if not, how should it be changed?
  3. Make flexibility a way of life. I am not saying absolutely everything should be abstracted. Abstraction often leads to increased complexity and possibly decreased maintainability. Make flexible components where it may be needed to allow for change, this is where dependency injection will be most helpful as it allows for swapping of components with minimal effort.
  4. Adopt some form of DevOps, automation will save everyone time, frustration and stress if leveraged correctly. There is little to no need for the Ops team to work on weekends because the change can only be done out of business hours! These changes can be in multiple environments with as little as a code check-in that has been approved for release.
  5. Maintain standards - even if they are held by a small team. The use of a standard will allow for everyone to work in a standardised way that is almost immediately understood by all.

Finally

Zombie code is inevitable. Accept that it exists, start to combat it and put it to bed. Your time is better served meeting new requirements and delivering better software.

well written and good read, even for a non coder. It assists me understand more which is relevant to API gateway management I'm tasked to take to market. Well done Junglist! Repsect

To view or add a comment, sign in

Others also viewed

Explore content categories