0% found this document useful (0 votes)
34 views

Object-Oriented Design Principles: The Pillars of The Paradigm

The document discusses object-oriented design principles including abstraction, encapsulation, inheritance, polymorphism, coupling, cohesion, the Law of Demeter, single responsibility principle, and open/closed principle. It provides examples and explanations of applying these principles to evaluate and improve class and module designs.

Uploaded by

Ashish Katlam
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
34 views

Object-Oriented Design Principles: The Pillars of The Paradigm

The document discusses object-oriented design principles including abstraction, encapsulation, inheritance, polymorphism, coupling, cohesion, the Law of Demeter, single responsibility principle, and open/closed principle. It provides examples and explanations of applying these principles to evaluate and improve class and module designs.

Uploaded by

Ashish Katlam
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 31

Object-Oriented

Design Principles

The Pillars of the


Paradigm
Abstraction

Encapsulation

Hierarchy

Association, Aggregation

Inheritance

Polymorphism

OOP- 2
What’s OO?

Is it using Objects?

Is it using C++, Java, C#, Smalltalk?

No, its got to be using UML?! :)

What makes a program OO?

How do you measure good design?

OOP- 3

Measuring Quality
of an Abstraction

Designing Classes & Objects

An incremental, iterative process

Difficult to design right the first time

OOP- 4
Metrics for class design
Coupling

inheritance Vs. coupling

Strong coupling complicates a system

design for weakest possible coupling

Cohesion

degree of connectivity among the elements of a single


module/class

coincidental cohesion: all elements related undesirable

Functional cohesion: work together to provide well-


bounded behavior
OOP- 5

Law of Demeter
“Methods of a class should not depend in any
way on the structure of any class, except the
immediate structure of their own class.
Further, each method should send messages to
objects belonging to a very limited set of
classes only.”

First part talks about encapsulation and cohesion


Second part talks about low coupling
OOP- 6
Tell Don’t Ask

“Procedural code gets information and then


makes decisions. OO code tells objects to do
things,” Alec Sharp in Smalltalk by Example.

Objects should take limited responsibility and


rely on others to provide appropriate service

Command-Query Separation: categorize


methods as command or query

OOP- 7

David Bock’s Example


on LoD/TDA
David Bocks’ The Paper Boy, The Wallet, and The Law Of Demeter

Failing LoD
=> drives away shiny new
PaperBoy’s method does: Jaguar!
customer.waller.totalMoney;

Honoring LoD => Customer controls


amount, where it’s kept
PaperBoy’s method does: (wallet, hidden in cookie
customer.getPayment(...); jar,...)

OOP- 8
Train Wreck Coding
You may find code that continues to call on objects
returned by methods in sequence

customer.getAddress().getCity().getCounty()...

This indicates that you are interested in working


with objects that are farther away than those that are
your close friends

Hard to understand

Hard to debug

Lacks Cohesion

Good candidate for refactoring


OOP- 9

Bad design
Perils of a bad design

Rigidity–Hard to change, results in cascade of changes

Fragility–Breaks easily and often

Immobility–Hard to reuse (due to coupling)

Viscosity–Easy to do wrong things, hard to do right things

Needless Complexity–Complicated class design, overly


generalized

Needless Repetition–Copy and Paste away

Opacity –Hard to understand


OOP- 10
Principles
Guiding Principles that help develop better
systems

Use principles only where they apply

You must see the symptoms to apply them

If you apply arbitrarily, the code ends up with


Needless Complexity
OOP- 11

YAGNI
You Aren’t Going To Need It

You are looking out for extensibility

You are not sure if a certain functionality is


needed

Designing what you do not know fully leads to


unnecessary complexity and heavy weight
design

If you really need it, design it at that time


OOP- 12
DRY
Don’t Repeat Yourself

“Every Piece of Knowledge must have a single,


unambiguous, authoritative representation within a system”

One of the most difficult, but most seen

How many times have you see this happen

Application where
Execution UI did business
Engine Font end
validation.
Start out due to flaw in
(chokes on Application Engine.
Once flaw was rectified,
certain took us weeks to fix
names of the UI due to duplication
of validation logic.
objects) OOP- 13

DRY
Some times hard to realize this

It is much easier to copy, paste and modify


code to get it working the way you want it,
isn’t it

Duplicating code results in

Poor maintainability

Expensive to fix bugs/errors

Hard to keep up with change


OOP- 14
SRP
Single-Responsibility Principle

What metric comes to mind?

“A class should have only one reason to


change”

Some C++ books promoted bad design

Overloading input/output operators!

What if you do not want to display on a


terminal any more?

GUI based, or web based?


OOP- 15

SRP…
Alarm
Control
UI +alert()
System
+display(Panel)

Faces more frequent change


Has greater dependency (to UI related stuff)

Related topics:
MVC Alarm
Analysis model stereotypes : Control
+alert() System
Control Entity Boundary

AlarmUI
UI +display(Panel)

OOP- 16
SRP at Module Level
Can be extended to module level as well

Component
GUI Framework GUI Framework
V 1.0 Development V 1.1
Utilities
Throw it in there

GUI Framework
Forced to accept V 1.2
Irrelevant change
User

OOP- 17

SRP affects Reuse


Lower cohesion results in poor reuse

My brother just bought a new DVD and a


big screen TV!

He offers to give me his VCR!

I have a great TV and all I need is a VCR

Here is what I found when I went to pickup!

Disclaimer: This slide not Tight coupling


intended to say anything
about the brand of product Poor Cohesion
shown here as an example!
Bad for reuse
OOP- 18
Nature of code
“Software Systems change during their life
time”

Both better designs and poor designs have to


face the changes; good designs are stable

OOP- 19

OCP…

Bertrand Meyer:

“Software Entities (Classes, Modules,


Functions, etc.) should be open for extension,
but closed for modification”

OOP- 20
OCP…
Characteristics of a poor design:

Single change results in cascade of changes

Program is fragile, rigid and unpredictable

Characteristics of good design:

Modules never change

Extend Module’s behavior by adding new


code, not changing existing code

OOP- 21

OCP…
Software Modules must

be open for extension

module’s behavior can be extended

closed for modification

source code for the module must not be


changed

OOP- 22
OCP…
Piston
Car
Engine

How to make the Car run efficiently with Turbo Engine ?


Only by changing Car in the above design

OOP- 23

OCP…
Abstract
Car
Engine

Piston
Engine
A class must not
Abstraction & Polymorphism depend on a
are the Key Concrete class; it
must depend on an
abstract class OOP- 24
OCP…
Strategic Closure:

No program can be 100% closed

There will always be changes against which


the module is not closed

Closure is not complete - it is strategic

Designer must decide what kinds of changes to


close the design for.

This is where the experience and problem


domain knowledge of the designer comes in
OOP- 25

OCP…
Heuristics and Conventions that arise from OCP

Make all member variables private

encapsulation: All classes/code that depend on


my class are closed from change to the variable
names or their implementation within my class.
Member functions of my class are never closed
from these changes

Further, if this were public, no class will be


closed against improper changes made
by any other class

No global variables OOP- 26


OCP…
Heuristics and Conventions that arise from
OCP...

RTTI is ugly and dangerous

If a module tries to dynamically cast a base


class pointer to several derived classes, any
time you extend the inheritance hierarchy,
you need to change the module

Not all these situations violate OCP


all the time

OOP- 27

Liskov Substitution
Principle
Inheritance is used to realize Abstraction

! and Polymorphism which are key to OCP

How do we measure the quality of inheritance?

LSP:

! “Functions that use pointers or references to


base classes must be

! able to use objects of derived classes without


knowing it”
OOP- 28
Inheritance
A

public/is-a

B
!B publicly inherits from (“is-a”) A means
!Every object of type B is also object of type A
!What’s true of object of A is also of object of B
!A represents a more general concept than B
!B represents more specialized concept than A
!anywhere an object of A can be used, an object of B can be used
OOP- 29

Behavior
Advertised Behavior of an object

Advertised Requirements (Pre-Condition)

Advertised Promise (Post Condition)

Stack and eStack example

OOP- 30
Design by Contract
Design by Contract

Advertised Behavior of the

Derived class is Substitutable for that of the


Base class

Substitutability: Derived class Services Require


no more and promise no less than the
specifications of the corresponding services in
the base class

OOP- 31

LSP

“Any Derived class object must be


substitutable where ever a Base class object is
used, without the need for the user to know
the difference”

OOP- 32
LSP in Java?
LSP is being used in Java at least in two places

Overriding methods can not throw new


unrelated exceptions

Overriding method’s access can’t be more


restrictive than the overridden method

for instance you can’t override a public


method as protected or private in derived
class

OOP- 33

Nature of Bad Design


Bad Design is one that is

Rigid - hard to change since changes affect


too many parts

Fragile - unexpected parts break upon


change

Immobile - hard to separate from current


application for reuse in another

OOP- 34
Ramifications
Depends
Controller Clock
for Alarm

Controller needs an alarm

Clock has it, so why not use it?

Concrete Controller depends on concrete Clock

Changes to Clock affect Controller

Hard to make Controller use different alarm (fails


OCP)

Clock has multiple responsibilities (fails SRP)


OOP- 35

Alternate Design
Controller IAlarm

Clock Timer

Dependency has been inverted

Both Controller and Clock depend on


Abstraction (IAlarm)

Changes to Clock does not affect Controller

Better reuse results as well


OOP- 36
Inheritance Vs.
Delegation
Inheritance is one of the most abused concepts
in OO programming

Often, delegation may be a better choice than


inheritance

When should you use inheritance vs.


delegation?

OOP- 37

Inheritance Vs.
Delegation...

If an object of B may be used in place of an


object of A, use inheritance

If an object of B may use an object of A, then


use delegation

OOP- 38
DIP

Dependency Inversion Principle

“High level modules should not depend upon


low level modules. Both should depend upon
abstractions.”

“Abstractions should not depend upon details.

! Details should depend upon abstractions.”

OOP- 39

The Founding
Principles
The three principles are closely related

Violating either LSP or DIP invariably results


in violating OCP

It is important to keep in mind these principles


to get the most out of OO development
OOP- 40
Fat Interfaces
C1 A Class C2

Clients should not know this as a single class


They should know about abstract base classes with cohesive interfaces
Classes tend to grow into fat interfaces

Examples of this can been seen in several APIs


Interface of the class
Less cohesive (fails SRP) may be split
I1
C1 C2
A Class
I2
Interface does not mean “all
methods in a class”
OOP- 41

Growth of an interface
IMicrowave
C1 +cook(time) C2
+stop()
A few days later,
A few days later,
Client C1 wants it to notify MicrowaveImpl Client C2 wants it to chime
(workaholic client?!)

IMicrowave
C1 +cook(time) C2
+stop()
Clients are forced to
+chime()
use interfaces they
+notify(…)
do not care about. All implementations
May result in greater
must carry the weights
coupling, dependency MicrowaveImpl
to more libraries
OOP- 42
ISP
Interface Segregation Principle

“Clients should not be forced to depend on


methods that they do not use”

IMicrowave
C1 C2
+cook(time)
+stop()
INotify IChimer
+notify(…) +chime()

MicrowaveImpl1 MicrowaveImpl2
OOP- 43

Reuse/Release
Equivalency Principle

“The granularity of reuse is the same as the


granularity of release. Only components that
are released through a tracking system can be
effectively reused.”

OOP- 44
Reuse/Release
Equivalency Principle

Release

A class generally collaborates with other


classes

For a class to be reused, you need also the


classes that this class depends on

All related classes must be released together

OOP- 45

Reuse/Release
Equivalency Principle
Tracking

A class being reused must not change in an


uncontrolled manner

Code copying is a poor form of reuse

Software must be released in small chunks -


components

Each chunk must have a version number

Reusers may decide on an appropriate time to


use a newer version of a component release OOP- 46
Common Closure Principle

“Classes within a released component should


share common closure. If one need to be
changed, they all are likely to need to be
changed. What affects one, affect all.”

OOP- 47

Common Closure Principle

A change must not cause modification to all


released components

Change must affect smallest possible number


of released components

Classes within a component must be cohesive

Given a particular kind of change, either all


classes in a component must be modified or no
class needs to be modified

Reduces frequency of re-release of component


OOP- 48
Common Reuse Principle

“Classes within a released component should


be reused together. That is, it must be
impossible to separate the component in order
to reuse less than the total.”

OOP- 49

Common Reuse Principle...

Components must be focused

Component must not contain classes that an


user is not likely to reuse

user may be forced to accept a new release


due to changes to unused classes

Component must be narrow

OOP- 50
Acyclic Dependence Principle

“The dependency structure for released


component must be a Directed Acyclic Graph.
There can be no cycles.”

OOP- 51

Acyclic Dependence Principle

If there are cycles, it becomes hard to maintain

Change ripples through

Can’t release components in small increments

OOP- 52
Stable Dependency Principle

“Dependencies between released components


must run in the direction of stability. The
dependee must be more stable than the
depender.”

OOP- 53

Stable Dependency
Principle
A component can never be more stable than the one
it depends upon

Instability I = Ce / (Ca + Ce),

where

Ca - # of classes outside that depend upon this


class

Ce - # of classes outside that this class depends


upon

0"I"1

0 - ultimately stable; 1 - ultimately unstable OOP- 54


Stable Dependency
Principle...

Components should be arranged such that


components with a high I metrics should
depend upon component with low I metrics

OOP- 55

Stable Abstraction
Principle

“The more stable a component is, the more it


must consist of abstract classes. A completely
stable category should consist of nothing but
abstract classes.”

OOP- 56
Stable Abstraction
Principle

Implementation of methods change more often


than the interface

Interfaces have more intrinsic stability than


executable code

Abstraction of a Component

! A = (# of abstract classes) / (# of classes)

0"A"1

0 - no abstract classes; 1 - all abstract classes


OOP- 57

Stability Vs.
Abstractness
A
(0, 1)
Th (1,1)
Highly
eM
Abstractness

instable &
ain abstract
Maximally
Se (Rigid)
stable qu
& abstract en
ce
(1, 0)
0 Instability
Highly
I
Maximally
stable &
instable
Concrete
& concrete
(Rigid) OOP- 58
Distance from the
main sequence
D = |(A + I - 1) / #2 |

0 " D " 0.707; Desirable value of D is closed to 0

Normalized form D' = |(A + I -1)|

Calculate D value for each component

Component whose D value is not near Zero can be


reexamined and restructured
OOP- 59

Applying the Principles


Developing with OO is more than

Using a certain language

Creating objects

Drawing UML

It tends to elude even experienced developers

Following the principles while developing code helps


attain agility

Use of each principle should be justified at each


occurrence, however OOP- 60
OO Principles and
Agile Development
These principles are more relevant during
iterative development and refactoring than
upfront design

As the requirements become clearer and we


understand the specifics the forces behind the
use of these principle become clear as well

OOP- 61

You might also like