Object design

39
OBJECT DESIGN Dhaval Dalal software-artisan.com Part I: OO Design Guidelines

description

 

Transcript of Object design

Page 1: Object design

OBJECT DESIGNDhaval Dalal

software-artisan.comPart I: OO Design Guidelines

Page 2: Object design

DESIGN SMELLS

Tell-tale signs of poor architectureSource: Robert C. Martin

Page 3: Object design

3

DESIGN SMELLS

Rigidity (Difficult to Change)

Every change causes too many changes in other parts of the system.

Fragility (Easily Breakable)

A change affects unexpected parts of the system and causes it to break.

Needless Repetition (Duplication)

Same code appears over and over again in different forms.

Page 4: Object design

4

DESIGN SMELLS

Immobility (Cannot Disentangle)

It is hard to reuse in another application because it cannot be disentangled from the current application.

Opacity (Difficulty in Understanding)

Tendency of a module to be difficult to understand.

Needless Complexity (Over Engineering)

Results from speculative approach (gold-plating!).

Use YAGNI

Page 5: Object design

5

DESIGN SMELLS

Viscosity (Toughness in preserving design)

High Design Viscosity

Design preserving methods are harder to employ than hacks.

Easy to do the wrong thing, but hard to do the right thing.

Environment Viscosity

Page 6: Object design

OO DESIGN GUIDELINESStrong Commitment to Encapsulation

Strong Commitment to Loose Coupling Law of Demeter

Single Responsibility PrincipleCoding to Super-Types & LSP

Encapsulate Variations & apply OCPCreate Role-Based Behaviors

Dependency InversionFavor Composition over Inheritance

Dependency InjectionDependency Elimination

Page 7: Object design

STRONG COMMITMENT TO ENCAPSULATION

Ask (or query) an Object to get something for you.

if (customer.getAge() == 60) { // do something}

// Still Query, but encapsulatedif (customer.isSenior()) {

// do something

}

Tell (or command) an Object to do something for you.

customer.loyaltyPoints()

Page 8: Object design

TELL, DON’T ASK!

Procedural code gets information, inspects that information and then makes decisions.

Object-oriented code tells objects to do things.

Declare or State (think declaratively) what you want and do not process (not procedurally) what you want.

Page 9: Object design

PRESERVE ENCAPSULATION

Getters and Setters generally break encapsulation.

Don’t introduce getters or setters for all fields of an object...just because IDEs provide this facility

Don’t introduce getters just because tests need it.

engine.start();

assertThat(engine.isRunning(), is(true));

Page 10: Object design

PRESERVE ENCAPSULATION

Don’t introduce getters just because tests need it.

engine.start();

assertThat(engine.isRunning(), is(true));

Use Observable Behavior instead, this improves the API

assertThat(engine.start(), is(true));

Page 11: Object design

PRESERVE ENCAPSULATION

Avoid returning a private collection

public class Building {

private List<Floor> floors = new ArrayList<Floor>();

//...

public List<Integer> getFloors() { return floors; }

}

Instead return a copy or a read-only version of it.

public class Building {

private List<Floor> floors = new ArrayList<Floor>();

//...

public List<Integer> getFloors() {

return Collections.unmodifiableList(floors);

}

}

Page 12: Object design

STRONG COMMITMENT TO LOOSE COUPLING

A E

D

C

B

dog.getBody().getTail().wag()

dog.expressHappiness()

dog.getBody().getTail().setLength(50)

state altering“train wrecks”

“train wrecks”refactored

dog.getBody().getTail().getLength()state querying“train wrecks”

Page 13: Object design

LAW OF DEMETER

No “Train Wrecks”

Send messages only to object’s immediate neighbors.

Principle of least knowledge

Don’t talk to more objects than required.

The more objects you talk to, more the risk of getting broken when any one of the object changes.

Restrict class interaction in order to minimize coupling among classes.

Page 14: Object design

CONFORMING TO LAW OF DEMETER

A method of an Object should invoke only the methods of the following kinds of objects

itself

its parameters

any objects it creates or directly collaborates

any composite object

As a guidance-rule, more than two “dots” means the Law of Demeter is being violated.

Page 15: Object design

15

SINGLE RESPONSIBILITY PRINCIPLE (SRP)

There should never be more than one reason to change a class.

A responsibility is an axis of change.

Key is in identifying which is an axis of change and which is not?

Many responsibilities means many reasons to change.

This is hard to see, as we think

responsibility in groups.

Page 16: Object design

16

BENEFITS OF SRP…

Removes the “Immobility Smell” from Design

Immobility is the inability to reuse software from other projects or from parts of the same project.

Deodorizes the “Rigidity Smell”

Generates a highly cohesive design.

Page 17: Object design

17

CODING TO WHAT?

Coding to an super-type

Shape s = new Circle();

s.draw();

Coding to an implementation

Circle c = new Circle();

c.draw();

Code to Super-type, not to Sub-Types

Page 18: Object design

18

LISKOV’S SUBSTITUTION PRINCIPLE (LSP)

Sub-types must be substitutable for their Base-types

Be able to operate upon derivatives of that base class without knowing it.

It makes clear that in OO Design “IS-A” relationship is about behavioral semantics; semantics that clients depend on.

Not intrinsic private behavior, but extrinsic public behavior.

Page 19: Object design

19

HANDLING CHANGES

When a single change to a program

Results in a cascade of changes to dependent modules.

The program becomes rigid, unpredictable and not reusable.

This is sign of

a bad design

Page 20: Object design

20

ENCAPSULATE VARIATIONS

Identify things that vary and separate them from the concepts that stay the same.

Evolve an Abstraction representing the concept.

Introduce Interface or Abstract super-type.

Unify variations on this pivot of abstraction.

Encapsulate each variation using a Concrete Class that implements/extends the above super-type.

Page 21: Object design

21

APPLY OPEN/CLOSED PRINCIPLE

It says that you should design modules that never change.

When requirements change, extend the behavior of modules

By adding new code.

Not by changing old code that already works.

Page 22: Object design

22

OPEN/CLOSED PRINCIPLE (OCP)

Software Entities (Classes, Modules, Methods, etc…)

Should be

Open for Extension

but

Closed for Modification.

Page 23: Object design

OPEN FOR EXTENSIONBehavior of the module can be extended.

Make the module behave in new and different ways as the requirements of the application change.

The source code of such a module is inviolate.

Resist making source code changes to it.

CLOSED FOR MODIFICATION

Page 24: Object design

HOW CAN THESE TWO OPPOSING

ATTRIBUTES BE RESOLVED?

Abstraction is the Key.

Page 25: Object design

25

WHAT MAKES A GOOD ABSTRACTION?

An Abstraction focuses

On client’s perspective and suppresses implementation perspective.

A simple logical model that can be described in a sentence or a two.

It does not mean class’s processing is simple!

It simply means that the class is focused on a small set of activities.

Source: S/W Design Studio, by Dr. Jim Fawcett, Syracuse University

Page 26: Object design

CREATE ROLES-BASED BEHAVIORS

Name a role around a metaphor or around the concepts which you are abstracting out.

This helps a client understand and relate to an object’s behavior.

Role should convey everything about the implemented behavior.

Page 27: Object design

27

OCP IN REALITY

100% closure is not attainable.

Closure must be strategic.

We design systems such that they are closed to the most likely kinds of changes that we foresee.

Page 28: Object design

28

DEPENDENCY STRUCTURE: PROCEDURAL DESIGN

Source: Robert C. Martin

Page 29: Object design

29

DEPENDENCY INVERSION PRINCIPLE (DIP)

High level modules should not depend on low level modules.

Both should depend upon abstractions.

Abstractions should not depend upon specifics.

Specifics should depend upon abstractions.

Page 30: Object design

30

DEPENDENCY STRUCTURE: OO DESIGN

Source: Robert C. Martin

Dependencies

are inverted

Page 31: Object design

31

EXTENDING OBJECT CAPABILITIES

Composition promotes “dynamic reuse”

Is a weaker association

Vary object behavior dynamically by changing collaborators

Inheritance promotes “static reuse”

Is a stronger association

Vary object behavior at compile time.

“has-a” can be better than “is-a”, leads to supple design

Page 32: Object design

SUB-TYPE PROLIFERATION

Evils of Inheritance

Deep hierarchies obscure understanding.

As a guidance, avoid creating hierarchies that are more than 2 levels deep.

Contractual changes on super-type ripple through Wide hierarchies.

Interfaces or Abstract Classes provide flexibility at the cost of themselves being rigid.

In general, Favor Composition over Inheritance

Page 33: Object design

33

INTERFACE SEGREGATION PRINCIPLE (ISP)

Deals with avoiding “Fat”, Non-cohesive class interfaces.

Groups of methods used by different clients.

Don’t force clients to depend on methods they don’t use.

Else they are subject to changes to those methods.

Results in an inadvertent coupling between all the clients.

Page 34: Object design

34

ABSTRACTION PROLIFERATION

Make these

code blocks

Too many abstractions make it hard to understand the system.

Page 35: Object design

LOOK MA....NO COUPLING!

Too many abstractions make it hard to understand the system.

Refactor to Closures/Lambdas wherever its sensible and possible

Dependency Elimination

You don’t need abstract classes or interfaces to achieve polymorphism.

Close your class against modifications.

Page 36: Object design

YET ANOTHER GUIDELINE

Dependency Elimination can be better than Dependency Inversion.

Requires Language Level support to achieve this

As of now, Java6 does not support closures.

Groovy, Ruby, C# make this possible to achieve.

Page 37: Object design

37

OBJECT DESIGN GUIDELINES SUMMARY

Design for preserving Encapsulation

Tell, Don’t Ask!

Extend Object Capabilities

By favoring Composition over Inheritance

Design for High Cohesion and Reuse

SRP, ISP

Page 38: Object design

38

OBJECT DESIGN GUIDELINES SUMMARY

Design for Reduced Coupling

Law of Demeter, OCP, LSP.

Separate Policy from Mechanism (DIP)

Design for No Coupling

Dependency Elimination

Page 39: Object design

39

OBJECT DESIGN GUIDELINES SUMMARY

Uphold Good Housekeeping Policy.

Use and clean your own stuff…

Uphold Green Environment Policy.

Undo changes made by you to your environment.