ICT INF5120 – Modellbasert Systemutvikling F10: Architectural Patterns, Design Patterns and Refactoring Forelesning 31.03.2005 Arne-Jørgen Berre
ICT
INF5120 – Modellbasert Systemutvikling
F10: Architectural Patterns, Design Patterns and Refactoring
Forelesning 31.03.2005Arne-Jørgen Berre
ICT
Agenda
Patterns
GRASP patterns Design principles Design Patterns
Refactoring
ICT
Analysis(Domain)Patterns
Architecture Patterns (Macro Architecture)
Design Patterns (Micro Architecture)
Domain Framework
(OO) Reusable Components
Analysis Design Implementation
Idioms(Language dependent patterns)
Patterns: From Analysis to Implementation
ICT
Patterns on various design levels
Object level patterns: GRASP
Collaboration level patterns: Design Patterns
Module level patterns: Architecture Patterns
Refactoring
ICT
Patterns
Patterns - konsepter og prinsipper Basis GRASP patterns Analyse/Domene patterns Design patterns Arkitektur patterns System integrasjons patterns Refactoring Antipatterns
ICT
Alexander - Patterns
• A way to capture the essence of good architecture• Each pattern describes a problem and its solution• A pattern language is a group of interacting patterns• Difficult in practice - The creative process is as important as
the patterns
Christopher Alexander “A Pattern Language”, Oxford University Press, 1977“The Timeless Way of Building”, 1979
ICT 7
What are patterns? "A solution to a problem in a context"?
Insufficient, says the “Gang of Four” (GOF) What’s missing? 3 things:
Recurrence Teaching (e.g., implementation consequences, trade-offs, and variations) A name
GOF: Patterns contain 4 essential elements
pattern name problem solution consequences
Christopher Alexander (as quoted in the GOF book): "Each pattern describes a problem which occurs over and over
again ... and then describes the core of [a] solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice."
ICT
Pattern Description Template
• Name• Classification• Rationale• Applicability• Description• Diagram• Steps/Process• Implementation• Variants• Examples (incl code)• Discussion
Patterns are ideally describedusing Ooram (UML) role models !!(See later)
ICT
Implementation alternatives
Class Libraries Components Business Objects Frameworks
Delivered through:
- OO Programming Languages
- Distributed Object Technologies (OMG/CORBA,DCOM/ActiveX, J2EE, ..)
ICT
Architectural patterns and style
Architect Christopher Alexander
“Quality without a name” – from The Timeless Way of Building, 1979
A Pattern Language: Towns, Buildings, Construction (Center for Environmental Structure Series), 1977
Ref. SW Engineering later: Design patterns, analysis patterns, architectural patterns
ICT
Arkitekturprinsipper - Trygdeetaten
ICT
Trends: The Waves of Client/Server Technology – towards SOA
Base Source: Client/Server Survival Guide, 1994, 1996 Robert Orfali, Dan Harkey OS/2 Edition, VNR Computer library + AJB update 2005
1982 1986 1990 1994 1998 1999 2000 2001 … 2005
FileServers
Database Servers
Groupware
TP Monitors
DistributedObjects
FirstWave
SecondWave
ThirdWave
OMG CORBACOM/OLEWeb/InternettJava
J2EE/EJBCOM+Corba Comp
Server-sidecomponentsc
MDA, WebServices, .NetService-orientedArchitecture SOAP, XMLWSDL/WSFL
FourthWave
FifthWave
P2PGridAgents,
FIPA
ICT
General Responsibility Assignment
Software Patterns.
Responsibility assignment.1. knowing (answering)2. or, doing
Guidance and evaluation in mechanistic design.
1. Expert1. Expert2. Creator2. Creator3. Controller3. Controller4. Low Coupling4. Low Coupling5. High Cohesion5. High Cohesion6. Polymorphism6. Polymorphism7. Pure Fabrication7. Pure Fabrication8. Indirection8. Indirection9. Don’t Talk to 9. Don’t Talk to StrangersStrangers
ICT
Controller What class should receive a system event message? Assign the responsibility for handling a system event
message to one of these choices:1 The business or “organization” (a façade controller).
2 or, The overall “system” or aggregate concept (a façade controller).
3 or, An artificial class representing the use case (a use case controller).
ICT
Expert
Most general purpose responsibility assignment principle?
Assign a responsibility to the information expert—the class that has the information necessary to fulfill the responsibility.
“That which knows, does”
Who has the most data/information for solving the problem?
ICT
Expert
To “have the information” means, for example, the object may:
know it as an attribute or object reference be able to derive it
What is the motivation for Expert?
Looking for task-owners that support encapsulation and low coupling.
This reduces change impacts.
ICT
High Cohesion
How to design classes to increase the likelihood of reuse and not be overwhelmingly complex?
Assign responsibilities so that cohesion remains high.
ICT
Low Coupling
How to create reusable components that are resilient to change?
Assign responsibilities so that coupling remains low.
ICT
Polymorphism
How to handle alternatives based on type?
When related alternatives or behaviors vary by type (class),
assign responsibility for the behavior—using polymorphic operations—to the types for which the behavior vary.
ICT
Applying Polymorphism
GoSquare
landOnBy( p: Player )
LuxuryTaxSquare
landOnBy( p: Player )
IncomeTaxSquare
landOnBy( p: Player )
Square {abstract}
name : String
...landOnBy( p: Player )...
PlainSquare
landOnBy( p: Player )
ICT
Other GRASP Patterns Creator—who creates?
Usually the aggregate or containing object.
Pure Fabrication— “design” objects. Make it up when desperate.
Indirection— “most problems in computer science …”
Don’t Talk to Strangers—Law of Demeter
1. Expert1. Expert2. Creator2. Creator3. Controller3. Controller4. Low Coupling4. Low Coupling5. High Cohesion5. High Cohesion6. Polymorphism6. Polymorphism7. Pure Fabrication7. Pure Fabrication8. Indirection8. Indirection9. Don’t Talk to 9. Don’t Talk to StrangersStrangers
for more information...for more information...
ICT
Quick overview of Design Principles
The Open-Closed Principle by Bertrand Meyer
The Dependency Inversion Principle by Robert C. Martin
The Liskov Substitution Principle by Barbara Liskov
The Interface Segregation Principle by Robert C. Martin
ICT
The Open-Closed Principle
Software should be “open” for extension but “closed” to modification
The goal is to design software that be easily extended without changing any of the existing code
Inheritance and the development of abstract base classes play a big role in trying to fulfill this goal
ICT
The Dependency Inversion Principle
High-level modules should not depend on low-level modules. Both should depend on abstractions
Abstractions should not depend on details. Details should depend on abstractions
ButtonClient
Lamp
Button
PushButton
Button and ButtonClient can Button and ButtonClient can now vary independently!now vary independently!
ICT
The Liskov Substitution Principle
Functions that use base class interfaces must not depend on or be confused by any derivatives of those interfaces
A logical extension of the Open-Closed Principle All subclasses should implement the interface of the base class in a
manner consistent with the intent of the base class
ICT
The Interface Segregation Principle
Clients should not be forced to depend on interfaces that they do not use
The principle here is to avoid cluttering up an interface with things (functions, inheritance relationships) that the clients don’t need to use
Take a clients’ perspective!!
ICT
Refactoring support in IntelliJ IDEA
IDE with Support for Refactoring
http://www.jetbrains.com/idea/
Rename refactorings allow to rename specified packages, classes, methods, fields, local variables and method parameters, with automatic corrections of all references in the code.
Move refactorings allow users to move specific packages to another packages, classes to another packages, class members to other classes and inner classes to upper hierarchy levels, with automatic corrections to all references in the code.
ICT
Patterns – Abstract Factory
ICT
Design patterns (with UML & Java examples)
Based on: Gamma/Helm/Johnson/Vlissides (GoF): Design Patterns, 1995R. Ryan:, D. Rosenstrauch:Design Patterns in Java, 1997
ICT 30
What are patterns?
"A solution to a problem in a context"? Insufficient, says the “Gang of Four” (GOF) What’s missing? 3 things:
Recurrence Teaching (e.g., implementation consequences, trade-offs, and variations) A name
GOF: Patterns contain 4 essential elements
pattern name problem solution consequences
Christopher Alexander (as quoted in the GOF book): "Each pattern describes a problem which occurs over and over again ... and then
describes the core of [a] solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice."
ICT
Design Pattern
A design pattern describes a basic scheme for structuringsubsystems and components of a software architecture aswell as their relationships. It identifies, names, and abstractsa common structural or functional principle by describingits different parts, their collaboration and responsibilities.
ICT
GOF (Gang of Four) 23 Patterns
Creational Patterns (5) Abstract FactoryAbstract Factory, Builder, Factory Method, Prototype,
Singleton Structural Patterns (7) Adapter, Bridge, CompositeComposite, Decorator, Façade,
Flyweight, Proxy Behavioural Patterns (11) Chain of responsibility, Command, Interpreter,
Iterator, Mediator, Memento, ObserverObserver, State, Strategy, Template method, Visitor
ICT 33
Skylight Spelunker
“Skylight Spelunker” is a Java framework for a file browser similar in appearance to the “Windows Explorer” included with Windows 98.
Spelunker has two views: Disks and folders in tree structure (FolderView - Left pane) All contents of selected folder (ContentsView - Right pane)
Spelunker provides support for : Multiple ways of arranging ContentsView icons Accessing network drives as well as local Deleting, renaming and viewing disk contents
ICT 34
Windows Explorer Screen Shot
FolderView ContentsView
ICT 35
Patterns in Spelunker example
Composite used to model the file tree data structure
Strategy used to layout the file and folder icons in ContentsView
Observer used to re-display FolderViews and ContentsViews after user
requests
Proxy and State used to model password-protected network disk drives
Command used to carry out user requests
ICT 36
The “Composite” pattern
Problem What is the best way to model the Spelunker file tree?
The Spelunker file tree is a classic tree structure. Thus we need a leaf class (File) and a tree class (Folder) which contains pointers to the Files and Folders in it.
However, there are many operations that are relevant to both a File and a Folder (e.g., getSize()).
The user doesn’t treat Files and Folders differently, so why should calling modules have to?
The design would be less complex and more flexible if the calling module could initiate operations on a target object, without knowing whether the target was a File or a Folder.
File and Folder should share a common interface.
ICT 37
The “Composite” pattern
How the pattern solves the problem Intent
“Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.” [GHJV94]
Explanation The Composite pattern works by having leaf and tree objects share a
common interface. Create an abstract base class (or interface) that represents both File
and Folder. Files and Folders need to provide implementations for the same
operations, but they can implement them differently. E.g., leaves usually handle an operation directly, while trees usually
forward the operation to its children (and/or perform additional work before or after forwarding)
ICT 38
The “Composite” pattern
How the pattern solves the problem, cont. Gang of Four UML [GHJV94]
children
Leaf
Operation( )
Client
Composite
Operation( )Add(Component)Remove(Component)GetChild(int)
Component
Operation( )Add(Component)Remove(Component)GetChild(int)
for all g in children g.Operation();
ICT 39
The “Composite” pattern
Use of the pattern in Spelunker Both File and Folder share a common interface: Node. Spelunker UML
children
File
getSize( )
Resource Tree
Folder
getSize()getContents()
Node
getSize( )
size =total of sizeof each child
ICT 40
The “Composite” pattern
Use of the pattern in Spelunker, cont. Code examples
public class File extends Node{ private long size = 0; public long getSize() { return size; }}public class Folder extends Node{ private Vector contents; public long getSize() { long size = 0; if (contents != null) { Enumeration e = contents.elements(); while (e.hasMoreElements()) { size += ((Node)e.nextElement()).getSize(); } } return size; }}
ICT 41
The “Strategy” pattern
Problem The way in which the icons are arranged varies according to user
preference - the user may choose an iconic view only, or a short/long detail view.
Including the algorithms to arrange the icons as methods in ContentsView would make it cumbersome to add new icon arrangement algorithms to ContentsView; ContentsView would have to be subclassed and some implementation details might have to be unnecessarily exposed.
A switch statement would most likely be used to choose the correct arrangement algorithm.
ICT 42
The “Strategy” pattern
How the pattern solves the problem Intent
“Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.” [GHJV94]
Explanation The algorithms for arranging the icons are encapsulated into a
separate interface. The correct arrangement algorithm is chosen polymorphically. ContentsView neither knows nor cares which arrangement is
presently in use.
ICT 43
The “Strategy” pattern
How the pattern solves the problem, cont. Gang of Four UML [GHJV94]
Strategy
AlgorithmInterface()
ConcreteStrategyC
AlgorithmInterface()
ConcreteStrategyB
AlgorithmInterface()
Context
ContextInterface()
strategy
ConcreteStrategyA
AlgorithmInterface()
ICT 44
The “Strategy” pattern
Use of the pattern in Spelunker ContentsView delegates the task of arranging the icons to ViewManager.
Spelunker UML
ViewManager
updateVisibleNodes()
ListViewManager
updateVisibleNodes()
IconViewManager
updateVisibleNodes()
ContentsView
updateVisibleNodes()
strategy
ICT 45
The “Strategy” pattern
Use of the pattern in Spelunker, cont. Code examples
public class ContentsView extends ResourceTreeView{ private ViewManager viewManager;
public void showIconView() { viewManager = new IconViewManager(this); }
public void showListView(boolean showDetail) { viewManager = new ListViewManager(this, showDetail); }
public void updateVisibleNodes(Folder activeFolder) { viewManager.updateVisibleNodes(activeFolder); }}
public interface ViewManager{ public void updateVisibleNodes(Folder activeFolder);}
ICT 46
The “Observer” pattern
Problem What is the best way to keep all views of the file tree in sync?
We need to be able to re-draw the display window after the user modifies a file/folder (e.g., when user clicks on a folder to select it)
However, there may be several windows and panes that display the same file/folder. We need to re-draw all of them.
To do this, the tree needs to keep a list of all of its views, and notify each one after a modification is done.
However, the tree and view objects might: have little other relationship besides this notification need to have their code modified independently need to be reused separately
So it would be preferable not to make them too tightly coupled to each other.
ICT 47
The “Observer” pattern
How the pattern solves the problem Intent
“Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.” [GHJV94]
Explanation The Observer pattern works by defining an abstract class (or
interface) with a single method signature. The method will be used as a mechanism for “observer” objects to be notified of changes in their “subject”.
Concrete observer sub-classes will each provide their own implementation of what to do when the notification occurs.
The subject can notify each observer the same way, without caring which specific sub-class of observer the object actually is.
ICT 48
The “Observer” pattern
How the pattern solves the problem, cont. Gang of Four UML [GHJV94]
subject
observers
Observer
Update( )
Subject
Attach(Observer)Detach(Observer)Notify( )
ConcreteSubjectSubjectState
GetState( )
ConcreteObserverObserverStateUpdate( )
return SubjectState ObserverState = subject.GetState()
for all o in observers o.update();
ICT 49
The “Observer” pattern
Use of the pattern in Spelunker ResourceTree notifies all ResourceTreeViews whenever its
state is modified. Spelunker UML
ResourceTreeObserver
subject
observers
resourceTreeChanged(Folder)
ResourceTreeactiveFolderAttachObserver(ResourceTreeObserver)DetachObserver(ResourceTreeObserver)NotifyObservers( )
ResourceTreeView
updateVisibleNodes(activeFolder);repaint();Enumeration e = observers.elements();
while (e.hasMoreElements()) { ResourceTreeObserver o = (ResourceTreeObserver)e.nextElement(); o.resourceTreeChanged(activeFolder);}
resourceTreeChanged( Folder activeFolder)
ICT 50
The “Observer” pattern
Use of the pattern in Spelunker, cont. Code examples
public class ResourceTree { private Vector observers; public void setActiveFolder(Folder folder) { if (activeFolder != folder) { activeFolder = folder; notifyObservers(); } } public void notifyObservers() { Enumeration e = observers.elements(); while (e.hasMoreElements()) { ((ResourceTreeObserver)e.nextElement()).resourceTreeChanged(activeFolder); } }}public abstract class ResourceTreeView extends Panel implements ResourceTreeObserver { public void resourceTreeChanged(Folder activeFolder) { updateVisibleNodes(activeFolder); repaint(); }}
ICT 51
The “Proxy” pattern
Problem Network drives might require the user to login before the drive can
be accessed - however, the protocol for accessing a network drive when logged in might not differ from accessing a local drive.
LocalDrive should not contain network code - this code should be moved to a separate class, i.e. NetworkDrive.
Creating NetworkDrive as a subclass of LocalDrive would be complicated and unwieldy - we would have to check access everytime a drive operation was requested.
Creating NetworkDrive as a subclass of Folder would force us to duplicate all drive access operations already in LocalDrive.
ICT 52
The “Proxy” pattern
How the pattern solves the problem Intent
“Provide a surrogate or placeholder for another object to control access to it.” [GHJV94]
“A Protection Proxy controls access to the original object. Protection Proxies are useful when objects should have different access rights.” [GHJV94]
Explanation The network protocols necessary for logging in and out are
moved into a subclass of Folder called NetworkDrive. NetworkDrive contains the code necessary for logging in and
out of a network drive. After logging in, NetworkDrive delegates drive access requests
to LocalDrive (indirectly through ConnectionState).
ICT 53
The “Proxy” pattern
How the pattern solves the problem, cont. Gang of Four UML [GHJV94]
Subject
Request()
Proxy
Request()
RealSubject
Request()
realSubject
...RealSubject->Request();...
ICT 54
The “Proxy” pattern
Use of the pattern in Spelunker NetworkDrive acts as a Proxy for a remote LocalDrive. Spelunker UML
Note:NetworkDrive delegates to LocalDrive indirectly through ConnectionOpenedState.
Folder
getContents()
NetworkDrive
getContents()
LocalDrive
getContents()
realSubject
...localDrive.getContents();...
ICT 55
The “Proxy” pattern
Use of the pattern in Spelunker, cont. Code examples
public class NetworkDrive extends Folder{ private ConnectionState connectionState; public Vector getContents(Folder folder) { return connectionState.getContents(folder); }}public class ConnectionOpenedState extends Object implements ConnectionState{ private LocalDrive localDrive; public Vector getContents(Folder folder) { return localDrive.getContents(folder); }}
ICT 56
The “State” pattern
Problem What is the best way to perform password-protection processing
on network drives? Network drives need to act differently depending on whether the user
has logged in or not; e.g., the user cannot examine or modify a network drive until they log in.
This can be accomplished by checking a condition before executing each operation; e.g., “if (loggedIn())”. But this is ugly code, as well as being inefficient and repetitive.
This is also difficult to extend: what if we need to implement another set of checks for another condition; e.g., “if (!disconnected())”?
The design would be less complex and more flexible if we could isolate in one location all behavior related to a particular state of the object.
ICT 57
The “State” pattern
How the pattern solves the problem Intent
“Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.” [GHJV94]
Explanation The State pattern works by creating an abstract class (or interface) with
method signatures for every state-dependent operation in the main object, and concrete sub-classes that provide implementations for these methods. The main object then delegates each of these operations to the state object it is currently using.
Each state class can implement each operation in its own way (e.g., perform unique processing, disallow the operation, throw an exception, etc.).
The main object can change its behavior by changing the state object it is using.
This is a very clean design - and also extendible: we can simply add new state classes to add additional behavior, without modifying the original object.
ICT 58
The “State” pattern
How the pattern solves the problem, cont. Gang of Four UML [GHJV94]
state
Context
Request( )
ConcreteStateB
HandleRequest( )
State
HandleRequest( )
ConcreteStateA
HandleRequest( )state.HandleRequest()
ICT 59
The “State” pattern
Use of the pattern in Spelunker The NetworkDrive delegates operations to its
ConnectionState. Spelunker UML
state
NetworkDrive
getContents()
ConnectionClosedState
getContents( )
ConnectionState
getContents( )
ConnectionOpenedState
getContents( )
return connectionState.getContents()
changeState(ConnectionState)
ICT 60
The “State” pattern
Use of the pattern in Spelunker, cont. Code examples
public class ConnectionClosedState implements ConnectionState { public void login() { LocalDrive localDrive = null; // login and initiate localDrive networkDrive.changeState(new ConnectionOpenedState(networkDrive, localDrive)); } public Vector getContents(Folder folder) { login(); return networkDrive.getContents(folder); }}public class ConnectionOpenedState implements ConnectionState { public void login() { // display error } public Vector getContents(Folder folder) { return localDrive.getContents(folder); }}
ICT 61
The “Command” pattern
Problem A request might need access to any number of classes. The initiator of the request should not be tightly coupled to
these classes. Requests should be storable to support undoable
operations; therefore, requests must be accessible through some common interface.
How do we implement requests without coupling them to the initiator or target, or requiring the initiator to know the implementation details of the request ?
Implementing the code for all requests in one class would centralize the application and make it difficult to create new requests.
ICT 62
The “Command” pattern
How the pattern solves the problem Intent
“Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.” [GHJV94]
Explanation Places the implementation of a request into a separate class. Initiators of the request do not know any implementation details of the
request - they simply fire it off by calling the execute() method. The targets of the request do not need to know anything about the
request. All requests are accessible through a common interface. The correct implementation is chosen polymorphically.
ICT 63
The “Command” pattern
How the pattern solves the problem, cont. Gang of Four UML [GHJV94]
Command
Execute()
ConcreteCommand
Execute()
Receiver
Action()receiver
Client Invoker
receiver->Action();
state
ICT 64
The “Command” pattern
Use of the pattern in Spelunker Used to implement user operations on files and folders. Spelunker UML
Command
execute()
DeleteCommand
execute()
ContentsView
getSelectedNodes()receiver
SkylightSpelunker
CommandButton
...Vector selectedNodes = contentsView.getSelectedNodes();...if (!node.deleteNode(node)) {...
ICT 65
The “Command” pattern
Use of the pattern in Spelunker, cont. Code examples
public class CommandButton extends Button { private Command command; public CommandButton(String label, Command command) { super(label); this.command = command; } public boolean action(Event e, Object what) { command.execute(); return super.action(e, what); }}
public class DeleteCommand extends Command { private ContentsView contentsView; private ResourceTree resourceTree; public void execute() { (code for retrieving all selected Nodes from ContentsView and deleting them) }}
public abstract class Command extends Object { public abstract void execute();}
ICT
Basis Litteratur (Pattern kataloger)
Design Patterns, Elements of Reusable Object-Oriented SoftwareGamma et. al. Addison-Wesley, ISBN 0-201-63361-2
Analysis Patterns, Reusable Object ModelsMartin Fowler, Addison-Weslwy, ISBN 0-201-89542-0
Pattern-Oriented Software ArchitectureF. Buschmann et. al, J. Wiley, ISBN 0-471-95869-7
http://st-www.cs.uiuc.edu/users/patterns/patterns.html http://c2.com/ppr/index.html
AntiPatterns - Refactoring Software, Architectures, and Projects in CrisisW. Brown et. al, J. Wiley, ISBN 0-471-19713-0
ICT
Tilleggs litteratur
Design Patterns for Object-Oriented Software Development,Pree, Addison-Wesley, ISBN 0-201-42294-8, 1995
CORBA Design Patterns, T. Mowbray, R. Malveau, j. Wiley, 1997, ISBN 0-471-15882-8
Communications of ACM, “Software Patterns” - special issueOctober 1996, Vol. 39, Number 10
Pattern Languages of Program Design 1J. Coplien, Douglas SchmidtAddison-Wesley, ISBN 0-201-60734-4, 1995
Pattern Languages of Program Design 2J. Vlissides, J. Coplien, N. KerthAddison-Wesley, ISBN 0-201-89527-7, 1996
ICT
Refactoring - Improving the design of existing code
1. Refactoring - a first example 2. Principles in refactoring 3. Bad Smells in Code 4. Building Tests 5. Toward a catolog of refactorings 6. Composing Methods 7. Moving Features between objects 8. Organizing data 9. Simplifying Conditional Expressions 10. Making Method calls simpler 11. Dealing with Generalization 12. Big Refactorings 13. Refactoring, Reuse and Reality 14. Refactoring tools
M. Fowler, with K. Beck, J. Brant, W. Opdyke, D. Roberts, Addison-Wesley, August 1999
Refactoring: Improving the design of existing code
ICT
Refactoring - What and Why ?
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.
Improving to make it easier to understand and cheaper to modify
ICT
When should you refactor
The rule of three - Three strikes and you refactor Refactor when you add function Refactor when you need to fix a bug Refactor as you do a code review
ICT
Why refactoring works
Programs that are hard to read are hard to modify Programs that have duplicated logic are hard to modify Program that require additional behaviour that requries
you to change running code are hard to modify Programs with complex conditional logic are hard to
modify
We want programs that are easy to read, that have all logic specified in one and only one place, do not allow changes to endanger existing behaviour, and allow conditional logic to be expressed as simply as possible
ICT
Refactoring strategies
Composing Methods Moving features between objects Organizing data Simplifying conditional expressions Making method calls simpler Dealing with generalization Big refactorings
ICT
Composing Methods
Extract method Inline method Inline temp Replace temp with query Introduce explaining variable Split temporary variable Remove assignments to parameters Replace method with method object Substitute algorithm
ICT
Moving Features between objects
Move method Move field Extract Class Inline Class Hide Delegate Remove middle man Introduce foreign method Introduce local extension
ICT
Bad Smells in Code (1/4)
Duplicated Code (extract method, extract class, pull up method, form template method)
Long Method (extract method, replace temp with query, replace method with method object, decompose conditional)
Large Class (extract class, extract subclass, extract interface, replace data value with object)
Long ParameterList (replace parameter with method, introduce parameter object, preserve whole object)
Divergent Change (extract class)
ICT
Bad Smells in Code (2/4)
Shotgun Surgery (move method, move field, inline class) Feature Envy (move method, move field, extract field) Data Clumps (extract class, introduce parameter object,
preserve whole object) Primitive Obsession (replace data value with object, extract
class, introduce parameter object, replace array with object, replace type code with class/subclasses, replace type code with state/strategy)
Switch Statements (replace conditional with polymorphism, replace type code with subclasses/state/strategy, replace parameter with explicit methods, introduce null object)
ICT
Bad Smells in Code (3/4)
Parallell Inheritance Hierarchies (move method, move field)
Lazy Class (inline class, collapse hierarchy) Speculative Generality (collapse hierarchy, inline
class, remove parameter, rename method) Temporary Field (extend class, introduce null
object) Message Chains (hide delegate) Middle Man (remove middle man, inline method,
replace delegation with inheritance) Inappropriate Intimacy (move method, move field,
change bidirection to unidirectional)
ICT
Bad Smells in Code (4/4)
Alternative classes with different interfaces (rename method, move method)
Incomplete Library Class (introduce foreign method, introduce local extension)
Data Class (move method, encapsulate field, encapsulate collection)
Refused Bequest (replace inheritance with delegation)
Comments (extract method, introduce assertion)
ICT
Organizing data Self encapsulate field Replace data value with object Change value to reference Change reference to value Replace array with object Duplicate observed data Change unidirectional association to bidirectional Change bidirectional association to unidirectional Replace magic number with symbolic constant Encapsulate field Encapsulate collection Replace record with data class Replace type code with class/sublasses Replace type code with state/strategy Replace subclass with fields
ICT
Simplifying Conditional Expressions
Decompose conditional Consolidate conditional expression Consolidate duplicate conditional fragments Remove control flag Replace nested conditional with guard clauses Replace conditional with polymorphism Introduce null object Introduce assertion
ICT
Making Method calls simpler Rename method Add parameter Remove parameter Separate query from modifier Parameterize method Replace parameter with explicit methods Preserve whole object Replace parameter with method Introduce parameter object Remove setting method Hide method Replace constructor with factory method Encapsulate downcast Replace error code with exception Replace exception with test
ICT
Dealing with Generalization
Pull up field Pull up method Pull up constructor body Push down method Push down field Extract subclass Extract superclass Extract interface Collapse hierarchy Form template method Replace inheritance with delegation Replace delegation with inheritance
ICT
Big refactorings
Tease apart inheritance Convert procedural design to objects Separate domain from presentation Extract hierarchy
ICT
The rhythm of refactoring ...
test, small change, test, small change, test, ….
… allows refactoring to move quickly and safely
ICT
AntiPatterns
Refactoring Software, Architectures , and Projects in Crisis: W. Brown, R. Malveau. H. McCormick, T. Mowbray, Wiley, 1998
AntiPattern: A commonly occuring patterns or solution that generates decidely negative consequences. An AntiPatterns may be a pattern in the wrong context. When properly documented, an AntiPattern comprises a paired AntiPattern solution with a refactored solution.
ICT
Software Development AntiPatterns The Blob (from the film) Continuous Obsolescence Lava Flow Ambiguous Viewpoint Functional Decomposition Poltergeists Boat Anchor Golden Hammer Dead End Spaghetti Code Input Kludge Walking through a Minefield Cut-and-Paste Programming Mushrooom management
ICT
Software Architecture AntiPatterns
Autogenerated Sovepipe Stovepipe Enterprise Jumble Stovepipe System Cover your Assets Vendor Lock-In Wolf Ticket Architecture by Implication Warm bodies Design by Committee Swiss Army Knife Reinvent the Wheel The Grand Old Duke of York
ICT
Software Project Management AntiPatterns
Blowhard Jamboree Analysis Paralysis Viewgraph Engineering Death by Planning Fear of Success Corncob Intellectual Violence Irrational Management Smoke and Mirrors Project Mismanagement Throw it over the wall Fire Drill The Feud E-mail is dangerous
ICT
Practical Refactoring exercise
ICT
Example:Video rental Bad smells: Long Method Feature Envy Switch statements Temporary Fields Support change ?: Add HTML
statement, change classification of films
C us to m er1
+ s ta te m e n t()
R e n ta l1
da ys R e n te d : in t
0 ..* 10 ..* 1
Mo vie 1
p rice C o d e : in t1 0 ..*1 0 ..*
ICT
extract from statement()
public String statement() {
/ ….. Determine amounts for each rental Switch (each.getMovie().getPriceCode()) { case Movie.REGULAR thisAmount += 2; …..
// add frequent renter pointsfrequentRenterPoints ++;
if (each.getMovie().getPriceCode() -----
// show figures for this rental
// add footer lines
}
ICT
Refactorings:Video rental
Create Tests to check refactoring correctness Decomposing and redistributing the statement
method (extract method, moving the amount calculation amountFor() (move the method from customer to rental), rename variables (I.e each -> aRental)
similar: extracting frequent renter points, removing temps (totals) replaceTempWithQuery totalAmount/freqRentPoint,
ICT
Extracting and Moving methods
Custom er1
+ s tatem ent()
Rent al1
daysRented : int
get Cha rge()getFreqRentP oints ()
0..* 10..* 1
M ovie1
priceCode : int1 0..*1 0..*
Cus tom er1
+ s tatem ent()+ getTotalCharge()+ getTotFreqRentP oints ()
Rental1
daysRente d : i nt
getCharge()getFreqRentP oi nts ()
0..* 10..* 1
Movie1
pri ceCode : i nt1 0..*1 0..*
ICT
Move calculation of charge and pointsto the “expert”
Cus tom er1
+ s tatem e nt()+ getTotalCharge()+ getTotFreqRentP oints ()
Rental1
da ysRented : i nt
getCharge()ge tFreqRentP oi nts ()
0..* 10..* 1
M ovie1
priceCode : int
getCharge(days : int)getFreqRentP oints (days : int)
1 0. .*1 0. .*
ICT
Refactorings:Video rental
replace conditional logic on price code with polymorphism, using inheritance - problem: a movie can change its classification during its lifetime -> use the state pattern for price code object (or strategy) -> replace type code with state/strategy, move method (switch into price class), replace conditional with polymorphism to eliminate switch
ICT
Cus tom er1
+ s tatem ent()+ getTotalCharge()+ getTotFreqRentP oints ()+ htm ls tatem ent()
R ent al1
daysRented : int
get Ch arge()get FreqRentP oin ts ()
0..* 10..* 1
ChildrensP rice
getCharge(days : int)
NewReleas eP rice
getCharge(days : int)getFreqRentP oints (days : int)
RegularP rice
getCharge(days : int)
M ovie1
priceCode : int
getCharge(days : int)getFreqRentP oints (days : int)
1
0..*
1
0..*
P r ice
getCharge(days : int)getFreqRentP oints (days : int)
11