Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code...
Transcript of Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code...
![Page 1: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/1.jpg)
Software ReengineeringWorking with Legacy Code
Martin Pinzger – Andy ZaidmanDelft University of Technology
![Page 2: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/2.jpg)
Outline
Introduction
Breaking dependencies
Strategies for breaking dependencies
2
![Page 3: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/3.jpg)
3
The Reengineering Life-Cycle
(1) requirementanalysis
(2) modelcapture
(3) problemdetection (4) problem
resolution
NewRequirements
Designs
Code
![Page 4: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/4.jpg)
4
The Legacy Code Dilemma
“When we change code, we should have tests in place. To put tests in place, we often have to change code.”
[Feathers 2005]
![Page 5: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/5.jpg)
5
Most applications are glued together
Singletons (a.k.a. global variables)If there can only be one of an object you’d better hope that it is good for your tests too
Internal instantiationWhen a class creates an instance of a hard coded class, you’d better hope that class runs well in tests
Concrete dependencyWhen a class uses a concrete class, you’d better hope that class lets you know what is happening to it
![Page 6: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/6.jpg)
6
How to get my tests in?
“By breaking dependencies”
SensingWhen we can’t access values our code computes
SeparationWhen we can’t even get a piece of code into a test harness to run
![Page 7: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/7.jpg)
The legacy code change algorithm
1. Identify change points
2. Find test points
3. Break dependencies
4. Write tests
5. Make changes and refactor
7
![Page 8: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/8.jpg)
8
Example: Breaking dependencies
![Page 9: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/9.jpg)
An ugly implementation
9
public class AccountDetailFrame extends Frame implements ActionListener, WindowListener {
private TextField display = new TextField(10); … private AccountDetailFrame(…) { … }
public void performAction(ActionEvent event) { String source = (String)event.getActionCommand(); if (source.equals(“project activity”)) { DetailFrame detailDisplay = new DetailFrame(); detailDisplay.setDescription(getDetailText() + “ “ + getProjectText()); detailDisplay.show(); String accountDescription = detailDisplay.getAccountSymbol(); accountDescription += “: “; … display.setText(accountDescription); … } }}
Where are the dependencies?
![Page 10: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/10.jpg)
After extract method
10
public class AccountDetailFrame extends Frame implements ActionListener, WindowListener {
private TextField display = new TextField(10); … private AccountDetailFrame(…) { … } public void performAction(ActionEvent event) { performCommand((String) event.getActionCommand()); }
void performCommand(String source) { if (source.equals(“project activity”)) { DetailFrame detailDisplay = new DetailFrame(); detailDisplay.setDescription(getDetailText() + “ “ + getProjectText()); detailDisplay.show(); String accountDescription = detailDisplay.getAccountSymbol(); accountDescription += “: “; … display.setText(accountDescription); … } }}
![Page 11: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/11.jpg)
After more refactoring
11
public class AccountDetailFrame extends Frame implements ActionListener, WindowListener {
private TextField display = new TextField(10); private DetailFrame detailDisplay; … private AccountDetailFrame(…) { … } public void performAction(ActionEvent event) { performCommand((String)event.getActionCommand()); }
void performCommand(String source) { if (source.equals(“project activity”)) { setDescription(getDetailText() + “” + getProjectText()); … String accountDescripton = getAccountSymbol(); accountDescription += “: “; … setDisplayText(accountDescription); … } }}
![Page 12: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/12.jpg)
12
The Aftermath ...
We can subclass AccountDetailFrame, and override getAccountSymbol, setDisplayText, and setDescription to sense our work
![Page 13: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/13.jpg)
13
Adding a test
public TestingAccountDetailFrame extends AccountDetailFrame { ...}
public class AccountDetailFrameTest { ... @Test public void testPerformCommand() { TestingAccountDetailFrame frame = new TestingAccountDetailFrame();
frame.accountSymbol = “SYM”; frame.performCommand(“project activity”); assertEquals(“06 080 012”, frame.getDisplayText()); }}
![Page 14: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/14.jpg)
14
More Aftermath ...
![Page 15: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/15.jpg)
15
Making it better
We can make the design better by extracting classes for those separate responsibilities
![Page 16: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/16.jpg)
16
Better vs. Best
“Best is the enemy of good” – Voltaire (paraphrased)
![Page 17: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/17.jpg)
Strategies for breaking dependencies
Lean on toolsUse tools with automated refactorings
Mock libraries
If manual, thenLean on the compiler
Use the compiler to report points of change by deliberately producing errors
Preserve signatures
Favor refactorings which allow you to cut/copy and paste signatures without modification
Single goal editing
Do one thing at a time!
17
![Page 18: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/18.jpg)
I can’t get this class in a test harness
![Page 19: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/19.jpg)
Common problems
Objects of the class can’t be created easily
The test harness won’t easily build with the class in it
The constructor we need to use has bad side effects
Significant work happens in the constructor, and we need to sense it
19
![Page 20: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/20.jpg)
public class CreditValidator {
public CreditValidator(RGHConnection connection, CreditMaster master, String validatorID) { ... }
! Certificate validateCustomer(Customer customer) throws InvalidCredit { ... } ...}
20
Irritating parameters How am I going to construct
these parameters for the test?
Setting up network connection is not possible…
![Page 21: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/21.jpg)
Extract interface + create FakeConnection class
public class FakeConnection implements IRGHConnection { public RFDIReport report; public void connect() {} public void disconnect() {} …}
21
Irritating parameter: Solution 1
+
![Page 22: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/22.jpg)
22
Irritating parameter: Solution 2
Pass nullIf an object requires a parameter that is hard to construct
If the parameter is used during your test execution an exception will be thrown
You can then still reconsider to construct a real object
Variant solution “null object”A sibling to the original class with no real functionality (returns default values).
![Page 23: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/23.jpg)
Consider this C++ constructor:
We don’t want to initialize the mail_service, because then weconnect to the network and start sending actual mails…
mailing_list_dispatcher::mailing_list_dispatcher()! : service(new mail_service), status(MAIL_OKAY){ const int client_type = 12; service->connect(); status = MAIL_OFFLINE; ...}
23
Hidden dependency
This constructor relies on the class
mail_service in the initialization list
![Page 24: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/24.jpg)
24
Hidden dependency: Solution
Parameterize constructor
Big improvement? (Yes)Allows for introducing a fake mail service
Extract interface for mail_service
Introduce fake class that senses the things we do
mailing_list_dispatcher::mailing_list_dispatcher(mail_service *service) : status(MAIL_OKAY)
![Page 25: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/25.jpg)
class WatercolorPane {public: WatercolorPane(Form *border, WashBrush *brush, Pattern *backdrop) { ... anteriorPanel = new Panel(border); anteriorPanel->setBorderCol(brush->getForeColor()); backgroundPanel = new Panel(border, backdrop); cursor = new FocusWidget(brush, backgroundPanel);! }}
25
The construction blob
How to sense the cursor?
![Page 26: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/26.jpg)
The construction blob: Solution 1
26
Extract and Override Factory MethodIf we have a refactoring tool
![Page 27: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/27.jpg)
27
The construction blob: Solution 2
Supersede Instance Variable
After the object has been constructed, swap in another instance of cursor
Be careful not to use superseding in production code
Using Extract Interface create a fake object for FocusWidget that you can use to sense
// C++void supersedeCursor(FocusWidget *newCursor) { delete cursor; cursor = newCursor;}
![Page 28: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/28.jpg)
Irritating global dependency
28
public class Facility { private Permit basePermit;
public Facility(int facilityCode, String owner, PermitNotice notice) throws PermitViolation {
Permit associatedPermit = PermitRepository.getInstance().findAssociatedPermit(notice); if (associatedPermit.isValid() && !notice.isValid()) { basePermit = associatedPermit; } else if (!notice.isValid()) { Permit permit = new Permit(notice); permit.validate(); basePermit = permit; } else { throw new PermitViolation(permit); } } ...}
Where is the irritating global dependency?
PermitRepository is a Singleton!
![Page 29: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/29.jpg)
Irritating global dependency: Solution
29
Introduce static setterpublic class PermitRepository { private static PermitRepository instance = null;
private PermitRepository() {} public static void setTestingInstance(PermitRepository newInstance) { instance = newInstance; }
public static PermitRepository getInstance() { if (instance == null) { instance = new PermitRepository(); } return instance; } ...}
Is it working?
make it public, protected, package
![Page 30: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/30.jpg)
Irritating global dependency: Solutions
30
Subclass and Override Method
Extract Interface
public class TestingPermitRepository extends PermitRepository { ...}
public class PermitRepository implements IPermitRepository { private static IPermitRepository instance = null;
protected PermitRepository() {} ...}
![Page 31: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/31.jpg)
I can’t run this method in a test harness
![Page 32: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/32.jpg)
Common problems
The method is not accessible to the test
It is hard to call the method because it is hard to construct the parameters
The method has bad side effects (modifies a database, launches a cruise missile, etc.)
We need to sense through some objects used by the method
32
![Page 33: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/33.jpg)
33
Hidden method
How do we write a test for a private method?
Two obvious solutions:Make the method public
Change the private method to protected and then subclass it
What solution to choose? A matter of design choice for the original class…
Private methods sometimes point to a SRP violation
![Page 34: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/34.jpg)
public class AccountDetailFrame extends Frame implements ActionListener, WindowListener {
private TextField display = new TextField(10); … private AccountDetailFrame(…) { … }
public void performAction(ActionEvent event) { String source = (String)event.getActionCommand(); if (source.equals(“project activity”)) { DetailFrame detailDisplay = new DetailFrame(); detailDisplay.setDescription(getDetailText() + “ “ + getProjectText()); detailDisplay.show(); String accountDescription = detailDisplay.getAccountSymbol(); accountDescription += “: “; … display.setText(accountDescription); … } }}
34
Undetectable side-effects
Do you remember the example?
![Page 35: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/35.jpg)
I need to make a change. What methods should I test?
![Page 36: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/36.jpg)
Reasoning about effects
36
public class CppClass { private String name; private List declarations; public CppClass(String name, List declarations) { this.name = name; this.declarations = declarations; } public int getDeclarationCount() { return declarations.size(); } public String getName() { return name; } public Declaration getDeclaration(int index) { return ((Declaration)declarations.get(index)); } public String getInterface(String interfaceName, int[] indices) { String result = "class " + interfaceName + " {\npublic:\n"; for (int n = 0; n < indices.length; n++) { Declaration virtualFunction = (Declaration)(declarations.get(indices[n])); result += "\t" + virtualFunction.asAbstract() + "\n"; } result += "};\n"; return result; }} Things which can be changed that would affect
results returned by any of CppClass methods?
![Page 37: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/37.jpg)
Reasoning about effects: first results
37
Additional elements to declarationsList is created first and passed to constructor
List is held by reference
Changes can alter the results of getInterface, getDeclaration, and getDeclarationCount
Alter or replace one of the objects held in declarationsAffecting the same methods getInterface, getDeclaration, and getDeclarationCount
What about getName() and changes to name attribute?
![Page 38: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/38.jpg)
BubblesVariables that can change
Methods whose return values are affected
ArrowsDepict the effect
Effect sketch
38
![Page 39: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/39.jpg)
Effect sketch of CppClass example
39
![Page 40: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/40.jpg)
public class InMemoryDirectory { private List elements = new ArrayList<Element>(); public void addElement(Element newElement) { elements.add(newElement); }
public void generateIndex() { Element index = new Element("index"); for (Element current : elements) { index.addText(current.getName() + "\n"); } addElement(index); }
public int getElementCount() { return elements.size(); } public Element getElement(String name) { for (Element current : elements) { if (current.getName().equals(name)) { return current; } } return null; }}
Reasoning forward
Directory index example
40
If we call generateIndex twice?
![Page 41: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/41.jpg)
Where are we going to make our changes?public class InMemoryDirectory { private List elements = new ArrayList<Element>(); public void addElement(Element newElement) { elements.add(newElement); }
public void generateIndex() { Element index = new Element("index"); for (Element current : elements) { index.addText(current.getName() + "\n"); } addElement(index); }
public int getElementCount() { return elements.size(); } public Element getElement(String name) { for (Element current : elements) { if (current.getName().equals(name)) { return current; } } return null; }}
Reasoning forward
41
Remove functionality
Add functionality
What are the effects of these changes?
![Page 42: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/42.jpg)
Reasoning forward: effect sketches (1)
Effect of changing functionality in generateIndex?
42
![Page 43: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/43.jpg)
Reasoning forward: effect sketches (2)
Effect of changing elements?
43
![Page 44: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/44.jpg)
Reasoning forward: effect sketches (3)
44Make sure you have found all clients
![Page 45: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/45.jpg)
Learning from effect analysis
45
Try to analyze effects in code whenever you get a chance
Try to narrow effects in a programWhenever you make a change you need less to understand the piece of code
Use toolsProgram slicing tools
![Page 46: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/46.jpg)
More info and strategies
46
Working Effectively with Legacy Code Michael Feathers, Prentice Hall, 1 edition, 2004
![Page 47: Software Reengineering Working with Legacy Code · Software Reengineering Working with Legacy Code Martin Pinzger – Andy Zaidman Delft University of Technology. ... (1) requirement](https://reader030.fdocuments.us/reader030/viewer/2022041021/5ed0f03652f5473a482ba176/html5/thumbnails/47.jpg)
47
Conclusions
In order to reengineer, you need tests When creating tests, you might need to reengineer
Breaking dependencies help to introduce tests
Analyze effects of changes
Lean on toolsBe careful with manual refactorings