Object-oriented design principles

Similar documents
Object Oriented Software Design - I

11/2/09. Code Critique. What goal are we designing to? What is the typical fix for code smells? Refactoring Liskov Substitution Principle

Liskov Substitution Principle

Lecture: Modular Design

Design Principles: Part 2

Outline. Design Principles: Part 2. e.g. Rectangles and Squares. The Liskov Substitution Principle (LSP) ENGI 5895: Software Design.

Design Principles: Part 2

OO Class Design Principles

Last Time: Object Design. Comp435 Object-Oriented Design. Last Time: Responsibilities. Last Time: Creator. Last Time: The 9 GRASP Patterns

Ingegneria del Software Corso di Laurea in Informatica per il Management. Software quality and Object Oriented Principles

Principles of Object-Oriented Design

Bruno Bossola SOLID Design Principles

Abstraction. Design fundamentals in OO Systems. Fundamental Software Development Principles

OO Package Design Principles

Principles of Object-Oriented Design

11/4/15. Review. Objec&ves. Refactoring for Readability. Review. Liskov Subs&tu&on Principle (LSP) LISKOV SUBSTITUTION PRINCIPLE

S.O.L.I.D: Software Engineering Principles

SOLID Principles. Equuleus Technologies. Optional Subheading October 19, 2016

17.11 Bean Rules persistent

Object-Oriented Design

The Release Reuse Equivalency Principle (REP) The Common Closure Principle (CCP) The Common Reuse Principle (CRP)

Object-Oriented Design

Conception Orientée Objets. Programmation SOLID

Software Engineering

Outline. Subtype Polymorphism, Subtyping vs. Subclassing, Liskov Substitution Principle. Benefits of Subtype Polymorphism. Subtype Polymorphism

Introduction to Object-Oriented Programming

Software Engineering CSC40232: SOFTWARE ENGINEERING. Guest Lecturer: Jin Guo SOLID Principles sarec.nd.edu/courses/se2017

OO Design Principles

Open Closed Principle (OCP)

COURSE 2 DESIGN PATTERNS

Test Code Patterns. How to design your test code

Index. Index. More information. block statements 66 y 107 Boolean 107 break 55, 68 built-in types 107

Objec&ves. Review. Liskov Subs&tu&on Principle Refactoring for Extensibility. What are reasons that we refactor our code?

Single Responsibility Principle

Testing and Inheritance. Test Code Patterns. Inheritance-related bugs. Inheritance. Testing of Inheritance. Inheritance-related bugs

Programming in the large

Highlights of Previous Lecture

Single Responsibility Principle (SRP)

n HW5 out, due Tuesday October 30 th n Part 1: Questions on material we ll cover today n Part 2: BFS using your graph from HW4

Principles of OO Design

Plan. Design principles: laughing in the face of change. What kind of change? What are we trying to achieve?

Intro to: Design Principles

Agile Software Development

Software Engineering Design & Construction Dr. Michael Eichberg Fachgebiet Softwaretechnik Technische Universität Darmstadt

CSC207H: Software Design SOLID. CSC207 Winter 2018

CMPS 115 Winter 04. Class #10 (2004/02/05) Changes/Review Programming Paradigms Principles of OOD <break> Design Patterns

OOD Smells and Principles

Chapter 6: Inheritance

UML and Design Patterns Prof. Dr. Eric Dubuis, V. June Engineering and Information Technology. On Package Design

Object design. François Schwarzentruber ENS Cachan Antenne de Bretagne

SOLID: Principles of OOD

CHAPTER 5: PRINCIPLES OF DETAILED DESIGN

CS 520 Theory and Practice of Software Engineering Fall 2018

S.O.L.I.D. Principles of

CSC207 Week 3. Larry Zhang

CS 520 Theory and Practice of Software Engineering Fall 2017

Object-oriented design heuristics

5. Application Layer. Introduction

Component-Level Design

Object Relationships

Software Engineering I (02161)

Software Engineering Design & Construction

Object design. François Schwarzentruber ENS Cachan Antenne de Bretagne

09. Component-Level Design

Welcome to Design Patterns! For syllabus, course specifics, assignments, etc., please see Canvas

Outline. Software Rots

Outline. Inheritance. Abstract Classes Interfaces. Class Extension Overriding Methods Inheritance and Constructors Polymorphism.

Stability. Introduction

Tecniche di Progettazione: Design Patterns

Software Engineering /48

GRASP Design Patterns A.A. 2018/2019

Object-Oriented Concepts and Design Principles

20 Years of. Improve the Design of your Code. Dr Dimitris Dranidis JAVA Meetup Group, Thessaloniki May 2015

Plan. Design principles: laughing in the face of change. What kind of change? What are we trying to achieve?

02291: System Integration

ITI Introduction to Computing II

Object-Oriented Design I

Object-Oriented Design II - GRASP

Agile Principles, Patterns, and Practices in C#

Build Testable Client and Service Applications

Cursul 6 27 Martie 2017

Inheritance and object compatibility

ITI Introduction to Computing II

Introduction to Testing and Maintainable code

Software Design and SOLID Principles

M301: Software Systems & their Development. Unit 4: Inheritance, Composition and Polymorphism

Course 2 October, 16, Adrian Iftene

The Liskov Substitution Principle

Object- Oriented Design with UML and Java Part I: Fundamentals

Princípy tvorby softvéru Dizajnové princípy

Object-oriented programming. and data-structures CS/ENGRD 2110 SUMMER 2018

Object Design Guidelines

C++ Modern and Lucid C++ for Professional Programmers

Class Design Principles

CMSC 132: Object-Oriented Programming II

CSCD01 Engineering Large Software Systems. Design Patterns. Joe Bettridge. Winter With thanks to Anya Tafliovich

Today's Agenda. References. Open Closed Principle. CS 247: Software Engineering Principles. Object-Oriented Design Principles

CPSC 410? Advanced Software Engineering Mid-term Examination (Term I ) SOLUTION Instructor: Gail Murphy

Influence of Design Patterns Application on Quality of IT Solutions

CSE 331 Final Exam 3/16/15 Sample Solution

Transcription:

Object-oriented design principles Objektumorientált szoftvertervezés Object-oriented software design Dr. Balázs Simon BME, IIT

Outline OO concepts Single Responsibility Principle (SRP) Open/Closed Principle (OCP) Liskov Substitution Principle (LSP), Design by Contract (DbC) Interface Segregation Principle (ISP) Dependency Inversion Principle (DIP) Release Reuse Equivalency Principle (REP) Common Closure Principle (CCP) Common Reuse Principle (CRP) Acyclic Dependencies Principle (ADP) Stable Dependencies Principle (SDP) Stable Abstractions Principle (SAP) Don t Repeat Yourself (DRY) Single Choice Principle (SCP) Law of Demeter (LoD) Dr. Balázs Simon, BME, IIT 2

OO concepts Dr. Balázs Simon, BME, IIT 3

OO concepts Class: type defines the methods/functions (behavior, services) of an object fields/attributes/variables support the behavior and their values define the state of an object Object: instance is an instance of a class Static members: class members methods and fields corresponding to the class as a whole only one copy across all objects static methods have no this pointer, cannot access instance members Instance members: object members methods and fields corresponding to an object different copy for each object instance methods have a common implementation, but they receive an implicit 0 th parameter: the this pointer (current object instance) Dr. Balázs Simon, BME, IIT 4

OO concepts Abstraction: ignoring the unnecessary details in the given context real-world objects can be mapped to objects in a program Classification: grouping things with common behavior and properties together objects with common behavior and properties can be described by the same class Encapsulation: a class should not allow direct access to the fields only through methods fields should be private Inheritance: a derived class of a base class can reuse the base class s behavior Base Derived inheritance means is-a-type-of relationship between the derived class and the base class important: never use inheritance for data reuse! use delegation instead! Polymorphism: the caller of a method does not have to worry whether an object belongs to a parent class or one of its descendants realized by virtual methods and inheritance: virtual methods can be overridden in derived classes Dr. Balázs Simon, BME, IIT 5

OO concepts Visibility: private (-): can only be accessed by the current class protected (#): can only be accessed by the current class or by a derived class public (+): can be accessed by anyone package (~): can be accessed from the same package in Java: we don t write it explicitly, no visibility means package visibility in C#: we don t have package visibility, but we have internal visibility: things can be accessed only from the same assembly (dll or exe) Virtual method: virtual methods can be overridden in a derived class this is a way to extend the behavior of a base class Abstract method: a virtual method with no implementation Abstract class: classes with at least one abstract (pure virtual) method (C++) classes can be marked as abstract explicitly (Java, C#) abstract classes cannot be instantiated Interface: a set of operations with no implementation defines the expected behavior/contract of a class implementing the interface Dr. Balázs Simon, BME, IIT 6

OO concepts Coupling: manner and degree of interdependence between software modules/classes/functions measure of how closely connected two routines or modules are the strength of the relationships between modules low coupling is good for maintainability: a change in one part of the system implies only a few changes in other parts of the system Cohesion: degree to which the elements of a module/class belong together measures the strength of relationship between pieces of functionality within a given module high cohesion is good for maintainability: in highly cohesive systems functionality is strongly related, therefore, changing the functionality is localized Dr. Balázs Simon, BME, IIT 7

OO design principles Dr. Balázs Simon, BME, IIT 8

Problem of change Software is subject to change A good design can make change less troublesome The problem is when the requirements change in a way that was not anticipated by design If the design fails under changing requirements, then it is the design s fault Changes in a later phase may violate the original design philosophy, and these changes can escalate this is why documentation is important Dr. Balázs Simon, BME, IIT 9

Bad design The design is bad when: it is hard to change because every change affects too many other parts of the system (Rigidity) changes break down unexpected parts of the system (Fragility) it is hard to reuse parts of the system in another application because these parts cannot be disentangled from the current application (Immobility) Cause of bad design: heavy interdependence between the parts of the application Solution: reduce dependency between parts drive dependency away from problematic or frequently changing parts Dr. Balázs Simon, BME, IIT 10

SOLID principles Five principles of good OO design Single responsibility Open-closed Liskov substitution Interface segregation Dependency inversion Introduced by Robert C. Martin These principles promote maintainability and extensibility over time by reducing dependency between parts of an application Dr. Balázs Simon, BME, IIT 11

Single Responsibility Principle (SRP) A class should have only one reason to change (Robert C. Martin) In this context: responsibility = reason to change ( the provided services) This means that if a class has more than one responsibilities it should be split into multiple classes Dr. Balázs Simon, BME, IIT 12

SRP If a class has more than one responsibilities, split the responsibilities: at implementation level (if they can be uncoupled) at interface level (if they cannot be uncoupled) Implementation level: separate classes one using the other (e.g. GUI using business logic) but not vica versa Interface level: interfaces for separate responsibilities implement both interfaces in the same class Advantage: dependencies flow away from the problematic responsibilities Dr. Balázs Simon, BME, IIT 13

SRP violation example Logic Monster +Move() +Collide() +Draw() GUI Dr. Balázs Simon, BME, IIT 14

SRP solution I. Logic Monster +Move() +Collide() MonsterView +Draw() GUI Dr. Balázs Simon, BME, IIT 15

SRP solution II. Logic Monster +Move() +Collide() <<interface>> IUpdatable +Update() GUI MonsterView +Draw() Dr. Balázs Simon, BME, IIT 16

Probability of change It is not always obvious that there are more reasons to change It is also possible that the change will never occur We have to estimate the probability of the change based on our past experiences and on our domain knowledge Don t design for change if it has low probability YAGNI = You Ain t Gonna Need It Dr. Balázs Simon, BME, IIT 17

Open/Closed Principle (OCP) Software entities (classes, modules, functions etc.) should be open for extension, but closed for modification. (Bertrand Meyer) Open for extension: the behavior of the module can be extended to satisfy the changes in the requirements Closed for modification: extending the behavior of the module does not result in changes to the source of the module Dr. Balázs Simon, BME, IIT 18

OCP Prepare for change Open for extension: new subclasses overriding methods polymorphism delegation Closed for modification: original code does not change only bugfixes Extend behavior by adding new code, not changing existing code Dr. Balázs Simon, BME, IIT 19

OCP violation example <<interface>> IDrawable Field Pacman Monster Wall GUI +DrawAll() void drawall(idrawable[] d, int n) { for (int i = 0; i < n; ++i) { if (d[i] instanceof Field) { //...draw field... } else if (d[i] instanceof Pacman) { //...draw pacman... } else if... } } Dr. Balázs Simon, BME, IIT 20

OCP solution <<interface>> IDrawable +Draw() 0..* -ds GUI +DrawAll() FieldView PacmanView MonsterView WallView +Draw() +Draw() +Draw() +Draw() void DrawAll() { for (IDrawable item: ds) { item.draw(); } } Dr. Balázs Simon, BME, IIT 21

Drawing bug A user reports a bug: the pacman and the monsters sometimes disappear Problem: the order of the drawing is important fields should be drawn at first, then walls, monsters, and pacman Solution: we have to introduce ordering e.g. Precedes function (operator< in C++) Dr. Balázs Simon, BME, IIT 22

Drawing bugfix <<interface>> IDrawable +Draw() +Precedes() 0..* -ds GUI +DrawAll() FieldView PacmanView MonsterView WallView +Draw() +Precedes() +Draw() +Precedes() +Draw() +Precedes() +Draw() +Precedes() Precedes violates OCP! class FieldView { boolean Precedes(IDrawable d) { return d instanceof PacmanView d instanceof MonsterView d instanceof WallView; }... Dr. Balázs Simon, BME, IIT } 23

Problems with the bugfix Precedes() violates OCP it is OK, if we don t expect new classes but if new classes are added frequently, this is a bad solution What if other ordering is necessary? e.g. 3D pacman: the furthest items should be drawn first The ordering should not be part of the responsibility of the classes it violates SRP, too The ordering should be separated from the classes although it won t be closed for modification but at least the classes will conform to OCP only the ordering logic should be changed if new classes are added Dr. Balázs Simon, BME, IIT 24

Drawing solution <<interface>> IComparator +Compare() <<interface>> IDrawable +Draw() 0..* +ds GUI +DrawAll() FieldView PacmanView MonsterView WallView +Draw() +Draw() +Draw() +Draw() Draw2DComparator +Compare() Dr. Balázs Simon, BME, IIT 25

Liskov Substitution Principle (LSP) Subtypes must be substitutable for their base types (Barbara Liskov) Any Derived class object must be substitutable where ever a Base class object is used, without the need for the user to know the difference Inheritance: Base Derived is a kind of Base every object of type Derived is also of type Base what is true for an object of Base it is also true for an object of Derived Derived Base represents a more general concept than Derived Derived represents a more specialized concept than Base Anywhere an object of Base can be used, an object of Derived can be used Dr. Balázs Simon, BME, IIT 26

LSP The importance of this principle becomes obvious when the consequences of its violations are considered Violations of LSP: explicit type check (runtime type information) is, instanceof, dynamic_cast, etc. square-rectangle problem Dr. Balázs Simon, BME, IIT 27

LSP violation: type check If a descendant class violates LSP, an inexperienced developer or a developer in a hurry may fix the problem with explicit type check for the problematic type For example: void Draw(Shape s) { if (s instanceof Rectangle) DrawRectangle((Rectangle)s); else if (s instanceof Ellipse) DrawEllipse((Ellipse)s); } Here Draw violates OCP, since it must know about every possible derivative of Shape Violation of LSP also leads to the violation of OCP Dr. Balázs Simon, BME, IIT 28

Which design is better? Square -width: double +GetArea(): double +GetWidth(): double +SetWidth(w: double) Rectangle -height: double +GetArea(): double +GetHeight(): double +SetHeight(h: double) Rectangle -width: double -height: double +GetArea(): double +GetWidth(): double +GetHeight(): double +SetWidth(w: double) +SetHeight(h: double) Square +SetWidth(w: double) +SetHeight(h: double) Neither: both of them violate LSP class Square extends Rectangle { void setwidth(double w) { super.setwidth(w); super.setheight(w); } void setheight(double h) { super.setwidth(h); super.setheight(h); } //... } Dr. Balázs Simon, BME, IIT 29

Both violate LSP Square Rectangle -width: double +GetArea(): double +GetWidth(): double +SetWidth(w: double) Rectangle -height: double +GetArea(): double +GetHeight(): double +SetHeight(h: double) -width: double -height: double +GetArea(): double +GetWidth(): double +GetHeight(): double +SetWidth(w: double) +SetHeight(h: double) Square +SetWidth(w: double) +SetHeight(h: double) void testsquare(square s) { s.setwidth(5); assert(s.getarea() == 25); } void testrectangle(rectangle r) { r.setwidth(5); r.setheight(4); assert(r.getarea() == 20); } Dr. Balázs Simon, BME, IIT 30

LSP The root of the square-rectangle problem: square is a kind of rectangle from the mathematic point of view (data) but square has a different behavior than a rectangle (SetWidth should not change the height) and the behavior is what counts in OO Another important warning: never use inheritance for data reuse, always inherit for behavior reuse Dr. Balázs Simon, BME, IIT 31

Design-by-Contract Advertised behavior of the Derived class is substitutable for that of the Base class (Bertrand Meyer) Contract is advertised behavior: pre-conditions post-conditions For example, the post-condition of SetWidth in the Rectangle class would be: assert(width == w && height == old.height) that is, the height remains unchanged this is violated by the Square class The rule for pre- and post-conditions: A derived method may only replace the original pre-condition by one equal or weaker, and the original post-condition by one equal or stronger. Expect no more, provide no less. Dr. Balázs Simon, BME, IIT 32

Design-by-Contract GetArea post: result=width*width GetArea post: result=width*height Square -width: double +GetArea(): double +GetWidth(): double +SetWidth(w: double) Rectangle -height: double +GetArea(): double +GetHeight(): double +SetHeight(h: double) Rectangle -width: double -height: double +GetArea(): double +GetWidth(): double +GetHeight(): double +SetWidth(w: double) +SetHeight(h: double) Square +SetWidth(w: double) +SetHeight(h: double) SetWidth post: width == w && height == old.height SetHeight post: height == h && width == old.width SetWidth post: width == w && height == w SetHeight post: height == h && width == h Dr. Balázs Simon, BME, IIT 33

Interface Segregation Principle (ISP) Clients should not be forced to depend on methods they do not use (Robert C. Martin) ISP acknowledges that objects require fat, non-cohesive interfaces However, clients should not know about them as a single class Instead, clients should know about abstractions with cohesive interfaces Dr. Balázs Simon, BME, IIT 34

ISP violation example CartClient PaymentClient ShippingClient WebShop +AddToCart() +RemoveFromCart() +Pay() +Ship() Dr. Balázs Simon, BME, IIT 35

ISP The clients should depend on the methods they actually call Break up the polluted or fat interface of a class into many client-specific interfaces Let the class implement all these interfaces The clients should depend only on the interface they require This breaks the dependence of clients on methods they do not use And hence, the clients will be independent of each other Dr. Balázs Simon, BME, IIT 36

ISP solution CartClient PaymentClient ShippingClient <<interface>> ICart <<interface>> IPayment <<interface>> IShipping +AddToCart() +RemoveFromCart() +Pay() +Ship() WebShop Dr. Balázs Simon, BME, IIT 37

Dependency Inversion Principle (DIP) High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions. (Robert C. Martin) An application consists of modules A natural way to implement these modules is to write the low-level modules (input-output, networking, database, etc.) and combine them in high-level modules However, this is bad: a change in a low-level module affects high-level modules Dr. Balázs Simon, BME, IIT 38

DIP violation example Example for bad design: GUI ---> Service ---> DataSource changing in the datasource or adding a new one causes changes in the service layer and maybe also in the GUI layer Dependency Inversion Principle: change the direction of the dependency: let low-level modules depend on high-level modules GUI Service DataSource Dr. Balázs Simon, BME, IIT 39

DIP solution Presentation layer GUI <<interface>> IService Business layer Service <<interface>> IDataSource Data layer DataSource Dr. Balázs Simon, BME, IIT 40

DIP solution II. GUI Presentation layer Business interface <<interface>> IService Business layer Service <<interface>> IDataSource Data layer DataSource Dr. Balázs Simon, BME, IIT 41

DIP Another interpretation of DIP: depend on abstractions According to this in the strong sense: no instances of a concrete class can be created no classes should be derived from a concrete class no method should override an implemented method of any of its base classes Clearly, these are too strong conditions, and the first one is always violated Use creational patterns to inject concrete instances for abstractions (e.g. abstract factory) If a concrete class is not going to change very much, and no other similar derivatives are going to be created, then its perfectly OK to depend on it Dr. Balázs Simon, BME, IIT 42

DIP criticism There are times when the interface of a concrete class has to change And this change must be propagated to the abstract interface that represents the class A change like this will break through of the isolation of the abstract interface However, the client classes declare the service interfaces they need, and the only time this interface will change is when the client needs the change Dr. Balázs Simon, BME, IIT 43

Release Reuse Equivalency Principle (REP) A reusable element (module, component, class, etc.) cannot be reused unless it is managed by a release system The released elements must have version numbers The author of the reusable element must be willing to support and maintain older versions until the users can upgrade to newer versions Otherwise, the released elements won t be reused Since packages are the unit of release, reusable classes should be grouped into packages Dr. Balázs Simon, BME, IIT 44

Common Closure Principle (CCP) Classes that change together, belong together The more packages that change in a release, the greater the work is to adjust, rebuild, test and deploy the new release Thus, classes that are likely to change together should be grouped into the same package We have to anticipate the possible changes, and decide based on these Dr. Balázs Simon, BME, IIT 45

Common Reuse Principle (CRP) Classes that aren t reused together should not be grouped together Dependency upon a package is a dependency upon everything in the package When a package changes, all its users have to be changed, even if they do not use the changed elements from the package This is similar to ISP at package level Dr. Balázs Simon, BME, IIT 46

Acyclic Dependencies Principle (ADP) Dependencies between packages must not form cycles A newly released package must be tested with its dependencies Hopefully, the number of dependencies is small But if there is a cycle in the dependency graph, all the packages in the cycle must be rebuilt and retested Dr. Balázs Simon, BME, IIT 47

ADP GUI Communication Business Logic Sockets Protocols Database Error Messages Dr. Balázs Simon, BME, IIT 48

ADP violation example GUI Communication Business Logic Sockets Protocols Database Error Messages Dr. Balázs Simon, BME, IIT 49

ADP solution I.: introducing a new package GUI Communication Business Logic Sockets Protocols Database Message Manager Error Messages Dr. Balázs Simon, BME, IIT 50

ADP solution II.: DIP and ISP GUI Communication Business Logic Sockets Protocols Database Error Messages <<interface>> IMessageManager Dr. Balázs Simon, BME, IIT 51

Stable Dependencies Principle (SDP) Depend in the direction of stability Stability is related to the amount of work to make a change X is stable: two packages depend on it, this is good reason not to change X; X is responsible to these packages X depends on nothing; X is independent Y is instable: X Y has no other packages depending on it; Y is irresponsible Y depends on two other packages, Y so change can come from two directions; Y is dependent Dr. Balázs Simon, BME, IIT 52

SDP Software is subject to change A good design means that changes can be made easily So the most frequently changing parts of the application should be instable, since changes in an instable package cost less Stable packages must never be dependent on flexible and continuously changing packages Examples: the GUI should depend on the model the model should not depend on the GUI Dr. Balázs Simon, BME, IIT 53

Stable Abstractions Principle (SAP) Stable packages should be abstract packages The software is built of packages: instable and flexible packages at the top stable and difficult to change packages at the bottom Question: is stability good? Although stable packages are difficult to change, they do not have be difficult to extend! Dr. Balázs Simon, BME, IIT 54

SAP If stable packages are highly abstract, they can be easily extended So the software is built of packages: instable and flexible packages at the top that are easy to change stable and highly abstract packages at the bottom that are easy to extend SAP is just another form of DIP Dr. Balázs Simon, BME, IIT 55

Don t Repeat Yourself (DRY) Every piece of knowledge must have a single, unambiguous, authoritative representation within a system Reduce repetition Duplication is bad: if something has to be changed in the repetitive part of the code, it has to be changed in all occurrences there is a high probability that some occurrences will be missed If you hit Ctrl+C think about creating a method from the copied part of the code Dr. Balázs Simon, BME, IIT 56

DRY violation example class Producer { private Object mutex = new Object(); private Queue queue; public void produce() { synchronized(mutex) { String item = "hello"; queue.enqueue(item); } } } class Consumer { private Object mutex = new Object(); private Queue queue; public void consume() { synchronized(mutex) { String item = queue.dequeue(item); } } } Dr. Balázs Simon, BME, IIT 57

DRY solution: making the Queue thead-safe class Queue { private Object mutex = new Object(); private ArrayList<String> items; public void enqueue(string item) { synchronized(mutex) { items.add(item); } } } public String dequeue() { synchronized(mutex) { String result = items.get(0); items.remove(0); return result; } } Dr. Balázs Simon, BME, IIT 58

DRY solution: making the Queue thead-safe class Producer { private Queue queue; public void produce() { String item = "hello"; queue.enqueue(item); } } class Consumer { private Queue queue; public void consume() { String item = queue.dequeue(item); } } Dr. Balázs Simon, BME, IIT 59

Single Choice Principle (SCP) Whenever a software system must support a set of alternatives, ideally only one class in the system knows the entire set of alternatives This is a corollary to DRY and OCP Also known as: Single Point Control (SPC) The exhaustive list of alternatives should live in exactly one place Dr. Balázs Simon, BME, IIT 60

Tell, don t ask (TDA) Methods should be called without checking the target object s state at first If the state of the target object is queried without just simply calling the method on the object, the state check is a behavior that should belong to the target object s responsibilities Dr. Balázs Simon, BME, IIT 61

TDA violation example class Pacman { void step() { Field next = field.getnext(); if (next.isfree()) { next.accept(this); } else { Thing other = next.getthing(); other.collide(this); } } } Dr. Balázs Simon, BME, IIT 62

TDA solution class Pacman { void step() { Field next = field.getnext(); field.remove(this); next.accept(this); } } class Field { void accept(thing t) { if (this.thing!= null) { this.thing.collide(t); } else { this.thing = t; } } } Dr. Balázs Simon, BME, IIT 63

TDA Violation of TDA also violates DRY It can cause a lot of problems: checking the condition may be forgotten in some places concurrency problems pre-condition violation problems Leave the checking of conditions to the object being called The violation of TDA means that the responsibilities are not at the right place Dr. Balázs Simon, BME, IIT 64

Law of Demeter (LoD) A method of an object should only invoke methods of: itself its parameters its members objects it creates A method should not invoke other objects members Dr. Balázs Simon, BME, IIT 65

LoD violation example Either: this.field.getnext().getthing().collide(this); Or: Field next = this.field.getnext(); Thing thing = next.getthing(); thing.collide(this); Dr. Balázs Simon, BME, IIT 66

LoD possible solutions //Acceptable: Field next = this.field.getnext(); next.accept(this); //Better: this.field.movethingtonextfield(); Dr. Balázs Simon, BME, IIT 67

LoD Chaining method calls means dependency on all the items of the chain Solution: provide a method in each object to delegate the call to the next object But make sure there is no combinatorial explosion of methods if there is, redesign responsibilities Only delegate to own members! This way if an item in the chain changes it probably won t affect the object at the beginning Dr. Balázs Simon, BME, IIT 68

Summary Single Responsibility Principle (SRP) Open/Closed Principle (OCP) Liskov Substitution Principle (LSP), Design by Contract (DbC) Interface Segregation Principle (ISP) Dependency Inversion Principle (DIP) Release Reuse Equivalency Principle (REP) Common Closure Principle (CCP) Common Reuse Principle (CRP) Acyclic Dependencies Principle (ADP) Stable Dependencies Principle (SDP) Stable Abstractions Principle (SAP) Don t Repeat Yourself (DRY) Single Choice Principle (SCP) Law of Demeter (LoD) Dr. Balázs Simon, BME, IIT 69