Object design
-
Upload
dhaval-dalal -
Category
Technology
-
view
2.781 -
download
8
description
Transcript of Object design
OBJECT DESIGNDhaval Dalal
software-artisan.comPart I: OO Design Guidelines
DESIGN SMELLS
Tell-tale signs of poor architectureSource: Robert C. Martin
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.
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
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
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
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()
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.
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));
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));
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);
}
}
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”
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.
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.
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.
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.
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
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.
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
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.
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.
22
OPEN/CLOSED PRINCIPLE (OCP)
Software Entities (Classes, Modules, Methods, etc…)
Should be
Open for Extension
but
Closed for Modification.
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
HOW CAN THESE TWO OPPOSING
ATTRIBUTES BE RESOLVED?
Abstraction is the Key.
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
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.
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.
28
DEPENDENCY STRUCTURE: PROCEDURAL DESIGN
Source: Robert C. Martin
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.
30
DEPENDENCY STRUCTURE: OO DESIGN
Source: Robert C. Martin
Dependencies
are inverted
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
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
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.
34
ABSTRACTION PROLIFERATION
Make these
code blocks
Too many abstractions make it hard to understand the system.
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.
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.
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
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
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.