You are on page 1of 26

SOLID

- OO DESIGN PRINCIPLES

© 2004 Capgemini - All rights reserved


SOLID

 SOLID
- Single Responsibility Principle
- Open Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inverison Principle
 Apply ’smart’
- don’t do stuff ’just because of’
- very importad to see the context of the program/code when applying SOLID
- Joel On Software advise – use with common sense!

Sida 2 2022-05-13
© 2009 Capgemini - All rights reserved
Single Responsibility Principle

 "There should never be more than one reason for a class to


change." — Robert Martin, SRP paper linked from
The Principles of OOD
 My translation: A class should concentrate on doing one thing and
one thing only

Sida 3 2022-05-13
© 2009 Capgemini - All rights reserved
Single Responsibility Principle

interface Modem {
 Two resposibilities public void dial(String pno);
public void hangup();

public void send(char c);


public char recv();
}

 Connection Management + Data Communication

Sida 4 2022-05-13
© 2009 Capgemini - All rights reserved
Single Responsibility Principle

 Separate into two interfaces

interface DataChannel {
public void send(char c);
public char recv();
}

interface Connection {
public void dial(String phn);
public char hangup();
}

Sida 5 2022-05-13
© 2009 Capgemini - All rights reserved
Single Responsibility Principle
public class Book {
public class Book { private String name;
private String name; private String author;
private String text;
private String author; //constructor, getters and setters
private String text; // methods that directly relate to the book properties
public String replaceWordInText(String word){
return text.replaceAll(word, text);
//constructor, getters and }
setters public boolean isWordInText(String word){
return text.contains(word);
}
}
} void printTextToConsole(){
// our code for formatting and printing the text
}

Sida 6 2022-05-13
© 2009 Capgemini - All rights reserved
Single Responsibility Principle
public class Book { public class BookPrinter {
private String name;
private String author; // methods for outputting text
private String text; void printTextToConsole(String text){
//constructor, getters and setters //our code for formatting and printing the text
// methods that directly relate to the book properties }

public String replaceWordInText(String word){ void printTextToAnotherMedium(String text){


return text.replaceAll(word, text); // code for writing to any other location..
} }
}
public boolean isWordInText(String word){
return text.contains(word);
}
}

Sida 7 2022-05-13
© 2009 Capgemini - All rights reserved
Open Closed Principle

 "Software entities (classes, modules, functions, etc.) should be


open for extension, but closed for modification." — Robert Martin
paraphrasing Bertrand Meyer, OCP paper linked from
The Principles of OOD
 My translation: Change a class' behavior using inheritance and
composition

Sida 8 2022-05-13
© 2009 Capgemini - All rights reserved
Open/Closed Principle (OCP)

• Any new functionality should be done by adding new classes instead of


changing existing one

How to implement OCP


• One may achieve this by adding new functionality to derived class
• Or allow client to access the original class with abstract interface

© 2009 Capgemini - All rights reserved


Open Closed Principle
// Open-Close Principle - Bad example
class GraphicEditor {

public void drawShape(Shape s) {


if (s.m_type==1)
drawRectangle(s);
else if (s.m_type==2)
drawCircle(s);
}
public void drawCircle(Circle r) {....}
public void drawRectangle(Rectangle r) {....}
}

class Shape {
int m_type;
}

class Rectangle extends Shape {


Rectangle() {
super.m_type=1;
}
}

class Circle extends Shape {


Circle() {
super.m_type=2;
}
}

Sida 10 2022-05-13
© 2009 Capgemini - All rights reserved
Open Closed Principle – a Few Problems….

 Impossible to add a new Shape without modifying GraphEditor


 Important to understand GraphEditor to add a new Shape
 Tight coupling between GraphEditor and Shape
 Difficult to test a specific Shape without involving GraphEditor
 If-Else-/Case should be avoided

Sida 11 2022-05-13
© 2009 Capgemini - All rights reserved
Open Closed Principle - Improved

 // Open-Close Principle - Good example


class GraphicEditor {
public void drawShape(Shape s) {
s.draw();
}
}

class Shape {
abstract void draw();
}

class Rectangle extends Shape {


public void draw() {
// draw the rectangle
}
}

Sida 12 2022-05-13
© 2009 Capgemini - All rights reserved
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 Martin, LSP paper linked from The Principles of OOD
 “If you have class B inherit from class A then class A should be
replaceable by class B without any changes”.

 My translation: Subclasses should behave nicely when used in


place of their base class

Sida 13 2022-05-13
© 2009 Capgemini - All rights reserved
Liskov Substitution Principle (LSP)

“If you have class B inherits from class A then class A should be replaceable by class
B without any changes ”

A objectA = new B();


B C A objectB = new C();

© 2009 Capgemini - All rights reserved


Liskov Substitution Principle
// Violation of Liskov's Substitution class Square extends Rectangle
Principle {
class Rectangle public void setWidth(int width){
{ m_width = width;
int m_width; m_height = width;
int m_height; }

public void setWidth(int width){ public void setHeight(int height){


m_width = width; m_width = height;
} m_height = height;
}
public void setHeight(int ht){ }
m_height = ht;
}

public int getWidth(){


return m_width;
}

public int getHeight(){


return m_height;
}

public int getArea(){


return m_width * m_height;
}
}

Sida 15 2022-05-13
© 2009 Capgemini - All rights reserved
Liskov Substitution Principle

class LspTest
{
private static Rectangle getNewRectangle()
{
// it can be an object returned by some factory ...
return new Square();
}
public static void main (String args[])
{
Rectangle r = LspTest.getNewRectangle();
r.setWidth(5);
r.setHeight(10);
// user knows that r it's a rectangle. It assumes that he's able to set the width and
height as for the base class
System.out.println(r.getArea());
// now he's surprised to see that the area is 100 instead of 50.
}
}

Sida 16 2022-05-13
© 2009 Capgemini - All rights reserved
Liskov Substitution Principle
The Rectangle/Square hierarchy violates the Liskov Substitution
Principle (LSP)! Square is behaviorally not a correct substitution for
Rectangle.

A Square does not comply with the behavior of a rectangle: Changing


the height/width of a square behaves differently from changing the
height/width of a rectangle. Actually, it doesn't make sense to
distinguish between the width and the height of a square.

Sida 17 2022-05-13
© 2009 Capgemini - All rights reserved
Liskov Substitution Principle
To get a LSP compliant solution, we make Rectangle and Square
siblings. We introduce the interface Shape to bundle common
methods.

Sida 18 2022-05-13
© 2009 Capgemini - All rights reserved
Interface Segregation Principle

 "Clients should not be forced to depend upon interfaces that they


do not use." — Robert Martin, ISP paper linked from
The Principles of OOD
 My translation: Keep interfaces small

Sida 19 2022-05-13
© 2009 Capgemini - All rights reserved
Interface Segregation Principle

 Don’t force classes so implement methods they can’t


 Don’t pollute interfaces with a lot of methods
 Avoid ’fat’ interfaces

Sida 20 2022-05-13
© 2009 Capgemini - All rights reserved
Interface Segregation Principle

//bad example (polluted interface)


interface Worker {
void work();
void eat();
}

ManWorker implements Worker { RobotWorker implements Worker {


void work() {…}; void work() {…};
void eat() {30 min break;}; void eat() {//Not Appliciable
for a RobotWorker};
}
}

Sida 21 2022-05-13
© 2009 Capgemini - All rights reserved
Interface Segregation Principle

 Solution
- split into two interfaces

interface Workable {
public void work();
}

interface Feedable{
public void eat();
}

Sida 22 2022-05-13
© 2009 Capgemini - All rights reserved
Dependency Inversion Principle

 "A. High level(interfaces and abstracts) modules should not


depend upon low level modules. Both should depend upon
abstractions (e.g., interfaces).
B. Abstractions should not depend upon details. Details (concrete
implementations) should depend upon abstractions." — Robert
Martin, DIP paper linked from The Principles of OOD
 My translation: Use lots of interfaces and abstractions

Sida 23 2022-05-13
© 2009 Capgemini - All rights reserved
Dependency Inversion Principle (DIP)

High level modules should not depend upon low level


modules. Both should depend upon abstractions.
“Agile Principles, Patterns, and Practices in C# “

© 2009 Capgemini - All rights reserved


Dependency Inversion Principle (DIP)
High Level
Notification

+GmailObj: Gmail
+HotmailObj: Hotmail

+SendByGmail(): void
+SendByHotmail(): void

Gmail Hotmail
+Send(): void Low Level +Send(): void

© 2009 Capgemini - All rights reserved


Dependency Inversion Principle (DIP)

High Level Abstraction


Notification IMessage
-MessageService: IMessage +Send(): void
+Send(): void

Gmail Hotmail
+Send(): void +Send(): void

Low Level Low Level

© 2009 Capgemini - All rights reserved

You might also like