Title: Basic OO Concepts
1Basic OO Concepts Principles
2What is an Object? An object is a software
bundle of related variables and methods. Software
objects are often used to model real-world
objects you find in everyday life.
Visual representation of a software object
A bicycle modeled as a software object
3What is a Class? A class is a blueprint or
prototype that defines the variables and the
methods common to all objects of a certain kind.
- ? Class is an implementation of an abstract data
type and so encapsulates both data and
operations. - ? Object is run-time instance of class.
- Classes just sit there, objects do the real work.
- Memory is allocated for Objects not for Classes.
4What is a Message? Software objects interact and
communicate with each other using messages.
? The object to which the message is addressed
(YourBicycle) ? The name of the method to
perform (changeGears) ? Any parameters needed by
the method (lowerGear)
5To be object oriented, a language must support ?
Encapsulation ? Inheritance ? Dynamic
Binding Some of the popular OO languages
are C Smalltalk Java Eiffel FORTRAN90 CLOS(Commo
n Lisp Object System) Ada95 Modula-3
6Encapsulation Packaging an object's variables
within the protective custody of its methods is
called encapsulation. Often, for practical
reasons, an object may wish to expose some of its
variables or hide some of its methods. Access
Levels
7What is Inheritance? A class inherits state and
behavior from its superclass. Inheritance
provides a powerful and natural mechanism for
organizing and structuring software programs.
Super Class
Subclasses
8- Properties
- ?Each subclass inherits state (in the form of
variable declarations) from the superclass. - Subclasses can add variables and methods to the
ones they inherit from the superclass. - Subclasses can also override inherited methods
and provide specialized implementations for
those methods. - You are not limited to just one layer of
inheritance. The inheritance tree, or class
hierarchy, can be as deep as needed. - Benefits
- ?Re-Usability
- Subclasses provide specialized behaviors from the
basis of common elements provided by the
superclass. Through the use of inheritance,
programmers can reuse the code in the superclass
many times. - ?Can define Abstract Classes
- Programmers can implement superclasses called
abstract classes that define "generic" behaviors.
9Types of Inheritance
A
B
Multi-level Inheritance
Multiple Inheritance
A
C
B
A-1
B-1
C
A-2
B-2
Multiple Multi-level Inheritance
AB
10Concept Classes form a hierarchy
- Classes are arranged in a treelike structure
called a hierarchy - The class at the root is named Object
- Every class, except Object, has a superclass
- A class may have several ancestors, up to Object
- When you define a class, you specify its
superclass - If you dont specify a superclass, Object is
assumed - Every class may have one or more subclasses
11Example of (part of) a hierarchy
A FileDialog is a Dialog is a Window is a
Container.
12C is different
- In C there may be more than one root
- but not in Java!
- In C an object may have more than one parent
(immediate superclass) - but not in Java!
- Java has a single, strict hierarchy
13Concept Objects inherit from their superclasses
- A class describes fields and methods
- Objects of that class have those fields and
methods - But an object also inherits
- the fields described in the class's superclasses
- the methods described in the class's superclasses
- A class is not a complete description of its
objects!
14Example of inheritance
class Person String name String age
void birthday () age age 1
class Employee extends Person
double salary void pay () ...
Every Employee has a name, age, and birthday
method as well as a salary and a pay method.
15Concept A variable can hold subclass objects
- Suppose B is a subclass of A
- A objects can be assigned to A variables
- B objects can be assigned to B variables
- B objects can be assigned to A variables, but
- A objects can not be assigned to B variables
- Every B is also an A but not every A is a B
- You can cast bVariable (B) aObject
- In this case, Java does a runtime check
16Example Assignment of subclasses
class Dog ... class Poodle extends Dog ...
Dog myDogDog rover new Dog () Poodle
yourPoodlePoodle fifi new Poodle ()
myDog rover //
ok yourPoodle fifi //
ok myDog fifi
//ok yourPoodle rover //
illegal yourPoodle (Poodle) rover
//runtime check
17Concept Methods can be overridden
class Bird extends Animal void fly (String
destination) location destination
class Penguin extends Bird void fly (String
whatever)
- So birds can fly. Except penguins.
18Sneaky trick You can still use overridden methods
class FamilyMember extends Person void
birthday () super.birthday () // call
overridden method givePresent () //
and add your new stuff
19Dynamic Binding
- ? Dynamic binding occurs when the type of
variable changes at run-time. - A common way for a variable to change its type is
via assignment. - Bike MoutainBike is safe
- MountainBikeBike is not safe
- MountainBike is declared to have all the features
of Bike so the assignment does no harm. - ? A variable that starts life of the type Bike
may be attached to any object that is a kind of
Bike, including MountainBike,RacingBike, - ? A variable that starts life of the type
MountainBike can only be attached to MountainBike
objects but does not include RacingBike or
general Bike.
20- Polymorphism
- ? The ability to appear in many forms.
- ? In object-oriented programming, polymorphism
refers to a programming language's ability to
process objects differently depending on their
data type or class. - It is the ability to redefine methods for derived
classes. - E.g. e-bike Acceleration system.
- Electronically / Mechanically
21Polymorphism
- Behavior promised in the public interface of
superclass objects - implemented by subclass objects
- in the specific way required for the subclass
- Why Is this Important?
- Allow subclasses to be treated like instances of
their superclasses - Flexible architectures and designs
- high-level logic defined in terms of abstract
interfaces - relying on the specific implementation provided
by subclasses - subclasses can be added without changing
high-level logic
22Polymorphism Example
23Concept An object has behaviors
- In old style programming, you had
- data, which was completely passive
- functions, which could manipulate any data
- An object contains both data and methods that
manipulate that data - An object is active, not passive it does things
- An object is responsible for its own data
- But it can expose that data to other objects
24Concept An object has state
- An object contains both data and methods that
manipulate that data - The data represent the state of the object
- Data can also describe the relationships between
this object and other objects - Example A CheckingAccount might have
- A balance (the internal state of the account)
- An owner (some object representing a person)
25Example A Rabbit object
- You could (in a game, for example) create an
object representing a rabbit - It would have data
- How hungry it is
- How frightened it is
- Where it is
- And methods
- eat, hide, run, dig
26Concept Classes describe objects
- Every object belongs to (is an instance of) a
class - An object may have fields, or variables
- The class describes those fields
- An object may have methods
- The class describes those methods
- A class is like a template, or cookie cutter
27Concept Classes are like Abstract Data Types
- An Abstract Data Type (ADT) bundles together
- some data, representing an object or "thing"
- the operations on that data
- Example a CheckingAccount, with operations
deposit, withdraw, getBalance, etc. - Classes enforce this bundling together
28Example of a class
class Employee // fields String name
double salary // a method void pay ()
System.out.println("Pay to the order of "
name " "
salary)
29Approximate Terminology
- instance object
- field variable
- method function
- sending a message to an object calling a
function - These are all approximately true
30Concept Objects must be created
- int n does two things
- it declares that n is an integer variable
- it allocates space to hold a value for n
- Employee secretary does one thing
- it declares that secretary is type Employee
- secretary new Employee ( ) allocates the space
31Notation How to declare and create objects
- Employee secretary // declares secretary
- secretary new Employee () // allocates space
- Employee secretary new Employee() // both
- But the secretary is still "blank"
- secretary.name "Adele" // dot notation
- secretary.birthday () // sends a message
32Notation How to reference a field or method
- Inside a class, no dots are necessary
- class Person ... age age 1 ...
- Outside a class, you need to say which object you
are talking to - if (john.age lt 75) john.birthday ()
- If you don't have an object, you cannot use its
fields or methods!
33Concept this object
- Inside a class, no dots are necessary, because
- you are working on this object
- If you wish, you can make it explicit
- class Person ... this.age this.age 1 ...
- this is like an extra parameter to the method
- You usually don't need to use this
34Concept Don't call functions, send messages
- Bird someBird pingu
- someBird.fly ("South America")
- Did pingu actually go anywhere?
- You sent the message fly(...) to pingu
- If pingu is a penguin, he ignored it
- otherwise he used the method defined in Bird
- You did not directly call any method
35Concept Constructors make objects
- Every class has a constructor to make its objects
- Use the keyword new to call a constructor
- secretary new Employee ( )
- You can write your own constructors but if you
dont, - Java provides a default constructor with no
arguments - It sets all the fields of the new object to zero
- If this is good enough, you dont need to write
your own - The syntax for writing constructors is almost
like that for writing methods
36Syntax for constructors
- Instead of a return type and a name, just use the
class name - You can supply arguments
Employee (String theName, double theSalary)
name theName salary theSalary
37Trick Use the same name for a parameter as for a
field
- A parameter overrides a field with the same name
- But you can use this.name to refer to the field
Person (String name, int age) this.name
name this.age age
- This is a very common convention
38Internal workingsConstructor chaining
- If an Employee is a Person, and a Person is an
Object, then when you say new Employee () - The Employee constructor calls the Person
constructor - The Person constructor calls the Object
constructor - The Object constructor creates a new Object
- The Person constructor adds its own stuff to the
Object - The Employee constructor adds its own stuff to
the Person
39The case of the vanishing constructor
- If you don't write a constructor for a class,
Java provides one (the default constructor) - The one Java provides has no arguments
- If you write any constructor for a class, Java
does not provide a default constructor - Adding a perfectly good constructor can break a
constructor chain - You may need to fix the chain
40Example Broken constructor chain
class Person String name Person (String
name) this.name name class Employee
extends Person double salary Employee (
) // here Java tries to call new Person()
but cannot find it salary 12.50
41Fixing a broken constructor chain
- Special syntax super(...) calls the superclass
constructor - When one constructor calls another, that call
must be first - class Employee double salary Employee
(String name) super(name) // must be
first - salary 12.50
- Now you can only create Employees with names
- This is fair, because you can only create Persons
with names
42Trick one constructor calling another
- this(...) calls another constructor for this same
class
class Something Something (int x, int y, int
z) // do a lot of work here
Something ( ) this (0, 0, 0)
- It is poor style to have the same code more than
once - If you call this(...), that call must be the
first thing in your constructor
43Concept You can control access
class Person public String name
private String age protected double salary
public void birthday age
- Each object is responsible for its own data
- Access control lets an object protect its data
- We will discuss access control shortly
44Concept Classes themselves can have fields and
methods
- Usually a class describes fields (variables) and
methods for its objects (instances) - These are called instance variables and instance
methods - A class can have its own fields and methods
- These are called class variables and class
methods - There is exactly one copy of a class variable,
not one per object - Use the special keyword static to say that a
field or method belongs to the class instead of
to objects
45Example of a class variable
class Person String name int age
static int population Person (String name)
this.name name this.age
0 population
46Advice Restrict access
- Always, always strive for a narrow interface
- Follow the principle of information hiding
- the caller should know as little as possible
about how the method does its job - the method should know little or nothing about
where or why it is being called - Make as much as possible private
47Advice Use setters and getters
class Employee extends Person private double
salary public void setSalary (double
newSalary) salary newSalary
public double getSalary () return salary
- This way the object maintains control
- Setters and getters have conventional names
48Kinds of access
- Java provides four levels of access
- public available everywhere
- protected available within the package (in the
same subdirectory) and to all subclasses - default available within the package
- private only available within the class itself
- The default is called package visibility
- In small programs this isn't important...right?
49Dependency Management
- The parts of a project depend on each other
- components, programs, groups of classes,
libraries - Dependencies limit
- flexibility
- ease of maintainance
- reuse of components or parts
- Dependency management tries to control
dependencies
50Dependency Management and Software
- Software systems are the most complex artificial
systems - There will be a lot of dependencies
- Software development was and is always concerned
with dependencies - OOAD gives us tools to manage dependencies
- trace dependencies e.g. in UML models
- use OO language to manipulate dependencies
51Problems with Software
- Rigid
- Fragile
- Not Reuseable
- High Viscosity
- Useless Complexity
- Repetition
- Opacity
These statements apply to an average
physicist/programmer who develops and/or
maintains some software system. Software gurus
will always find some solution in their code. Do
you want to rely on the guru? What if that person
retires, finds a well-paid job or gets moved
to another project?
52Rigid Software
- Difficulties with changes
- Unforeseen side effects occur frequently
- Hard to estimate time to complete modifications
- "Roach Motel"
- Always in need of more effort
- Management reluctant to allow changes
- Official rigidity, "don't touch a working system"
- Users forced to develop workarounds
53Fragile Software
- Small changes have large side effects
- New bugs appear regularly
- In the limit of P(bugchange) 1 system is
impossible to maintain - It looks like control has been lost
- Users become critical
- Program looses credibility
- Developers loose credibility
54Not Reuseable
- You have a problem and find some piece of code
which might solve it - but it brings in a lot of other stuff
- it needs changes here and there
- Eventually you have two choices
- Take over maintainance of the branched code
- Roll your own
- You would like to include headers and link a
library maintained by somebody else
55High Viscosity
- Viscosity of the design
- Hard to make changes properly, i.e. without
breaking the design ? make hacks instead - Viscosity of the environment
- Slow and inefficient development environment
- Large incentive to keep changes localised even if
they break designs - Design changes are very difficult
56Useless Complexity
- Design/code contains useless elements
- Often for anticipated changes or extension
- May pay off
- Meanwhile makes design/code harder to understand
- Or leftovers of previous design changes?
- Time for a clean-up
- Tradeoff between complexity now and anticipated
changes later
57Repetition
- Added functionality using cut-and-paste
- Then slight modifications for local purpose
- Find same structure repeatedly
- More code
- Harder to debug and modify
- There is an abstraction somewhere
- Refactor into function/method
- Create class(es) to do the job
58Opacity
- Design/code difficult to understand
- We have all suffered ...
- What is clear now may seem strange later
- Ok when its your code
- You suffer in silence
- Not acceptable in collaboration
- Need to code clearly, may need to rearrange
- Code reviews?
59Dependencies Managed
- Code is less rigid
- Code is less fragile
- Reuse is possible
- Viscosity is low
60Less Rigid Code
- Modules can be interchanged
- Changes are confined to a few modules
- Cost of changes can be estimated
- Changes can be planned and scheduled
- Management is possible
61Less Fragile Code
- Confined changes mean P(bugchange) is small
- New bugs will most likely appear where the
changes was made, i.e. localised - Easier to fix (hopefully)
- Risk of changes can be estimated
- Credibility of code and developers conserved
62 Reuseable Code
- A module can be used in a different context
without changes - Just use headers and link a library
- No need to compile and/or link lots of unrelated
stuff
63Low Viscosity
- Design is easy to modify
- No quick hacks needed
- Proper design improvements will actually happen
- Large scale changes affecting many modules are
possible - Reasonable compile and link times for the whole
system - May depend on adequate hardware as well
64Compile and Link Times
- Compile and link times are unproductive
- In a project with N modules compile and link time
can grow like N2 (assuming every module is
tested) when dependencies are not controlled - Loss of productivity
- Long turnaround times ? slow development
- Dependency management essential in large projects
65Code Changes
- Modules/packages and makefiles
- Verify that makefiles are reliable
- Changes to libraries (reuseable code)
- All affected users must relink (and retest)
- Shared libraries
- Need to distribute (and restart programs)
- Validation by users still needed
- Need recompile after interface changes
66The Copy Routine
- Code rots
- There are many reasons for code rot
- We'll make a case study (R. Martin)
- A routine which reads the keyboard and writes to
a printer
67Copy Version 1
A simple solution to a simple problem ReadKeyboar
d and WritePrinter are probably reuseable
68Copy Version 2
Many users want to read files too ... But they
don't want to change their code ... can't put a
flag in the call Ok, so we use a global
flag Its backwards compatible To read files you
have to set the flag first
69Copy Version 3
Oh dear, we introduced a bug in version 2
(printing EOF isn't nice) Version 3 fixes this
bug
bool GFile void Copy(void) char ch
while( 1 ) if( GFile ) ch ReadFile()
else ch ReadKeyboard() if( ch EOF
) break WritePrinter( ch )
70Copy Version 4
Users want to write to files, of course they want
it backwards compatible We know how to do
that! The Copy routine seems to grow in size and
complexity every time a feature is added The
protocol to use it becomes more complicated
71Copy done properly in C
Finally a good C programmer comes to the rescue!
But this is C?! FILE, fgetc and fputc behave
like an interface class FILE represents a
generic byte stream manipulated by fgetc, fputc
etc.
72Copy in C
More complicated but easy to add new features
73Copy Routine Summary
- Lack of sensible design leads to code rot
- Useless complexity, repetition, opacity
- Software systems are dynamic
- New requirements, new hardware
- A good design makes the system flexible and
allows easy extensions - Abstractions and interfaces
- An OO design may be more complex but it builds in
the ability to make changes
74Dependency Management Summary
- Controlling dependencies has several advantages
for software system - Not rigid, not fragile, reuseable, low viscosity
- Also affects development environment
- Lower compile and link times, less testing
- More productive work
- Plan for changes and maintainance
75Packages Introduction
- What is a package?
- Classes are not sufficient to group code
- Some classes collaborate ? dependencies
- Some don't know each other
- Grouping related classes together seems natural
- But how?
- Dependencies between packages
76Package
- A package is a group of classes
- Classes in a package are often compiled together
into a library - but unit of compilation is mostly individual
class - A package is a unit for testing
- A package can be a releasable component
- a CVS module
77Packages in UML
A package
A dependency between packages
A package with classes shown inside
78Realization
GUI depends on AbsUI Associations exist between
classes in GUI and AbsUI
AbsUI is an abstract package
ServerStuff realises AbsUI, it is a concrete
package An inheritance relationship
exists between classes in AbsUI and ServerStuff
79Three Package Design Principles
- Reuse-Release Equivalency Principle
- Common Closure Principle
- Common Reuse Principle
80Reuse-Release Equivalency Principle (REP)
The unit of reuse is the unit of release Bob
Martin
It is about reusing software Reuseable software
is external software, you use it but somebody
else maintains it. There is no difference between
commercial and non-commercial external software
for reuse.
81Reuse-Release Equivalency
- Expectations on external software
- Documentation
- complete, accurate, up-to-date
- Maintainance
- bugs will be fixed, enhancements will be
considered - Reliability
- no major bugs
- no sudden changes
- can stay with proven versions (for a while)
82Release Control
- Requirements for reuseable software
- Put reuseable components into a package
- Track versions of the package (CVS)
- Assign release numbers to stable releases
- Stable releases need release notes
- Allow users to use older releases for a while
- The unit of reuse is the unit of release
83REP Summary
- Group components (classes) for reusers
- Single classes are usually not reuseable
- Several collaborating classes make up a package
- Classes in a package should form a reuseable and
releaseable module - Module provides coherent functionality
- Dependencies on other packages controlled
- Requirements on other packages specified
- Reduces work for the reuser
84Common Closure Principle (CCP)
Classes which change together belong together Bob
Martin
Minimise the impact of change for the
programmer. When a change is needed, it is good
for the programmer if the change affects as few
packages as possible, because of compile and link
time and revalidation
85From OCP to CCP
- OCP Classes should be open for extension, but
closed for modification - This is an ideal
- Classes will be designed for likely kinds of
changes - Cohesion of closure for packages
- Classes in a package should be closed to the same
kinds of changes - Changes will be confined within few packages
- Reduces frequency of release of packages
86CCP Summary
- Group classes with similar closure together
- package closed for anticipated changes
- Confines changes to a few packages
- Reduces package release frequency
- Reduces work for the programmer
87 Commom Reuse Principle (CRP)
Classes in packages should be reused together Bob
Martin
Packages should be focused, users should use all
classes from a package CRP for packages is
analogous to SRP for classes
88Common Reuse
- Use of a package brings in all its dependencies
- When a user is only interested in a few classes
of a package - the user code still depends on all dependencies
of the package - the user code must be recompiled/relinked and
retested after a new release of the package, even
if the actually used classes didn't change - CRP helps to avoid this situation
89CRP Summary
- Group classes according to common reuse
- avoid unneccessary dependencies for users
- Following the CRP often leads to splitting
packages - Get more, smaller and more focused packages
- CRP analogous to SRP for classes
- Reduces work for the reuser
90The Triad Triangle
91The Development Environment
- Controlling relations between packages
- Critical for large projects
- Programming, compile and link time
- Three more package design principles
- Acyclic Dependencies
- Stable Dependencies
- Stable Abstractions
- Other aspects of the development environment
92The Acyclic Dependencies Principle (ACP)
The dependency structure for packages must be a
Directed Acyclic Graph (DAG)
Stabilise and release a project in pieces Avoid
interfering developers ? Morning after
syndrome Organise package dependencies in a
top-down hierarchy
93Morning-After-Syndrome
- Not the one after an extended pub crawl
- You work on a package and eventually it works ?
you go home happy - The next day your package stopped working!
- A package you depend upon changed
- Somebody stayed later or came in earlier
- When this happens frequently
- Developers interfere with each other
- Hard to stabilise and release
94Dependencies are a DAG
It may look complicated, but it is a DAG
(Directed Acyclic Graph)
Can exchange ObjyIO and RootIO
95Dependency Cycles
A cycle between Framework and ObjyIO Must
develop together May need multipass link
96ADP Summary
- Dependency structure of packages is a DAG
- Dependency cycles ? Morning-After-Syndrome
- Dependency hierarchy should be shallow
- Break cycles with
- Abstract interfaces (DIP)
- Splitting packages (CRP)
- Reorganising packages
97Stable Dependencies Principle (SDP)
Dependencies should point in the direction of
stability
Robert Martin
Stability corresponds to effort required to
change a package stable package ? hard to
change within the project Stability can be
quantified
98Quantifying Stability
A is a stable package, many other packages depend
on it ? Responsible I 0
Ca classes outside the package which depend
on classes inside the package (incoming
dependencies) Ce classes outside the package
which classes inside the package depend upon
(outgoing dependencies)
A is unstable, it depends on many other
packages ? Irresponsible I 1
Instability I-Metric
99SDP Example
Bad
Good
A is responsible for B, C and D. It depends on
E, ? irresponsible
A is responsible for B, C, D and E. It will be
hard to change
E depends on F, G and E. A depends on it. E is
responsible and irresponsible.
E depends on A, F, G and H. It is irresponsible
and will be easy to modify.
100SDP Summary
- Organise package dependencies in the direction of
stability - (In-) Stability can be quantified ? I-Metric
- Dependence on stable packages corresponds to DIP
for classes - Classes should depend upon (stable) abstractions
or interfaces - These can be stable (hard to change)
101Stable Abstractions Principle (SAP)
Stable packages should be abstract
packages. Unstable packages should be concrete
packages.
Robert Martin
Stable packages contain high level design. Making
them abstract opens them for extension but closes
them for modifications (OCP). Some flexibility is
left in the stable hard-to-change packages.
102Quantifying Abstractness
- The Abstractness of a package can be quantified
- Abstractness A is defined as the fraction of
abstract classes in a package. - Corresponds to abstract classes
- Abstract classes have at least one pure virtual
member function - Abstract packages have at least one abstract class
103Correlation of Stability and Abstractness
- Abstract packages should be responsible and
independent (stable) - Easy to depend on
- Concrete packages should be irresponsible and
dependent (unstable) - Easy to change
104The A vs I Plot
Abstractness A
1
Abstract and unstable ? probably useless
Abstract and stable ? good
Main Sequence
Unstable and concrete ? good
Stable and concrete ? problematic, CLHEP,
STL, database schema ok, not volatile
0
1
I Instability
105Distance from Main Sequence D-Metric
D AI-1
Normalised so that D ? 0,1
Can use mean and standard deviation to set
control limits Can find troublesome
packages Concrete and stable packages like CLHEP
or STL will have D ? 1
106Examples from BaBar
Offline code packages release 6.0.1 (early 1999)
Much of the BaBar code at the time was too
concrete for its stability At least the problem
was recognised ...
107SAP Summary
- Stable packages should be abstract
- In a large project packages should have a balance
of Abstractness and Instability - Lie close to the main sequence in A-I-plot
- Metrics I and A help to quantify code quality
- Other metrics exist too
- Code volume and code growth rate
- Bug discovery and extinction rate
108Mapping Packages on the Computer
- The BaBar example
- Each package corresponds to a directory with flat
structure under individual CVS control - Contains headers (.hh), code (.cc), documentation
- GNUmakefile fragment for building and
dependencies - Build target is a link library and possibly
binaries - include "package/class.hh"
- Works well ... easy to understand
109Object Oriented Design Summary
- Package Design Principles
- Reuse-Release Equivalence
- Common Closure
- Common Reuse
- Acyclic Dependencies
- Stable Dependencies
- Stable Abstractions
- Class Design Principles
- Single Responsibility
- Open-Closed
- Liskov Substitution
- Dependency Inversion
- Interface Segregation
110The Object-Oriented ... Hype
- What are object-oriented (OO) methods?
- OO methods provide a set of techniques for
analysing, decomposing, and modularising software
system architectures - In general, OO methods are characterized by
structuring the system architecture on the basis
of its objects (and classes of objects) rather
than the actions it performs - What is the rationale for using OO?
- In general, systems evolve and functionality
changes, but objects and classes tend to
remain stable over time - Use it for large systems
- Use it for systems that change often
111OO Design vs. OO Programming
- Object-Oriented Design
- a method for decomposing software architectures
- based on the objects every system or subsystem
manipulates - relatively independent of the programming
language used - Object-Oriented Programming
- construction of software systems as
- Structured collection of Abstract Data Types
(ADT) - Inheritance
- Polymorphism
- concerned with programming languages and
implementation issues
112Signs of Rotting Design
- Rigidity
- code difficult to change (Continuity)
- management reluctance to change anything becomes
policy - Fragility
- even small changes can cause cascading effects
- code breaks in unexpected places (Protection)
- Immobility
- code is so tangled that it's impossible to reuse
anything - Composability
- Viscosity
- much easier to hack than to preserve original
design
113Causes of Rotting Design
- Changing Requirements
- is inevitable
- "All systems change during their life-cycles.
This must be borne in mind when developing
systems expected to last longer than the first
version". (I. Jacobson, OOSE, 1992) - Dependency Management
- the issue of coupling and cohesion
- It can be controlled!
- create dependency firewalls
- see DIP example
114Open-Closed Principle (OCP)
- "Software Systems change during their life time"
- both better designs and poor designs have to face
the changes - good designs are stable
Software entities should be open for extension,
but closed for modification B. Meyer, 1988 /
quoted by R. Martin, 1996
- 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
115Open the door ...
- How to make the Car run efficiently with a
TurboEngine? - Only by changing the Car!
- ...in the given design
116 ... But Keep It Closed!
- A class must not depend on a concrete class!
- It must depend on an abstract class ...
- ...using polymorphic dependencies (calls)
117Strategic Closure
- "No significant program can be 100 closed "
- R.Martin, The Open-Closed Principle, 1996
- Closure not complete but strategic
- Use abstraction to gain explicit closure
- provide class methods which can be dynamically
invoked - to determine general policy decisions
- e.g. draw Squares before Circles
- design using abstract ancestor classes
- Use "Data-Driven" approach to achieve closure
- place volatile policy decisions in a separate
location - e.g. a file or a separate object
- minimizes future change locations
118OCP Heuristics
Make all object-data private No Global Variables!
- Changes to public data are always at risk to
open the module - They may have a rippling effect requiring changes
at many unexpected locations - Errors can be difficult to completely find and
fix. Fixes may cause errors elsewhere. - Non-private members are modifiable
- Case 1 "I swear it will not change"
- may change the status of the class
- Case 2 the Time class
- may result in inconsistent times
119OCP Heuristics (2)
RTTI is Ugly and Dangerous!
- 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 - recognize them by type switch-es or if-else-if
structures - Not all these situations violate OCP all the time
- when used only as a "filter"
120 Liskov Substitution Principle (LSP)
- The key of OCP Abstraction and Polymorphism
- Implemented by inheritance
- How do we measure the quality of inheritance?
Inheritance should ensure that any property
proved about supertype objects also holds for
subtype objects B. Liskov, 1987
Functions that use pointers or references to base
classes must be able to use objects of derived
classes without knowing it. R. Martin, 1996
121Inheritance Appears Simple
- class Bird // has beak,
wings,... - public virtual void fly() // Bird can fly
-
- class Parrot public Bird // Parrot is a
bird - public virtual void mimic() // Can Repeat
words... -
- // ...
- Parrot mypet
- mypet.mimic() // my pet being a parrot can
Mimic() - mypet.fly() // my pet is-a bird, can fly
122Penguins Fail to Fly!
- class Penguin public Bird
- public void fly()
- error (Penguins dont fly!)
-
- void PlayWithBird (Bird abird)
- abird.fly() // OK if Parrot.
- // if bird happens to be Penguin...OOOPS!!
-
- Does not model Penguins cant fly
- It models Penguins may fly, but if they try it
is error - Run-time error if attempt to fly ? not desirable
- Think about Substitutability - Fails LSP
123Design by Contract
- Advertised Behavior of an object
- advertised Requirements (Preconditions)
- advertised Promises (Postconditions)
When redefining a method in a derivate class, you
may only replace its precondition by a weaker
one, and its postcondition by a stronger one B.
Meyer, 1988
- Derived class services should require no more and
promise no less
int Basef(int x) // REQUIRE x is odd //
PROMISE return even int
int Derivedf(int x) // REQUIRE x is int //
PROMISE return 8
124Square IS-A Rectangle?
Square
?
- Should I inherit Square from Rectangle?
125The Answer is ...
- Override setHeight and setWidth
- duplicated code...
- static binding (in C)
- void f(Rectangle r) r.setHeight(5)
- change base class to set methods virtual
- The real problem
- void g(Rectangle r)
- r.setWidth(5) r.setHeight(4)
- // How large is the area?
-
- 20! ... Are you sure? -)
- IS-A relationship must refer to the behavior of
the class!
126LSP is about Semantics and Replacement
- The meaning and purpose of every method and class
must be clearly documented - Lack of user understanding will induce de facto
violations of LSP - Replaceability is crucial
- Whenever any class is referenced by any code in
any system, - any future or existing subclasses of that class
must be 100 replaceable - Because, sooner or later, someone will substitute
a subclass - its almost inevitable.
127LSP and Replaceability
- Any code which can legally call another classs
methods - must be able to substitute any subclass of that
class without modification
Client
Service Class
Service Class
Client
Unexpected Subclass
128LSP Related Heuristic (2)
It is illegal for a derived class, to override
a base-class method with a NOP method
- NOP a method that does nothing
- Solution 1 Inverse Inheritance Relation
- if the initial base-class has only additional
behavior - e.g. Dog - DogNoWag
- Solution 2 Extract Common Base-Class
- if both initial and derived classes have
different behaviors - for Penguins ? Birds, FlyingBirds, Penguins
- Classes with bad state
- e.g. stupid or paralyzed dogs...
129Example of Rigidity and Immobility
enum OutputDevice printer, disk void
Copy(OutputDevice dev) int c while((c
ReadKeyboard())! EOF) if(dev
printer) WritePrinter(c) else
WriteDisk(c)
Copy
Read Keyboard
Write Printer
Write Disk
void Copy() int c while ((c
ReadKeyboard()) ! EOF)
WritePrinter(c)
130Dependency Inversion Principle
- 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
- OCP states the goal DIP states the mechanism
- 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
131Procedural vs. OO Architecture
Procedural Architecture
Object-Oriented Architecture
132DIP Applied on Example
class Reader public virtual int
read()0 class Writer public
virtual void write(int)0 void Copy(Reader
r, Writer w) int c while((c r.read())
! EOF) w.write(c)
Copy
Reader
Writer
Keyboard Reader
Printer Writer
133DIP Related Heuristic
Design to an interface, not an implementation!
- Use inheritance to avoid direct bindings to
classes
Interface(abstract class)
Client
Implementation(concrete class)
134Design to an Interface
- Abstract classes/interfaces
- tend to change much less frequently
- abstractions are hinge points where it is
easier to extend/modify - shouldnt have to modify classes/interfaces that
represent the abstraction (OCP) - Exceptions
- Some classes are very unlikely to change
- therefore little benefit to inserting abstraction
layer - Example String class
- In cases like this can use concrete class
directly - as in Java or C
135DIP Related Heuristic
Avoid Transitive Dependencies
- Avoid structures in which higher-level layers
depend on lower-level abstractions - In example below, Policy layer is ultimately
dependant on Utility layer.
Policy Layer
Mechanism Layer
UtilityLayer
Depends on
Depends on
136Solution to Transitive Dependencies
- Use inheritance and abstract ancestor classes to
effectively eliminate transitive dependencies
Policy Layer
Mechanism Interface
depends on
Mechanism Layer
UtilityInterface
depends on
UtilityLayer
137DIP - Related Heuristic
When in doubt, add a level of indirection
- If you cannot find a satisfactory solution for
the class you are designing, try delegating
responsibility to one or more classes
Problem Holder
ProblemSolver
138When in doubt ...
- It is generally easier to remove or by-pass
existing levels of indirection than it is to add
them later
Blue classs indirect message calls to red class
fail to meet some criteria (e.g. real-time
constraints, etc.)
X
So, Blue class re-implements some or all of green
classs responsibilities for efficiency and calls
red object directly
139The Founding Principles
- The three principles are closely related
- Violating either LSP or DIP invariably results in
violating OCP - LSP violations are latent violations of OCP
- It is important to keep in mind these principles
to get most out of OO development... - ... and go beyond buzzwords and hype )
140High-Level Design
- Dealing with large-scale systems
- gt 50 KLOC
- team of developers, rather than an individual
- Classes are a valuable but not sufficient
mechanism - too fine-grained for organizing a large scale
design - need mechanism that impose a higher level of
order - clusters (Meyer) class-category (Booch)
subject-areas (Coad) - Packages
- a logical grouping of declarations that can be
imported in other programs (in Java and Ada) - containers for a group of classes (UML)
- reason at a higher-level of abstraction
141Issues of High-Level Design
- Goal
- partition the classes in an application according
to some criteria and then allocate those
partitions to packages - Issues
- What are the best partitioning criteria?
- What principles govern the design of packages?
- creation and dependencies between packages
- Design packages first? Or classes first?
- i.e. top-down vs. bottom-up approach
- Approach
- Define principles that govern package design
- the creation and interrelationship and use of
packages
142Principles of OO High-Level Design
- Cohesion Principles
- Reuse/Release Equivalency Principle (REP)
- Common Reuse Principle (CRP)
- Common Closure Principle (CCP)
- Coupling Principles
- Acyclic Dependencies Principle (ADP)
- Stable Dependencies Principle (SDP)
- Stable Abstractions Principle (SAP)
143What is really Reusability ?
- Does copy-paste mean reusability?
- Disadvantage You own that copy!
- you must change it, fix bugs.
- eventually the code diverges
- Maintenance is a nightmare
- Martins Definition
- I reuse code if, and only if, I never need to
look at the source-code - treat reused code like a product ? dont have to
maintain it - Clients (re-users) may decide on an appropriate
time to use a newer version of a component release
144Reuse/Release Equivalency Principle (REP)
The granule of reuse is the granule of
release. Only components that are released
through a tracking system can be efficiently
reused. R. Martin, 1996
- What means this ?
- A reusable software element cannot really be
reused in practice unless it is managed by a
release system of some kind - e.g. release numbers or names
- There is no such thing as reusable class
- without guarantees of notification, safety and
support - must integrate the entire module (cant reuse
less)
Either all the classes in a package are reusable
or none of it is! R. Martin, 1996
145The Common Reuse Principle
- All classes in a package library should be
reused together. If you reuse one of the classes
in the package, - you reuse them all.
- R. Martin, Granularity 1996
- Packages of reusable components should be grouped
by expected usage, not by - common functionality, nor
- another arbitrary categorization.
- Classes are usually reused in groups based on
collaborations between library classes - e.g. containers and iterators
When I depend on a package, I like to depend on
every class in that package!
146Common Closure Principle (CCP)
The classes in a package should be closed against
the same kinds of changes. A change that affects
a package affects all the classes in that
package R. Martin, 1996
- What means this ?
- Classes that change together belong together
- Goal limit the dispersion of changes among
released packages - changes must affect the smallest number of
released packages - relation with OCP
-
- Classes within a package must be cohesive
- Given a particular kind of change, either all
classes or no class in a component needs to be
modified
147Reuse vs. Maintenance
- REP and CRP makes life easier for reuser
- packages very small
- CCP makes life easier for maintainer
- large packages
- Packages are not fixed in stone
- early lifetime dominated by CCP
- later you want to reuse focus on REP CRP
148Acyclic Graph of Dependencies
149Cyclic Dependencies
150Acyclic Dependencies Principles (ADP)
The dependency structure for released component
must be a Directed Acyclic Graph (DAG) There can
be no cycles. R. Martin, 1996
151Breaking the Cycles
152Copy Program Revisited
class Reader public virtual int
read()0 class Writer public
virtual void write(int)0 void Copy(Reader
r, Writer w) int c while((c r.read())
! EOF) w.write(c)
Copy
Reader
Writer
Keyboard Reader
Printer Writer
153Good Dependencies
- Lack of interdependencies
- makes the Copy program robust, maintainable,
reusable - Targets of unavoidable dependencies are
non-volatile - unlikely to change
- e.g. Reader and Writer classes have a low
volatility ? the Copy class is immune
to changes
A Good Dependency is a dependency upon
something with low volatility.
154Volatility and Stability
- Volatility Factors
- hard-coding of improper information
- e.g. print version number
- market pressure
- whims of customers
- Volatility is difficult to understand and predict
- Stability
- defined as not easily moved
- a measure of the difficulty in changing a module
- not a measure of the likelihood of a change
- modules that are stable are going to be less
volatile - e.g. Reader and Writer classes are stable
Stability Responsibility Independence
155Stability Metrics
- Afferent Coupling (Ca)
- number of classes outside this package that
depend upon the measured package - "how responsible am I?" (FAN-IN)
- Efferent Coupling (Ce)
- number of classes outside this package that
classes within the measured package depend on - "how dependent am I ?" (FAN-OUT)
- Instability Factor (I)
- I ? 0, 1
- 0 totally stable 1 totally unstable
156Computing Stability Metrics
157Stable Dependencies Principle (SDP)
The dependencies between components in a design
should be in the direction of stability. A
component should only depend upon components that
are more stable than it is. R. Martin, 1996
Depend only upon components whose I metric is
lower than yours R. Martin, 1996
SDP Violation
158Where to Put High-Level Design?
- High-level architecture and design decisions
don't change often - shouldn't be volatile ? place them in stable
packages - design becomes hard to change ? inflexible design
- How can a totally stable package (I 0) be
flexible enough to withstand change? - improve it without modifying it...
- Answer The Open-Closed Principle
- classes that can be extended without modifying
them - ? Abstract Classes
159Stable Abstractions Principle (SAP)
The abstraction of a package should be
proportional to its stability! Packages that are
maximally stable should be maximally
abstract. Instable packages should be
concrete. R. Martin, 1996
- Ideal Architecture
- Instable (changeable) packages on the top
- must be concrete
- Stable (hard to change) package on the bottom
- hard to change, but easy to extend
- highly abstract (easily extended)
- Interfaces have more intrinsic stability than
executable code - SAP is a restatement of DIP