SlideShare a Scribd company logo
C++ : принципы проектирования, часть 2 Дмитрий Штилерман, Рексофт
Основные принципы проектирования иерархий классов The Open-Closed Principle The Liskov Substitution Principle Design By Contract The Dependency Inversion Principle
The Open-Closed Principle (OCP) Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. (Bertrand Meyer) “ Open for extension” - п оведение модуля может быть расширено в свете новых требований. “ Closed for modification”  - исходный код модуля не должен меняться.
OCP - простой конкретный пример (1) struct Shape {ShapeType type; Rect bounds;}; void DrawShapes(Shape shapes[], int count)  {   for(int i = 0; i < count; i++)   switch(shapes[i])   {   case Circle:    DrawCircle(shapes[i].bounds); break;   case Rectangle:   DrawRectangle(shapes[i].bounds); break;   }  } Процедурный стиль. Как добавить новый тип фигуры? ???
ОО-стиль - полиморфизм. OCP - простой конкретный пример (2) class Shape {public: virtual void draw() = 0;}; class Circle : public Shape {void draw();}; class Rectangle : public Shape {void draw();}; void DrawShapes(std::vector<Shape*>& v)  {   std::vector<Shape*>::iterator itr;   for(itr = v.begin(); itr != v.end(); itr++)   (*itr)->draw();  } Добавление нового типа фигуры не меняет старый код.
OCP -  простой абстрактный пример Поведение клиента зависит от конкретного класса сервера и не может быть изменено без изменения исходного кода клиента Поведение клиента может быть изменено путем использования разных реализаций сервера
OCP - strategic closure (1) Модуль не может быть полностью закрыт для модификации! class Shape {public: virtual void draw() = 0;}; class Circle : public Shape {void draw();}; class Rectangle : public Shape {void draw();}; void DrawShapes(std::vector<Shape*>& v)  {   std::vector<Shape*>::iterator itr;   for(itr = v.begin(); itr != v.end(); itr++)   (*itr)->draw();  } Новое требование: все круги рисовать до всех прямоугольников. ???
OCP - strategic closure (2) Дизайнер должен решить, от каких будущих изменений требований должен быть «закрыт» модуль. Основания для решения: знание предметной области и/или заказчика и оценка вероятности того или иного класса изменений. Важно: способ «закрытия» оказывает влияние на способ «открытия».
The Liskov Substitution Principle (LSP) An object-oriented function that uses pointers or references to a base class must be able to use objects of derived classes without knowing it. (Barbara Liskov,  цит. по  Robert C. Martin) Родственная концепция: Design By Contract (Bertrand Meyer)
Пример н арушения  LSP - RTTI class Person {}; class Student : public Person {}; class Teacher : public Person {}; void processStudent(Student& student); void processTeacher(Teacher& teacher); void processPerson(Person& person)  {   if(typeid(person) == typeid(Student))   processStudent(static_cast<Student&>(person));   else if(typeid(person) == typeid(Teacher))   processTeacher(static_cast<Teacher&>(person));  } class SysAdmin : public Person {}; processPerson is broken!
Пример н арушения  LSP -  нарушение контракта class Rectangle  {   public:   int getHeight() const;   virtual void setHeight(int);   int getWidth() const;   virtual void setWidth(int);  }; void RectangleTest(Rectangle& r)  {   r.setHeight(4);    r.setWidth(5);   int S = r.getHeight()*r.getWidth();    assert(S==20);   } class Square : public Rectangle  {   public:   void setHeight(int h)   {   Rectangle::setHeight(h);   Rectangle::setWidth(h);   }   void setWidth(int w)   {   Rectangle::setWidth(w);   Rectangle::setHeight(w);   }  };
Design By Contract (DBC) A routine (i.e. a method or a function) declares its preconditions and postconditions. The preconditions must be true in order for the routine to execute. Upon completion, the routine guarantees that the postcondition will be true. When redefining a routine in a derivative (i.e. a method in a derived class), you may only replace its precondition by a weaker one, and its postcondition by a stronger one (“contract rule for derivatives”). This rule is logically equivalent to LSP. Bertrand Meyer, “Object-Oriented Software Construction”
DBC -  анализ примера class Rectangle  {   public:   int getHeight() const;   virtual void setHeight(int);   int getWidth() const;   virtual void setWidth(int);  }; class Square : public Rectangle  {   public:   void setHeight(int h)   {   Rectangle::setHeight(h);   Rectangle::setWidth(h);   }   void setWidth(int w)   {   Rectangle::setWidth(w);   Rectangle::setHeight(w);   }  }; Square::setHeight(h) postcondition: getHeight() == h getWidth() == h Square::setWidth(w) postcondition: getWidth() == w getHeight() == w Rectangle::setHeight(h) postcondition: getHeight() == h getWidth() unchanged Rectangle::setWidth(w) postcondition: getWidth() == w getHeight() unchanged
The Dependency Inversion Principle (DIP) High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions. Robert C. Martin, “The Dependency Inversion Principle”
DIP -  простой пример Клиент напрямую зависит от класса сервера и не может быть использован отдельно от него. Клиент зависит от абстрактного интерфейса  Почему dependency inversion?  Простой ответ: разворот стрелочек у серверных классов. Более сложный ответ: см ниже.
DIP -  проектирование многоуровневых систем (1) Высшие уровни зависят от нижних. Изменения в нижних уровнях диктуют изменения в высших. Повторное использование высших уровней невозможно без использования нижних.
DIP -  проектирование многоуровневых систем (2) DIP  позволяет решить описанные проблемы.
The Interface Segregation Principle (ISP) Clients should not be forced to depend upon interfaces that they do not use. Robert C. Martin, “The Interface Segregation Principle” …  to be continued …

More Related Content

TXT
Script clases ide bd espacial
PPT
Generalized Functors - Realizing Command Design Pattern in C++
PDF
Smart Pointers
KEY
Mysterious c++
PDF
C++ idioms by example (Nov 2008)
PDF
C++ Advanced Features (TCF 2014)
PPT
Advanced Programming C++
DOC
Quiz using C++
Script clases ide bd espacial
Generalized Functors - Realizing Command Design Pattern in C++
Smart Pointers
Mysterious c++
C++ idioms by example (Nov 2008)
C++ Advanced Features (TCF 2014)
Advanced Programming C++
Quiz using C++

Similar to OO Design with C++: 5. Design Principles, part 2 (20)

PPTX
GraphQL Relay Introduction
PDF
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
PPTX
3D Design with OpenSCAD
PDF
05-Debug.pdf
PPT
OO Design with C++: 1. Inheritance, part 1
PPTX
Build Your Own VR Display Course - SIGGRAPH 2017: Part 2
PPTX
Beginning direct3d gameprogramming06_firststepstoanimation_20161115_jintaeks
PPTX
Vlsi ii project presentation
PPTX
Zarzadzanie pamiecia w .NET - WDI
PDF
GPU Accelerated Domain Decomposition
PPTX
Clean Code Development
PPT
CS 354 Transformation, Clipping, and Culling
PPT
Multivariate outlier detection
PDF
Software Engineering for Indies #gcmuc18
PDF
building_games_with_ruby_rubyconf
PDF
building_games_with_ruby_rubyconf
PDF
Asynchronous single page applications without a line of HTML or Javascript, o...
PDF
Overlap Layout Consensus assembly
DOCX
Graphics practical lab manual
PDF
MapReduce Algorithm Design
GraphQL Relay Introduction
breaking_dependencies_the_solid_principles__klaus_iglberger__cppcon_2020.pdf
3D Design with OpenSCAD
05-Debug.pdf
OO Design with C++: 1. Inheritance, part 1
Build Your Own VR Display Course - SIGGRAPH 2017: Part 2
Beginning direct3d gameprogramming06_firststepstoanimation_20161115_jintaeks
Vlsi ii project presentation
Zarzadzanie pamiecia w .NET - WDI
GPU Accelerated Domain Decomposition
Clean Code Development
CS 354 Transformation, Clipping, and Culling
Multivariate outlier detection
Software Engineering for Indies #gcmuc18
building_games_with_ruby_rubyconf
building_games_with_ruby_rubyconf
Asynchronous single page applications without a line of HTML or Javascript, o...
Overlap Layout Consensus assembly
Graphics practical lab manual
MapReduce Algorithm Design
Ad

More from Dmitry Stillermann (7)

PPTX
DiSC Model in Practice
PPTX
Как расти самому, помогая расти другим — практическое применение Management T...
PPT
OO Design with C++: 4. Design Principles, part 1
PPT
OO Design with C++: 3. Inheritance, part 3
PPT
OO Design with C++: 2. Inheritance, part 2
PPT
OO Design with C++: 6. Templates & Patterns
PPT
OO Design with C++: 0. Intro
DiSC Model in Practice
Как расти самому, помогая расти другим — практическое применение Management T...
OO Design with C++: 4. Design Principles, part 1
OO Design with C++: 3. Inheritance, part 3
OO Design with C++: 2. Inheritance, part 2
OO Design with C++: 6. Templates & Patterns
OO Design with C++: 0. Intro
Ad

Recently uploaded (20)

PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Encapsulation_ Review paper, used for researhc scholars
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Empathic Computing: Creating Shared Understanding
PDF
A comparative analysis of optical character recognition models for extracting...
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
Big Data Technologies - Introduction.pptx
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PPTX
A Presentation on Artificial Intelligence
PDF
Approach and Philosophy of On baking technology
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
Cloud computing and distributed systems.
Spectral efficient network and resource selection model in 5G networks
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Encapsulation_ Review paper, used for researhc scholars
Digital-Transformation-Roadmap-for-Companies.pptx
Empathic Computing: Creating Shared Understanding
A comparative analysis of optical character recognition models for extracting...
Reach Out and Touch Someone: Haptics and Empathic Computing
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Big Data Technologies - Introduction.pptx
The AUB Centre for AI in Media Proposal.docx
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Network Security Unit 5.pdf for BCA BBA.
NewMind AI Weekly Chronicles - August'25-Week II
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
A Presentation on Artificial Intelligence
Approach and Philosophy of On baking technology
Building Integrated photovoltaic BIPV_UPV.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Diabetes mellitus diagnosis method based random forest with bat algorithm
Cloud computing and distributed systems.

OO Design with C++: 5. Design Principles, part 2

  • 1. C++ : принципы проектирования, часть 2 Дмитрий Штилерман, Рексофт
  • 2. Основные принципы проектирования иерархий классов The Open-Closed Principle The Liskov Substitution Principle Design By Contract The Dependency Inversion Principle
  • 3. The Open-Closed Principle (OCP) Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. (Bertrand Meyer) “ Open for extension” - п оведение модуля может быть расширено в свете новых требований. “ Closed for modification” - исходный код модуля не должен меняться.
  • 4. OCP - простой конкретный пример (1) struct Shape {ShapeType type; Rect bounds;}; void DrawShapes(Shape shapes[], int count) { for(int i = 0; i < count; i++) switch(shapes[i]) { case Circle: DrawCircle(shapes[i].bounds); break; case Rectangle: DrawRectangle(shapes[i].bounds); break; } } Процедурный стиль. Как добавить новый тип фигуры? ???
  • 5. ОО-стиль - полиморфизм. OCP - простой конкретный пример (2) class Shape {public: virtual void draw() = 0;}; class Circle : public Shape {void draw();}; class Rectangle : public Shape {void draw();}; void DrawShapes(std::vector<Shape*>& v) { std::vector<Shape*>::iterator itr; for(itr = v.begin(); itr != v.end(); itr++) (*itr)->draw(); } Добавление нового типа фигуры не меняет старый код.
  • 6. OCP - простой абстрактный пример Поведение клиента зависит от конкретного класса сервера и не может быть изменено без изменения исходного кода клиента Поведение клиента может быть изменено путем использования разных реализаций сервера
  • 7. OCP - strategic closure (1) Модуль не может быть полностью закрыт для модификации! class Shape {public: virtual void draw() = 0;}; class Circle : public Shape {void draw();}; class Rectangle : public Shape {void draw();}; void DrawShapes(std::vector<Shape*>& v) { std::vector<Shape*>::iterator itr; for(itr = v.begin(); itr != v.end(); itr++) (*itr)->draw(); } Новое требование: все круги рисовать до всех прямоугольников. ???
  • 8. OCP - strategic closure (2) Дизайнер должен решить, от каких будущих изменений требований должен быть «закрыт» модуль. Основания для решения: знание предметной области и/или заказчика и оценка вероятности того или иного класса изменений. Важно: способ «закрытия» оказывает влияние на способ «открытия».
  • 9. The Liskov Substitution Principle (LSP) An object-oriented function that uses pointers or references to a base class must be able to use objects of derived classes without knowing it. (Barbara Liskov, цит. по Robert C. Martin) Родственная концепция: Design By Contract (Bertrand Meyer)
  • 10. Пример н арушения LSP - RTTI class Person {}; class Student : public Person {}; class Teacher : public Person {}; void processStudent(Student& student); void processTeacher(Teacher& teacher); void processPerson(Person& person) { if(typeid(person) == typeid(Student)) processStudent(static_cast<Student&>(person)); else if(typeid(person) == typeid(Teacher)) processTeacher(static_cast<Teacher&>(person)); } class SysAdmin : public Person {}; processPerson is broken!
  • 11. Пример н арушения LSP - нарушение контракта class Rectangle { public: int getHeight() const; virtual void setHeight(int); int getWidth() const; virtual void setWidth(int); }; void RectangleTest(Rectangle& r) { r.setHeight(4); r.setWidth(5); int S = r.getHeight()*r.getWidth(); assert(S==20); } class Square : public Rectangle { public: void setHeight(int h) { Rectangle::setHeight(h); Rectangle::setWidth(h); } void setWidth(int w) { Rectangle::setWidth(w); Rectangle::setHeight(w); } };
  • 12. Design By Contract (DBC) A routine (i.e. a method or a function) declares its preconditions and postconditions. The preconditions must be true in order for the routine to execute. Upon completion, the routine guarantees that the postcondition will be true. When redefining a routine in a derivative (i.e. a method in a derived class), you may only replace its precondition by a weaker one, and its postcondition by a stronger one (“contract rule for derivatives”). This rule is logically equivalent to LSP. Bertrand Meyer, “Object-Oriented Software Construction”
  • 13. DBC - анализ примера class Rectangle { public: int getHeight() const; virtual void setHeight(int); int getWidth() const; virtual void setWidth(int); }; class Square : public Rectangle { public: void setHeight(int h) { Rectangle::setHeight(h); Rectangle::setWidth(h); } void setWidth(int w) { Rectangle::setWidth(w); Rectangle::setHeight(w); } }; Square::setHeight(h) postcondition: getHeight() == h getWidth() == h Square::setWidth(w) postcondition: getWidth() == w getHeight() == w Rectangle::setHeight(h) postcondition: getHeight() == h getWidth() unchanged Rectangle::setWidth(w) postcondition: getWidth() == w getHeight() unchanged
  • 14. The Dependency Inversion Principle (DIP) High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions. Robert C. Martin, “The Dependency Inversion Principle”
  • 15. DIP - простой пример Клиент напрямую зависит от класса сервера и не может быть использован отдельно от него. Клиент зависит от абстрактного интерфейса Почему dependency inversion? Простой ответ: разворот стрелочек у серверных классов. Более сложный ответ: см ниже.
  • 16. DIP - проектирование многоуровневых систем (1) Высшие уровни зависят от нижних. Изменения в нижних уровнях диктуют изменения в высших. Повторное использование высших уровней невозможно без использования нижних.
  • 17. DIP - проектирование многоуровневых систем (2) DIP позволяет решить описанные проблемы.
  • 18. The Interface Segregation Principle (ISP) Clients should not be forced to depend upon interfaces that they do not use. Robert C. Martin, “The Interface Segregation Principle” … to be continued …