Many conversations about the complexity of implementing a new feature or the post mortem of a defect with eventually involve the phrase "the problem is this is legacy code".
Since on this basis it seems inevitable that all code is eventually considered legacy what can we do to ensure that this doesn't cripple our ability to move our product forward?
Well to do this we probably need to start with defining what we mean by legacy code?
Defining Legacy
Whilst the age of a code base is likely to be a contributing factor in whether or not it is considered legacy it is by no means the definitive measure, there are many well established and long serving code bases that are still being actively developed.
Instead we should defined legacy by the effect it has on us, legacy code instills a lack of confidence in those who have to work with it.
This lack of confidence generally comes from either an inability to refactor, an inability to test or potentially the most frightening of all an inability to build the code.
The inability to refactor may come from simply a lack of understanding of how the code works or potentially from the "ball of string effect" that causes refactoring and rewriting to become synonymous, the inability to test usually has similar roots.
The inability to build is somewhat more serious as it immediately rules out any remediation with regard to the other problems the code base may have, its roots generally lie in an overly custom build process that may be heavy reliant on technology that has disappeared from the mainstream.
Without getting into a discussion about how the root causes of these problems could be countered, can we form an escape plan to get ourselves out of this situation?
What Over How
Two of the problems that create a legacy code base can be somewhat addressed by shifting the perspective of the analysis, instead of agonising over "how" this code works start thinking about "what" it should be doing.
Concentrating on "what" code should be doing is all that is required to construct tests for the code, after all "what" is all we have to go on if we are following a TDD approach.
It maybe that we have to accept that these tests are not strictly unit tests and that they aren't following FIRST principles but before embarking on any other change we need to have a crutch to restore confidence that this code is still doing what we need it to do.
Concentrating on "what" is also a decent starting place for refactoring, this view point can act as a microscope to identify what is wrong with the current API, architecture or implementation.
That still doesn't mean that the required refactoring will be easy but it will help shape it, which is a necessary starting point before any technical debt can be dealt with.
Strangling the Problem
Martin Fowler identified an approach to refactoring a legacy system that he termed a Strangler Application.
Using this approach rather than simply starting again and trying to create a new system we gradually build the new system around the edges of the old.
The new code gradually grows taking on more and more of the required functionality until it strangles the legacy code.
To achieve this he identifies two strategies, Event Interception and Asset Capture.
Many systems can be defined by the events that they handle and the data that they capture, when building a strangler system these events and data items are gradually moved to become the responsibility of the strangler system until most of the critical items reside in it.
An important secondary aspect to this approach is that we can make our lives easier in the future by designing a system to be strangled, a modular design where responsibilities and the data model can be moved around and migrated will enable us to replace and re-work in the future.
Whilst it is obviously inevitable that a code base will age it doesn't have to imply that it will eventually becoming a legacy code base with all the negative connotations that may bring.
The ability for a code base to evolve, grow and be maintained is what will prevent it from having the terrifying legacy label applied to it.
For this to be true, no matter how old the code may be, we must have the confidence to refactor it, and this will come from us having the ability to build, test and deploy it.
No comments:
Post a Comment