DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
OO Design with C++: 5. Design Principles, part 2
1. C++ : принципы проектирования, часть 2 Дмитрий Штилерман, Рексофт
2.
3.
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.
6. OCP - простой абстрактный пример Поведение клиента зависит от конкретного класса сервера и не может быть изменено без изменения исходного кода клиента Поведение клиента может быть изменено путем использования разных реализаций сервера
7.
8.
9.
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.
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.
15. DIP - простой пример Клиент напрямую зависит от класса сервера и не может быть использован отдельно от него. Клиент зависит от абстрактного интерфейса Почему dependency inversion? Простой ответ: разворот стрелочек у серверных классов. Более сложный ответ: см ниже.
16.
17. DIP - проектирование многоуровневых систем (2) DIP позволяет решить описанные проблемы.