Download presentation
Presentation is loading. Please wait.
1
Legacy Systems and Software Reuse
CS 560 Lecture 10
2
Software systems Economics
Software is expensive. Most software development makes extensive use of existing software. Developers avoid building new software if it duplicates what already exists.
3
Software systems Economics
Avoiding building new software has several aspects: Program and system design makes use of existing components. Modular design Working with legacy code. Code that’s no longer supported by the original development team/operating environment Design patterns that allow replacing or updating components in the future. Refactoring
4
Software Reuse It is often good to design components to be reusable and that reuse existing components. Can lead to better software at lower cost. Potential benefits of reuse: Reduced development time and cost Improved reliability Reduced maintenance cost Potential disadvantages of reuse: Difficulty in finding appropriate components Components may be a poor fit for the application Quality control and security may be unknown
5
Software Reuse Examples
Standard functions: Mathematical methods Format conversion Type conversion User interface and application development: Toolkits ( SDKs) Class libraries Web frameworks (Bootstrap, Django)
6
Evaluating software Software from established developers is likely to be well written and tested. Likely to be much better than a new development team would write. But...still may have bugs and security issues. Sometimes it is sensible to write code for a specific purpose rather than using/creating general purpose software. General purpose software can become too complex Tries to accommodate all cases. General purpose software doesn’t fit well with your components.
7
Reuse: open source software
Open source software varies enormously in quality. Major systems such as Linux, Apache, MySQL, OpenSSH, etc. tend to be very robust and free from (most) problems. They can sometimes be better than their commercial equivalents. More experimental systems like Hadoop have solid cores But their lesser used features may not be thoroughly tested. Some open source software can be of poor quality and should not be incorporated in production systems. Abandoned, incomplete projects on GitHub, SourceForge, etc.
8
Design for change: Replacement of Components
Software design should anticipate possible changes over its life cycle. Inevitable based on software/hardware evolution Components are replaced because: Its supplier/development team no longer exists Ceases to provide adequate support/performance Difficult to troubleshoot Increased price Better software from other sources
9
Design for reuse: Class Hierarchies
Example: Java Java is a relatively straightforward language with a very rich set of class hierarchies. Java programs derive much of their functionality from standard classes. Experienced Java programmers can write complex systems quickly. Languages such as Java and Python change their class hierarchies over time. Commonly the changes replace special purpose functionality with more general frameworks.
10
Design for reuse: Inheritance and Abstract classes
Classes can be defined in terms of other classes using inheritance. The generalized class is called the superclass The specialization is called the subclass. If the inheritance relationship serves only to model shared attributes and operations: The class is called an abstract class.
11
Legacy Systems The Worst Case, a large system that was developed several decades ago: Used within a large company or by an unknown number of customers. No list of requirements. It is uncertain what functionality the system provides and who uses which functions. System and program documentation incomplete and not kept up to date. Written in out-of-date versions of programming languages using system software that is also out of date. Numerous patches over the years that have ignored the original system architecture and program design. Extensive code duplication and redundancy.
12
Legacy requirements Develop a plan for rebuilding the system
Involve the client(s) in this step Develop requirements as seen by the customers and users Who are the users? How do they actually use the system? Does the system have undocumented features that are important? How many people use unconventional parts of the system? Develop requirements described by the system design If system documentation exists, what does it say about the requirements? Does the source code include any hints about the requirements? Is there code to support obsolete hardware or services? If so, does anybody still use them?
13
Legacy code Characteristics: Definition: Legacy source code
Inherited from someone who inherited it from someone else… Missing comments, documentation, or test cases. Moved from original operating environment. Added functionality over the years. Characteristics: Poor architecture Non-uniform coding styles Extremely valuable! Only successful code becomes legacy code
14
Reason for Legacy code Instead of building new software solutions:
Add more and more features to existing software Developers rotate into and away from projects Project time constraints Project team growth Microsoft has ~45k software engineers Creates communication issues
15
Steps for modifying legacy code
Identify what (module/component/interface) to change Identify what to test Determine legacy component dependencies Write tests Modify and refactor code
16
legacy code – what to change
Identify what (module/component/interface) to change Do you have enough knowledge to know where to make changes to the code? Sometimes you need to modify many different places just to make a simple change.
17
legacy code – what to change
How to gain knowledge about the legacy code: Read source code and generate flow graphs Used to visualize program control Scratch Refactoring Modify component internal algorithms without making changes to interface(s) Delete unused code Determined by basis paths (covered later)
18
legacy code – What to test
Identify what to test Based on effective analysis of code and structure. Can be difficult depending on legacy code complexity. How much time does it take to test? What kinds of tests?
19
legacy code –testing Be careful combining new code with legacy code for testing. Updating functionality by adding new code could cause issues in other areas of the legacy system. Always try to isolate new (tested) code from legacy code. Sprout method/class
20
legacy code – Sprout methods
Add functionality to classes/methods by isolating new code. Easy reversal if sprout code functions incorrectly. public class ProductLabelPrinter{ … public void printLabel(int productID){ String barcode; //compute barcode //print barcode }//end printLabel }// end class
21
legacy code – Sprout methods
Add functionality to classes/methods by isolating new code. Easy reversal if sprout code functions incorrectly. public class ProductLabelPrinter{ … public void printLabel(int productID){ String barcode; //compute barcode newBarCodeCompute(barcode) //print barcode newBarCodePrint(barcode) }//end printLabel protected void newBarCodeCompute(String barcode){ //new tested code.. }//end newBarCodeCompute protected void newBarCodePrint(String barcode){ }// end class
22
legacy code – dependencies
Identify what (module/component/interface) to change Identify what to test Determine legacy component dependencies Multi-dependency problem Dependency chains Dependency conflicts Circular dependencies Write tests Modify and refactor code
23
legacy code – dependencies
Software dependency: Components designed for use everywhere. Readily available (download, repository) sudo apt-get install php7.0 Multi-dependency problem: Components may require many packages Packages must be downloaded taking time/space Decreases component portability Difficult to find legacy packages
24
legacy code – dependencies
Dependency chain problem: Components rely on packages, which those packages rely on other packages.. Application A depends on pkgA, which depends on pkgB, which depends on pkgB.1 and pkgC, ….
25
legacy code – dependencies
Dependency conflict problem: Different components rely on different versions of the same package. Application A1 depends on libfoo1.1, and application A2 depending on libfoo1.2, and different versions of libfoo can’t be installed at the same time. In this case, application A1 and A2 can’t be used at the same time due to a package dependency conflict. How can we approach this issue?
26
legacy code – dependencies
Circular dependency problem: Different applications depend specific versions of each other to function correctly. Modifying either application causes the other application to break. pkg(A), which requires pkg(B) to function, may brick itself while upgrading pkg(B) to a new version. Due to incorrect pkg(B) version, pkg(A) is now broken, thus no modification of pkg(B) is possible.
27
legacy code – Tests Write tests Based on sprout methods/classes.
Generating specific test cases will be covered later.
28
Legacy code The following tasks may be finished in any order, based on the condition of the code. (Try to) understand the original systems architecture and program design. Establish a component architecture, define interfaces, even if much of the code violates the architecture and needs adapters. Move to current versions of programming languages and systems software. If there are any subsystems that do not have source code, carry out a development cycle to create new code that implements that subsystem’s requirements. If there is duplicate code, replace with a single version. Clean up/Refactor and document as you go along.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.