1 / 48

Class design principles

Class design principles. Lecture 2. The quality of the architecture. What is a good design? It is the design that at least does not have signs of “bad”. What is a bad design? Signs of a bad design: Rigidity Fragility Monolithic Viscosity Unjustified complexity Duplication Obscurity.

jason
Télécharger la présentation

Class design principles

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Class design principles Lecture 2

  2. The quality of the architecture • What is a good design? It is the design that at least does not have signs of “bad”. • What is a bad design? • Signs of a bad design: • Rigidity • Fragility • Monolithic • Viscosity • Unjustified complexity • Duplication • Obscurity

  3. Rigidity • Design is rigorous if one change involve cascade of subsequent changes in the dependent modules. • The more modules change, the more the project is rigorous.

  4. Fragility • The project is fragile, if when you make one change to the program is «destroyed» in many places. • New problems often occur in places that are not associated with the changed component. • In the process of fixing bugs new errors appear.

  5. Monolithic • The project is a monolithic one, if it contains components that can be reused in other systems, but the effort of involving the isolation of a component are too large. • As a result the duplication of source code increases.

  6. Viscosity • The project is viscous, when you implement any functionality much easier with “wrong” methods (actually using anti-patterns). • When implementing the functionality with “wrong” methods the probability of making a mistake is high, and the implementation of the “correct” methods is too complicated. • As a result the cost and time of implementation the functionality unnecessarily increases.

  7. Unjustified complexity • The project has unjustified complexity if it contains elements that are not used at the present time (and probably will never be used). • It occurs when developers try to foresee possible changes in the code and conduct activities associated with these potential changes.

  8. Architecture principles • Robert Martin made a list of the five principles of improving the design: • the principle of uniqueness responsibility (SRP, The Single Responsibility Principle), • the principle of openness/closeness (OCP, The Open Closed Principle), • the principle of the Liskov substitution (LSP, The Liskov Substitution Principle), • the principle of separation of interface (ISP, The Interface Segregation Principle), • dependency inversion principle (DIP, The Dependency Inversion Principle).

  9. Coupling • Coupling (connectivity) is a measure that determines how tough one item is associated with other elements, or how many data about the other elements it has. • The design needs to ensure the lowest coupling. • The element with a low degree of coupling depends on a not very large number of other elements and has the following properties: • A small number of dependencies between classes (subsystems) • Weak dependence of one class (subsystem) on the changes in the other class (subsystem). • A high degree of re-use subsystems.

  10. Cohesion • Cohesion (functional connectivity) is a measure of the focus responsibilities of the class. • An object possesses a high degree of cohesion, if its responsibilities are closely linked. • Object with a low degree of cohesion performs many different functions or unconnected responsibilities. • A weak cohesion leads to the following issues: • the difficulty of understanding • the complexity of re-use • the complexity of support • insecurity and constant exposure to changes

  11. The principle of uniqueness responsibility • A class or a module must have one and only one reason to change. • Consequences of the violation: • Monolithic • Potential duplication • Big classes • The effect of the use: • Compact classes • Reduction of coupling • Increase of cohesion

  12. The principle of uniqueness responsibility • Let us have a class representing a certain product with a built-in data validation.

  13. The principle of uniqueness responsibility • Suppose that the object of the product was used by some object “CustomerService” that uses a different algorithm validation:

  14. The principle of uniqueness responsibility • It is very likely that soon the new algorithms of validation will be added. It becomes clear that a separate object must be responsible for the validation of the data.

  15. The principle of uniqueness responsibility • The implementation of the class of product will change as follows:

  16. The principle of uniqueness responsibility • Now the object will be used as follows:

  17. The principle of openness/closeness • The software entities should be open for extension but closed for changes • Consequences of the violation: • Fragility • The effect of the use: • Increase flexibility of the system. • Simplify testing.

  18. The principle of openness/closeness • Let us consider a hierarchy of classes used to represent objects in the database (so-called meta-object). The root essence of such a hierarchy would be the following class:

  19. The principle of openness/closeness • Let us denote classes tables and views:

  20. The principle of openness/closeness • Class Field might look like this:

  21. The principle of openness/closeness • Let us now consider the class SqlDumpGenerator, which allows to get an SQL script that creates the specified database objects:

  22. The principle of openness/closeness • This class violates the principle of openness/closeness, because in order to add a new functionality (for example, a new child of the class MetaObject) you need to modify the function “Generate”. • It is obvious that the observance of the principle should create a method “GetCreateScrip”tin class “MetaObject”

  23. The principle of openness/closeness • Now when you add new objects, there is no need in modification of the method “Generate”, it suffices to add the class child of MetaObject. • Note, however, that if the function “Generate” should add scripts to create in a different order (for example, first add all the tables, and then all of the views), there arises a need in modification. • Generally speaking, there is always such a change, which would require modification but not addition to the source code. The developer must determine the most likely changes and create abstractions that help to guard against these changes.

  24. The Liskov Substitution Principle • Let q(x) is the property faithful relatively concerning x of type T. Then q(y) should be true for objects y of type S, where S is a subtype of type T. • Functions that use references to base classes must be able to use objects of derived classes without knowing it. • Consequences of the violation: • Violation of abstractions. • The difficulty of the test. • The effect of the use: • Clear definition of abstractions. • Simplify testing. • Simplification of understanding of the code.

  25. The Liskov Substitution Principle • Consider the classic example of violation of this principle.We define the class rectangle:

  26. The Liskov Substitution Principle • Let now our system required a class of the square. As is known, the square is a special case of the rectangle, in other words, a square is a rectangle.

  27. The Liskov Substitution Principle • However, all sides of the square are equal, therefore, we are forced to announce methods of setting the width and height of the virtual class rectangle and block them in the class square accordingly.

  28. The Liskov Substitution Principle • The obvious problem seems obvious redundancy data in the class of the square (enough to keep only one way). But suppose that we are not concerned with the problem of saving memory. Consider the following simple test.

  29. The Liskov Substitution Principle • Note that by themselves classes of square and rectangle are correct. • However, the above tests assumed that the width and height of the rectangle are independent, that is, the class Square violated the invariant of the Rectangle class. • This means that inheritance relationship also applies to the behavior of objects. From this perspective, the «square» is not «rectangle».

  30. The Interface Segregation Principle • Clients should not depend on the interfaces that are not needed. • Consequences of the violation: • Complication of a code. • The occurrence of unnecessary dependencies between modules. • The effect of the use: • Simplification of understanding of the code. • Reduction of connectedness.

  31. The Interface Segregation Principle • As a practical demonstration of violation of this principle, consider the following example. We consider the classes representing the two types of workers with the methods of Work and to Eat:

  32. The Interface Segregation Principle

  33. The Interface Segregation Principle • Note that if the specified system classes we want to add a class robot prove that the method implementation Eat in this class will be empty:

  34. The Interface Segregation Principle • Another drawback of the specified interface shows class Manager which manages employee as follows. • This class uses only part of the interface IWorker.

  35. The Interface Segregation Principle • The above examples demonstrate the violation of the principle. • The solution is to split the interface IWorker:

  36. The Interface Segregation Principle • Now in class Robot there is no need to create a dummy implementation methods: • Class Manager depends only on the part of the interface, which requires:

  37. The Dependency Inversion Principle • Modules upper level should not depend on the lower level modules. Both should depend upon abstractions. • Abstractions should not depend on the details. • Details should depend upon abstractions. • Abstraction is the abstract classes (interfaces)that describe the basic nature of the system. • Consequences of the violation: • Monolithic.Fragility. • The effect of the use: • Increase flexibility of the system. • The reusability of the code. • Simplify testing.

  38. The Dependency Inversion Principle • Consider a simple application that prints to console the SQL-dump the contents of a table. The Central object of our application will object DataScripter, and the client code that uses it, will be as follows:

  39. The Dependency Inversion Principle • Class DataScripter looks as follows:

  40. The Dependency Inversion Principle • Class InsertDataDumper may have the following form:

  41. The Dependency Inversion Principle • Function GetSqlDump may be a bit overloaded knowledge and responsibilities: • knows what InsertDataDumper generates the SQL-dump-is line; • able to create an object InsertDataDumper.

  42. The Dependency Inversion Principle • Let us now consider the application of the principle of dependency inversion. • For this purpose we interface IDataDumper:

  43. The Dependency Inversion Principle • Now instead of creating an object InsertDataDumper inside the method GetSqlDump, pass the object DataScripter the appropriate option:

  44. The Dependency Inversion Principle • Now the code to use the object DataScripter will look as follows:

  45. The Dependency Inversion Principle • Application of the principle of dependency inversion reduces connectivity, enabling us to easilychange the method of generating the dump rows with INSERT the UPSERT:

  46. The Dependency Inversion Principle • Note that the dump data always fully retained in the string. This approach can lead to excessive consumption of memory. Change the mechanism to record data and apply the principle of dependency inversion. For this purpose, available in the library .NET abstraction TextWriter:

  47. The Dependency Inversion Principle • Now the code that dumps the data in the console, will be as follows:

  48. The Dependency Inversion Principle • To output data to a file, you can use the following code:

More Related