© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map...

126
© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance Detailed Model Capture Initial Understanding First Contact Setting Direction Migration Strategies Detecting Duplicated Code Redistribute Responsibilit ies Transform Conditionals to Polymorphism

Transcript of © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map...

Page 1: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

1

A Map of Reengineering Patterns

Tests: Your Life Insurance

Detailed Model Capture

Initial Understanding

First Contact

Setting Direction

Migration Strategies

Detecting Duplicated Code

Redistribute Responsibilities

Transform Conditionals to Polymorphism

Page 2: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

Setting Direction

Page 3: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

3

A Map of Reengineering Patterns

Tests: Your Life Insurance

Detailed Model Capture

Initial Understanding

First Contact

Setting Direction

Migration Strategies

Detecting Duplicated Code

Redistribute Responsibilities

Transform Conditionals to Polymorphism

Page 4: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

4

The Reengineering Life-Cycle

(0) req. analysis(1) model captureissues• scale• speed• accuracy• politics

Requirements

Designs

Code

(0) requirementanalysis

(1) modelcapture

(2) problemdetection

(3) problemresolution

(4) program transformation

Page 5: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

5

Forces — Setting Direction

> Conflicting interests (technical, ergonomic, economic, political)

> Presence/absence original developers> Legacy architecture> Which problems to tackle?

— Interesting vs important problems?— Wrap, refactor or rewrite?

Page 6: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

6

Setting Direction

Agree on Maxims

Appoint aNavigator

Speak to theRound Table

Most Valuable First

Fix Problems,Not Symptoms

If It Ain't BrokeDon't Fix It

Keep it Simple

Set direction

Maintaindirection

Coordinatedirection

Where to start

What not to doWhat to do

How to do itPrinciples & Guidelines for Software project management especially relevant for reengineering projects

Principles & Guidelines for Software project management especially relevant for reengineering projects

Page 7: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

7

Most Valuable First

> Problem: Which problems should you focus on first?> Solution: Work on aspects that are most valuable to

your customer

— Maximize commitment, early results; build confidence— Difficulties and hints:

– Which stakeholder do you listen to?– What measurable goal to aim for?– Consult change logs for high activity– Play the Planning Game– Wrap, refactor or rewrite? — Fix Problems, not Symptoms

Page 8: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

First Contact

Page 9: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

9

A Map of Reengineering Patterns

Tests: Your Life Insurance

Detailed Model Capture

Initial Understanding

First Contact

Setting Direction

Migration Strategies

Detecting Duplicated Code

Redistribute Responsibilities

Transform Conditionals to Polymorphism

Page 10: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

10

Forces — First Contact

> Legacy systems are large and complex—Split the system into manageable pieces

> Time is scarce—Apply lightweight techniques to assess feasibility and risks

> First impressions are dangerous—Always double-check your sources

> People have different agendas—Build confidence; be wary of skeptics

Page 11: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

11

First Contact

System experts

Chat with theMaintainers

Interviewduring Demo

Talk withdevelopers

Talk withend users

Software System

Read All the Codein One Hour

Do a MockInstallation

Read it Compile it

Skim theDocumentation

Talk about it

Verify whatyou hear Read

about it

Feasibility assessment (one week time)Feasibility assessment (one week time)

Page 12: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

12

> Problem: What are the typical usage scenarios?> Solution: Ask the user!

— ... however– Which user ?– Users complain– What should you ask ?

• Solution: interview during demo- select several users- demo puts a user in a positive

mindset- demo steers the interview

• Solution: interview during demo- select several users- demo puts a user in a positive

mindset- demo steers the interview

Interview during Demo

Page 13: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

13

Chat with the Maintainers

> Problem: What are the history and politics of the legacy system?

> Solution: Discuss the problems with the system maintainers.

— Documentation will mislead you (various reasons)— Stakeholders will mislead you (various reasons)— The maintainers know both the technical and political history

Page 14: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

14

Chat with the Maintainers

> Questions to ask:— Easiest/hardest bug to fix in recent months?— How are change requests made and evaluated?— How did the development/maintenance team evolve during the

project?— How good is the code? The documentation?— Why was the reengineering project started? What do you hope

to gain?— The major problems of our work are no so much technological

as sociological.– DeMarco and Lister, Peopleware ‘99

Page 15: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

15

I took a course in speed reading and read “War and Peace” in twenty minutes. It’s about Russia.

—Woody Allen

Read all the Code in One Hour

> Problem: How can you get a first impression of the quality of the source code?

> Solution: Scan all the code in single, short session.— Use a checklist (code review guidelines, coding styles etc.)— Look for functional tests and unit tests— Look for abstract classes and root classes that define domain

abstractions— Beware of comments— Log all your questions!

Page 16: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

16

First Project Plan

> Use standard templates, including:— project scope

– see "Setting Direction"

— opportunities– e.g., skilled maintainers, readable source-code, documentation

— risks– e.g., absent test-suites, missing libraries, …– record likelihood (unlikely, possible, likely)

& impact (high, moderate, low) for causing problems

— go/no-go decision— activities

– fish-eye view

Page 17: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

Initial Understanding

Page 18: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

18

A Map of Reengineering Patterns

Tests: Your Life Insurance

Detailed Model Capture

Initial Understanding

First Contact

Setting Direction

Migration Strategies

Detecting Duplicated Code

Redistribute Responsibilities

Transform Conditionals to Polymorphism

Page 19: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

19

Forces — Initial Understanding

> Data is deceptive— Always double-check your sources

> Understanding entails iteration— Plan iteration and feedback loops

> Knowledge must be shared— “Put the map on the wall”

> Teams need to communicate— “Use their language”

Page 20: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

20

Initial Understanding

Top down

Speculate about Design

Recover design

Analyze the Persistent Data

Study the Exceptional Entities

Read it Compile it

Bottom up

understand higher-level modelunderstand higher-level model

Page 21: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

21

Speculate about Design

> Problem: How do you recover design from code?> Solution: Develop hypotheses and check them

— Develop a plausible class diagram and iteratively check and refine your design against the actual code.

— Variants:– Speculate about Business Objects– Speculate about Design Patterns– Speculate about Architecture

Page 22: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

22

Study the Exceptional Entities

> Problem: How can you quickly identify design problems?

> Solution: Measure software entities and study the anomalous ones

— Use simple metrics— Visualize metrics to get an overview— Browse the code to get insight into the anomalies

Page 23: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

23

Visualizing Metrics

(x,y)width

height colour

Use simple metrics and layout algorithms

Visualizes up to 5 metrics per node

Page 24: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

24

Initial Understanding (revisited)

Top down

Speculate about Design

Analyze the Persistent Data

Study the Exceptional Entities

understand higher-level model

understand higher-level model

Bottom up

ITERATION

Recover design

Recover database

Identify problems

Page 25: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

Detailed Model Capture

Page 26: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

26

A Map of Reengineering Patterns

Tests: Your Life Insurance

Detailed Model Capture

Initial Understanding

First Contact

Setting Direction

Migration Strategies

Detecting Duplicated Code

Redistribute Responsibilities

Transform Conditionals to Polymorphism

Page 27: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

27

Forces — Detailed Model Capture

> Details matter— Pay attention to the details!

> Design remains implicit— Record design rationale when you discover it!

> Design evolves— Important issues are reflected in changes to the code!

> Code only exposes static structure— Study dynamic behaviour to extract detailed design

Page 28: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

28

Detailed Model Capture

Tie Code and Questions

Refactor to UnderstandKeep track of

your understanding

Expose design

Step through the Execution

Look for the Contracts

Learn from the Past

Expose collaborations

Expose contracts

Expose evolution

Write Teststo Understand

Expose the design & make sure it remains exposedExpose the design & make sure it remains exposed

• Use Your Tools• Look for Key Methods• Look for Constructor Calls• Look for Template/Hook Methods• Look for Super Calls

• Use Your Tools• Look for Key Methods• Look for Constructor Calls• Look for Template/Hook Methods• Look for Super Calls

Page 29: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

29

Tie Code and Questions

> Problem: How do you keep track of your understanding?

> Solution: Annotate the code

— List questions, hypotheses, tasks and observations— Identify yourself!— Use conventions to locate/extract annotations— Annotate as comments, or as methods

Page 30: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

30

Refactor to Understand

> Problem: How do you decipher cryptic code?> Solution: Refactor it until it makes sense

— Goal (for now) is to understand, not to reengineer— Work with a copy of the code— Refactoring requires an adequate test base

– If this is missing, Write Tests to Understand

— Hints:– Rename attributes to convey roles– Rename methods and classes to reveal intent– Remove duplicated code– Replace condition branches by methods

Page 31: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

31

Step Through the Execution

> Problem: How do you uncover the run-time architecture?

> Solution: Execute scenarios of known use cases and step through the code with a debugger

— Tests can also be used as scenario generators– If tests are missing Write Tests to Understand

— Put breakpoints in the code— Difficulties

– OO source code exposes a class hierarchy, not the run-time object collaborations

– Collaborations are spread throughout the code– Polymorphism may hide which classes are instantiated

— Focused use of a debugger can expose collaborations

Page 32: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

32

Look for the Contracts

> Problem: Which contracts does a class support?> Solution: Look for common programming idioms

— Look for “key methods”– Intention-revealing names– Key parameter types– Recurring parameter types represent temporary associations

— Look for constructor calls— Look for Template/Hook methods— Look for super calls— Use your tools!

Page 33: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

33

Learn from the Past

> Problem: How did the system get the way it is?> Solution: Compare versions to discover where code

was removed

— Removed functionality is a sign of design evolution— Use or develop appropriate tools— Look for signs of:

– Unstable design — repeated growth and refactoring– Mature design — growth, refactoring and stability

Page 34: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

34

Conclusion

> Setting Direction + First Contact— First Project Plan

> Initial Understanding + Detailed Model Capture— Plan the work … and Work the plan— Frequent and Short Iterations

> Issues— scale— speed vs. accuracy— politics

Page 35: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

Tests: Your Life Insurance

Page 36: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

36

A Map of Reengineering Patterns

Tests: Your Life Insurance

Detailed Model Capture

Initial Understanding

First Contact

Setting Direction

Migration Strategies

Detecting Duplicated Code

Redistribute Responsibilities

Transform Conditionals to Polymorphism

Page 37: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

37

What and Why ?

Definitions> Restructuring refers to transforming a system from one

representation to another while remaining at the same abstraction level. — Chikofsky & Cross, ’90

> Refactoring is the process of changing a software system in such a way that it does not alter the external behaviour of the code, yet improves its internal structure — Fowler, ’99

Motivation> Alter the source-code to

— solve problems identified earlier— without introducing new defects— and while the system remains in operation

Page 38: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

38

The Reengineering Life-Cycle

Requirements

Designs

Code

(0) requirementanalysis

(1) modelcapture

(2) problemdetection (3) problem

resolution

(4) program transformation

(3) problem resolution(4) program transformationissues• reliability• time• risk

Page 39: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

39

Forces — Testing

> Many legacy systems don’t have tests> Software changes introduce new bugs> You can’t test everything> Concurrency and user interfaces are hard to test> Testing is usually everyone’s lowest priority> Knowledge concentration poses high risk> Customers pay for features, not tests> Customers don’t want buggy systems> Good programmers don’t need tests> New tools and techniques are more fun than testing> Testing is akin to street-cleaning

Page 40: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

40

Tests: Your Life Insurance

Write Tests to Enable Evolution

Grow Your TestBase Incrementally

Managing testsUse a Testing

Framework

Test the Interface,Not the Implementation

Record BusinessRules as Tests

Designingtests

Write Teststo Understand

• Test Fuzzy features• Test Old Bugs• Retest Persistent Problems

Regression Testafter Every Change

Migration StrategiesMigration Strategies

Page 41: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

41

Write Tests to Enable Evolution

Problem: How do you minimize the risks of change?Solution: Introduce automated, repeatable, stored tests

Automated tests are the foundation of reengineering

Long-term evolutionLong-term evolution

System documentationSystem documentation Architectural evolutionArchitectural evolution

System ConfidenceSystem Confidence Turnover Risk minimizationTurnover Risk minimization Confidence in ChangeConfidence in Change

Automated TestsAutomated Tests

Page 42: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

42

Grow Your Test Base Incrementally

> Problem: When can you stop writing tests?> Solution: When your tests cover all the code!

— … however– you're paid to reengineer, not to write tests– testing ALL the code is impossible– design documentation is out-of date

» semi-automated black-box testing is not an option

Answer: Grow Your Test Base Incrementally• first test critical components

(business value; likely to change; …)• keep a snapshot of old system

(run new tests against old system)• focus on business values• test old bugs + new bugs that are reported

Answer: Grow Your Test Base Incrementally• first test critical components

(business value; likely to change; …)• keep a snapshot of old system

(run new tests against old system)• focus on business values• test old bugs + new bugs that are reported

Page 43: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

43

Use a Testing Framework

> Problem: How do you encourage systematic testing?> Solution: Use a framework to structure your tests

Page 44: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

44

Running tests

Page 45: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

45

Test the Interface, Not the Implementation

> Problem: How do you protect your investment in tests?> Solution: Apply black-box testing

— Test interfaces, not implementations– Be sure to exercise the boundaries

— Test scenarios, not paths– Use tools to check for coverage

— Beware;– Enabling testing will influence your design!

Page 46: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

46

Write Tests to Understand

> Problem: How to decipher code without adequate tests or documentation?

> Solution: Encode your hypotheses as test cases

— Exercise the code— Formalize your reverse-engineering hypotheses— Develop tests as a by-product

Page 47: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

47

Solution: Record Business Rules as Tests- canonical examples exist- can be turned into input/output tests

Solution: Record Business Rules as Tests- canonical examples exist- can be turned into input/output tests

Record Business Rules as Tests

> Problem: How do you keep your system in sync with the business rules it implements?

> A Solution: Good documentation + Good design— … however

– business rules are too complex to design well– documentation & design degrades when the rules change– business rules become implicit in code and minds

Page 48: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

48

Example: Payroll Business Rule

> A person or couple gets an amount of money for every child he, she or they raise. Basically parents get CHF 150,- per month for every child younger than 12 years, and CHF 180,- for every child between 12 and 18 and for every child between 18 and 25 as long as the child is not working and is still in the educational system. A single parent gets the full 100% of this money as long as he or she is working more than 50%. Couples get a percentage of the money that is equal to the summed working percentages of both partners.

Page 49: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

49

Example: Payroll Test Case

"--- input-cases are extracted from a database"singlePerson80WithOneKidOf5 := extract....couplePerson40occupationWithOneKidOf5 := extract....couplePerson100occupationWithOneKidOf5 := extract....couplePersonWithOneKidOf14 := extract....

"--- tests compare expected output against actual output"self assert: singlePerson80occupationWithOneKidOf5 moneyForKid

= 150.self assert: couplePerson40occupationWithOneKidOf5 moneyForKid

= 150*4.self assert: couplePerson100occupationWith2KidsOf5 moneyForKid

= 150*2.self assert: couplePersonWithOneKidOf14 moneyForKid

= 180.

Page 50: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

50

Other patterns

> Retest Persistent Problems— Always tests these, even if you are making no changes to this

part of the system

> Test Fuzzy Features— Identify and write tests for ambiguous or ill-defined parts of the

system

> Test Old Bugs— Examine old problems reports, especially since the last stable

release— DeLano and Rising, 1998

Page 51: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

Migration Strategies

Page 52: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

52

A Map of Reengineering Patterns

Tests: Your Life Insurance

Detailed Model Capture

Initial Understanding

First Contact

Setting Direction

Migration Strategies

Detecting Duplicated Code

Redistribute Responsibilities

Transform Conditionals to Polymorphism

Page 53: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

53

The Reengineering Life-Cycle

Requirements

Designs

Code

(0) requirementanalysis

(1) modelcapture

(2) problemdetection (3) problem

resolution

(4) program transformation

(3) problem resolution(4) program transformationissues• reliability• time• risk

Page 54: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

54

Forces — Migration

> Big-bang migration often fails> Users hate change> You need constant feedback to stay on track> Users just want to get their work done> The legacy data must be available during the transition

Page 55: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

55

Migration

Migrate SystemsIncrementally

ConserveFamiliarity

HowUse Profiler

before Optimizing

Build ConfidenceInvolve the UsersHow Why

Why

Prototype theTarget Solution

Always Have aRunning Version

Regression Testafter Every Change

Present theRight Interface

Distinguish Publicfrom Published Interfaces

DeprecateObsolete Interfaces

Make a Bridgeto the New Town

How

Tests, yourLife-Insurance

Tests, yourLife-Insurance

Where to

Page 56: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

56

Involve the Users

> Problem: How to get users to accept change?> Solution: Get them involved by giving them what they

want

— Start with the Most Valuable First— Prototypes can help raise enthusiasm, but may also raise

expectations too high— Deploy early to increase commitment

– Diverts energy from development– Pays back in quality feedback

Page 57: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

57

Build Confidence

> Problem: How do you overcome skepticism?> Solution: Deliver results in short, regular intervals

— Requires time to sync with users— Requires effort to support the changes— Requires care not to alienate original developers— Requires regular, big demos to convince management

Page 58: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

58

Migrate Systems Incrementally

> Problem: When should you deploy the new system? > Solution: As soon as possible

— Decompose the legacy system into parts— Tackle one part at a time (Most Valuable First)— Put suitable tests in place— Decide whether to wrap, reengineer, or replace— Deploy, support and obtain feedback— Iterate

Page 59: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

59

Prototype the Target Solution

> Problem: How do you evaluate the target solution?> Solution: Develop a prototype

— Evaluate the technical risks– New system architecture– Migrating legacy data– Adequate performance …

— Exploratory prototype?– Explore specific issues, then throw it away!

— Evolutionary prototype?– Capture new architecture– Migrate, wrap, reengineer or reimplement parts

Page 60: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

60

Always Have a Running Version

> Problem: Maintaining confidence during development> Solution: Integrate changes on a daily basis

— Use version and configuration management tools— Maintain exhaustive regression tests where needed— Plan short iterations — Continuous Integration

– If necessary, re-architect the system to enable short build times

Page 61: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

61

Regression Test After Every Change

> Problem: Making sure changes don’t break the system> Solution: Run the regression tests at each “stable”

point

— You must relentlessly write tests!– Write new tests whenever new (untested) bugs are discovered– Take time to convince your team of the Joy of Testing

— If testing takes too long, categorize tests– But run all the tests at least once a day

— Consider writing tests up front— Remember to Retest Persistent Problems

Page 62: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

62

Bridge

1:read() 2:write()

1.1:read()

1.2:write() 2.1:write()

Legacy System

New System

Data Store

Make a Bridge to the New Town

> Problem: How to migrate data?

> Solution: Convert the underlying files/databases/…

— ... however– Legacy and new system

must work in tandem– Too much data; too

many unknown dependencies

– Data is manipulated by components

Page 63: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

63

Present the Right Interface

> Problem: How do you prevent the legacy design from polluting the new system?

> Solution: Wrap old services as new abstractions

— Identify the new abstractions you want— Wrap the legacy services to emulate the new interface

– Avoid directly accessing old procedural interfaces– Avoid wrapping as pseudo-OO «utility» classes

Page 64: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

64

Solution: Distinguish between “public” and“published” interface

• public = stable target interface• published = available, but unstable

(use at your own risk)• language features (protected, friends, …)• naming conventions

Solution: Distinguish between “public” and“published” interface

• public = stable target interface• published = available, but unstable

(use at your own risk)• language features (protected, friends, …)• naming conventions

Public vs. Published Interface

> Problem: How to design interface for target solution?> Solution?: Think deeply

— ... however– Enable migration to target system ASAP– Avoid freezing the interface of target component– Costly ripple-effects of changes to public interface

Page 65: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

65

Deprecate Obsolete Interfaces

> Problem: How to modify an interface without invalidating all clients?

> Solution: Flag the old interface as «deprecated»

— Old and new interfaces can co-exist for a time– Deprecated usage can be lazily patched

— Various techniques possible– Documentation (easy to ignore)– Move or rename old interfaces (painful)– Add warnings to deprecated code (should be non-intrusive)

Page 66: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

66

Conserve Familiarity

> Problem: How to avoid disrupting Users’ work? > Solution: Avoid radical changes

— Avoid alienating users— Introduce a constant, small number of changes with each

release

Page 67: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

67

Use Profiler Before Optimizing

> Problem: When should you rewrite inefficient code?> Solution: Only when you have benchmarks that prove it

is worthwhile

— “Do it, then do it right, then do it fast”

Page 68: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

68

Conclusion

> Avoid risk— small increments (“chicken little”)— develop suite of regression tests

> … at acceptable cost— Migration costs as much as new development !— But you avoid "hidden costs"

– team morale in maintenance team– satisfying two customer bases

Page 69: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

Detecting Duplicated Code

Page 70: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

70

A Map of Reengineering Patterns

Tests: Your Life Insurance

Detailed Model Capture

Initial Understanding

First Contact

Setting Direction

Migration Strategies

Detecting Duplicated Code

Redistribute Responsibilities

Transform Conditionals to Polymorphism

Page 71: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

71

Detecting Duplicated Code

Compare Code Mechanically

Visualize Code as Dotplots

Redistribute Responsibilities

Redistribute Responsibilities Transform

Conditionals to Polymorphism

Transform Conditionals to Polymorphism

Detect

Understand

Page 72: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

72

Duploc: Detecting Duplicated Code

Compare, visualize and navigate multiple source files

Page 73: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

73

Pattern: Visualize Code as Dotplots

Problem— How can you effectively identify significant duplication in a

complex software system?

Solution— Visualize the code as a dotplot, where dots represent

duplication.

Steps— Normalize the source files— Compare files line-by-line— Visualize and interpret the dotplots

Page 74: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

74

File A

File A

File B

File B

Clone detection by string-matching

Solid diagonals indicate significant duplication between or within source files.

Solid diagonals indicate significant duplication between or within source files.

Page 75: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

75

Dotplot Visualization

Exact Copies Copies with Inserts/Deletes Repetitive

a b c d e f a b c d e f a b c d e fa b x y e f b c d e a b x y dc ea x b c x d e x f xg ha

Variations Code Elements(Helfman, 1995)

Sample Dot Configurations:

Page 76: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

Redistribute Responsibilities

Page 77: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

77

Tests: Your Life Insurance

Detailed Model Capture

Initial Understanding

First Contact

Setting Direction

Migration Strategies

Detecting Duplicated Code

Redistribute Responsibilities

Transform Conditionals to Polymorphism

A Map of Reengineering Patterns

Page 78: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

78

The Reengineering Life-Cycle

Requirements

Designs

Code

(0) requirementanalysis

(1) modelcapture

(2) problemdetection (3) problem

resolution

(4) program transformation

(2) problem detection(3) problem resolutionissues• OO paradigm• When/When not

Page 79: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

79

Redistribute Responsibilities

Eliminate Navigation Code

Data containers

Monster client ofdata containers

Split Up God Class

Move Behaviour Close to Data

Chains of datacontainers

Page 80: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

80

The Law of Demeter

> A method M of an object O should invoke only the methods of the following kinds of objects:1. O itself2. parameters of M3. any object M creates /instantiates4. direct component objects of O

http://en.wikipedia.org/wiki/Law_of_Demeterhttp://en.wikipedia.org/wiki/Law_of_Demeter

Page 81: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

81

IndirectProviderdoSomething()

ImmediateProvider+providergetProvider()

IndirectClient

intermediate.provider.doSomething()Or intermediate.getProvider.doSomething()

intermediate.provider.doSomething()Or intermediate.getProvider.doSomething()

provider intermediate

The Core of the Problem

Page 82: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

82

Move Behavior Close to Data

> Problem: How do you transform a data container into a service provider

> Solution: Move behavior defined by indirect clients to the class defining the data they manipulate

> …however— Visitor — Difficult to identify client code to be moved in

– Responsibility of the provider– Access attributes of the provider– Accessed by multiple clients

Page 83: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

83

Transformation…

Provider+x+y+sety(val)+setx(val)

ClientOp2()

…provider.sety(provider.x + provider.y)…

…provider.sety(provider.x + provider.y)…

Provider-x-y-sety(val)+bump()

ClientOp2()

…provider.bump()…

…provider.bump()…

this.sety(provider.x + provider.y)this.sety(provider.x + provider.y)

Page 84: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

84

Detection strategy

> Look for data containers— Classes with only accessors

> Duplicated client code

> Methods using sequence of accessors

Page 85: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

85

Difficulties

> When the moved behavior accessed client data, having extra parameters can lead to complex interface

> Certain classes (Set or Stream) are data containers. Move functionality to provider if— It represents a provider responsibility— It accesses attributes of the provider— The same behavior defined in multiple clients

Page 86: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

86

When Legacy Solution is not a Problem

> A Visitor typically defines behavior that acts on another class

> Configuration classes (global settings, language dependent information..)

> Mapping classes between objects and UI or databases representation

Page 87: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

87

Eliminate Navigation Code

> Problem: How do you reduce the coupling due to classes that navigate object graph?

> Solution: iteratively move behavior close the data

— …however– Systematic uses produce large interfaces (shield collections)– AKA Law of Demeter

Page 88: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

88

Eliminate Navigation Code

…engine.carburetor.fuelValveOpen = true…engine.carburetor.fuelValveOpen = true

Engine+carburetor

Car-engine+increaseSpeed()

Carburetor+fuelValveOpen

Engine-carburetor+speedUp()

Car-engine+increaseSpeed()

…engine.speedUp()…engine.speedUp()

carburetor.fuelValveOpen = truecarburetor.fuelValveOpen = true

Carburetor+fuelValveOpen

Car-engine+increaseSpeed()

Carburetor-fuelValveOpen+openFuelValve()

Engine-carburetor+speedUp()

carburetor.openFuelValve()carburetor.openFuelValve()fuelValveOpen = truefuelValveOpen = true

Page 89: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

89

Detection (i)

> Class with lot of accessors few methods

> Each time a class changes, indirect clients get impacted

> Search for patterns— a.b.c.d.op() identified by

– egrep ‘.*\..*\..*\..’ *.java

— anObject.m1().m2().op() identified by– egrep ‘.*\(\).*\(\).*\(\).’ *.java

Page 90: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

90

Detection (ii)

> Not a problem—(a.isNode()) & (a.isAbstract())

> Beware of disguised navigationToken token;

token = parseTree.token();if (token.identifier() != null){…

if(parseTree.token().identifier() != null){…

Page 91: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

91

When the Legacy Solution is the Solution

> User Interfaces or databases may need to have access to indirect providers

> Brokers or object servers are special objects returning objects

Page 92: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

92

Law of Demeter’s Dark Side

> Can produce large interfaces

Class A instVar: myCollection

A>>do: aBlock myCollection do: aBlock

A>>collect: aBlockmyCollection collect: aBlock

… … …

Page 93: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

93

Split Up God Class

> Problem: How to break a class that controls the complete system logic?

> Solution: Incrementally distribute responsibilities into slave classes

— …however it is difficult to – Identify abstractions in blob– Limit impact of changes on other parts

Page 94: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

94

Detection

> Huge, monolithic class with no clear and simple responsibility

> “The heart of the system”> One single class contains all the logic and control flow> Other classes only serve as passive data holders> Names like “Manager”, “System”, “Root”, “*Controller*” > Changes to the system always entail changes to the

same class

Page 95: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

95

Transformation

> Difficult because God Class is a usually a huge blob> Identify cohesive set of attributes and methods

— Create classes for these sets

> Identify all classes used as data holder and analyze how the god class uses them— Itaeratively Move Behavior close to the Data

> Try to always have a running system before decomposing the God Class— Use accessors to hide the transformation — Use method delegation from the God Class to the providers— Use Façade to minimize change in clients

Page 96: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

96

Strategies

> If God Class does not need to be changed don’t touch it!> Wrap it with different OO views

— but a God Class usually defines the control flow of the application

Page 97: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

Transform Conditionals to Polymorphism

Page 98: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

98

A Map of Reengineering Patterns

Tests: Your Life Insurance

Detailed Model Capture

Initial Understanding

First Contact

Setting Direction

Migration Strategies

Detecting Duplicated Code

Redistribute Responsibilities

Transform Conditionals to Polymorphism

Page 99: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

99

TransformSelf Type Checks

Test providertype

Test self typeTest external

attribute

TransformClient Type Checks

Transform Conditionalsinto Registration

Testnull values Introduce

Null Object

Factor Out Strategy

Factor Out State

Test object state

Transform Conditionals to Polymorphism

Page 100: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

100

Forces

> Requirements change, so new classes and new methods will have to be introduced

> Adding new classes may clutter the namespace

> Conditionals group all the variant in one place but make changes difficult— Conditionals clutter logic— Editing several classes and fixing case statements to introduce

a new behavior is error prone

Page 101: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

101

Overview

> Transform Self Type Checks— eliminates conditionals over type information in a provider by

introducing new subclasses

> Transform Client Checks — eliminates conditionals over client type information by introducing new

method to each provider classes

> Factor out State— kind of Self Type Check

> Factor out Strategy— kind of Self Type Check

> Introduce Null Object— eliminates null tests by introducing a Null Object

> Transform Conditionals into Registration— eliminates conditional by using a registration mechanism

Page 102: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

102

Am()

Client …case Text: this.doSomething()case Border: this.doOther()case D:

…case Text: this.doSomething()case Border: this.doOther()case D:

Transform Self Type Checks

> Symptoms— Simple extensions require many changes in conditional code— Subclassing impossible without duplicating and updating

conditional code— Adding new case to conditional code

Page 103: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

103

Am()

Client …case Text: this.doSomething()case Border:case D:

…case Text: this.doSomething()case Border:case D:

ClientAm()hook()

this.doSomething()this.doSomething()

…this.hook()…this.hook()

Texthook()

Borderhook()

Dhook()

Transformation

Page 104: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

104

Example: Transform Self Type Checks

class Message {private:

int type_; void* data;...void send (Channel* ch) {

switch (type_) {case TEXT : {

ch->nextPutAll(data);break;

}case ACTION : {

ch->doAction(data); ...

Page 105: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

105

Messagesend()

Messagesend()

ActionMessagesend()

TextMessagesend()

switch (type_) {case TEXT : {ch->nextPutAll(data);break;}

case ACTION : {ch->doAction(data);

...

switch (type_) {case TEXT : {ch->nextPutAll(data);break;}

case ACTION : {ch->doAction(data);

...

Client1

Client1

Client2

Client2

Transform Self Type Check

Page 106: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

106

Detection

> Long methods with complex decision logic— Look for attribute set in constructors but never changed— Attributes to model type or finite set constants— Multiple methods switch on the same attribute— grep switch ‘find . -name “*.cxx” -print’

Page 107: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

107

Pros/Cons/Difficulties

> Pros— New behavior are easy to add and to understand: a new class— No need to change different method to add a behavior— All behaviors share a common interface

> Cons— Behavior are dispersed into multiple but related abstractions— More classes

> Difficulties— Not always one to one mapping between cases and subclasses— Clients may be changed to create instance of the right subclass

Page 108: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

108

Ainit()

Clienta : Am()

switch (a.class)case B: a.init(); ((B) a).x();case C: a.init(); ((C)) a).y();Case D: ((D) a).z()

switch (a.class)case B: a.init(); ((B) a).x();case C: a.init(); ((C)) a).y();Case D: ((D) a).z()

Bx()

Cinit()Y()

Dz()

Transform Client Type Checks

> Symptoms— Clients perform explicit type checks / type coercions— Adding a new provider (A subclass) change all clients— Clients are defining logic about providers

Page 109: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

109

Transformation

Ainit()

Clienta : Am()

switch (a.class)case B: a.init(); ((B) a).x();case C: a.init(); ((C)) a).y();Case D: ((D) a).z()

Clienta : Am()

a.doit();a.doit(); Ainit()doit()

Bx()doit()

Cinit()Y()doit()

Dz()doit()

this.init ();this.x();this.init ();this.x();

this.init ();this.y();this.init ();this.y();

this.z();this.z();

Bx()

Cinit()Y()

Dz()

Page 110: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

110

Example: Transform Client Type Checks

void makeCalls (Telephone* phoneArray[]) {for (Telephone *p = phoneArray; p; p++) {

switch (p-> phoneType()) {case TELEPHONE::POTS : {

POTSPhone* potsp =(POTSPhone*)p

potsp->tourne();potsp->call();...

case TELEPHONE::ISDN : {ISDNPhone* isdnp =

(ISDNPhone*)pisdnp->initLine();isdnp->connect();...

Page 111: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

111

TelephoneBoxmakeCall ()

Telephone

POTSPhone...

ISDNPhone...

TelephoneBoxmakeCall ()

TelephonemakeCall()

POTSPhonemakeCall()

...

ISDNPhonemakeCall

...

Transform Client Type Check

Page 112: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

112

Detection

> Transform Self Type Checks> Changing clients of method when new case added> Attribute representing a type

In Smalltalk: isKindOf:, isMemberOf:> In Java: instanceof> x.getClass() == y.getClass()> x.getClass().getName().equals(….)

Page 113: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

113

Pros/Cons/Difficulties

> Pros— The provider offers now a polymorphic interface that can be

used by other clients— A class represent one case— Clients are not responsible of provider logic— Adding new case does not impact all clients

> Cons— Behavior is not group per method but per class

> Difficulties— Refactor the clients (Deprecate Obsolete Interfaces)— Instance creation should not be a problem

Page 114: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

114

When the Legacy Solution is the Solution

> Abstract Factory may need to check a type variable to know which class to instantiate. — For example streaming objects from a text file requires to know

the type of the streamed object to recreate it

> If provider hierarchy is frozen— Wrapping the classes could be a good migration strategy

> Software that interfaces with non-OO libraries— Switch to simulate polymorphic calls

Page 115: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

115

Factor Out Strategy

> Problem: — How do you make a class whose behavior depends on testing

certain value more extensible?

> Solution:— Apply State Pattern— Encapsulate the behavior and delegate using a polymorphic call

Page 116: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

116

Transformation

AbstractStrategy

handleOperation()

Aoperation()

…strategy.handleOperation()…

…strategy.handleOperation()…

StrategyXhandleOperation()

Aoperation()

…case X: …case Z: ….…

…case X: …case Z: ….…

strategy

StrategyZhandleOperation()

Page 117: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

117

Pros/Cons/Difficulties

> Pros— Behavior extension is well-identified— Behavior using the extension is clearer— Change behavior at run-time

> Cons— Namespace get cluterred— Yet another indirection

> Difficulties— Behavior can be difficult to convert and encapsulate (passing

parameter…)

Page 118: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

118

Transform Conditional into Registration

> Problem— How do you reduce the coupling between tools providing

services and clients so that addition/removal of tools does not change client code?

> Solution: Introduce a registration mechanism— Tools register/unregister— Clients query them via the registration repository

Page 119: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

119

Symptoms

> Long methods in clients checking which tools to invoke based on external properties e.g., file extension

> Removing or adding a tool forces you to change client code

> Difficulty to have run-time tool loading / unloading

Page 120: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

120

Transformation (i)

ToolClientread()

XMLReaderopenFile (File)

WordReaderon (file)

suffix := selectedFile suffix = ‘xml’.suffix = ‘xml’

ifTrue: [ XMLReader openFile: selectedFile.

^ self]suffix = ‘doc’

ifTrue: [WordReader on: selectedFile.

^ self].…

suffix := selectedFile suffix = ‘xml’.suffix = ‘xml’

ifTrue: [ XMLReader openFile: selectedFile.

^ self]suffix = ‘doc’

ifTrue: [WordReader on: selectedFile.

^ self].…

Page 121: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

121

Transformation (ii)

XMLReaderopenFile (File)load()unload()

ToolClientread()

(PluginManager uniqueInstance findToolFor: selectedFile suffix) action(PluginManager uniqueInstance findToolFor: selectedFile suffix) action

WordReaderon (file)load()unload()

Pluginactionfor: String use: class with: method

PluginManageradd/remove (Tool)findToolFor (String)

(PluginManager uniqueInstance add: (Plugin for: ‘xml’ use: XMLReader

with: openFile)

(PluginManager uniqueInstance add: (Plugin for: ‘xml’ use: XMLReader

with: openFile)

(PluginManager uniqueInstance remove: (Plugin for: ‘xml’ use: XMLReader

with: openFile)

(PluginManager uniqueInstance remove: (Plugin for: ‘xml’ use: XMLReader

with: openFile)

Page 122: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

122

Pros/Cons/Difficulties

> Pros— New tools can be added without impacting clients— Interaction between tools and clients is normalized— Reduce coupling and support modular design

> Cons— Every tool should register and unregister

> Difficulties— Action should be defined on the tool and not the client anymore,

information should be passed from the client to the tool— Client knew statically the tools, now it is dynamic so more effort

for UI (i.e., consistent menu ordering)

Page 123: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

123

Introduce NullObject

> Problem: — How can you avoid repeated tests for null values?

> Solution: — Encapsulate the null behavior as a separate class that is

polymorphic to the provider

Page 124: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

124

Transformation

AbstractObject

doit()

Clientm()

RealObjectdoit()

nothingnothing

NullObjectdoit()

RealObjectdoit()

Clientm()

…a.doit()…

…a.doit()…

…if (a!=Null) { a.doit()}…

…if (a!=Null) { a.doit()}…

Page 125: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

125

Pros/Cons/Discussions

> Pros— Clients do not need to test for null values

> Difficulties— Different clients may have different null behavior— In strongly typed languages, you have to introduce Null

interface> Hint

— The NullObject does not have to be a subclass of RealObject superclass as soon as it implements RealObject’s null interface (in Java and Smalltalk)

> Do not apply when— Very little code uses direct variable access — Code that checks is well-encapsulated in a single place

Page 126: © Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz Object-Oriented Reengineering Patterns 1 A Map of Reengineering Patterns Tests: Your Life Insurance.

© Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz

Object-Oriented Reengineering Patterns

126

Conclusion

> Navigation Code & Complex Conditionals— Most common lack of OO use

> Polymorphism is key abstraction mechanism— adds flexibility reduces maintenance cost

> Avoid Risk— Only refactor when inferior code must be changed

(cf. God Class)

> Performance?— Small methods with less navigation code are easier to optimise— Deeply nested if-statements cost more than virtual calls

Long case statements cost as much as virtual calls