Legacy Systems Refactoring

2020 06 01 head

In computer programming and software design, code refactoring is the process of restructuring existing computer code without changing its external behavior.

Refactoring is intended to improve the design, structure, or implementation of the software (its non-functional attributes), while preserving its functionality.

Using refactoring, you can take bad design, even chaos software and rework it into well-designed code. Most often, it is cheaper to refactoring a legacy application instead of rewriting it from scratch.

Simply put, refactoring is a way of decreasing Technical Debt.

There are two general categories of benefits to the activity of refactoring.

Maintainability

It is easier to fix bugs because the source code is easy to read and the intent of its author is easy to grasp. This might be achieved by reducing large monolithic routines into a set of individually concise, well-named, single-purpose methods. It might be achieved by moving a method to a more appropriate class, or by removing misleading comments.

Extensibility

It is easier to extend the capabilities of the application if it uses recognizable design patterns. It provides flexibility where none before May have existed.

Refactoring is the process of changing a software system in such a way that it does not alter the external behavior of the code. Yet the internal structure improves. It is a disciplined way to clean up code that minimizes the chances of introducing bugs. In essence, when you refactor, you are improving the design of the code after it has been written.

— Martin Fowler

Introduction

For a developer, new to a legacy software solution, it is often hard to understand the existing application. He must determine the extent of source code and architectural decay, and identify smells and metric violations.

Legacy applications are often critical to business and have been in use for years, sometimes decades. Since business is evolving, there is constant pressure to support additional requirements. However, changing these applications is challenging. You end up spending an increasing number of resources maintaining the software.

There are many reasons why maintaining legacy software is a difficult problem. Often, most, if not all, of the original developers are gone, and no one understands how the application is implemented. The technologies used in the application are no longer current, having been replaced by newer and more exciting technologies. Also, software complexity increases as it evolves over time as you add new requirements.

The key to managing the lifecycle of software is to continuously work as a professional and skilled developer. A professional engineer opportunistically refactor each time he modifies source code.

Understand Your Product

  • Understand how it is used. These scenarios define the acceptance tests you need to start creating a set of automated validation criteria. And you will better understand how your users are working with your product.

  • Understand how it is deployed. You need a reproducible and in the long-run automated process to deploy a new version of your application. We are talking about continuous delivery and even continuous deployment.

  • Understand how it is built. You need a reproducible and automated build process. This process must be integrated into your continuous integration and delivery pipeline.

  • Understand how it is structured. You need a tentative architecture description to start refactoring and to untangle this big ball of mud into a more modular solution.

Refactor Your Product

Refactoring is always a successful activity. You cannot fail. But you need discipline, continuous involvement, and measurement.

Each refactoring step is simple, even simplistic. Yet the cumulative effect of these small changes can radically improve the design.

— Martin Fowler

If you are new to refactoring, it is worth having a coach to smooth the learning curve.

  1. Extract one big service, refactor, test, and deploy. Iterate. If you are not successful, discard your failure and check out the current working version of git. You should have learnt enough so that the next try will be successful.

  2. Refactor code. Use static analysis tools to detect the flaws in your source code. You should only improve live code, meaning code you must correct or extend. See Agile Code is Clean Code. Use a modern IDE to automate the smaller refactoring steps, and avoid spurious errors.

  3. Resolve design issues. Your senior design specialists already know the flaws. Now it is time to correct them.

  4. Increase code coverage. Code coverage is the security net when you are refactoring code.

  5. Slowly add fitness functions to continuously validate your non-functional requirements.

Beware of good practices how to write good software products and refactor successfully applications.

  • Move to Domain Driven Design as an architecture approach. It works either for micro architecture or for modular monolith approaches.

  • Master long live domain driven design and event storming

  • Master your technical stack and use current tools and libraries.

  • Modularize one big service extraction one after the other Avoid using dead architectural techniques. TOGAF, UML, PMI, CMMI are obsolete - various activities they recommend are good, do them in your sprints. Avoid a lengthy, slow and expensive review approach.

  • ATAM is dead The quality tree technique is wonderful, use fitness functions to implement your quality tree.

The Architecture Tradeoff Analysis Method ATAM is hosted under the Carnage Mellon University CMU Software Engineering Institute SEI. The latest revision of the method was published in August 2000, almost a quarter of a century.

The approach relies heavily on human review activities. The execution of these tasks is expensive and slow. The time horizon of an ATAM review is between one and two weeks. The results are heavily document-centric. No formal or programmatic validation of the findings is usually provided.

This process is too slow in the context of a DevOps or Scrum development approach. Agile product development wants to deliver updates with an hourly or daily rhythm.

If you are running legacy technology, this not only becomes a threat to your business but also to your hiring and employer branding efforts. As fewer and fewer programmers and operation managers will have the knowledge of those systems, you will face a dwindling talent pool.

Ameliorate Your Process

Applications do not degrade to legacy or geriatric systems overnight. The organization and development group failed to work professionally over years before the product was ultimately doomed.

By continuously improving the design of code, we make it easier and easier to work with. This is in sharp contrast to what typically happens: little refactoring and a great deal of attention paid to expediently adding new features. If you get into the hygienic habit of refactoring continuously, you will find that it is easier to extend and maintain code.

— Joshua Kerievsky
Refactoring to Patterns

You must establish a culture of professional software development. Professional software developers write code which is maintainable and legible. Only unprofessional organizations create legacy applications.

Embrace software craftsmanship. All your developers should have formal software development training and frequent training in new approaches and techniques. They consistently read books. Is it not that you expect from your physician or the pilot of the plane you are taking?

Agile Architecture Series

The agile architecture track contains the following blogs

We also published our agile architecture course (3 ECTS) used for teaching computer science students at bachelor level at Swiss technical universities.