Enterprise legacy software systems tend to be large and complex. The analysis of system architecture therefore becomes a difficult task. To solve the problem, it would be better if legacy software architecture can be decomposed to reduce the complexity associated with analyzing large scale architecture artifacts. Architecture decomposition is an efficient way to limit the complexity and risk associated with the re-engineering activities of a large legacy system. It divides the system into a collection of meaningful modular parts with low coupling, high cohesion, and minimizes the interface, thus to facilitate the incremental approach to implement the progressive software re-engineering process.
A legacy code can be considered as any code that was written before today. Traditional approach is to start performing changes in a secured manner because it is not sure what’s really going to happen when a data structure is changed or update a variable i.e. adding a wrapper on top of existing code or copying the code from another place which already works. In the cases mentioned in the previous lines, the code will blot and maintainability, testability and understandability will be a big problem in future. But, for people who deal with it day in and day out "legacy code" is a Pandora’s box: sleepless nights and anxious days poring through bad structure, code that works in some incomprehensible way. Martin Fowler defines refactoring legacy code as “a change made to the internal structure of the software to make it easier to understand and cheaper to modify without changing its observable behavior.
Most of the tasks in the evolution and servicing phases require program comprehension, understanding how and why a software program functions in order to work with it effectively. Effective comprehension requires viewing a legacy program not simply as a product of inefficiency or stupidity, but instead as an artifact of the circumstances in which it was developed. This information can be an important factor in determining appropriate strategies for the software program's transition from the evolution stage to the servicing or phase-out stage.
This article will talk about the definition of re-engineering and refactoring and also present the situation in which this process need to be used in an effective manner.
Refactoring is the process of changing a software system in such a way that the external behavior of the code is unchanged but its internal structure and architecture are improved. It is a behavior-preserving source code transformation.
Programmers hold onto software designs for long duration even after they have become unwieldy. The life span of the legacy code will be alive only as long as product is running at customer place. We reuse code that is no longer maintainable because it still works in some way and are bit scared for modification. But is it really cost effective to do so?. When we remove redundancy, eliminate unused functionality and rejuvenate obsolete designs, we are in the process of refactoring the code that are not maintainable.
Refactoring throughout the entire project life cycle saves time and improves quality. During this phase, a series of question will arise for all the programmers like:
· “Changing the design/code might break the system!”
o Solution: Use tests to prove behavior preservation
· “I don't understand how it works now!”
o Solution: Learn through the process and Build documentation as you refactor and simplify
· “I don't have the time to refactor!”
o Solution: Refactoring will pay for itself later
The below mentioned graphical picture will depict the cost saving if continuous refactoring followed during the lifecycle of a project/product: [Reference: http://www.jacoozi.com/blog/?p=11 ]
|
But it is important for the programmers to understand that refactoring process will help to improve readability, flexibility, extensibility, understandability and improve performance. Refactoring process can be applied during application, maintenance, testing, coding and during framework development. Below mentioned section will explain the refactoring cycle that can be used for refactoring code under maintenance:
· Program source code should go through expansion and contraction phases.
o Expansion phase: code is added to meet functional requirements
o Contraction phase: code is removed and refactored to better address those requirements and plan for the future.
· This cycle will be repeated many times during a program's lifetime.
The objective of refactoring is to keep the design simple as time goes on and also avoid clutter and complexity in the legacy code. Refactoring is the process which will help in cleaning up the code which is easier to understand, modify and extend. In the longer run, it will groom the system which is well defined and more maintainable.
There is certain amount of Zen to refactoring. It is hard at first because the design which is envisioned and working has to set off and accept the design that was serendipitously identified while refactoring. It is important to know that the design envisioned was competent but is obsolete now. Before implementing this process, it is better to remove the notions about what the system should or should not be and try to see the new design emerge as code changes take place.
The number of refactoring that would be beneficial to any code is infinite. Some of the refactor techniques that are used in java development are
· Organize imports
· Rename {field, method, class, package}
· Move {field, method, class}
· Extract {method, local variable, interface}
· Inline {method, local variable}
· Reorder method parameters
· Push members down
Legacy systems might have written in different architecture which in turn written in different computer languages. The key issue will be in maintenance and the integration of these systems. Companies that optimize business processes must often change legacy information systems to support the new processes. The required changes can involve new features, porting, performance optimization, or bug fixes. Changes for the legacy systems often require replacement of the existing code but also of supporting tools (e.g., compilers and editors), development processes (testing and version control).
This change requires discarding part or all of the existing system, modifying existing parts, writing new parts and purchasing new or improved parts from external vendors. Based on this criteria, we can termed in two different forms and the same is mentioned below
· If the change is accomplished primarily through discarding the existing system and buying or building new parts then those systems are termed as a rewrite or redevelopment.
· If the change is accomplished primarily by modifying the existing system, the project is termed as a reengineering project.
Rewriting and reengineering are the extremes along a spectrum of strategies for change but in reality most major upgrades are accomplished by some combination of the two.
Reengineering and refactoring might look quite similar at the beginning however, reengineering deals with the examination and alteration of a system to reconstitute it in a new form, and the subsequent implementation of the new form.
The primary benefits that reengineering will include:
· Reduced operating and maintenance costs caused by overheads of older applications.
· Improved application maintainability, even if there is limited application knowledge, high staff turnover, lack of qualified resources, outdated documentation, or obsolete application platform support.
· Improved access to legacy applications in case of a merger or organizational change.
Based on the process followed in reengineering project, the lifecycle involves two major steps in reengineering processes and the same is mentioned below:
Forward reengineering: Forward engineering starts with system specification and involves the design and implementation of a new system.
Reverse reengineering: Reverse engineering is the process of analyzing a subject system to identify the systems’ components and their interrelationships and create representations of the system in another form or at a higher level of abstraction
Perspective | Reengineering | Refactoring |
Scope | Reengineering always affects the entire system or part of the system (in this case we will take hybrid approach). | Refactoring has typically (many) local effects |
Process | Reengineering follows a disassembly / reassembly approach in technical domain. | Refactoring is a behavior-preserving, structure transforming process. |
Result | Reengineering can create a whole new system – with different structure and possibly a different behavior. | Refactoring improves the structure of an existing system – leaving its behavior |
Cost | Cost is higher when compared with refactoring. | Continuous refactoring will decrease the total cost of ownership. |
Below are the some of the scenario in which reengineering will suitable:
· System’s documentation is missing or obsolete.
· Team has only limited understanding of the system, its architecture and implementation
· Bug fix in one place causes bugs in other places.
· New system level requirements and functions cannot be addressed or integrated appropriately.
· Code is becoming ‘brittle’ and difficult to update.
Legacy software systems are an ongoing challenge for software developers. Refactoring according to Martin Fowler, is a controlled technique for improving the design of an existing code base. It is important to maintain the health code for better maintainability by refactoring.
Developing a custom built system requires a lot of effort and cost. Hence, organizations need to maintain their old systems in order to reduce the cost and increase the lifetime of the old system. For these purpose re-engineering becomes a useful way to convert old, obsolete systems to efficient and streamlined systems. The intent of reengineering to create version of existing programs that are of high quality and easier to maintain.