The evolution of programming paradigms and languages allows us to manage the increasing complexity of systems. Furthermore, we have introduced (and demanded) increasingly complex requirements because various paradigms provide mechanisms to support their implementation. As a result, complex requirements constitute a driving factor for the evolution of languages which in turn can support system complexity. In this circular relationship, the maintenance phase of the software life cycle becomes increasingly important and factors which affect maintenance become vital. In this chapter we review the notions of software aging and discuss activities undertaken during maintenance. We also discuss challenges and trends for the development of well-maintained systems as well as for aiding in the maintenance of legacy systems.
Aging in Software
In the literature, many authors tend to have drawn analogies between software systems and biological systems (ISO/IEC 12207:1995(E); Jones, 2007; Parnas, 1994). Two such notable examples are the widely used notions of aging and software life cycle, implying that we can view software systems as a category of organisms. This analogy is convenient because it creates certain realizations about software. First, we note that systems exist (by operating as a community of intercommunicating agents) inside a given environment. Furthermore, much like their biological counterparts, they evolve (to adapt to their environment) and they grow old. Finally, when speaking of the life cycle of software, we also imply the unavoidable fact that software systems eventually die.
However, the causes of software aging are very different from those of biological organisms or those that cause aging in other engineering artifacts. Unlike biological organisms (such as humans) software systems are not subjected to fatigue or physical deterioration. Unlike other engineering products (such as machinery and structures), software systems are not subjected to physical wear caused by factors such as friction and climate. Aging in software systems is predominantly (but not always) caused by changes that take place in their surrounding (operating) environment.
In his seminal paper on aging, author David Parnas (1994) describes two causes of software aging: The first factor, referred to as lack of movement, is the failure of owners to provide modifications to the software in order to meet changing needs (requirements) of its environment which results in end-users changing to newer products. The second factor, referred to as ignorant surgery, is the careless introduction of changes in the implementation which can cause the implementation to become inconsistent with the design, or even to introduce new bugs. This latter factor is associated with two significant implications: The first is a bloating of the implementation, resulting in a reduction in performance (memory demands, throughput and response time). This weight gain makes new changes difficult to be introduced quickly enough to meet market demands. The second implication is a phenomenon known as bad fix injection (Jones, 2007), which refers to the introduction of errors during maintenance resulting in a decrease in reliability. As a result, software systems become unable to be competitive in the market, thus loosing customers to newer products.
Key Terms in this Chapter
Reverse Engineering: A model transformation activity where the target language is at a higher level of abstraction.
Reengineering: An activity to reimplement a software in a new form. Normally comprised by reverse engineering (for comprehension), restructuring, and forward engineering.
Rephrasing: A model transformation activity where the source and target languages are at the same level of abstraction.
Translation: A model transformation activity where the source and target languages are at a different level of abstraction.
Data-Flow Analysis (DFA): A process for collecting run-time information about data in a computer program without actually executing it. A program’s control-flow graph is deployed to determine those parts of a program to which a particular value assigned to a variable might propagate.
Program Dependency Graph (PDG): A refinement of DFA for a program routine with CFA information.
Control-Flow Analysis (CFA): An investigation to determine properties of the program control structure such as possible control flow paths (branches) and to find basic blocks and loops.
Program Slicing: A derivative of Program Dependency Graph (PDG) and System Dependency Graph (SDG).
Formal Concept Analysis (FCA): Mathematical technique for analyzing binary relations, capturing conceptual structures among data sets.
System Dependency Graph (SDG): A refinement of DFA for a program with CFA information. It captures the union of all PDGs in a program.