object-oriented design principles

of 33 /33
Object Oriented Design Principles –– class level Xiao-Yan Chen Beijing/July 13, 2007

Upload: xiaoyan-chen

Post on 10-May-2015

393 views

Category:

Engineering


2 download

DESCRIPTION

Summary of good object-oriented design principles which should be followed.

TRANSCRIPT

Page 1: Object-oriented design principles

Object Oriented Design Principles –– class level Xiao-Yan Chen Beijing/July 13, 2007

Page 2: Object-oriented design principles

2

Agenda

> Introduction

> OO Design Principles

> Evil Stuff and Anti-Patterns

Page 3: Object-oriented design principles

3

Introduction

> Where we are?

Methodology and Design Tech

Process

Tools

Methodology Design

technique

Heavyweight

process

Agile

process

Process

appraisal and improvement

For supporting

process

For supporting

methodology

For supporting

Design technique

Page 4: Object-oriented design principles

4

Principles

> What is a bad design?

> The principles

• OCP open-closed principle

• SRP single responsibility principle

• ISP interface segregation principle

• LSP Liskov substitution principle

• DIP dependency inversion principle

> Principles reviewed

Page 5: Object-oriented design principles

5

Bad designs

> Rigidity – hard to change

> Fragility – easy to break

> Immobility – hard to reuse

> Viscosity – hard to do the right thing

> Needless Complexity – over design

> Needless Repetition – error prone

> Opacity – hard to read and understand

Page 6: Object-oriented design principles

6

Open Closed Principle

> Examples of OCP violation

public interface Shape extends Comparable{

public void draw();

}

public class Circle implements Shape {

public void draw() {

}

public int compareTo(Object o) {

if (o instanceof Rectangel) {

return -1;

}

else if (o instanceof Circle) {

return 0;

}

else {

return 1;

}

}

}

Shape

Circle Rectangle

New

Shape

Page 7: Object-oriented design principles

7

Open Closed Principle

Software entities should be open for extension,

but closed for modification

B. Meyer, 1988

> 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

Page 8: Object-oriented design principles

8

Open Closed Principle

> How to:

• Encapsulate what varies.

• Abstraction is the KEY.

• Use “Data-Driven” approaches.

> This principle implies that:

• Make all member variables private.

• No global variables.

• RTTI (Run-Time Type Information) is dangerous.

> Also:

• No significant program can be 100% closed.

• OK to take the first bullet.

Page 9: Object-oriented design principles

9

Single Responsibility Principle

> Examples of SRP violation

Computational

Geometry

Application

Graphical

Application

GUI

Rectangle

draw()

area()

> This violation is bad for that:

• We must include the GUI in the Computational Geometry application.

• If a change to the Graphical Application causes the Rectangle to change, that change may force us to rebuild, retest, and redeploy the Computational Geometry Application.

Page 10: Object-oriented design principles

10

Single Responsibility Principle

> A Class should have one reason to change

• A Responsibility is a reason to change

> Single Responsibility = increased cohesion

> Not following results in needless dependencies

• More reasons to change.

• Rigidity, Immobility

Page 11: Object-oriented design principles

11

Single Responsibility Principle

> Conform to SRP:

Computational

Geometry

Application

Graphical

Application

Rectangle

draw()

GUI

Geometric

Rectangle

area()

Page 12: Object-oriented design principles

12

Interface Segregation Principle

Page 13: Object-oriented design principles

13

Interface Segregation Principle

> Many client specific interfaces are better than one general purpose interface

> Create an interface per client type not per client

• Avoid needless coupling to clients

GraphicalRect_I

draw()

Computational

Geometry

Application

Graphical

Application

Rectangle

draw()

area()

GUI

GeometricRect_I

Area()

Page 14: Object-oriented design principles

14

Liskov Substitution Principle

“What is wanted here is something like the following substitution property: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.”

(Barbara Liskov, 1988)

Page 15: Object-oriented design principles

15

Liskov Substitution Principle

> Any subclass should always be usable instead of its parent class.

• Pre-conditions can only get weaker

• Post-conditions can only get stronger

> Derived classes should require no more and promise no less.

Page 16: Object-oriented design principles

16

Liskov Substitution Principle

public interface Bird{

public void fly();

}

public class Parrot implements Bird {

public void fly() {

System.out.println(“OK, I can fly.”);

}

}

public class Penguin implements Bird {

public void fly() {

throw new IllegalStateExeption(“Sorry, I can not fly…”);

}

}

>Example of LSP violation:

public class BirdCustomer {

……………..

Bird bird = new Parrot();

bird.fly();

……………..

……………..

bird = new Penguin();

bird.fly(); // oops, the customer will be surprised!

…………….

…………….

}

Page 17: Object-oriented design principles

17

Liskov Substitution Principle

public class Rectangle {

public void setWidth(double w) {

this.width = w;

}

public void setHeight(double h) {

this.height = h;

}

public double area() {

return this.width * this.height;

}

}

public class Square extends Rectangle {

public void setWidth(double w) {

super.setWidth(w);

super.setHeight(w);

}

public void setHeight(double h) {

super.setWidth(h);

super.setHeight(h);

}

}

>Example of LSP violation:

public class RectangleCustomer {

……………..

Rectangel rect = new Square();

rect.setWidth(4);

rect.setHeight(5);

assert rect.area()==20;// oops, the customer will be surprised!

…………….

…………….

}

Page 18: Object-oriented design principles

18

Liskov Substitution Principle

> IS-A (inheritance) relationship refers to the BEHAVIOR of the class.

> BEHAVIOR = public members.

Page 19: Object-oriented design principles

19

Dependency Inversion Principle

> Procedural layering: violation of DIP

Policy layer

Mechanism

layer

Utility layer

> Bad for:

• Transitive dependency

• Transitive change impacts

Page 20: Object-oriented design principles

20

Dependency Inversion Principle

> 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

> OCP states the goal; DIP states the mechanism;

> LSP is the insurance for DIP

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

Page 21: Object-oriented design principles

21

Dependency Inversion Principle

> OO layering: Conforming to DIP

Policy

Policy

Layer

Policy Service

Interface

Mechanism

Mechanism Layer Mechanism Service

Interface

Utility

Utility

Layer

Page 22: Object-oriented design principles

22

Dependency Inversion Principle

> This principle implies:

• Programming to interfaces, not implementations.

• Both the naming and the physical location of interfaces should respect their customers, not their implementations.

• Dependency Injection.

Anyway, I need to depend on a concrete implementation object at runtime, how can I get it?

Page 23: Object-oriented design principles

23

Dependency Inversion Principle

> Dependency Injection:

• Don’t use new operator to instantiate a concrete class where you need, instead inject it from outside.

> Dependency Injection options:

• Constructor Injection with PicoContainer

• Setter Injection with Spring

• Interface Injection

• Using a Service Locator

For details, refer to http://www.martinfowler.com/articles/injection.html

Page 24: Object-oriented design principles

24

OO Principles Reviewed

> Encapsulate what varies.

> Favor composition over inheritance.

> Program to interfaces, not implementations.

> Strive for loosely coupled designs between objects

that interact.

> Classes should be open for extension but closed for

modification.

> Depend on abstraction. Do not depend on concrete

classes.

> Only talk to your friends.

> Don’t call us, we’ll call you.

> A class should have only one reason to change.

Oh, what is this?

Page 25: Object-oriented design principles

25

Law of Demeter

> Only talk to your friends, also known as “Law of Demeter”.

> Only invoke methods that belong to:

• The object itself.

• Objects passes in as a parameter to the method.

• Any object the method creates or instantiates.

• Any components of the object. (objects directly referred to)

> Violating when you write a_object.m1().m2();

> Keep our circle of friends small clear responsibility decrease complexity

> Law of Demeter for Concerns (LoDC) is good for Aspect Oriented Software Development.

Page 26: Object-oriented design principles

26

Agenda

> Introduction

> OO Design Principles

> Evil Stuff and Anti-Patterns

Page 27: Object-oriented design principles

27

Evil Stuff

> Singletons / Global variables • Singletons are actually OO global variables.

> Getters, Setters • Evil for exposing information/implementation which should be hidden.

• Eliminate data movement. Data flow is procedure-oriented thinking.

• Don't ask for the information you need to do the work; ask the object that has the information to do the work for you.

• Exceptions: computational query, get/set an interface

• http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html?page=1

• http://www.javaworld.com/javaworld/jw-01-2004/jw-0102-toolbox.html

> Helper Classes • Actually global procedures, hard to maintain.

• http://blogs.msdn.com/nickmalik/archive/2005/09/06/461404.aspx

• http://blogs.msdn.com/nickmalik/archive/2005/09/07/462054.aspx

Page 28: Object-oriented design principles

28

Anti-Patterns

> Category • Design related: The Blob, Poltergeist, Swiss Army Knife, Dead End

• Development related: Golden Hammer, Input Kludge

• Architecture related: Reinvent the wheel, Vendor lock-in

> The category: • http://www.antipatterns.com/briefing/index.htm

• http://www.devx.com/Java/Article/29162

> Poltergeist: http://www.icmgworld.com/corp/news/Articles/RS/jan_0302.asp

> Dead End: http://www.icmgworld.com/corp/news/Articles/RS/jan_0402.asp

Page 29: Object-oriented design principles

Much enough principles! Tired of this session? Here are some cookies

Page 30: Object-oriented design principles

30

Cookie – Thread Safe Singleton

public class Singleton {

private static Singleton instance = null;

private Singleton() {

}

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton();

}

}

}

return instance;

}

}

public class Singleton {

private volatile static Singleton instance = null;

private Singleton() {

}

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton();

}

}

}

return instance;

}

}

volatile can make the double-check singleton thread safe, but only since Java5.

Page 31: Object-oriented design principles

31

Cookie – The dilemma of Observer

private class Model extends Observable {

public void handleAttributeChange(int value) {

this.setChanged();

this.notifyObservers(value);

}

}

Observer observer = new Observer() {

public void update(Observable o, Object arg) {

System.out.println(arg);

}

};

model.addObserver(observer)

new Thread() {

public void run() {

model.handleAttributeChange(1);

}

}.start();

new Thread() {

public void run() {

model.handleAttributeChange(2);

}

}.start();

Not thread safe, notifications to observers may be lost!

Notification order not guaranteed, early notification, maybe late received by observers.

Page 32: Object-oriented design principles

32

Cookie – The dilemma of Observer

private class Model extends Observable {

public synchronized void handleAttributeChange(int value) {

this.setChanged();

this.notifyObservers(value);

}

}

model.addObserver(observer);

final Object object = new Object();

Observer observer = new Observer() {

public void update(Observable o, Object arg) {

synchronized (object) {

System.out.println(arg);

}

}

};

model.addObserver(observer);

new Thread() {

public void run() {

synchronized (object) {

model.addObserver()

}

}

}.start();

model.handleAttributeChange(1);

Notifications will not be lost.

But, still not thread safe, dead-lock is permitted!

Page 33: Object-oriented design principles

The End Thank You!