sp-lecture-01-02.pdf
Document Details
Uploaded by AdorableSpessartine
Tags
Full Transcript
Şabloane de Proiectare Daniel POP Diverse Prezenta – Min 7 Lab (Informatica Aplicata) / 3 (Informatica Romana) – Daca nu sunt indeplinite, prezenta doar in sesiunea B1 (nu mai exista sesiunea C) https://www.uvt.ro/wp-content/uploads/sites/3/2023/05/Structura-anului-uni...
Şabloane de Proiectare Daniel POP Diverse Prezenta – Min 7 Lab (Informatica Aplicata) / 3 (Informatica Romana) – Daca nu sunt indeplinite, prezenta doar in sesiunea B1 (nu mai exista sesiunea C) https://www.uvt.ro/wp-content/uploads/sites/3/2023/05/Structura-anului-universitar-2023-2024.pdf Evaluare – Test de evaluare cunostinte teoretice (curs) in sesiune – Lab IA Code challenge (~ lab 8) Proiect individual final & teme incarcate la timp pe git – Lab IR Proiect individual final & teme incarcate la timp pe git Classroom code: b24oyn2 2 The Plan Object Oriented Design Principles. Fundamental patterns (2 weeks) Learning design patterns through case study (10 weeks) – Messaging App Other talks (2 weeks) 3 Definition A pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice. [Christopher Alexander, Sara Ishikawa, Murray Silverstein, Max Jacobson, Ingrid Fiksdahl-King, and Shlomo Angel. A Pattern Language. Oxford University Press, New York, 1977] 5 essential elements: – Pattern name – Problem description – Solution – Consequences – Implementation 4 Types of Patterns Architectural Patterns: MVC, Layers GUI Design Patterns: Window per task, Disabled irrelevant things, Explorable interface Database Patterns: decoupling patterns, resource patterns, cache patterns Concurrency Patterns: Double buffering, Lock object, Producer- consumer, Asynchronous processing Enterprise (J2EE) Patterns: Data Access Object, Data Transfer Object Design Patterns – GoF patterns – GRASP (General Responsibility Assignment Patterns): Low coupling/high cohesion, Controller, Law of Demeter (don’t talk to strangers), Expert, Creator Anti-patterns = bad solutions largely observed: God class, Singletonitis, Basebean, CallSuper 5 OOD Key Principles Motto: “Imitation is the sincerest form of not being stupid.” DEFINITION [Design principle] A design principle is a basic tool or technique that can be applied to designing or writing code to make that code more maintainable, flexible, or extensible. Design Goals: The code should be Readable, Extendable, Modifiable, Testable Easy to refactor Key OOD principles are (S.O.L.I.D): SRP OCP LSP ISP DIP Example and details: https://stackify.com/solid-design-principles/ 6 Single Responsibility Principle (SRP) A class should have one and only one reason to change, meaning that a class should have only one job. ONLY one reason to change something! Code will be simpler and easier to maintain. Example: Container and Iterator (Container manages objects; Iterator traverses the container) How to spot multiple responsibilities? Forming sentences ending in itself. 7 Single Responsibility Principle (SRP) A class should have one and only one reason to change, meaning that a class should have only one job. ONLY one reason to change something! Code will be simpler and easier to maintain. Example: Container and Iterator (Container manages objects; Iterator traverses the container) How to spot multiple responsibilities? Forming sentences ending in itself. Driver Automobile The Automobile start itself. NOK Drive(Automobile) The Automobile stop itself. Automobile Start() The Automobile changeTires itself. Start() Stop() The Automobile Drive itself. Stop() ChangeTires() The Automobile getOilLevel itself. GetOilLevel() Drive() GetOilLevel() Mechanic ChangeTires(Automobile) OK 8 Open-Close Principle (OCP) Classes should be open for extension and closed for modification. Allowing change, but without modifying existing code. It offers flexibility. Use inheritance to extend/change existing working code and don’t touch working code. OCP can also be achieved using composition. 9 Open-Close Principle (OCP) Classes should be open for extension and closed for modification. Allowing change, but without modifying existing code. It offers flexibility. Use inheritance to extend/change existing working code and don’t touch working code. OCP can also be achieved using composition. class Shape { int type; void drawPolygon() { } void drawPoint() { } public: void draw(); }; void Shape::draw() { switch(type) { case POLYGON: drawPolygon(); break; case POINT: drawPoint(); break; } } 10 Open-Close Principle (OCP) Classes should be open for extension and closed for modification. Allowing change, but without modifying existing code. It offers flexibility. Use inheritance to extend/change existing working code and don’t touch working code. OCP can also be achieved using composition. class Shape { class Shape { int type; public: void drawPolygon() { } virtual void draw() = 0; void drawPoint() { } }; public: void draw(); class Polygon : public Shape { }; NOK public: void draw(); void Shape::draw() { }; switch(type) { case POLYGON: class Point : public Shape { drawPolygon(); public: break; void draw(); case POINT: }; drawPoint(); } break; OK void Polygon::draw() { } Void Point::draw() { } } 11 Liskov Substitution Principle (LSP) Subtypes must be substitutable for their base types. Let q(x) be a property provable against objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T. Well-designed class hierarchies Liskov Substitution Principle (LSP) Subtypes must be substitutable for their base types. Let q(x) be a property provable against objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T. Well-designed class hierarchies Board tiles: Tile[][] getTile(int, int) setTile(Tile, int, int) 3DBoard tiles3D: Tile[][][] getTile(int, int, int) setTile(Tile, int, int, int) void f() { Board* board = new 3DBoard; // ok! // doesn’t make sense for a 3D board board->getTile(1,7); } All member functions of Board are members of 3DBoard as well (that’s inheritance), but, being defined for 2D world, they don’t make sense in the new context (3D world). 13 Liskov Substitution Principle (LSP) Subtypes must be substitutable for their base types. Let q(x) be a property provable against objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T. Well-designed class hierarchies Board Board tiles: Tile[][] tiles: Tile[][] getTile(int, int) getTile(int, int) setTile(Tile, int, int) setTile(Tile, int, int) 3DBoard 3DBoard NOK tiles3D: Tile[][][] boards: Board[] getTile(int, int, int) setTile(Tile, int, int, int) getTile(int, int, int) setTile(Tile, int, int, int) void f() { Board* board = new 3DBoard; // ok! // doesn’t make sense for a 3D board board->getTile(1,7); } Tile 3DBoard::getTile(int x, int y, int z) { All member functions of Board are members of OK return boards[x].getTile(y, z); 3DBoard as well (that’s inheritance), but, being } defined for 2D world, they don’t make sense in the new context (3D world). 14 Interface Segregation Principle (ISP) A client should never be forced to implement an interface that it doesn’t use or clients shouldn’t be forced to depend on methods they do not use. Splits interfaces that are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them (role interfaces). Promotes decoupling and => code is easier to modify. Interface Segregation Principle (ISP) A client should never be forced to implement an interface that it doesn’t use or clients shouldn’t be forced to depend on methods they do not use. Splits interfaces that are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them (role interfaces). Promotes decoupling and => code is easier to modify. class IShape { // interface public: virtual double area() = 0; virtual double volume() = 0; }; class Polygon : public IShape { }; class Cone : public IShape { }; double Polygon::area() { } double Polygon::volume() { return 0; } double Cone::area() { } double Cone::volume() { } Interface Segregation Principle (ISP) A client should never be forced to implement an interface that it doesn’t use or clients shouldn’t be forced to depend on methods they do not use. Splits interfaces that are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them (role interfaces). Promotes decoupling and => code is easier to modify. class IShape { // interface public: class IShape { // interface virtual double area() = 0; public: }; virtual double area() = 0; virtual double volume() = 0; class ISolidShape { // interface }; public: virtual double volume() = 0; class Polygon : public IShape { }; NOK }; class Cone : public IShape { }; class Polygon : public IShape { }; double Polygon::area() { } class Cone : public IShape, public ISolidShape { }; double Polygon::volume() { return 0; } double Polygon::area() { } double Cone::area() { } OK double Cone::area() { } double Cone::volume() { } double Cone::volume() { } 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. Promotes decoupling class OracleDB { void connect() }; class ShapeSaver { public: ShapeSaver(OracleDB& dbConnection); }; 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. Promotes decoupling class DBConnection { // interface public: class OracleDB { virtual void connect() = 0; void connect() }; }; class ShapeSaver { class ShapeSaver { public: public: ShapeSaver(DBConnection& ShapeSaver(OracleDB& dbConnection); NOK dbConnection) {} }; }; class OracleDB : public DBConnection { void connect() }; void OracleDB::connect() { } OK void main() { OracleDB db; ShapeSaver ss{db}; } 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. Promotes decoupling NOK OK Don’t Repeat Yourself (DRY) The Don’t Repeat Yourself Principle (DRY). Avoid duplicate code by abstracting out things that are common and placing those things in a single location. No duplicate code => ONE requirement in ONE place! This principle can and should be applied everywhere (e.g. in Analysis phase – don’t duplicate requirements or features!) Code is easier and safer to maintain because we have to change only one place. 21 Don’t Repeat Yourself (DRY) The Don’t Repeat Yourself Principle (DRY). Avoid duplicate code by abstracting out things that are common and placing those things in a single location. No duplicate code => ONE requirement in ONE place! This principle can and should be applied everywhere (e.g. in Analysis phase – don’t duplicate requirements or features!) Code is easier and safer to maintain because we have to change only one place. String::String(const char* pch) { String::init(const char* pch) { if(pch!=NULL) { if(pch!=NULL) { str = new char[(sz=strlen(pch))+1]; str = new char[(sz=strlen(pch))+1]; strcpy(str, pch); strcpy(str, pch); } } else { else { NOK str = NULL; str = NULL; sz = 0; sz = 0; } } } } void String::set(const char* pch) { String::String(const char* pch) { if(str!=NULL) delete [] str; init(pch); if(pch!=NULL) { } str = new char[(sz=strlen(pch))+1]; strcpy(str, pch); void String::set(const char* pch) { } if(str!=NULL) delete [] str; else { str = NULL; init(pch); sz = 0; OK } } } 22 Types of Design Patterns Based on the type of the problem it addresses (Purpose) – Fundamental – Creational – Structural – Behavioral Based on the technique it uses (Scope) – Class: uses inheritance – Object: uses object composition 23 Fundamental Patterns Inheritance DEFINITION Inheritance is a mechanism which allows a class A to inherit members (data and functions) of a class B. We say “A inherits from B”. Objects of class A thus have access to members of class B without the need to redefine them. Inheritance is identified by the phrase: “kind-of” at class level (Circle is a kind-of Shape) “is-a” at object level (The object circle1 is-a shape.) B is called superclass, supertype, base class or parent class. A is called subclass, subtype, derived class or child class. Person + name : string Inheritance graph / Class hierarchy + Age() : double Multiple inheritance: a class has 2 or more parent classes. Student Teacher Exercise: model the list of courses of each + university : Organization + Grade(topic) : double + getPublications() : List student. 24 Fundamental Patterns Delegation Delegation = Handing of a task over another object Consequences: – Behavior can be changed at run-time (comparing to inheritance that is static) – The ‘delegate’ is hidden to delegator’s clients – More difficult to implement comparing to inheritance Exercise: model the list of courses of each student. (using delegation) 25 Fundamental Patterns Interface Interface – decouples the service provider from its client Consequences: – Programming to abstraction – Easily change the service provider – Transparency for client JDK Examples: – DataInputStream, Iterable, Collection, List and many more 26 Fundamental Patterns Abstract Superclass Abstract superclass – ensures consistent behavior for its subclasses Consequences: – Common behavior is consistent over subclasses – Clients are using the abstract superclass JDK Examples: – AbstractList, AbstractAction, AbstractExectorService and many more 27 Fundamental Patterns Interface and Abstract Superclass Combines Interface and Abstract Superclass patterns Consequences: – Combines the advantages of both patterns – May provide a default behavior for the entire, or just a subset, of the ServiceIF via AbstractService JDK Examples: ExecutorService (interface), AbstractExecutorService (abstract class), ThreadPoolExecutor (concrete class) List (interface), AbstractList (abstract class), Vector (concrete class) 28 Fundamental Patterns Immutable Object Immutable object – the internal state of the object doesn’t change after its creation Consequences: – Only constructors can set object’s state – All member functions are const functions (in C++) – Any member function that need to change the state will create a new instance – Increase design’s robustness and maintainability JDK Example: – String class 29 Fundamental Patterns Marker Interface A class implements a marker interface in order to support a semantic attribute of the system Consequences: – Used by utility classes that need a specific behavior from their elements, without requesting a common base class JDK Examples: – Cloneable, Serializable 30 Design Strategies Dependency injection: The basic idea is that if an object depends upon having an instance of some other object then the needed object is "injected" into the dependent object For example: being passed a database connection as an argument to the constructor instead of creating one internally. Acyclic dependencies principle: The dependency graph of packages or components (the granularity depends on the scope of work for one developer) should have no cycles, i.e. it’s a DAG (Direct Acyclic Graph) For example: package C depends on package B, which depends on package A. If package A also depended on package C, then you would have a cycle. Composite reuse principle: Favor polymorphic composition of objects over inheritance 31 Design Strategies General Responsibility Assignment Software Patterns (or Principles), abbreviated GRASP, consist of guidelines for assigning responsibility to classes and objects in object-oriented design. It is not related to the SOLID design principle. The different patterns and principles used in GRASP are: controller, creator, indirection, information expert, high cohesion, low coupling, polymorphism, protected variations, pure fabrication. https://en.wikipedia.org/wiki/GRASP_(object-oriented_design) 32 Bibliography http://www.amazon.com/D http://www.amazon.com/F http://www.oodesign.com esign-Patterns-Elements- irst-Design-Patterns- Reusable-Object- Elisabeth- Oriented/dp/0201633612/r Freeman/dp/0596007124/r ef=sr_1_1?ie=UTF8&qid=132 ef=sr_1_2?ie=UTF8&qid=132 4985583&sr=8-1 4985583&sr=8-2 33