ST Refactoring and Design Patterns 9 Refactoring and

  • Slides: 51
Download presentation
ST — Refactoring and Design Patterns 9. Refactoring and Design Patterns © Oscar Nierstrasz

ST — Refactoring and Design Patterns 9. Refactoring and Design Patterns © Oscar Nierstrasz

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring?

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring? > The Law of Demeter > Common Code Smells > Design Patterns > The Singleton Pattern © Oscar Nierstrasz 2

ST — Refactoring and Design Patterns Literature > Martin Fowler, Kent Beck, John Brant,

ST — Refactoring and Design Patterns Literature > Martin Fowler, Kent Beck, John Brant, William Opdyke and Don Roberts, Refactoring: Improving the Design of Existing Code, Addison Wesley, 1999. > Serge Demeyer, Stéphane Ducasse and Oscar Nierstrasz, Object. Oriented Reengineering Patterns, Morgan Kaufmann, 2002. > Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, Addison Wesley, Reading, Mass. , 1995. > Sherman R. Alpert, Kyle Brown and Bobby Woolf, The Design Patterns Smalltalk Companion, Addison Wesley, 1998. © Oscar Nierstrasz 3

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring?

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring? > The Law of Demeter > Common Code Smells > Design Patterns > The Singleton Pattern © Oscar Nierstrasz 4

ST — Refactoring and Design Patterns The Open-Closed Principle > Software entities should be

ST — Refactoring and Design Patterns The Open-Closed Principle > Software entities should be open for extension but closed for modifications. — Design classes and packages so their functionality can be extended without modifying the source code © Oscar Nierstrasz 5

ST — Refactoring and Design Patterns The Object Manifesto > Delegation and encapsulation: —

ST — Refactoring and Design Patterns The Object Manifesto > Delegation and encapsulation: — “Don’t do anything you can push off to someone else. ” — “Don’t let anyone else play with you. ” – © Oscar Nierstrasz Joseph Pelrine 6

ST — Refactoring and Design Patterns The Programmer Manifesto > Once and only once

ST — Refactoring and Design Patterns The Programmer Manifesto > Once and only once — Avoiding writing the same code more than once > Don’t ask, tell! My. Window>>display. Object: a. Gr. Object is. Square if. True: […] a. Gr. Object is. Circle if. True: […] … My. Window>>display. Object: a. Gr. Object display. On: self © Oscar Nierstrasz 7

ST — Refactoring and Design Patterns Good Signs of OO Thinking > Short methods

ST — Refactoring and Design Patterns Good Signs of OO Thinking > Short methods — Simple method logic > Few instance variables > Clear object responsibilities — State the purpose of the class in one sentence — No super-intelligent objects — No manager objects © Oscar Nierstrasz 8

ST — Refactoring and Design Patterns Some Principles > The Dependency Inversion Principle —

ST — Refactoring and Design Patterns Some Principles > The Dependency Inversion Principle — Depend on abstractions, not concrete implementations – Write to an interface, not a class > The Interface Segregation Principle — Many small interfaces are better than one “fat” one > The Acyclic Dependencies Principle — Dependencies between package must not form cycles. – Break cycles by forming new packages http: //www. objectmentor. com/resources/articles/Principles_and_Patterns. PDF © Oscar Nierstrasz 9

ST — Refactoring and Design Patterns Packages, Modules and other > The Common Closure

ST — Refactoring and Design Patterns Packages, Modules and other > The Common Closure Principle — Classes that change together, belong together – Classes within a released component should share common closure. That is, if one needs to be changed, they all are likely to need to be changed. > The Common Reuse Principle — Classes that aren’t reused together don’t belong together – The classes in a package are reused together. If you reuse one of the classes in a package, you reuse them all. http: //www. objectmentor. com/resources/articles/Principles_and_Patterns. PDF © Oscar Nierstrasz 10

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring?

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring? > The Law of Demeter > Common Code Smells > Design Patterns > The Singleton Pattern © Oscar Nierstrasz 11

ST — Refactoring and Design Patterns What is Refactoring? > The process of changing

ST — Refactoring and Design Patterns What is Refactoring? > 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, et al. , Refactoring, 1999. © Oscar Nierstrasz 12

ST — Refactoring and Design Patterns The Refactoring Browser © Oscar Nierstrasz 13

ST — Refactoring and Design Patterns The Refactoring Browser © Oscar Nierstrasz 13

ST — Refactoring and Design Patterns Typical Refactorings Class Refactorings Method Refactorings Attribute Refactorings

ST — Refactoring and Design Patterns Typical Refactorings Class Refactorings Method Refactorings Attribute Refactorings add (sub)class to hierarchy add method to class rename method remove class remove method push method down push method up add parameter to method move method to component extract code in new method add variable to class rename variable remove variable push variable down pull variable up create accessors abstract variable Refactorings provided by the refactoring browser © Oscar Nierstrasz 14

ST — Refactoring and Design Patterns Why Refactor? “Grow, don’t build software” — Fred

ST — Refactoring and Design Patterns Why Refactor? “Grow, don’t build software” — Fred Brooks > The reality: — — — > Extremely difficult to get the design “right” the first time Hard to fully understand the problem domain Hard to understand user requirements, even if the user does! Hard to know how the system will evolve in five years Original design is often inadequate System becomes brittle over time, and more difficult to change Refactoring helps you to — Manipulate code in a safe environment (behavior preserving) — Recreate a situation where evolution is possible — Understand existing code © Oscar Nierstrasz 15

ST — Refactoring and Design Patterns Rename Method — manual steps > Do it

ST — Refactoring and Design Patterns Rename Method — manual steps > Do it yourself approach: — Check that no method with the new name already exists in any subclass or superclass. — Browse all the implementers (method definitions) — Browse all the senders (method invocations) — Edit and rename all implementers — Edit and rename all senders — Remove all implementers — Test > Automated refactoring is better ! © Oscar Nierstrasz 16

ST — Refactoring and Design Patterns Rename Method > Rename Method (method, new name)

ST — Refactoring and Design Patterns Rename Method > Rename Method (method, new name) > Preconditions — No method with the new name already exists in any subclass or superclass. — No methods with same signature as method outside the inheritance hierarchy of method > Post. Conditions — method has new name — relevant methods in the inheritance hierarchy have new name — invocations of changed method are updated to new name > Other Considerations — Typed/Dynamically Typed Languages => Scope of the renaming © Oscar Nierstrasz 17

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring?

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring? > The Law of Demeter > Common Code Smells > Design Patterns > The Singleton Pattern © Oscar Nierstrasz 18

ST — Refactoring and Design Patterns The Law of Demeter > “Do not talk

ST — Refactoring and Design Patterns The Law of Demeter > “Do not talk to strangers” — You should only send messages to: – – an argument passed to you an object you create self, super your class > Don’t send messages to objects returned from other message sends en. wikipedia. org/wiki/Law_Of_Demeter © Oscar Nierstrasz 19

ST — Refactoring and Design Patterns Law of Demeter by Example Node. Manager>>declare. New.

ST — Refactoring and Design Patterns Law of Demeter by Example Node. Manager>>declare. New. Node: a. Node |node. Description| (a. Node is. Valid) "OK — passed as an argument to me" if. True: [ a. Node certified]. node. Description : = Node. Description for: a. Node. node. Description local. Time. ”OK — I created it" self add. Node. Description: node. Description. ”OK — I can talk to myself" node. Description data "Wrong! I should not know" at: self creator. Key "that data is a dictionary" put: self creator © Oscar Nierstrasz 20

ST — Refactoring and Design Patterns The Dark Side of the Law of Demeter

ST — Refactoring and Design Patterns The Dark Side of the Law of Demeter To avoid giving direct access to instance variables, you may need to introduce many delegating methods … Traits can help — see final lecture © Oscar Nierstrasz Class A inst. Var: my. Collection A>>do: a. Block my. Collection do: a. Block A>>collect: a. Block ^ my. Collection collect: a. Block A>>select: a. Block ^ my. Collection select: a. Block A>>detect: a. Block ^ my. Collection detect: a. Block A>>is. Empty ^ my. Collection is. Empty 21

ST — Refactoring and Design Patterns Curing Navigation Code > Iteratively move behaviour close

ST — Refactoring and Design Patterns Curing Navigation Code > Iteratively move behaviour close to data — Use Extract Method and Move Method See: Object-Oriented Reengineering Patterns © Oscar Nierstrasz 22

ST — Refactoring and Design Patterns The Law of Demeter, violated Indirect Provider do.

ST — Refactoring and Design Patterns The Law of Demeter, violated Indirect Provider do. Something() provider Intermediate Provider +provider get. Provider() intermediate Indirect Client intermediate. provider. do. Something() or intermediate. get. Provider(). do. Something() Law of Demeter: A method "M" of an object "O" should invoke only the methods of the following kinds of objects. 1. itself 2. its parameters © Oscar Nierstrasz 3. any object it creates /instantiates 4. its direct component objects 23

ST — Refactoring and Design Patterns Eliminate Navigation Code Carburetor +fuel. Valve. Open Engine

ST — Refactoring and Design Patterns Eliminate Navigation Code Carburetor +fuel. Valve. Open Engine +carburetor Car -engine +increase. Speed() … engine. carburetor. fuel. Valve. Open = true Carburetor +fuel. Valve. Open Engine -carburetor +speed. Up() carburetor. fuel. Valve. Open = true Carburetor -fuel. Valve. Open +open. Fuel. Valve() fuel. Valve. Open = true © Oscar Nierstrasz Engine -carburetor +speed. Up() Car -engine +increase. Speed() … engine. speed. Up() Car -engine +increase. Speed() carburetor. open. Fuel. Valve() 24

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring?

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring? > The Law of Demeter > Common Code Smells > Design Patterns > The Singleton Pattern © Oscar Nierstrasz 25

ST — Refactoring and Design Patterns Misplaced Methods > Avoid implementing a method which

ST — Refactoring and Design Patterns Misplaced Methods > Avoid implementing a method which neither accesses instance variables nor accesses any state — Probably belongs in one of the classes of the objects it does send to My. Class>>pop: an. Ordered. Collection remove. First. Klimas, et al. , Smalltalk with Style © Oscar Nierstrasz 26

ST — Refactoring and Design Patterns Code Smells “If it stinks, change it” —

ST — Refactoring and Design Patterns Code Smells “If it stinks, change it” — Grandma Beck — Duplicated Code – Missing inheritance or delegation — Long Method – Inadequate decomposition — Large Class / God Class — Too many responsibilities — Long Parameter List — Object is missing — Type Tests — Missing polymorphism — Divergent Change — Same class changes differently depending on addition — Shotgun Surgery — © Oscar Nierstrasz Small changes affect too many objects 27

ST — Refactoring and Design Patterns Code Smells — Feature Envy – Method needing

ST — Refactoring and Design Patterns Code Smells — Feature Envy – Method needing too much information from another object — Data Clumps – Data always used together (x, y -> point) — Parallel Inheritance Hierarchies – Changes in one hierarchy require change in another hierarchy — Lazy Class – Does too little — Middle Man – Class with too many delegating methods — Temporary Field – Attributes only used partially under certain circumstances — Message Chains – Coupled classes, internal representation dependencies — Data Classes – © Oscar Nierstrasz Only accessors 28

ST — Refactoring and Design Patterns Curing Long Methods > Long methods — Decompose

ST — Refactoring and Design Patterns Curing Long Methods > Long methods — Decompose into smaller methods — Self sends should read like a script self set. Up; run; tear. Down. — Comments are good delimiters — A method is the smallest unit of overriding © Oscar Nierstrasz 29

ST — Refactoring and Design Patterns Curing Duplicated Code > In the same class

ST — Refactoring and Design Patterns Curing Duplicated Code > In the same class — Extract Method > Between two sibling subclasses — Extract Method — Push identical methods up to common superclass — Form Template Method > Between unrelated class — Create common superclass — Move to Component — Extract Component (e. g. , Strategy) © Oscar Nierstrasz 30

ST — Refactoring and Design Patterns Curing God Class > God Class — Incrementally

ST — Refactoring and Design Patterns Curing God Class > God Class — Incrementally redistribute responsibilities to existing (or extracted) collaborating classes — Find logical sub-components – Set of related working methods/instance variables — Move methods and instance variables into components — Extract component — Extract Subclass – If not using all the instance variables See: Object-Oriented Reengineering Patterns © Oscar Nierstrasz 31

ST — Refactoring and Design Patterns Curing Type Tests > Missing Polymorphism — Tell,

ST — Refactoring and Design Patterns Curing Type Tests > Missing Polymorphism — Tell, don’t ask! — Shift case bodies to (new) methods of object being tested — Self type checks: – Introduce hook methods and new subclasses — Client type checks – Introduce “tell” method into client hierarchy — Possibly introduce State / Strategy or Null Object Design Patterns See: Object-Oriented Reengineering Patterns © Oscar Nierstrasz 32

ST — Refactoring and Design Patterns Transformation a. doit(); this. init (); this. x();

ST — Refactoring and Design Patterns Transformation a. doit(); this. init (); this. x(); this. init (); this. y(); © Oscar Nierstrasz Client a: A m() B x() doit() A init() Client a: A m() switch (a. class) case B: a. init(); ((B) a). x(); case C: a. init(); ((C)) a). y(); Case D: ((D) a). z() A init() doit() C init() Y() doit() B x() C init() Y() D z() doit() this. z(); 33

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring?

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring? > The Law of Demeter > Common Code Smells > Design Patterns > The Singleton Pattern © Oscar Nierstrasz 34

ST — Refactoring and Design Patterns > Design Patterns document recurrent solutions to design

ST — Refactoring and Design Patterns > Design Patterns document recurrent solutions to design problems — They have names – Composite, Visitor, Observer. . . — They are not components! — Design Patterns entail tradeoffs — Will be implemented in different ways in different contexts © Oscar Nierstrasz 35

ST — Refactoring and Design Patterns Why Design Patterns? > Smart — Elegant solutions

ST — Refactoring and Design Patterns Why Design Patterns? > Smart — Elegant solutions that a novice would not think of > Generic — Independent of specific system type, language > Well-proven — Successfully tested in several systems > Simple — Combine them for more complex solutions > Caveat — Not everything that is called a “pattern” fulfils these criteria! © Oscar Nierstrasz 36

ST — Refactoring and Design Patterns Alert!!! Patterns are invading! > Design Patterns are

ST — Refactoring and Design Patterns Alert!!! Patterns are invading! > Design Patterns are not “good” just because they are patterns — It is just as important to understand when not to use a Design Pattern — Every Design Pattern has tradeoffs — Most Design Patterns will make your design more complicated – More classes, more indirections, more messages — Don’t use Design Patterns unless you really need them! © Oscar Nierstrasz 37

ST — Refactoring and Design Patterns About Pattern Implementation > Do not confuse structure

ST — Refactoring and Design Patterns About Pattern Implementation > Do not confuse structure and intent! — Design Patterns document a possible implementation – Not a definitive one — Design Patterns are about intent and tradeoffs © Oscar Nierstrasz 38

ST — Refactoring and Design Patterns Common Design Patterns Pattern Adapter Proxy Composite Template

ST — Refactoring and Design Patterns Common Design Patterns Pattern Adapter Proxy Composite Template Method Intent Convert the interface of a class into another interface clients expect. Provide a surrogate or placeholder for another object to control access to it. Compose objects into part-whole hierarchies so that clients can treat individual objects and compositions uniformly. Define the skeleton of an algorithm in an operation, deferring some steps so they can be redefined by subclasses. What tradeoffs do these patterns introduce? © Oscar Nierstrasz 39

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring?

ST — Refactoring and Design Patterns Roadmap > Some Principles > What is Refactoring? > The Law of Demeter > Common Code Smells > Design Patterns > The Singleton Pattern © Oscar Nierstrasz 40

ST — Refactoring and Design Patterns The Singleton Pattern Intent: > Ensure that a

ST — Refactoring and Design Patterns The Singleton Pattern Intent: > Ensure that a class has only one instance, and provide a global point of access to it Problem: > We want a class with a unique instance. Solution: > Give the class the responsibility to initialize and provide access to the unique instance. Forbid creation of new instances. © Oscar Nierstrasz 41

ST — Refactoring and Design Patterns Singleton Example: System. Change. Notifier Object subclass: #System.

ST — Refactoring and Design Patterns Singleton Example: System. Change. Notifier Object subclass: #System. Change. Notifier instance. Variable. Names: 'event. Source silence. Level' class. Variable. Names: 'Unique. Instance' pool. Dictionaries: '' category: 'System-Change Notification' System. Change. Notifier class instance. Variable. Names: '' System. Change. Notifier class>>new ^self error: self instance. Creation. Error. String System. Change. Notifier class>>unique. Instance Unique. Instance if. Nil: [Unique. Instance : = self create. Instance]. ^Unique. Instance NB: This example uses a class variable rather than a class instance variable. © Oscar Nierstrasz 43

ST — Refactoring and Design Patterns Singleton Example: Change. Set class instance. Variable. Names:

ST — Refactoring and Design Patterns Singleton Example: Change. Set class instance. Variable. Names: 'current' Change. Set class>>new ^ self basic. New. Change. Set: Change. Set default. Name Change. Set class>>new. Changes: a. Change. Set System. Change. Notifier unique. Instance no. More. Notifications. For: current isolation. Set: nil. current : = a. Change. Set. … Change. Set class>>current ^ current Here we have many instances, but only a Singleton is active. A class instance variable is used. new is not forbidden. © Oscar Nierstrasz 44

ST — Refactoring and Design Patterns Implementation Issues > Class variable — One singleton

ST — Refactoring and Design Patterns Implementation Issues > Class variable — One singleton for a complete hierarchy > Class instance variable — One singleton per class © Oscar Nierstrasz 45

ST — Refactoring and Design Patterns Implementation Issues > Singletons may be accessed via

ST — Refactoring and Design Patterns Implementation Issues > Singletons may be accessed via a global variable — E. g. , Notification. Manager unique. Instance notifier Session. Model>>startup. Window. System Notifier initialize. Window. Handles. . old. Windows : = Notifier windows. Notifier initialize. . ^old. Windows > Global Variable vs. Class Method Access — Global Variable Access is dangerous: if we reassign Notifier we lose all references to the current window. — Class Method Access is better because it provides a single access point. © Oscar Nierstrasz 46

ST — Refactoring and Design Patterns Implementation Issues > Persistent Singleton: — only one

ST — Refactoring and Design Patterns Implementation Issues > Persistent Singleton: — only one instance exists and its identity does not change – > E. g. , notification manager Transient Singleton: — only one instance exists at any time, but that instance changes – > E. g. , current session Single Active Instance Singleton: — a single instance is active at any point in time, but other dormant instances may also exist. – E. g. , active project Singleton is about time, not access © Oscar Nierstrasz 47

ST — Refactoring and Design Patterns Access using new — not a good idea

ST — Refactoring and Design Patterns Access using new — not a good idea > The intent (uniqueness) is not clear anymore! — new is normally used to return newly created instances. The programmer does not expect this: Singleton class>>new ^self unique. Instance |screen 1 screen 2| screen 1 : = Screen new. screen 2 : = Screen unique. Instance © Oscar Nierstrasz 48

ST — Refactoring and Design Patterns What you should know! How does the Open-Closed

ST — Refactoring and Design Patterns What you should know! How does the Open-Closed Principle apply to OOP? What are signs that an object has clearly-defined responsibilities? How can you recognize misplaced methods? How should you refactor long methods? How can you eliminate duplicated code between unrelated classes? Why are type tests a code smell? When do design patterns themselves turn into code smells? Why is it a bad idea to use global variables to store Singleton instances? © Oscar Nierstrasz 49

ST — Refactoring and Design Patterns Can you answer these questions? How do the

ST — Refactoring and Design Patterns Can you answer these questions? How do the Common Closure and Common Reuse Principles alter the usual notion of cohesion? How does refactoring differ from reengineering? Can refactoring be fully automated? In what situations does the Law of Demeter not apply? How do design patterns make use of delegation? Why are Long Parameter Lists a code smell? Are is. Nil tests a code smell? What design pattern could help you eliminate them? Is the Smalltalk System. Dictionary a good example of a Singleton? © Oscar Nierstrasz 50

ST — Refactoring and Design Patterns License > http: //creativecommons. org/licenses/by-sa/2. 5/ Attribution-Share. Alike

ST — Refactoring and Design Patterns License > http: //creativecommons. org/licenses/by-sa/2. 5/ Attribution-Share. Alike 2. 5 You 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. © Oscar Nierstrasz 51