Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 OO Design Principles Project Group eXtreme Programming Md. Abul Bashar 07/09/2004.

Similar presentations


Presentation on theme: "1 OO Design Principles Project Group eXtreme Programming Md. Abul Bashar 07/09/2004."— Presentation transcript:

1 1 OO Design Principles Project Group eXtreme Programming Md. Abul Bashar 07/09/2004

2 2 Outline Problems with software system Basic OO Principles OCP, LSP, DIP  Class Cohesion and Coupling Principles  ISP, SRP, LoD  Package Cohesion Principles  REP, CRP, CCP  Package Coupling Principles  ADP, SDP, SAP

3 What goes wrong with S/W? Changing requirements You start with a clear picture in your mind what the SW should do. Then something goes wrong, the software starts to rot: Changes and Additions are harder to make. Simplest changes terrify you because of rippling unexpected effects You must redesign the whole !!

4 4 Bad Signs of Rotting Design Rigidity Code difficult to change Management reluctance to change anything becomes policy Fragility Even small changes can cause cascading effects Code breaks in unexpected places Immobility Code is so tangled that it’s impossible to reuse anything –a module could be reused in another system, but the effort and risk of separating the module from original environment is too high Viscosity Much easier to hack than to preserve original design.

5 5 Open-Closed Principle (OCP) "Software Systems change during their life time" –both better designs and poor designs have to face the changes; –good designs are stable Software entities should be open for extension, but closed for modification B. Meyer, 1988 / quoted by R. Martin, 1996  Be open for extension  module's behavior can be extended  Be closed for modification  source code for the module must not be changes  Modules should be written so they can be extended without requiring them to be modified

6 6 Really the Heart of OO Design 100% satisfaction to OCP is never possible But we should attempt to minimize the number of modules that do not satisfy it Conformance to this principle yields the greatest level of reusability and maintainability Open-Closed Principle (OCP)

7 7 Consider the following method of some class: public double totalPrice(Part[] parts) { double total = 0.0; for (int i=0; i<parts.length; i++) { total += parts[i].getPrice(); } return total; } - The job of the above function is to total the price of each part in the specified array of parts - If Part is a base class or an interface and polymorphism is being used, then this class can easily accommodate new types of parts without having to be modified! - It conforms to the OCP ?? Open-Closed Principle (OCP)

8 8 But what if the Accounting Department decided some price increase on motherboard parts and memory parts ? - How about the following code? public double totalPrice(Part[] parts) { double total = 0.0; for (int i=0; i<parts.length; i++) { if (parts[i] instanceof Motherboard) total += (1.45 * parts[i].getPrice()); else if (parts[i] instanceof Memory) total += (1.27 * parts[i].getPrice()); else total += parts[i].getPrice(); } return total; } Open-Closed Principle (OCP)

9 9 Does this conform to the OCP? - Every time the Accounting Department comes out with a new pricing policy, we have to modify the totalPrice() method! - It is not Closed For Modification. - Obviously, policy changes such as that mean that we have to modify code somewhere, so what could we do? - To use our first version of totalPrice(), we could incorporate pricing policy in the getPrice() method of a Part Open-Closed Principle (OCP)

10 10 Here are example Part and ConcretePart classes: // Class Part is the superclass for all parts. public class Part { private double price; public Part(double price) (this.price = price;} public void setPrice(double price) {this.price = price;} public double getPrice() {return price;} } // Class ConcretePart implements a part for sale. // Pricing policy explicit here! public class ConcretePart extends Part { public double getPrice() { // return (1.45 * price); //Premium return (0.90 * price); //Labor Day Sale } Open-Closed Principle (OCP) Part ConcretePart1ConcretePart2

11 11 But now we must modify each subclass of Part whenever the pricing policy changes! - A better idea is to have a PricePolicy class which can be used to provide different pricing policies: // The Part class now has a contained PricePolicy object. public class Part { private double price; private PricePolicy pricePolicy; public void setPricePolicy(PricePolicy pricePolicy) { this.pricePolicy = pricePolicy; } public void setPrice(double price) {this.price = price;} public double getPrice() {return pricePolicy.getPrice(price);} } Open-Closed Principle (OCP)

12 12 /** * Class PricePolicy implements a given price policy. */ public class PricePolicy { private double factor; public PricePolicy (double factor) { this.factor = factor; } public double getPrice(double price) {return price * factor;} } Open-Closed Principle (OCP) Part ConcretePart1ConcretePart2 > ConcretePolicy

13 13 Liskov Substitution Principle (LSP) Functions That Use References To Base Classes Must Be Able To Use Objects Of Derived Classes Without Knowing it.

14 14 // A very nice Rectangle class. public class Rectangle { private double width; private double height; public Rectangle(double w, double h) { width = w; height = h; } public double getWidth() {return width;} public double getHeight() {return height;} public void setWidth(double w) {width = w;} public void setHeight(double h) {height = h;} public double area() {return (width * height); } LSP Example

15 15 Now, What about a Square class? Clearly, a square is a rectangle, so the Square class should be derived from the Rectangle class, right? Let's see! Observations: A square does not need both a width and a height as attributes but it will inherit them from Rectangle anyway. The inherited setWidth() and setHeight() methods are not really appropriate for a Square, since the width and height of a square are identical. So we'll need to override setWidth() and setHeight(). Having to override these simple methods is a clue that this might not be an appropriate use of inheritance! LSP Example

16 16 Here's the Square class: // A Square class. public class Square extends Rectangle { public Square(double s) {super(s, s);} public void setWidth(double w) { super.setWidth(w); super.setHeight(w); } public void setHeight(double h) { super.setHeight(h); super.setWidth(h); } LSP Example Rectangle setWidth(w) setHeight(h) Circle setWidth(w) setHeight(h)

17 17 Everything looks good. But check this out! public class TestRectangle { // Define a method that takes a Rectangle reference. public static void testLSP(Rectangle r) { r.setWidth(4.0); r.setHeight(5.0); System.out.println( "Width is 4.0 and Height is 5.0, so Area is " + r.area() ); if (r.area() == 20.0) System.out.println("Looking good!\n"); else System.out.println("Huh?? What kind of rectangle is this??\n"); } LSP Example

18 18 public static void main(String args[]) { //Create a Rectangle and a Square Rectangle r = new Rectangle(1.0, 1.0); Square s = new Square(1.0); // Now call the method above. According to the // LSP, it should work for either Rectangles or // Squares. Does it?? testLSP(r); testLSP(s); } LSP Example

19 19 Test program output: Width is 4.0 and Height is 5.0, so Area is 20.0 Looking good! Width is 4.0 and Height is 5.0, so Area is 25.0 Huh?? What kind of rectangle is this?? Looks like we violated the LSP! LSP Example

20 20 What’s the problem here? Implicit assumptions The programmer made the assumption that changing the width of a Rectangle leaves its height unchanged. Didn’t consider that, the base class can write a method that causes the design model to break down. Behaviorally, a Square is not a Rectangle! A Square object is not polymorphic with a Rectangle object. Solutions can not be viewed in isolation.

21 21 Liskov Substitution Principle (LSP) IS-A relationship is all about behavior All subclasses must conform to the behavior as of base class Subclass must NOT have more constraints than it’s base class The guarantee of the LSP is – a subclass can always be used whenever it’s base class is used.

22 22 Dependency Inversion Principle (DIP) Depend upon Abstraction, Do NOT Depend upon Concretions.

23 23 I. High-level modules should not depend on low-level modules. Both should depend on abstractions. II. Abstractions should not depend on details. Details should depend on abstractions R. Martin, 1996  OCP states the goal; DIP states the mechanism  A base class in an inheritance hierarchy should not know any of its subclasses  Modules with detailed implementations are not depended upon, but depend themselves upon abstractions Dependency Inversion Principle (DIP)

24 24 DIP Related Heuristic Use inheritance to avoid direct bindings to classes: Design to an interface, not an implementation! Client Interface (abstract class) Implementation (concrete class)

25 25 Design to an Interface Abstract classes/interfaces: –tend to change much less frequently –abstractions are ‘hinge points’ where it is easier to extend/modify –shouldn’t have to modify classes/interfaces that represent the abstraction (OCP) Exceptions –Some classes are very unlikely to change; therefore little benefit to inserting abstraction layer Example: String class –In cases like this can use concrete class directly as in Java or C++

26 26 Avoid structures in which higher-level layers depend on lower-level abstractions: –In example below, Policy layer is ultimately dependant on Utility layer. Avoid Transitive Dependencies Policy Layer Mechanism Layer Utility Layer Depends on DIP Related Heuristic

27 27 Use inheritance and abstract ancestor classes to effectively eliminate transitive dependencies: Policy Layer Mechanism Layer Utility Layer depends on Utility Interface Mechanism Interface Solution to Transitive Dependencies

28 28 If you cannot find a satisfactory solution for the class you are designing, try delegating responsibility to one or more classes: When in doubt, add a level of indirection Problem Holder Problem Solver DIP Related Heuristic

29 29 It is generally easier to remove or by-pass existing levels of indirection than it is to add them later: X So, Blue class re-implements some or all of green class’s responsibilities for efficiency and calls red object directly Blue class’s indirect message calls to red class fail to meet some criteria (e.g. real-time constraints, etc.) When in doubt …

30 30 Many client-specific interfaces are better than one general purpose interface Consequence: –impact of changes to one interface aren’t as big if interface is smaller –interface pollution Clients should not be forced to depend upon interfaces that they do not use. R. Martin, 1996 Interface Segregation Principle (ISP)

31 31 Interface Segregation Principle (ISP)

32 32 Single Responsibility Principle (SRP) There Should NEVER be More Than One Reason for a Class to Change.

33 33 Single Responsibility Principle (SRP) More than one reason means More than one Responsibilities. Responsibilities become coupled

34 34 Single Responsibility Principle (SRP)

35 35 Single Responsibility Principle (SRP)

36 36 Cohesion Principles –Reuse/Release Equivalency Principle (REP) –Common Reuse Principle (CRP) –Common Closure Principle (CCP) Coupling Principles –Acyclic Dependencies Principle (ADP) –Stable Dependencies Principle (SDP) –Stable Abstractions Principle (SAP) Principles of OO High Level Design

37 37 What means this ? –A reusable software element cannot really be reused in practice unless it is managed by a release system of some kind e.g. release numbers or names –All related classes must be released together –Release granule  Reuse granule no reuse without release must integrate the entire module (can’t reuse less) –Classes are to small we need larger scale entities, i.e. package The granule of reuse is the granule of release. Only components that are released through a tracking system can be efficiently reused. R. Martin, 1996 Reuse/Release Equivalency Principle

38 38 All classes in a package [library] should be reused together. If you reuse one of the classes in the package, you reuse them all. R. Martin, Granularity 1996  Packages of reusable components should be grouped by expected usage, Not:  common functionality, nor  another arbitrary categorization.  Classes are usually reused in groups based on collaborations between library classes Common Reuse Principle (CRP)

39 39  The Façade Pattern becomes critical when the level of reuse becomes a targeted goal:  If you started with… (e.g. a mess!) Common Reuse Principle (CRP)

40 40 The Façade Solution “Façade” says you should clean it up like this: Common Reuse Principle (CRP)

41 41 What means this ? –Classes that change together belong together –Goal: limit the dispersion of changes among released packages changes must affect the smallest number of released packages –Classes within a package must be cohesive –Given a particular kind of change, either all classes or no class in a component needs to be modified The classes in a package should be closed against the same kinds of changes. A change that affects a package affects all the classes in that package R. Martin, 1996 Common Closure Principle (CCP)

42 42 REP and CRP makes life easier for re-users –packages very small CCP makes life easier for maintainer –large packages Packages are not fixed in stone –early lifetime dominated by CCP –later you want to reuse: focus on REP CRP Reuse vs. Maintenance

43 43 The dependency structure for released component must be a Directed Acyclic Graph (DAG) There can be no cycles. R. Martin, 1996 Acyclic Dependencies Principles (ADP)

44 44 Acyclic Dependencies Principles (ADP)

45 45 A Cycle Creeps In ! Acyclic Dependencies Principles (ADP)

46 46 Breaking a cycle Acyclic Dependencies Principles (ADP)

47 47 The dependencies between components in a design should be in the direction of stability. A component should only depend upon components that are more stable than it is. R. Martin, 1996 Depend only upon components whose I metric is lower than yours R. Martin, 1996 SDP Violation Stable Dependencies Principles (SDP)

48 48 Where to Put High-Level Design? High-level architecture and design decisions don't change often –shouldn't be volatile  place them in stable packages –design becomes hard to change  inflexible design How can a totally stable package (I = 0) be flexible enough to withstand change? –improve it without modifying it...  Answer: The Open-Closed Principle  classes that can be extended without modifying them  Abstract Classes Stable Dependencies Principles (SDP)

49 49 Ideal Architecture –Instable (changeable) packages on the top must be concrete –Stable (hard to change) package on the bottom hard to change, but easy to extend highly abstract (easily extended) Interfaces have more intrinsic stability than executable code SAP is a restatement of DIP The abstraction of a package should be proportional to its stability! Packages that are maximally stable should be maximally abstract. Instable packages should be concrete. R. Martin, 1996 Stable Abstractions Principles (SAP)

50 50 The Main Sequence Instability ( I ) should increase as abstraction ( A ) decreases. R. Martin, 2000 Stable Abstractions Principles (SAP)

51 51 Temperature Sensor Temperature Display Application Instable Abstract Stable Abstractions Principles (SAP)

52 52 Temperature Sensor Temperature Display Application Instable Abstract Observer Subject Stable Abstractions Principles (SAP)

53 53 OO Principles and Design Patterns We introduce dependency when we create object OO Principles favor abstraction. –How to use abstraction? –Abstract classes can’t be instantiated. Part ConcretePart1ConcretePart2 > ConcretePolicy

54 54 Abstract Factory Patterns DIP and Abstract Factory

55 55 Composite Patterns

56 56 Summery OO Principles lead to a software which conforms with changing requirements. Basic OO Principles OCP, LSP, DIP  Class Cohesion and Coupling Principles  ISP, SRP, LoD  Package Cohesion Principles  REP, CRP, CCP  Package Coupling Principles  ADP, SDP, SAP

57 57 Questions ?!


Download ppt "1 OO Design Principles Project Group eXtreme Programming Md. Abul Bashar 07/09/2004."

Similar presentations


Ads by Google