oo design rules 2012
TRANSCRIPT
-
8/10/2019 Oo Design Rules 2012
1/50
ceCS 5751
7 Object-oriented Design Principles
1. Favor Composition Over Inheritance2. Program To An I nterface, Not An Implementation
3. The Open-Closed Principle: Software Entities ShouldBe Open For Extension, Yet Closed For Modification
4. The L iskov Substitution Pr inciple: Functions ThatUse References To Base Classes Must Be Able To UseObjects Of Derived Classes Without Knowing It
5. TheLaw of Demeter6. Minimize The Accessibility of Classes and Members
7. The Dependency Inversion Principle
-
8/10/2019 Oo Design Rules 2012
2/50
ceCS 5752
Favor Composition Over Inheritance
Composition- Method of reuse in which newfunctionality is obtained by creating an objectcomposed of other objects
The new functionality is obtained by delegating
functionality to one of the objects being composed Sometimes called aggregation or containment,
although some authors give special meanings tothese terms
-
8/10/2019 Oo Design Rules 2012
3/50
ceCS 5753
Favor Composition Over Inheritance
For example:Aggregation - when one object owns or is responsible
for another object and both objects have identicallifetimes (GoF)
Aggregation - when one object has a collection ofobjects that can exist on their own (UML)
Containment - a special kind of composition inwhich the contained object is hidden from otherobjects and access to the contained object is only via
the container object (Coad)
-
8/10/2019 Oo Design Rules 2012
4/50
ceCS 5754
Advantages/Disadvantages Of Composition
Advantages: Contained objects are accessed by the containing class solely
through their interfaces
"Black-box" reuse, since internal details of contained objects arenot visible
Good encapsulation Fewer implementation dependencies
Each class is focused on just one task
The composition can be defined dynamically at run-time throughobjects acquiring references to other objects of the same type
Disadvantages:
Resulting systems tend to have more objects
Interfaces must be carefully defined in order to use many differentobjects as composition blocks
-
8/10/2019 Oo Design Rules 2012
5/50
ceCS 5755
Inheritance
Method of reuse in which new functionality is obtained byextending the implementation of an existing object
The generalization class (the base class) explicitly captures thecommon attributes and methods
The specialization class (the derived class) extends theimplementation with additional attributes and methods
You can choose your associates, but youre stuck with yourancestors.
Inheritance is often held to be sacrosanct in OOD.
Tendency for OO developers to gauge the success of theirefforts by the complexity of their inheritance hierarchy.
-
8/10/2019 Oo Design Rules 2012
6/50
ceCS 5756
Advantages/Disadvantages Of Inheritance
Advantages: New implementation is easy, since most of it is inherited
Easy to modify or extend the implementation being reused
Disadvantages:
Breaks encapsulation, since it exposes a derived class toimplementation details of its base class
White-box" reuse, since internal details of base classes are oftenvisible to derived classes
Derived classes may have to be changed if the implementation of thebase class changes
Implementations inherited from base classes can not be changed atruntime
-
8/10/2019 Oo Design Rules 2012
7/50
ceCS 5757
Inheritance occurs in two types
1. Implementation Inheritance inheritance of implementation fragments/code from a base class.
2. Interface Inheritance
inheritance of contract fragments/interfaces.
Inheritance is a complex issue. Basic notions differ among OO languages
Some controversial issues--e.g. multiple inheritance.
Inheritance can break encapsulation.
Poorly conceived inheritance relationships can frustrate system
reliability, maintainability, and evolvability.
Inheritance is neither inherently good or bad. It must be usedin a disciplined manner.
-
8/10/2019 Oo Design Rules 2012
8/50
ceCS 5758
A Wacky Inheritance Example
An example of multiple inheritance from an OO text
Of course, a pie is not a fruit
-
8/10/2019 Oo Design Rules 2012
9/50
ceCS 5759
Composed Pie
Pies (and most objects in the world) are combinations ofproperties from divergent sources.
-
8/10/2019 Oo Design Rules 2012
10/50
ceCS 57510
Example Two
Inheritance is generally not appropriate for is a role playedby relationships.
For instance, consider roles in an airline reservation system:
passenger
ticket agent
flight crew
etc.
-
8/10/2019 Oo Design Rules 2012
11/50
ceCS 57511
Problems with Example 2
What happens if a pilot doubles as mechanic. And triples as aticket agent?
-
8/10/2019 Oo Design Rules 2012
12/50
ceCS 57512
Composition Version
Sometimes called delegation
I h it V C iti
-
8/10/2019 Oo Design Rules 2012
13/50
ceCS 57513
Inheritance Versus Composition--Some Guidelines
It is generally not a good idea to use inheritance for thefollowing purposes:
To represent dynamically changing alternative roles of a base class
To hide methods or attributes inherited from a base class.
To implement a domain-specific class as a derived class of a utility
class.
Potential Drawbacks of Composition
There may be some minor performance penalty for invoking anoperation across object boundaries as opposed to using an inheritedmethod.
Delegation cant be used with partially abstract (uninstantiable)classes
Delegation does not, in and of itself, impose any disciplinedstructure on the design (but neither does a class hierarchy).
-
8/10/2019 Oo Design Rules 2012
14/50
ceCS 57514
Coad's Rules
Use inheritance only when all of the following criteria aresatisfied:
A derived class expresses "is a special kind of" and not "is arole played by a"
An instance of a derived class never needs to become an objectof another class (transmutes)
A derived class extends, rather than overrides or nullifies, theresponsibilities of its base class
A derived class does not extend the capabilities of what is
merely a utility class
For a class in the actual Problem Domain, the derived classspecializes a role, transaction or device
-
8/10/2019 Oo Design Rules 2012
15/50
ceCS 57515
Inheritance VS Composition Example 1
-
8/10/2019 Oo Design Rules 2012
16/50
ceCS 57516
Inheritance VS Composition Example 1
"Is a special kind of" not "is a role played by a" Fail. A passenger is a role a person plays. So is an agent.
Never needs to transmute
Fail. A instance of a subclass of Person could change from Passengerto Agent to Agent Passenger over time
Extends rather than overrides or nullifies
Pass.
Does not extend a utility class
Pass.
Within the Problem Domain, specializes a role, transaction ordevice
Fail. A Person is not a role, transaction or device.
Inheritance not appropriate in this situation
-
8/10/2019 Oo Design Rules 2012
17/50
ceCS 57517
Inheritance VS Composition Example 1
Use composition to complete the relationships
-
8/10/2019 Oo Design Rules 2012
18/50
ceCS 57518
Inheritance VS Composition Example 2
Is inheritance okay here?
-
8/10/2019 Oo Design Rules 2012
19/50
ceCS 57519
Inheritance VS Composition Example 2
"Is a special kind of" not "is a role played by a" Pass. Passenger and agent are special kinds of person roles.
Never needs to transmute
Pass. A Passenger object stays a Passenger object; the same is truefor an Agent object.
Extends rather than overrides or nullifies
Pass.
Does not extend a utility class
Pass.
Within the Problem Domain, specializes a role, transaction ordevice
Pass. A PersonRole is a type of role.
Inheritance ok here!
-
8/10/2019 Oo Design Rules 2012
20/50
ceCS 57520
Inheritance VS Composition Example 3
-
8/10/2019 Oo Design Rules 2012
21/50
ceCS 57521
Inheritance VS Composition Example 3
"Is a special kind of" not "is a role played by a"
Pass. Reservation and purchase are a special kind of transaction.
Never needs to transmute
Pass. A Reservation object stays a Reservation object; the same istrue for a Purchase object.
Extends rather than overrides or nullifies Pass.
Does not extend a utility class Pass.
Within the Problem Domain, specializes a role, transaction ordevice Pass. It's a transaction.
Inheritance is okay in this situation
-
8/10/2019 Oo Design Rules 2012
22/50
ceCS 57522
Inheritance vs. Composition Summary
Both composition and inheritance are important methods ofreuse
Inheritance was overused in the early days of OO development
Over time we've learned that designs can be made morereusable and simpler by favoring composition
Of course, the available set of classes that can be composed canbe enlarged using inheritance
So composition and inheritance work together
But our fundamental principle is:
Favor Composition Over Inheritance
Program To An Interface Not An
-
8/10/2019 Oo Design Rules 2012
23/50
ceCS 57523
Program To An Interface, Not AnImplementation
An interface is the set of methods one object knows it caninvoke on another object
An object can have many interfaces. (Essentially, an interfaceis a subset of all the methods that an object implements).
A type is a specific interface of an object
Different objects can have the same type and the same objectcan have many different types
An object is known by other objects only through its interface
In a sense, interfaces express "is a kind of" in a very limitedway as "is a kind of that supports this interface"
Interfaces are the key to reusability!
-
8/10/2019 Oo Design Rules 2012
24/50
ceCS 57524
Implementation Inheritance vs InterfaceInheritance
Implementation Inheritance (Class Inheritance) - an object'simplementation is defined in terms of another's objectsimplementation
Interface Inheritance (Subtyping) - describes when one objectcan be used in place of another object
The C++ inheritance mechanism means both class and interfaceinheritance
C++ can perform interface inheritance by inheriting from apure abstract class
Java has a separate language construct for interface inheritance- the Java interface
Java's interface construct makes it easier to express andimplement designs that focus on object interfaces
-
8/10/2019 Oo Design Rules 2012
25/50
-
8/10/2019 Oo Design Rules 2012
26/50
ceCS 57526
The Open-Closed Principle: Software Entities Should BeOpen For Extension, Yet Closed For Modification
The Open-Closed Principle (OCP) says that we should attempt todesign modules that never need to be changed
To extend the behavior of the system, we add new code. We donot modify old code.
Modules that conform to the OCP meet two criteria:
Open For Extension - The behavior of the module can be extended tomeet new requirements
Closed For Modification - the source code of the module is not allowedto change
How can we do this?
Abstraction
Polymorphism
Inheritance
Interfaces
-
8/10/2019 Oo Design Rules 2012
27/50
ceCS 57527
The Open-Closed Principle
It is not possible to have all the modules of a software systemsatisfy the OCP, but we should attempt to minimize the numberof modules that do not satisfy it
The Open-Closed Principle is really the heart of OO design
Conformance to this principle yields the greatest level ofreusability and maintainability
Open Closed Principle Open Closed
-
8/10/2019 Oo Design Rules 2012
28/50
ceCS 57528
Open-Closed Principle Open-ClosedPrinciple Example
Consider the following method of some class:
public double totalPrice(Part[] parts) {
double total = 0.0;
for (int i=0; i
-
8/10/2019 Oo Design Rules 2012
29/50
ceCS 57529
Open-Closed Principle Example ( Open-Closed PrincipleExample (Continued)
But what if the Accounting Department decrees that motherboardparts and memory parts should have a premium applied whenfiguring the total price.
How about the following code?public double totalPrice(Part[] parts) {
double total = 0.0;
for (int i=0; i
-
8/10/2019 Oo Design Rules 2012
30/50
ceCS 57530
Open-Closed Principle Example ( Open-Closed PrincipleExample (Continued)
Does this conform to the OCP? No way! Every time the Accounting Department comes out with a new
pricing policy, we have to modify the totalPrice() method! It isnot Closed For Modification. Obviously, policy changes suchas 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
-
8/10/2019 Oo Design Rules 2012
31/50
ceCS 57531
Closed for Modification? Open for Extension?
#include
using namespace std;
class pizza {
public:
virtual float cost()=0 {}
};
class small_pizza : public pizza {public:
float cost(){
return 10.0;
}
};
class medium_pizza : publicpizza {
public:
float cost(){
return 12.0;
}
};
enum psize {none, small, medium};
pizza *factory(int size) {if(size==small)
return new small_pizza;
else
if(size==medium)
return new medium_pizza;
else
return none;}
int main(){
pizza *p;
int size;
cout > size;
p=factory(size);
cout
-
8/10/2019 Oo Design Rules 2012
32/50
ceCS 57532
The Liskov Substitution Principle:
Functions That Use References To Base (Super)Classes Must Be Able To Use Objects Of Derived(Sub) Classes Without Knowing It
In intent, Liskov Substitution Principle (LSP) forces
software designers to not override base classfunctionality if it affects the performance ofcomponents designed to work with the base class.
-
8/10/2019 Oo Design Rules 2012
33/50
ceCS 57533
If Sis a subtype of T, then objects of typeTmay be replaced with objects of type S
without altering the correctness of the
program.
Definition
-
8/10/2019 Oo Design Rules 2012
34/50
ceCS 57534
Example
class W {
(..)
void use (T obj) {
String s = obj.getInfo()
}
(..)}
objW.use(objT)
/* no error is introduced if S is
compliant with the principle*/
objW.use(objS)
-
8/10/2019 Oo Design Rules 2012
35/50
ceCS 57535
Example
-
8/10/2019 Oo Design Rules 2012
36/50
ceCS 57536
Example
/*Method to print informationabout someone on the screen*/
void printInfo(Person obj) { ()
parser.parseName(obj.getName());() }
A programmer may write
expecting this code to work for all derived types ofPerson, including Employee. This code will
actually result in error.
The redefinition of getName changed the behaviorof the method, and introduced an error (or severalerrors) in the program.
-
8/10/2019 Oo Design Rules 2012
37/50
ceCS 57537
LSP Summary
In order for the LSP to hold (and with it the Open-Closed
Principle) all subclasses must conform to the behavior that clientsexpect of the base classes they use
A subtype must have no more constraints than its base type, sincethe subtype must be usable anywhere the base type is usable
If the subtype has more constraints than the base type, there wouldbe uses that would be valid for the base type, but that wouldviolate one of the extra constraints of the subtype and thus violatethe LSP!
The guarantee of the LSP is that a subclass can always be usedwherever its base class is used!
-
8/10/2019 Oo Design Rules 2012
38/50
ceCS 57538
Minimize The Accessibility of Classes and Members
We must define several key concepts:
abstraction,
information hiding, and
encapsulation,
All three are different, independent characteristics, and allthree are possible in non-OO languages
-
8/10/2019 Oo Design Rules 2012
39/50
ceCS 57539
Abstraction
"Abstraction is the selective examination of certain aspects of a
problem. The goal of abstraction is to isolate those aspects that areimportant for some purpose and suppress those aspects that areunimportant."
-- [Rumbaugh et al, 1991]
"A view of a problem that extracts the essential informationrelevant to a particular purpose and ignores the remainder of theinformation."
-- [IEEE, 1983]
"An abstraction denotes the essential characteristics of an objectthat distinguish it from all other kinds of object and thus providecrisply defined conceptual boundaries, relative to the perspective ofthe viewer."
-- [Booch, 1991]
Abstraction is one of the fundamental ways to deal with complexity
-
8/10/2019 Oo Design Rules 2012
40/50
ceCS 57540
Information Hiding
The second decomposition was made using 'information hiding'... as a criterion. The modules no longer correspond to steps inthe processing. ... Every module in the second decomposition ischaracterized by its knowledge of a design decision which ithides from all others. Its interface or definition was chosen toreveal as little as possible about its inner workings."
-- [Parnas, 1972b]
"The process of hiding all the details of an object that do notcontribute to its essential characteristics; typically, the structureof an object is hidden, as well as the implementation of its
methods. The terms information hiding and encapsulation areusually interchangeable." -- [Booch, 1991]
"... [I]nformation hiding: a module is characterized by theinformation it hides from other modules, which are called itsclients. The hidden information remains a secret to the clientmodules." -- [Ghezzi et al, 1991]
-
8/10/2019 Oo Design Rules 2012
41/50
ceCS 57541
Encapsulation
"[E]ncapsulation -- also known as information hiding -- preventsclients from seeing its inside view, were the behavior of theabstraction is implemented."
-- [Booch, 1991]
"Encapsulation (also information hiding) consists of separatingthe external aspects of an object which are accessible to otherobjects, from the internal implementation details of the object,which are hidden from other objects."
-- [Rumbaugh et al, 1991]
"The concept of encapsulation as used in an object-orientedcontext is not essentially different from its dictionary definition.It still refers to building a capsule, in the case a conceptual
barrier, around some collection of things."
-- [Wirfs-Brock et al, 1990]
-
8/10/2019 Oo Design Rules 2012
42/50
ceCS 57542
Use Accessors and Mutators, Not Public Members
Use private members and appropriate accessors and mutators wherever possible
For example:
Replace
public double speed;
with
private double speed;public double getSpeed() {
return(speed);
}
public void setSpeed(double newSpeed) {
speed = newSpeed;}
-
8/10/2019 Oo Design Rules 2012
43/50
ceCS 57543
Benefits of Information Hiding
You can put constraintson values
public void setSpeed(double newSpeed) {
if (newSpeed < 0) {
sendErrorMessage(...);
newSpeed = Math.abs(newSpeed);}
speed = newSpeed;
}
If users of your class accessed the fields directly, then theywould each be responsible for checking constraints
-
8/10/2019 Oo Design Rules 2012
44/50
ceCS 57544
Benefits of Information Hiding
You can change your internal representation without changing the interface// Now using metric units (kph, not mph)
public void setSpeedInMPH(double newSpeed) {
speedInKPH = convert(newSpeed);
}
public void setSpeedInKPH(double newSpeed) {speedInKPH = newSpeed;
}
-
8/10/2019 Oo Design Rules 2012
45/50
ceCS 57545
Benefits of Information Hiding
You can perform arbitrary side effects
public double setSpeed(double newSpeed) {
speed = newSpeed;
notifyObservers();}
If users of your class accessed the fields directly, then theywould each be responsible for executing side effects
-
8/10/2019 Oo Design Rules 2012
46/50
ceCS 57546
The Law of Demeter
Only talk to your immediate friends.
An object should assume as little as possible about the structureor properties of anything else (including its subcomponents).
More formally, the Law of Demeter for functions requires thata methodMof an object Omay only invoke the methods of the
following kinds of objects: Oitself
M's parameters
any objects created/instantiated withinM
O's direct component (aggregated) objects
-
8/10/2019 Oo Design Rules 2012
47/50
ceCS 57547
Demeter Example
class C {
public:void HiC(){
return;
}
};
class P {
public:void op1(){
return;
}
};
class DontTalk2Me {public:
void DontTalkToMe(){
return;
}
};
DontTalk2Me dt2m;
class O {
C cobj;
public:void op1(P pobj) {
pobj.op1();
cobj.HiC();
dt2m.DontTalkToMe();
}
Void op2() {
op1();
};
int main(){
O obj;
P p;
obj.op1(p);
return 0;
}
-
8/10/2019 Oo Design Rules 2012
48/50
-
8/10/2019 Oo Design Rules 2012
49/50
-
8/10/2019 Oo Design Rules 2012
50/50
Simple Example
// Dependency Inversion Principle - Bad example
class Worker {public void work() {
// ....working
}
}
class Manager {
Worker m_worker;
public void setWorker(Worker w) {
m_worker=w;
}
public void manage() {
m_worker.work();
}}
class SuperWorker {
public void work() {
//.... working much more
}
}
// Dependency Inversion Principle - Good example
interface IWorker {
public void work();
}
class Worker implements IWorker{
public void work() {
// ....working
}
}
class SuperWorker implements IWorker{public void work() {
//.... working much more
}
}
class Manager {
IWorker m_worker;public void setWorker(IWorker w) {
m_worker=w;
}
public void manage() {
m_worker.work();
}