advanced programming & c++ language · (1) single responsibility principle 6 a class should...

76
Dr. Miri (Kopel) Ben-Nissan Ariel University 2018 Advanced Programming & C++ Language Software Development Principles ~4~

Upload: others

Post on 23-Jun-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

Dr. Miri (Kopel) Ben-NissanAriel University2018

Advanced Programming & C++ Language

Software Development Principles

~4~

Page 2: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Introduction2

There are many heuristics associated with object oriented design.

For example, “all member variables should be private”, or “global variables should be avoided”, or “using run time type identification (RTTI) is dangerous”.

What is the source of these heuristics? What makes them true? Are they always true?

Page 3: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

SOLID (object-oriented design)3

Five basic principles of object-oriented programming and design.

The principles when applied together intend to make it more likely that a programmer will create a system that is easy to maintain and extend over time.

Page 4: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Software Development – General Principles4

SRP - single responsibility principle

OCP - open-closed principle

LSP - Liskov substitution principle

ISP - interface segregation principle

DIP - dependency inversion principle

Dependency Injection

Page 5: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Single Responsibility Principle

Page 6: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

(1) Single Responsibility Principle6

A Class should have one reason to change

A Responsibility is a reasons to change

Every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class.

The reason it is important to keep a class focused on a single concern is that it makes the class more robust.

Page 7: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Single Responsibility Principle (Cont…)

:המודול הספציפי יודע/ ידע שרק המחלקה , אחריות היא מומחיות.היכרות אינטימית עם מבנה נתונים מורכב•.ביצוע חישוב מסוים•או פרוטוקול HTTPלמשל (או פרוטוקול ) Parserעבור (היכרות עם פורמט •

).אפליקטיביflow .7-היכרות עם סדר פעולות ב•

Page 8: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Page 9: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Page 10: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Page 11: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Page 12: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Page 13: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Page 14: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

SRP Example14

Suppose we have a DB with customer’s details. We would like to send an email to all the

customers who didn’t purchase anything in the last month.

We have two tasks here: Find all those customers. Sent them an email.

The idea: write a code that connects to our DB, extract the list of those customers and sends them an email.

Single Responsibility Principle (Cont…)

Page 15: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

The right design will be to separate the code into two different interfaces: One for handling the connection to the DB.One for handling the email sending.

Like this we get a flexible code.

We can parallelize the development.

Single Responsibility Principle (Cont…)

Page 16: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

חשיבה מונחית ממשקים16

נניח שאנחנו רוצים לכתוב מתודה שמקבלתURL והיא צריכה, של תמונה:

להוריד את התמונה מהאינטרנט לשנות את הגודל של התמונה כך שהרוחב והגובה

ולשמור על פרופורציית (פיקסלים 100לא יעלו על )רוחב-גובה

לשמור את התמונה החדשה בפורמטPNG .בתיקיה מסוימת

Single Responsibility Principle (Cont…)

http://heblog.ronklein.co.il/tag/srp/

Page 17: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

17

public class ImageProcessing{public void ProcessImage(Uri imageUrl, IDownloader downloader,

IImageResizer imageResizer, IFileSystem fileSystem){

byte[ ] imageBytes = downloader.Get(imageUrl);Image bitmap = Image.FromStream(new MemoryStream(imageBytes));Image afterResize = imageResizer.ResizeToMax(bitmap, 100);fileSystem.StoreImage(afterResize);

}}

public interface IFileSystem{void StoreImage(Image image);

}

public interface IImageResizer{Image ResizeToMax(Image bitmap, int maxWidthOrHeight);

}

public interface IDownloader{byte[] Get(Uri imageUrl);

}

...ממשקים במקום מתודות

Single Responsibility Principle (Cont…)

Page 18: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

נוצרו מספר ״מתכונים מוכנים״ לחלוקת , ארכיטקטים/ כדי להקל על המפתחים .ניהול התלויות+ המערכת למודולים ארכיטקטורות אינסטנט מוכרות . היא אולי המוכרת מכולן-חלוקה ע״פ שכבות

.Pipes and Filters-ו MVCאחרות הן

Single Responsibility Principle (Cont…)

18

Page 19: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Close Principle

Page 20: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

(2) Open Closed Principle20

Software entities ( Classes, Modules,

Methods, etc. ) should be open for

extension, but closed for modification.

Also Known As

Protected Variation

“Information hiding”

Old code can

use the new

code as well!

Page 21: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)

21

Page 22: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)22

If not followed, a single change to a program results in a cascade of changes to dependent modules.The program becomes fragile, rigid,

unpredictable and un-reusable.

You should design modules that never change.

When requirements change, you extend the behavior of such modules by adding new code, not by changing old code that already works.

Page 23: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)

23

“Open For Extension”.The behavior of the module can be extended. We can make the module behave in new and

different ways as the requirements of the application change, or to meet the needs of new applications.

“Closed for Modification”The source code of such a module is inviolate. No one is allowed to make source code changes to it.

Page 24: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)

24

How can these two opposing attributes be resolved?

Abstraction and Polymorphism is the Key!

Page 25: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)25

Benefits of Open Closed Design Principle:Application will be more robust because we

are not changing already tested class.Flexible because we can easily

accommodate new requirements.Easy to test and less error prone.

Page 26: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)

26

How can we confirm to OCP principle?

Allow the modules (classes) to depend on the abstractions, there by new features can be added by creating new extensions of these abstractions.

Page 27: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

OCP Example 27

A module to approve personal loans, after validating the personal information.

Open Closed Principle (Cont…)

Page 28: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)

28

class CPersonalLoanValidator

}

public:

bool isValid();

};

class CLoanApprovalHandler

{

public:

void approveLoan(const CPersonalValidator& cPv)

{

if(cPv.IsValid()){

//Process the loan

}

}

};

is this implementation

follows the OCP?

Page 29: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)

29

Now its required to approve vehicle loans, consumer goods loans and what not.

class IValidator

{

public:

virtual bool isValid()=0;

};

class CPersonalLoanValidator : public IValidator

{

public:

bool isValid();

};

IValidator

CPersonalLoanV

alidator

CVehicleLoan

Validator

Page 30: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)

30

class CLoanApprovalHandler

{

public:

void approveLoan(const IValidator& cV)

}

if(cV.isValid()){

//Process the loan

{

{

};

Page 31: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

31

The goal:writing a controller that handles adding new

comments from visitors to a blog post.We want to stop spam bots from posting

comments, but we don’t want to force visitors to fill in some CAPTCHA text.

OCP Example 2

Page 32: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Solution:The algorithm: checking commenting visitors IP

address’ against Project Honey Pot’s IP black list.While that strategy doesn’t give bulletproof protection

against spam bots it’s very easy to implement. On next phase we will add other protection later.

The application is consisted of a single method that is called when a new comment is about to be saved.

OCP Example 2 (Cont…)

Page 33: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)

33

class CEntryController

{

public:

void AddComment(std::string comment,

long ipaddress)

{

if(ValidateNotSpam(ipaddress)){

//Save the comment to the database

}

}

bool ValidateNotSpam(long ipaddress)

{

//Check if the IP-address that made the

//request is known as a spammer by Project

//Honey Pot

}

};

OCP Example 2 (Cont…)

Page 34: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)

34

This code has a few problems: It is responsible for doing two things,

validating the request and persisting the comment, which isn't optimal.

It's dependency on an external service renders it almost impossible to test.

It is also clearly violating the Open/Closed principle.

Page 35: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)

35

How can we extend this class so that it also used another service for validating the comment?

We would then have no other choice but to modify the ValidateNotSpammethod.

Hence, it's not possible to extend the class, that is it isn't open for extension, and to modify behavior that isn't at the core of what the class should do (persisting comments) requires the actual class to be changed, it isn't closed for modification.

Page 36: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Open Closed Principle (Cont…)

36

ISpamChecker

CSpamIPBlackListChe

cker

CCAPTCHAtextChe

cker

CEntryController

Page 37: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Liskov Substitution Principle

Page 38: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

(3) Liskov Substitution Principle38

Subclasses should be substitutable for their base classes. Functions that use pointers or references to base classes,

must be able to use objects of derived classes without knowing it.

“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.” (Barbara Liskov, 1988)

Page 39: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Liskov Substitution Principle (Cont…)39

Any subclass should always be usable instead of its parent class.

Failing to follow LSP result in a mess

OCP violations (if/then to identify types)

Superclass unit test will fail

Strange behavior

Page 40: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Liskov Substitution Principle (Cont…)

40

One of the most glaring violations of this principle is the use of C++ Run-Time Type Information (RTTI) to select a function based upon the type of an object. i.e.:

void DrawShape(const Shape& s)

{

if (typeid(s) == typeid(Square))

DrawSquare(static_cast<Square&>(s));

else if (typeid(s) == typeid(Circle))

DrawCircle(static_cast<Circle&>(s));

{

Page 41: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Liskov Substitution Principle (Cont…)41

Clearly the DrawShape function is badly formed.

It must know about every possible derivative of the Shape class, and it must be changed whenever new derivatives of Shape are created.

Indeed, many view the structure of this function as anathema to Object Oriented Design.

Page 42: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

UML-מלבן וריבוע 42

Liskov Substitution Principle (Cont…)

Page 43: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

( 1)קוד –מלבן וריבוע 43

class Rectangle

{

public:

virtual void setWidth(double aWidth) {width= aWidth;}

virtual void setHeight(double aHeight){height=aHeight;}

double getHeight() const {return height;}

double getWidth() const {return width;}

private:

double height;

double width;

};

Liskov Substitution Principle (Cont…)

Page 44: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

( 2)קוד –מרובע וריבוע

44

class Square : Rectangle{

public:

void setWidth(double aWidth)

{

Rectangle::setWidth(aWidth);

Rectangle::SetHeight(aWidth);

}

void setHeight(double aHeight)

{

Rectangle::setWidth(aHeight);

Rectangle::SetHeight(aHeight);

}

};

Liskov Substitution Principle (Cont…)

Page 45: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

:בעיה

מה מצפה הקליינט שיקרה בקריאה לפונקציה?Squareהבאה עם אובייקט

void g(Rectangle& r)

{

r.setWidth(5);

r.setHeight(4);

assert(r.GetWidth()*r.GetHeight() ==20);

}

Liskov Substitution Principle (Cont…)

45

Page 46: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

LSPפי -פתרון הבעיה על46

Liskov Substitution Principle (Cont…)

Page 47: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Interface Segregation Principle

Page 48: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

(4) Interface Segregation Principle48

Clients should not be forced to depend upon interfaces that they do not use.

Many client specific interfaces are better than one general purpose interface

Create an interface per client type not per client Avoid needless coupling to clients

Page 49: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Interface Segregation Principle (Cont…)49

Clients should not be forced to implement interfaces they don’t use.

Instead of one fat interface, many small interfaces are preferred based on groups of methods, each one serving one sub-module

Page 50: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Interface Segregation Principle (Cont…)

50

class Contact{

public:

void SetName(const std::string&);

std::string GetName() const;

void SetAddress(const std::string&);

std::string GetAddress() const;

void SetEmailAddress(const std::string&);

std::string GetEmailAddress() const;

void SetTelephone(const std::string&);

std::string GetTelephone();

};

Page 51: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Interface Segregation Principle (Cont…)

51

class Emailer // sends email messages to contacts

{

public:

void SendMessage( const Contact& contact,

const std::string& subject,

const std::string& body)

{

// Code to send email,

//using contact's email address and name

}

};

class Dialler // extracts the telephone number

{ // from the Contact and calls it

public:

void MakeCall(const Contact& contact)

{

// Code to dial telephone number of contact

}

};

Page 52: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Interface Segregation Principle (Cont…)

52

The example code violates the ISP. The Emailer class is a client of the Contact

class. Although it only requires access to the Nameand EmailAddress properties, it is aware of other members too.

Similarly, the Dialler class uses a single property, "Telephone". However, it has access to the entire Contact interface.

Page 53: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Interface Segregation Principle (Cont…)

53

To re-factor the code to comply with the ISP we need to hide unused members from the client classes.

We can achieve this by introducing two new interfaces, both implemented by Contact.

Page 54: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Interface Segregation Principle (Cont…)54

class IEmailable

{

public:

virtual void SetName(const std::string&)=0;

virtual void SetEmailAddress(

const std::string&)=0;

virtual std::string GetName() const =0;

virtual std::string GetEmailAddress() const =0;

};

class IDiallable

{

public:

virtual void SetTelephone(const std::string&) =0;

virtual std::string GetTelephone() const =0;

};

Page 55: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Interface Segregation Principle (Cont…)

55

class Contact : public IEmailable,

public IDiallable

{

public:

void SetName(const std::string&);

void SetEmailAddress(const std::string&);

void SetAaddress(const std::string&);

void SetTelephone(const std::string&);

std::string GetName() const;

std::string GetEmailAddress() const;

std::string GetAddress const();

std::string GetTelephone() const;

};

Page 56: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Interface Segregation Principle (Cont…)

56

class MobileEngineer : public IDiallable

{

public:

void SetName(const std::string&);

std::string GetName() const;

void SetTelephone(const std::string&);

std::string GetTelephone() const;

void SetVehicle(const std::string&);

std::string GetVehicle() const;

};

Page 57: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Interface Segregation Principle (Cont…)

57

class Emailer

{

public:

void SendMessage(IEmailable* pTarget,

const std::string& subject,

const std::string& body)

{

// Code to send email,

//using target's email address and name

}

};

class Dialler

{

public:

void MakeCall(IDiallable* pTarget)

{ // Code to dial telephone number of target

}

};

Page 58: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

OperatingSystem

Admin

User

Guest

Interface Segregation Principle (Cont…)

58

Page 59: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

class IAdminOSInterface

{

virtual operation1()=0;

virtual operation2()=0;

virtual operation3()=0;

virtual operation4()=0;

virtual operation5()=0;

virtual operation6()=0;

virtual operation7()=0;

};

class IUserOSInterface

{

virtual operation2()=0;

virtual operation3()=0;

virtual operation5()=0;

virtual operation7()=0;

};

class IGuestOSInterface

{

virtual operation1()=0;

virtual operation6()=0;

virtual operation7()=0;

};

Interface Segregation Principle (Cont…)

59

Page 60: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Class COperatingSystem : public IAdminOSInterface,

public IUserOSInterface,

public IGuestOSInterface

{

public:

virtual operation1();

virtual operation2();

virtual operation3();

virtual operation4();

virtual operation5();

virtual operation6();

virtual operation7();

};

Interface Segregation Principle (Cont…)

60

Page 61: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

OperatingSystem

Admin

User

Guest

IAdminOSInterface*IGuestOSInterface*

IUserOSInterface*

Interface Segregation Principle (Cont…)

61

Page 62: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Dependency Inversion Principle

Page 63: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

(5) Dependency Inversion Principle63

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.

B. Abstractions should not depend upon details. Details should depend upon abstractions.

Page 64: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Dependency Inversion Principle (cont…)

64 Example 1:

A copy module which read characters from keyboard and write them to the printer device.

The high level class containing the logic is the Copy class.

The low level classes are KeyboardReader and PrinterWriter.

BAD DESIGN: the high level class uses directly the low level classes. In this case if we want to change the design to direct the

output to a new FileWriter class we have to change the Copy class.

Page 65: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Dependency Inversion Principle (cont…)65

GOOD DESIGN: introduce an abstraction layer between the high level classes and low level classes. Since the high level modules contains the complex

logic, they should not depend on the low level modules, and that the new abstraction layer should not be created based on low level modules.

The low level modules are created based on the abstraction layer.

Page 66: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Dependency Inversion Principle (cont…)

According to this principle the way of designing a class structure is to start from high level modules to the low level modules:

High Level

Classes

Abstraction

Layer

Low Level

Classes

Page 67: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Example: Separating IO from data67

C++

Dependency Inversion Principle (cont…)

Page 68: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Simple Solution68

Remove printouts from class. Add “Set” and “Get” for accessing the

class information.

class CMyClass

getData()

setData(…);

Dependency Inversion Principle (cont…)

Page 69: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

class CMyClass

{

private:

int m_iVar;

public:

void setVar(int v);

int getVar();

};

class CConsoleIO

{

private:

CMyClass* m_pObj;

public:

void printVar() {cout<<m_pObj->getVar();<<endl;}

void setVar() {int v; cin>>v; m_pObj->setVar(v);}

};

Separating IO from data – Simple examples69

Dependency Inversion Principle (cont…)

Page 70: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

Problem: messages70

“Set” and “Get” is good if an outside class is responsible of setting and printing the data.

What if the class itself wants to print a message?Example: an error message.

Dependency Inversion Principle (cont…)

Page 71: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

class InOutHandler

virtual void print(const char* msg) = 0;

Dependency Inversion Principle (cont…)

71

Page 72: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

class CMyClass

+ getData()

+ setData(…);

Class InOutData

+ void setIOHandler(InOutHandler*) ;

# InOutHandler* m_pHadler;

72

Dependency Inversion Principle (cont…)

Page 73: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

class CMyClass : public InOutData

{

private:

int m_iVar;

public:

void setVar(int v)

{

if(v<0)

{

m_pHandler->print("error: var must be

positive");

return;

}

}

int getVar();

};

73

Dependency Inversion Principle (cont…)

Page 74: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

class CConsoleIO : public InOutHadler

{

private:

CMyClass* m_pObj;

public:

CConsoleIO(CMyClass* pObj) : m_pObj(pObj)

{

m_pObj->setIOHandler(this);

}

void print(const char* str) {

cout<< str <<endl;

}

void setVar() {

int v; cin>>v; m_pObj->setVar(v);

}

};

74

Dependency Inversion Principle (cont…)

Page 75: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

class CMfcIO : public InOutHadler

{

private:

CMyClass* m_pObj;

public:

CMfcIO(CMyClass* pObj) : m_pObj(pObj)

{

m_pObj->setIOHandler(this);

}

void print(const char* str) {

//create a message box with the text...

}

void setVar() {

//get input from a text box in the window.

m_pObj->setVar(v);

}

};

75

Dependency Inversion Principle (cont…)

Page 76: Advanced Programming & C++ Language · (1) Single Responsibility Principle 6 A Class should have one reason to change A Responsibility is a reasons to change Every object should have

© Miri Ben-Nissan

int main(){

CConsoleIO cConsoleObj;

CMyClass cMyClObj;

cMyClObj.setIOHandler(&cConsoleObj);

CMfcIO cMfcObj;

cMyClObj.setIOHandler(& cMfcObj);

}

Dependency Inversion Principle (cont…)