Reducing Cost and Complexity in Legacy Systems

 

Michael Oara

CEO, System Renewal, Inc.

 

 

Introduction

 

Over time even the best implemented legacy applications degenerate to the point where they become difficult to maintain. Costs trend upward as developers struggle with systems that are the product of generations past. Although aging applications present significant technical and operational challenges, their critical role in running modern enterprises necessitates an ongoing commitment of resources to ensure support for evolving business requirements.

 

The need to maintain legacy applications will persist well into the future. Gartner research estimates that as much as sixty percent of the world’s active business applications are written in COBOL. And the world of COBOL is constantly in flux: applications are being extended and updated at an estimated rate of five billion lines per year. The continued reliance on legacy code has brought maintenance challenges to the forefront as the resources of IT organizations are stretched thinner than ever before.

 

Pain Points

 

The hallmark of an effective IT organization is its ability to quickly adapt to new business drivers while keeping costs under control. People change, technologies change, and companies change. Unfortunately, without enormous effort legacy systems stay the same. The consequences of this inflexibility are far reaching as the inability to support changing requirements often negatively impacts corporate goals.

 

Applications must change with the times, business simply demands this. Unfortunately, modifying code that has existed for decades is a task that can border on the impossible: new functionality has been added, errors corrected and processes updated. What started out as a few hundred thousand lines of code can end up running into the millions.

 

Software changes that were once simple to make now take Herculean efforts as developers attempt to understand code that has grown unwieldy over the years. The problem is exacerbated because the mission-critical nature of many applications makes managing risk a top priority. It becomes difficult to determine not just how an application should be modified, but what effects the change will have on other parts of the system.

 

Maintenance activities are further hampered by productivity issues. Adding personnel to increase throughput only seems to slow progress. New team members suffer a grueling learning period because inadequate documentation and overwhelming complexity hinder productivity. As a result organizations expend most of their time just keeping legacy systems running, rather than focusing on the future.

 

Root Causes

 

The typical legacy application did not become a maintenance problem overnight. In their time many were considered state-of-the-art solutions to large-scale business computing problems. The fact that many have been in service since the 1950s only illustrates their capabilities and the quality of their original implementation. Paradoxically, it is these positive traits that have led organizations into the maintenance quagmire of today.

 

As time has marched on the mission-critical role of these applications has further solidified. With this role come responsibilities: the application must be continually available and it must support business needs, now and in the future. This has resulted in few alternatives other than heaping change upon change on poorly understood and fragile code bases.

 

Just because an application has been around for decades does not mean institutional knowledge of it is widespread. To the contrary, the passing of time ensures a steady decline of trained expertise. It is not just that developers are assigned to other projects; they often leave the organization, taking their knowledge of the application with them permanently.

 

Documentation is a time-tested method of smoothing knowledge transfer between team members. Unfortunately few have managed to keep it current throughout the years. Determining how and why control is handed off between routines in a multi-million line application is a daunting task especially when the documentation does not match reality. Worse yet, lacking a useful description of how the application declares, uses and shares data, programmers simply create new variables instead of using those that already exist.

 

The end result of years of ad hoc modifications is that formerly well implemented applications become maintenance headaches as complexity grows and productivity declines.

 

Simplicity is the Cure

 

Reining in maintenance costs is a goal shared by all organizations. The challenge is reaching this goal without expending large amounts of time and effort converting legacy code to newer technologies. Unfortunately there is no silver bullet that magically transforms a maintenance intensive application into a low maintenance one. Only by systematically working to remove complexity can costs be brought under control.

 

It is intimate knowledge of an application that fosters the insights necessary to reduce complexity. Gaining this knowledge through manual code inspection is problematic as the time involved and minimal chance of success dwarf expected returns. Furthermore, manual approaches and one-off methods only provide a single snapshot of the application. Since changes are often made to the most important applications on a regular basis, this knowledge quickly becomes irrelevant.

 

What is needed is a tool that can analyze even the largest applications and provide detailed metrics and useful insights. Armed with this information teams gain a better understanding of how a system is put together and can then assess where their time will be best spent. A key benefit of using an automated solution is that analyses can be run on an as-needed basis: before changes to the application are made, or afterwards to verify the desired outcome was achieved. This flexibility is not possible using manual techniques.

 

When selecting an automated analysis tool one should look for a solution that not only provides useful insights into an application, but also helps developers implement changes initiated by those insights.

 

Identify Complexity

 

When faced with the task of reducing application complexity, developers may find that just determining where to focus their efforts is a challenge. A broad array of metrics could be used to measure complexity. Such metrics distill even the most labyrinthine applications into a series of industry-standard measures that gauge how difficult it is to maintain, analyze and transform the code.

 

Among these metrics developers often find that McCabe’s cyclomatic complexity and Halstead’s program volume are the most useful indicators of application complexity.  Cyclomatic complexity measures the number of linearly independent paths through a program. Program volume serves a similar purpose as it measures complexity by summarizing how many operators and operands the program contains. Each metric provides a single ordinal number that can be used to rank programs by complexity.

 

McCabe cyclomatic complexity information can be used to determine which programs to work on first.  Furthermore, because it makes little sense to simplify code that is infrequently updated, developers can further shorten the list of complexity reduction candidates with knowledge of how often an application is modified; this data that is commonly available in the existing version control system.

 

All complexity is not the same. For instance, an application may exhibit high cyclomatic complexity because it contains many GO TOs and deeply nested IF statements. While nested IFs do materially contribute to complexity, the use of GO TOs may not. Metrics alone cannot differentiate between the acceptable use of coding constructs such as branching to error and exit paragraphs and code that relies on GO TOs for control flow.

 

Developers may solve this problem with a pattern-based search that can differentiate between programs that look complex and programs that actually are complex. Such a tool can find occurrences of a particular coding construct—such as GO TOs that are used for control flow, or IF statements that are more deeply nested than desirable. With this information developers can whittle down the list of complexity reduction candidates.

 

Reduce Complexity

 

Complexity manifests itself in many ways: the code’s control flow may be obfuscated by its “spaghetti” like nature; the purpose and use of data structures is not readily apparent; obsolete functionality hinders readability and contributes to code bloat. These problems represent only some of the challenges developers face when attempting to bring complexity under control.

 

Techniques for solving these problems are well known but often difficult to carry out. Here are some time-tested techniques:

 

 

 

Cut-and-paste programming results in code with identical logic dispersed throughout it. Code consolidation is an attempt to reduce the code to reusable components, such as COBOL copybooks or subprograms.

 

 

 

 

 

          IF condition1

                   Statement1

           ELSE IF condition2

                             Statement2

                   ELSE   IF condition3

                                      Statement3

                             END-IF

                   END-IF

          END-IF.

 

          This will be changed to the following construct.

          EVALUTE TRUE

                   WHEN condition1

                             Statement1

                   WHEN condition2

                             Statement2

                   WHEN condition3

                             Statement3

          END-EVALUATE

 

Conclusion

 

The challenges of complexity reduction have resulted in organizations tolerating difficult to maintain legacy applications. An investment in simplification may lead to increased productivity and more agility. IT shops can thus focus their limited resources on supporting future business needs rather than just maintaining the past.