oorpt object-oriented reengineering patterns and techniques 8. restructuring prof. o. nierstrasz

63
OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

Post on 20-Dec-2015

220 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

OORPTObject-Oriented Reengineering Patterns and Techniques

8. Restructuring

Prof. O. Nierstrasz

Page 2: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.2

Roadmap

> Redistribute Responsibilities> Transform Conditionals to Polymorphism

Page 3: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.3

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 4: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.4

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 5: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.5

Roadmap

> Redistribute Responsibilities— The Law of Demeter— Move Behaviour Close to Data— Eliminate Navigation Code— Split Up God Class

> Transform Conditionals to Polymorphism

Page 6: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.6

Redistribute Responsibilities

Eliminate Navigation Code

Data containers

Monster client ofdata containers

Split Up God Class

Move Behaviour Close to Data

Chains of datacontainers

Page 7: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.7

Roadmap

> Redistribute Responsibilities— The Law of Demeter— Move Behaviour Close to Data— Eliminate Navigation Code— Split Up God Class

> Transform Conditionals to Polymorphism

Page 8: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.8

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 9: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.9

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 10: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.10

Roadmap

> Redistribute Responsibilities— The Law of Demeter— Move Behaviour Close to Data— Eliminate Navigation Code— Split Up God Class

> Transform Conditionals to Polymorphism

Page 11: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.11

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 12: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.12

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 13: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.13

Detection strategy

> Look for data containers— Classes with only accessors

> Duplicated client code

> Methods using sequence of accessors

Page 14: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.14

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 15: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.15

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 16: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.16

Roadmap

> Redistribute Responsibilities— The Law of Demeter— Move Behaviour Close to Data— Eliminate Navigation Code— Split Up God Class

> Transform Conditionals to Polymorphism

Page 17: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.17

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 18: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.18

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 19: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.19

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 20: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.20

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 21: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.21

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 22: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.22

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 23: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.23

Roadmap

> Redistribute Responsibilities— The Law of Demeter— Move Behaviour Close to Data— Eliminate Navigation Code— Split Up God Class

> Transform Conditionals to Polymorphism

Page 24: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.24

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 25: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.25

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 26: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.26

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 27: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.27

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 28: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.28

Roadmap

> Redistribute Responsibilities> Transform Conditionals to Polymorphism

— Transform Self Type Checks— Transform Client Checks — [Factor out State]— Factor out Strategy— Introduce Null Object— Transform Conditionals into Registration

Page 29: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.29

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 30: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.30

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 31: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.31

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 32: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.32

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 33: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.33

Roadmap

> Redistribute Responsibilities> Transform Conditionals to Polymorphism

— Transform Self Type Checks— Transform Client Checks — [Factor out State]— Factor out Strategy— Introduce Null Object— Transform Conditionals into Registration

Page 34: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.34

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 35: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.35

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 36: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.36

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 37: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.37

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 38: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.38

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 39: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.39

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 40: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.40

Roadmap

> Redistribute Responsibilities> Transform Conditionals to Polymorphism

— Transform Self Type Checks— Transform Client Checks — [Factor out State]— Factor out Strategy— Introduce Null Object— Transform Conditionals into Registration

Page 41: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.41

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 42: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.42

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 43: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.43

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 44: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.44

TelephoneBoxmakeCall ()

Telephone

POTSPhone...

ISDNPhone...

TelephoneBoxmakeCall ()

TelephonemakeCall()

POTSPhonemakeCall()

...

ISDNPhonemakeCall

...

Transform Client Type Check

Page 45: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.45

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 46: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.46

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 47: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.47

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 48: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.48

Roadmap

> Redistribute Responsibilities> Transform Conditionals to Polymorphism

— Transform Self Type Checks— Transform Client Checks — [Factor out State]— Factor out Strategy— Introduce Null Object— Transform Conditionals into Registration

Page 49: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.49

Factor Out Strategy

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

certain values more extensible?

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

Page 50: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.50

Transformation

AbstractStrategy

handleOperation()

Aoperation()

…strategy.handleOperation()…

…strategy.handleOperation()…

StrategyXhandleOperation()

Aoperation()

…case X: …case Z: ….…

…case X: …case Z: ….…

strategy

StrategyZhandleOperation()

Page 51: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.51

Pros/Cons/Difficulties

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

> Cons— Namespace get cluttered— Yet another indirection

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

parameter…)

Page 52: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.52

Roadmap

> Redistribute Responsibilities> Transform Conditionals to Polymorphism

— Transform Self Type Checks— Transform Client Checks — [Factor out State]— Factor out Strategy— Introduce Null Object— Transform Conditionals into Registration

Page 53: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.53

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 54: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.54

Transformation

AbstractObject

doit()

Clientm()

RealObjectdoit()

nothingnothing

NullObjectdoit()

RealObjectdoit()

Clientm()

…a.doit()…

…a.doit()…

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

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

Page 55: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.55

Pros/Cons/Discussions

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

> Difficulties— Different clients may have different null behavior— In statically 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 56: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.56

Roadmap

> Redistribute Responsibilities> Transform Conditionals to Polymorphism

— Transform Self Type Checks— Transform Client Checks — [Factor out State]— Factor out Strategy— Introduce Null Object— Transform Conditionals into Registration

Page 57: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.57

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 58: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.58

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 59: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.59

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 60: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.60

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 61: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.61

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 62: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.62

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

Page 63: OORPT Object-Oriented Reengineering Patterns and Techniques 8. Restructuring Prof. O. Nierstrasz

© Stéphane Ducasse, Serge Demeyer, Oscar Nierstrasz

OORPT — Restructuring

8.63

License

> http://creativecommons.org/licenses/by-sa/2.5/

Attribution-ShareAlike 2.5You are free:• to copy, distribute, display, and perform the work• to make derivative works• to make commercial use of the work

Under the following conditions:

Attribution. You must attribute the work in the manner specified by the author or licensor.

Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

• For any reuse or distribution, you must make clear to others the license terms of this work.• Any of these conditions can be waived if you get permission from the copyright holder.

Your fair use and other rights are in no way affected by the above.

Attribution-ShareAlike 2.5You are free:• to copy, distribute, display, and perform the work• to make derivative works• to make commercial use of the work

Under the following conditions:

Attribution. You must attribute the work in the manner specified by the author or licensor.

Share Alike. If you alter, transform, or build upon this work, you may distribute the resulting work only under a license identical to this one.

• For any reuse or distribution, you must make clear to others the license terms of this work.• Any of these conditions can be waived if you get permission from the copyright holder.

Your fair use and other rights are in no way affected by the above.