Introduction to the SOLID OO Design Principles.
Single Responsability Principle
Open Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
Visit http://jpereira.eu/2012/04/16/oo-design-principles-part-2/
If you want to download the presentation, please contact me (find my contact in my blog)
1. OO Design Principles
João Miguel Pereira
http://jpereira.eu
March 2012
OO Design Principles by João Miguel Pereira is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0
Unported License.
2. OO Design Principles
• Single Responsibility Principle (SRP)
• Open Closed Principle (OCP)
• Liskov Substitution Principle (LSP)
• Interface Segregation Principle (ISP)
• Dependency Inversion Principle (DIP)
• Don’t Repeat Yourself (DRY)
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 2
ShareAlike 3.0 Unported License.
3. OO Design Principles
• Single Responsibility Principle (SRP)
• Open Closed Principle (OCP)
• Liskov Substitution Principle (LSP)
• Interface Segregation Principle (ISP)
• Dependency Inversion Principle (DIP)
• Don’t Repeat Yourself (DRY)
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 3
ShareAlike 3.0 Unported License.
4. Single Responsibility Principle
• Tom DeMarco and Meilir Page-Jones call it
Cohesion
– The Practical Guide to Structured Systems
Design, 2d. ed., Meilir PageJones, Yourdon Press
Computing Series, 1988
http://amzn.to/book_TPGSS
– Structured Analysis and System Specification, Tom
DeMarco, Yourdon Press Computing Series, 1979
http://amzn.to/book_SASS
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 4
ShareAlike 3.0 Unported License.
5. Single Responsibility Principle
There shouldn’t never be more than one
reason for a class to change!
Robert C. Martin http://www.objectmentor.com/resources/articles/srp.pdf
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 5
ShareAlike 3.0 Unported License.
6. Single Responsibility Principle
Responsability Class implementing
Move ball Ball
Kick Ball Player
Score Ball,ScoreBoard
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 6
ShareAlike 3.0 Unported License.
7. Single Responsibility Principle
Change in responsability
Responsability Class implementing
Move Ball
Move ball Ball
Kick Ball Player
Score Ball,ScoreBoard
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 7
ShareAlike 3.0 Unported License.
8. Single Responsibility Principle
Ball has one reason to change!
Responsability Class implementing
Move Ball
Move ball Ball
Ball
Kick Ball Player
Score Ball,ScoreBoard
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 8
ShareAlike 3.0 Unported License.
9. Single Responsibility Principle
Change in responsability
Responsability Class implementing
Move ball Ball
Kick Ball
Kick Ball Player
Score Ball,ScoreBoard
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 9
ShareAlike 3.0 Unported License.
10. Single Responsibility Principle
Player has one reason to change!
Responsability Class implementing
Move ball Ball
Kick Ball
Kick Ball Player
Player
Score Ball,ScoreBoard
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 10
ShareAlike 3.0 Unported License.
11. Single Responsibility Principle
Change in responsability
Responsability Class implementing
Move ball Ball
Kick Ball Player
Score
Score Ball,ScoreBoard
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 11
ShareAlike 3.0 Unported License.
12. Single Responsibility Principle
ScoreBoard has one reason to change!
Ball has TWO reasons to change!
Responsability Class implementing
Move Ball
Move ball Ball
Ball
Kick Ball Player
Score
Score Ball,ScoreBoard
Ball, Scoreboard
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 12
ShareAlike 3.0 Unported License.
13. Single Responsibility Principle
• Avoid responsibility coupling by giving a
class/module a single reason to change
• Every line of code should only focus on
carrying out that single responsibility
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 13
ShareAlike 3.0 Unported License.
14. Single Responsibility Principle
public class EmployeeBoard {
public void showListOfEmployeeNames(List<Employee> employees) {
for (Employee employee : employees) {
if (employee.getGender.equals("M")) {
printMessage("Mr. "+employee.getName());
} else {
printMessage("Miss. "+employee.getName());
}
}
}
}
}
This class shows the names of
employees in a screen… but also
format each employee's name!!
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 14
ShareAlike 3.0 Unported License.
15. Single Responsibility Principle
public class EmployeeBoard {
public void showListOfEmployeeNames(List<Employee> employees) {
for (Employee employee : employees) {
printMessage(employee.getFormattedName());
}
}
}
public class Employee {
public String getFormattedName() {
String formattedName;
if (this.getGender.equals("M")) {
formattedName = "Mr. " + this.getName();
} else {
formattedName = "Miss. " + this.getName();
}
return formattedName;
}
}
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 15
ShareAlike 3.0 Unported License.
16. Single Responsibility Principle
• Read the article:
– http://www.objectmentor.com/resources/articles/
srp.pdf
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 16
ShareAlike 3.0 Unported License.
17. OO Design Principles
• Single Responsibility Principle (SRP)
• Open Closed Principle (OCP)
• Liskov Substitution Principle (LSP)
• Interface Segregation Principle (ISP)
• Dependency Inversion Principle (DIP)
• Don’t Repeat Yourself (DRY)
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 17
ShareAlike 3.0 Unported License.
18. Open Close Principle
• Classes should be closed for modification but
open for extension
public class Calculator { Well tested, robust
public int sum(int a, int b) { and correctly
return a + b; implemented class.
} Why modify it?
public int multiply(int a, int b) {
return a * b;
}
}
How to extend Calculator class to add
the square root function ?
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 18
ShareAlike 3.0 Unported License.
19. Open Close Principle
• Classes should be closed for modification but
open for extension
public class Calculator {
public int sum(int a, int b) {
return a + b;
}
public int multiply(int a, int b) {
return a * b;
}
}
//AdvancedCalulator extends a well tested class
public class AdvancedCalculator extends Calculator {
public double sqrt(int a) {
return Math.sqrt(Float.valueOf(a));
}
}
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 19
ShareAlike 3.0 Unported License.
20. Open Close Principle
Extreme
public class SpaceShip {
private String crew1Name= "Matt"; example!
private String crew2Name= "Daemon";
private String crew3Name= "Willis";
public String getCrew1Name() {
return this.crew1Name;
}
public String getCrew2Name() {
return crew2Name;
}
public void setCrew2Name(String crew2Name) {
this.crew2Name = crew2Name;
}
public String getCrew3Name() {
return crew3Name;
}
public void setCrew3Name(String crew3Name) {
this.crew3Name = crew3Name;
}
}
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 20
ShareAlike 3.0 Unported License.
21. Open Close Principle Hey! I want to
replace Daemon
for Bob. Can you
public class SpaceShip {
private String crew1Name= "Matt"; Extreme do it?
private String crew2Name= "DaemonBob"; example!
private String crew3Name= "Willis";
public String getCrew1Name() {
return this.crew1Name;
}
public String getCrew2Name() { Sure! I just
return crew2Name;
}
replace the
string ;)
public void setCrew2Name(String crew2Name) {
this.crew2Name = crew2Name;
}
public String getCrew3Name() {
return crew3Name;
}
public void setCrew3Name(String crew3Name) {
this.crew3Name = crew3Name;
}
}
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 21
ShareAlike 3.0 Unported License.
22. Hey! We
increased the
Open Close Principle capacity of the
spaceship and
public class SpaceShip { now we want to
private String crew1Name= "Matt"; Extreme add 2 new guys
private String crew2Name= "Bob"; example! to the crew.
private String crew3Name= "Willis";
public String getCrew1Name() {
return this.crew1Name;
}
public String getCrew2Name() {
return crew2Name; Well… that
} will cost you
public void setCrew2Name(String crew2Name) { a lot!
this.crew2Name = crew2Name;
}
public String getCrew3Name() {
return crew3Name;
}
public void setCrew3Name(String crew3Name) {
this.crew3Name = crew3Name;
}
}
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 22
ShareAlike 3.0 Unported License.
23. Open Close Principle
“How can we create designs that
are stable in the face of change
and that will last longer than the
first version?”
Robert C. Martin
SOFTWARE ENTITIES
(CLASSES, MODULES, FUNCTIO
NS, ETC.)
SHOULD BE OPEN FOR
EXTENSION, BUT CLOSED FOR
MODIFICATION.
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- Bertrand Meyer 23
ShareAlike 3.0 Unported License.
24. Open Close Principle
• An object model that follows this
principle, show two primary attributes:
– Are “Open For Extension” An object can be
extended and behave in new and different ways.
– Are “Closed for Modification” The source code
of such an object is inviolate. No one is allowed to
make source code changes to it.
Robert C. Martin - http://objectmentor.com/resources/articles/ocp.pdf
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 24
ShareAlike 3.0 Unported License.
25. OO Design Principles
• Single Responsibility Principle (SRP)
• Open Closed Principle (OCP)
• Liskov Substitution Principle (LSP)
• Interface Segregation Principle (ISP)
• Dependency Inversion Principle (DIP)
• Don’t Repeat Yourself (DRY)
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 25
ShareAlike 3.0 Unported License.
26. Liskov Substitution Principle
What is wanted here is something like the following
substitution property: If for each object o1 of type S there is
an object o2 of type T such that for all programs P defined in
terms of T, the behavior of P is unchanged when o1 is
substituted for o2 then S is a subtype of T." - BarbaraLiskov, Data
Abstraction and Hierarchy, SIGPLAN Notices, 23,5 (May, 1988)
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 26
ShareAlike 3.0 Unported License.
27. Liskov Substitution Principle
FUNCTIONS THAT USE POINTERS OR REFERENCES TO BASE
CLASSES MUST BE ABLE TO USE OBJECTS OF DERIVED
CLASSES WITHOUT KNOWING IT. – Robert C. Martin
http://www.objectmentor.com/resources/articles/lsp.pdf
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 27
ShareAlike 3.0 Unported License.
28. Liskov Substitution Principle
• Design rule to create hierarchies of classes
that conform to OCP
• Client code:
Piece piece = null;
if (this.board instanceof Board ) {
piece = board.getPieceFromPosition(x, y);
} else if (this.board instanceof ThreeDimensionalBoard) {
piece = ((ThreeDimensionalBoard)board).getPieceFromPosition(x, y, z);
}
Violation of
LSP
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 28
ShareAlike 3.0 Unported License.
29. Liskov Substitution Principle
• Subtypes must be substitutable for their base
types.
OK
OK
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 29
ShareAlike 3.0 Unported License.
30. Liskov Substitution Principle
Consider this class:
public class Board {
public Piece getPieceFromPosition(int x, int y) {}
public void addPiecetoPosition(int x, int y, Piece piece) {}
}
And its use:
public class Game {
public void setBoard(Board board) { this.board = board; }
public void play(int x, int y, int newX, int newY) {
Piece piece = board.getPieceFromPosition(x, y);
board.addPieceToPosition(newX, newY, piece);
}
}
Now, extend Board to have a 3D board:
public class ThreeDimensionBoard extends Board{
public Piece getPieceFromPosition(int x, int y, int z) {}
public void addPiecetoPosition(int x, int y, int z, Piece piece) {}
}
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 30
ShareAlike 3.0 Unported License.
31. Liskov Substitution Principle
Running….
public void main(String args[]) {
Board board = new Board();
Game game = new Game();
game.setBoard(board);
game.play(0, 0, 0, 2); //Ok
Board threeDimensionalBoard = new ThreeDimensionBoard();
game.setBoard(threeDimensionalBoard);
game.play(0, 0, 0, 2); ////And the z and newZ
}
Compiling, running but not working!
Discussions http://c2.com/cgi/wiki?LiskovSubstitutionPrinciple
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 31
ShareAlike 3.0 Unported License.
32. Liskov Substitution Principle
• Read the article:
– http://www.objectmentor.com/resources/articles
/lsp.pdf
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 32
ShareAlike 3.0 Unported License.
33. OO Design Principles
• Single Responsibility Principle (SRP)
• Open Closed Principle (OCP)
• Liskov Substitution Principle (LSP)
• Interface Segregation Principle (ISP)
• Dependency Inversion Principle (DIP)
• Don’t Repeat Yourself (DRY)
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 33
ShareAlike 3.0 Unported License.
34. Interface Segregation Principle
Clients should not be forced to depend
on methods that they do not use.
Robert. C. Martin - http://www.objectmentor.com/resources/articles/isp.pdf
Interface does not necessarily
means Java Interface
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 34
ShareAlike 3.0 Unported License.
35. Interface Segregation Principle
• ‘Fat’ and polluted interfaces should be splitted
into smaller and specific interfaces, achieving
high cohesive interfaces
• Clients should only depend on methods they
use, thus reducing coupling
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 35
ShareAlike 3.0 Unported License.
36. Interface Segregation Principle
Phone interface is High Cohesive
OK SimplePhone needs all methods
from Phone Interface
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 36
ShareAlike 3.0 Unported License.
37. Interface Segregation Principle
Phone interface is start to being polluted with
takePhoto method
PhoneWithCamera is Ok with the Phone interface.
SimplePhone does not cares about taking photo,
but the interface is polluted and have to implement it!
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 37
ShareAlike 3.0 Unported License.
38. Interface Segregation Principle
• SimplePhone does not need
takePhoto, zoomIn or
connectToInternet methods, but has
to implement them.
• PhoneWithCamera does not know
how to connect to internet, but has
to implement the method
connectToInternet
• SmartPhone is ok with the interface
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 38
ShareAlike 3.0 Unported License.
39. Interface Segregation Principle
• Every time you change
Phone
interface, you’ll, general
ly, have to change the
clients, even when they
don’t care about the
reason of the change.
• Clients are forced to
implement methods
they don’t need
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 39
ShareAlike 3.0 Unported License.
40. Interface Segregation Principle
public interface Phone {
void ring();
void answerCall();
void rejectCall();
void terminateCall();
void takePhoto();
}
class SimplePhone implements Phone {
@Override
public void takePhoto() {
throw new UnsupportedOperationException("Sorry. I don't know how to do that");
}
}
Sign that you should rethink about the design!
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 40
ShareAlike 3.0 Unported License.
41. Interface Segregation Principle
Possible solution applying the ISP
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 41
ShareAlike 3.0 Unported License.
42. OO Design Principles
• Single Responsibility Principle (SRP)
• Open Closed Principle (OCP)
• Liskov Substitution Principle (LSP)
• Interface Segregation Principle (ISP)
• Dependency Inversion Principle (DIP)
• Don’t Repeat Yourself (DRY)
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 42
ShareAlike 3.0 Unported License.
43. Dependency Inversion Principle
High Level Modules should not depend upon
low level modules. Both should depend on
abstractions.
Abstractions should not depend upon details.
Details should depend upon abstractions.
Robert C. Martin - http://www.objectmentor.com/resources/articles/dip.pdf
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 43
ShareAlike 3.0 Unported License.
44. Dependency Inversion Principle
• Higher level modules are best candidates for reuse,
so they should not be coupled with details.
Higher Level Class
Lower Level Class providing
details for communication
• How to reuse the class vehicle in a new application
that uses WIFI for communication?
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 44
ShareAlike 3.0 Unported License.
45. Dependency Inversion Principle
• Transitive dependencies should be avoided
• If GSMModem changes, most likely Vehicle should be
recompiled also, because there is a transitive
dependency between Vehicle and GSMModem
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 45
ShareAlike 3.0 Unported License.
46. Dependency Inversion Principle
• Applying DIP
Higher Level Class does not
depends on details, but rather on
an abstraction
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 46
ShareAlike 3.0 Unported License.
47. Dependency Inversion Principle
“All well structured object-oriented
architectures have clearly-defined layers,
with each layer providing some coherent
set of services through a well defined and
controlled interface”
Layer A
Layer B
Layer C Grady Booch
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 47
ShareAlike 3.0 Unported License.
48. Dependency Inversion Principle
“Each layer builds upon equally
well-defined and controlled
facilities at lower levels of
abstraction”
AbstractLayer A
AbstractLayer B
AbstrctLayer C Grady Booch
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 48
ShareAlike 3.0 Unported License.
49. Dependency Inversion Principle
• Going deeper with DIP
Abstract Classes only depend on
abstract classes, i.e. higher layers
are build upon abstractions of
lower layers
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 49
ShareAlike 3.0 Unported License.
50. OO Design Principles
• Single Responsibility Principle (SRP)
• Open Closed Principle (OCP)
• Liskov Substitution Principle (LSP)
• Interface Segregation Principle (ISP)
• Dependency Inversion Principle (DIP)
• Don’t Repeat Yourself (DRY)
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 50
ShareAlike 3.0 Unported License.
51. Don’t Repeat Yourself principle
• Avoid duplicate code by abstracting out things
that are common and placing those things in a
single location
public void businessMethod(String buinsesCommand) {
if (Logger.isEnabled() && Configuration.getLevel() >= LogLevel.DEBUG.value()) {
Logger.info("Entering business method");
}
//Business code
}
public void otherBusinessMethod(String buinsesCommand) {
if (Logger.isEnabled() && Configuration.getLevel() >= LogLevel.DEBUG.value()) {
Logger.info("Entering business method");
}
//Business Code
}
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 51
ShareAlike 3.0 Unported License.
52. Don’t Repeat Yourself principle
public void businessMethod(String buinsesCommand) {
Logger.attemptDebug("Entering business method");
Abstracting out
//Business code
}
public void otherBusinessMethod(String buinsesCommand) {
Logger.attemptDebug("Entering business method");
//Business Code
}
public class Logger {
public static void attemptDebug(String message) {
if (Logger.isEnabled() && Configuration.getLevel() >= LogLevel.DEBUG.value()) {
Logger.info(message);
}
}
}
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 52
ShareAlike 3.0 Unported License.
53. Don’t Repeat Yourself principle
• Have each piece of information and behavior
in a single small place (SRP)
• Changes to your system only affect small
portions of your code
• Potential bugs arising from changes are kept
to a minimum, in isolated places
• Cost and risk of changes are reduced
OO Design Principles is licensed under a Creative Commons Attribution-NonCommercial- 53
ShareAlike 3.0 Unported License.