Principles of object-oriented design

from Wikipedia, the free encyclopedia

Principles of object-oriented design are principles that should lead to good object-oriented design . They were published and propagated by Robert C. Martin , Bertrand Meyer and Barbara Liskov , among others . Many object-oriented techniques such as design patterns , domain-driven design or dependency injection are based on these principles of object-oriented design.

For a group of these principles, Robert C. Martin coined the acronym “SOLID”. According to Robert C. Martin, these principles, applied together, lead to a higher maintainability and thus the service life of software. These principles are the " S ingle Responsibility principle", the " O pen-closed principle", the " L iskovsches substitution principle", the " I nterface segregation principle" and the " D ependency inversion principle".

In addition, there are a number of other more or less well-known principles of object-oriented design such as design by contract or Demeter's law . The so-called packaging principles have a special position among the principles of object-oriented design, as they all deal with the grouping of classes into packages.

SOLID principles

Single responsibility principle

The single responsibility principle says that each class should only have one responsibility. Responsibility is defined as a "reason to change":

"There should never be more than one reason for a class to change."

"There should never be more than one reason to change a class."

- Robert C. Martin : Agile Software Development: Principles, Patterns, and Practices

Having more than one responsibility for a class leads to several areas in which future changes may be necessary. The likelihood that the class will need to be changed at a later date increases, along with the risk of making subtle mistakes in such changes. This principle usually leads to classes with high cohesion in which all methods have a strong common reference.

Open-closed principle

The open-closed principle states that software units (here modules , classes , methods , etc.) should make extensions possible (be open to them), but without changing their behavior (their source code and their interface should not change) . It was formulated by Bertrand Meyer in 1988 as follows:

"Modules should be both open (for extension) and closed (for modification)."

"Modules should be both open (for extensions) and closed (for modifications)."

- Bertrand Meyer : Object Oriented Software Construction

An extension in the sense of the open-closed principle is, for example, inheritance . This does not change the existing behavior of a class, but extends it with additional functions or data. Overridden methods do not change the behavior of the base class either, only that of the derived class. If one continues to follow Liskov's substitution principle, even overwritten methods do not change the behavior, only the algorithms.

Liskov's principle of substitution

Liskov's principle of substitution (LSP) or substitutability principle requires that an instance of a derived class must behave in such a way that someone who thinks they are looking at a base class object is not surprised by unexpected behavior when it is actually one Object of a subtype. It was formulated in 1993 by Barbara Liskov and Jeannette Wing . In a subsequent article it was phrased as follows:

“Let be a property provable about objects of type . Then should be true for objects of type where is a subtype of . "

"Be a property of the object type , then you should for all objects of the type considered, with a subtype of is."

- Barbara H. Liskov, Jeannette M. Wing : Behavioral Subtyping Using Invariants and Constraints

This guarantees that operations of the type Superklassethat are applied to an object of the type Subklasseare also correctly carried out. Then an object of the type can always be Superklassereplaced by an object of the type without hesitation Subklasse. Object-oriented programming languages ​​can not rule out a violation of this principle from the outset, which can occur due to the polymorphism associated with inheritance . A violation of the principle is often not obvious at first glance.

Interface segregation principle

The interface segregation principle is used to divide interfaces that are too large. The division should be made according to the requirements of the clients on the interfaces - in such a way that the new interfaces exactly match the requirements of the individual clients. The clients therefore only have to act with interfaces that can and only do what the clients need. The principle was formulated by Robert C. Martin in 1996 as follows:

"Clients should not be forced to depend upon interfaces that they do not use."

"Clients shouldn't be forced to depend on interfaces that they don't use."

- Robert C. Martin : The Interface Segregation Principle

With the help of the interface segregation principle, it is possible to divide software into decoupled and therefore easier refactorizable classes in such a way that future functional or technical requirements for the software only require minor changes to the software itself.

Dependency inversion principle

The dependency inversion principle deals with reducing the coupling of modules. It says that dependencies should always be directed from more concrete modules of lower levels to abstract modules of higher levels. It was first described by Robert C. Martin in October 1994 and later formulated as follows:

“A. High-level modules should not depend on low level modules. Both should depend on abstractions.
B. Abstractions should not depend upon details. Details should depend upon abstractions. "

"A. High level modules should not depend on low level modules. Both should depend on abstractions.
B. Abstractions shouldn't depend on details. Details should depend on abstractions. "

- Robert C. Martin : The Dependency Inversion Principle

This ensures that the dependency relationships always run in one direction, from the concrete to the abstract modules, from the derived classes to the base classes. This reduces the dependencies between the modules and, in particular, avoids cyclical dependencies.

Further principles

In addition to the SOLID group of principles of object-oriented design propagated by Robert C. Martin, the following principles are also known as principles of object-oriented design:

Law of Demeter

The law of Demeter (English: Law of Demeter, short: LoD) essentially states that objects should only communicate with objects in their immediate vicinity. This is intended to reduce the coupling in a software system and thereby increase maintainability.

The law was described by Karl J. Lieberherr and Ian Holland in 1989 in the paper Assuring Good Style for Object-Oriented Programs as follows:

“A supplier object to a method M is an object to which a message is sent in M. The preferred supplier objects to method M are: The immediate parts of self or the argument objects of M or the objects which are either objects created directly in M or objects in global variables.
Every supplier object to a method must be a preferred supplier. "

“A provider object of method M is an object to which a message is sent from M. The preferred provider objects of method M are: The immediate components of the object of M, objects that were passed to M as arguments and objects that were either created directly in M ​​or are located in global variables.
Each provider object of a method must be a preferred provider object. "

- Karl J. Lieberherr, I. Holland : Assuring good style for object-oriented programs

Due to the formal specification, Demeter's law can easily be implemented as automatically checked software metrics. It is therefore suitable for the early detection of coupling problems.

Design by contract

The design-by-contract principle, English for design under the contract , and Programming by Contract called, has the smooth interaction of individual program modules by defining formal "contract" for use of interfaces, the static on their definition beyond the goal. It was developed and introduced by Bertrand Meyer with the development of the Eiffel programming language .

The smooth interaction of the program modules is achieved by means of a "contract" which, for example, must be adhered to when using a method . This consists of

  • Preconditions (English precondition ), that the assurances must comply with the caller
  • Postconditions (English postcondition ), that the assurances will comply with the callee, and the
  • Invariants (English class invariants ), quasi the state of health of a class.

The use of the design-by-contract principle leads to safer and less error-prone software, since a breach of the contract leads to an immediate error ( fail-fast ) already in the software development phase. Furthermore, the explicit definition of the contract can be seen as a form of documentation of the behavior of the corresponding module. This in turn makes the software easier to learn and maintain.

Data encapsulation

Data encapsulation , also known as information hiding after David Parnas , is another principle of object-oriented design according to Bertrand Meyer. It describes the hiding of data or information from outside access. Direct access to the internal data structure is prevented and instead takes place via defined interfaces. The types of access used in object orientation (private, protected, ...) as well as a number of design patterns - for example Facade - support the implementation of data encapsulation.

Linguistic modular units principle

The linguistic modular units principle (English for the principle of linguistic modular units ) states that modules must be represented by syntactic units of the language used - be it a programming, design or specification language. In the case of a programming language, modules must be represented by separately compilable units of this selected programming language:

"Modules must correspond to syntactic units in the language used."

"Modules must correspond to the syntactic units of the language used."

- Bertrand Meyer : Object Oriented Software Construction

Self-documentation principle

The Self-Documentation principle (for English Selbstdokumentierungsprinzip ) states that all information should be contained in a module in this themselves. This means that the code either speaks for itself (i.e. no further documentation is required) or that the technical documentation is as close as possible to the source code (for example when using Javadoc ). This ensures, on the one hand, that the technical documentation corresponds to the code and, on the other hand, that the complexity of the code is so low that no complex documentation is necessary:

"The designer of a module should strive to make all information about the module part of the module itself."

"When designing a module, you should make sure that all information about the module itself is part of the module."

- Bertrand Meyer : Object Oriented Software Construction

Uniform access principle

The uniform access principle (for English principle of the same kind Zugriffes ) requires that all the services of a module can be accessed by means of a similar notation - is without abandoned by whether the services behind access data sets, or perform calculations. Services should therefore not disclose to the outside world how they are providing their service, but only what their service is:

"All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation."

“All services of a module should be offered using a similar notation; a notation that does not reveal whether it was implemented via data access or calculations. "

- Bertrand Meyer : Object Oriented Software Construction

Single choice principle

The single choice principle states that different alternatives (for example of data or algorithms) in a software system should be mapped in just a single module. For example, the Abstract Factory design pattern supports this principle by deciding once in the factory from a set of alternatives which classes and which algorithms are to be used. This decision does not have to be made anywhere else in the program:

"Whenever a software system must support a set of alternatives, one and only one module in the system should know their exhaustive list."

"Whenever software has to support different alternatives, there should be exactly one module that knows the complete list of alternatives."

- Bertrand Meyer : Object Oriented Software Construction

Persistence closure principle

The persistence closure principle states that persistence mechanisms must save objects with all their dependencies and also reload them. This ensures that objects do not change their properties when they are saved and then loaded.

“Whenever a storage mechanism stores an object, it must store with it the dependents of that object. Whenever a retrieval mechanism retrieves a previously stored object, it must also retrieve any dependent of that object that has not yet been retrieved. "

“When a storage mechanism stores an object, it must also store its dependencies. When a loading mechanism loads a previously saved object, it must also load its dependencies that have not yet been loaded. "

- Bertrand Meyer : Object Oriented Software Construction

Packaging principles

The following principles, defined by Bertrand Meyer and Robert C. Martin, deal with the question of how classes should be combined into modules (packages). In particular, they lead to high cohesion within the modules and low coupling between the modules.

Reuse-Release-Equivalence-Principle

"Either all of the classes in a package are reusable or none of them are."

"Either all or none of the classes in a package can be reused."

- Robert C. Martin :

The reuse-release equivalence principle refers to the structure of packages in the sense of a module as the smallest unit of a release. It stipulates that packages may only consist of classes, either all of which or none of which are intended for reuse.

If the package is reusable, the principle requires, on the one hand, that all changes can be traced and the version history can be traced, and, on the other hand, that only classes are included that are also intended for the same user group (a user who has a Wants to reuse the container class library does not require a financial framework).

Common closure principle

The common closure principle requires that all classes in a module should be closed to the same type of changes according to the open-closed principle . Changes to the requirements of a software, which require changes to a class of a module, should also affect the other classes of the module. Adhering to this principle enables the software to be broken down into modules in such a way that (future) changes can be implemented in just a few modules. This ensures that changes to the software can be made without major side effects and therefore relatively inexpensive.

“The classes in a package should be closed together against the same kinds of changes. A change that affects a package affects all the classes in that package. "

“Classes in a package should be closed to the same types of change. A change that affects a package should affect all classes of this package. "

- Robert C. Martin : Granularity

Common Reuse Principle

The common reuse principle deals with the use of classes. It says that those classes that are used together should also be combined to form a module. Compliance with this principle ensures that the software is subdivided into functional or technically related units.

“The classes in a package are reused together. If you reuse one of the classes in a package, you reuse them all. "

“The classes of a package should be reused together. If you reuse a class of a package, you should reuse all classes of the package. "

- Robert C. Martin : Granularity

Acyclic dependencies principle

The acyclic dependencies principle requires that the dependencies between modules must be cycle-free. I.e. if classes in one module depend on other classes in another module, for example through inheritance or relational relationships, then none of the classes in the other module may depend directly or indirectly on classes in the former module.

“The dependency structure between packages must be a directed acyclic graph (DAG). That is, there must be no cycles in the dependency structure. "

“The dependencies between packages must correspond to a directed acyclic graph. This means that there must be no cycles in the dependency structure. "

- Robert C. Martin : Granularity

Such cycles can always be broken. There are basically two ways of doing this:

  • Application of the dependency inversion principle : If the dependency of package A on package B is to be inverted, then introduce interfaces in the package of A, which hold the methods required by B. Implement these interfaces in the corresponding classes of Package B. Thus the dependency between Package A and B has been inverted.
  • Restructuring of the packages: Collect all classes of a cycle in a separate package and introduce one or more new packages, filled with the classes on which the classes depend outside the cycle

Stable dependencies principle

The stable dependencies principle states that the dependencies between modules should be directed towards the greater stability of the modules. A module should therefore only be dependent on modules that are more stable than itself.

“The dependencies between packages in a design should be in the direction of the stability of the packages. A package should only depend upon packages that are more stable that it is. "

“The dependencies between packages should be in the same direction as the stability. A package should only depend on packages that are more stable than itself. "

- Robert C. Martin : Stability

Here, stability is understood as the inverse ratio of the outgoing dependencies to the sum of all dependencies. The less dependencies a module has on others and the more dependencies other modules have on this module, the more stable the module is. The stability is calculated indirectly via the instability as follows:

I… instability of a module
Ae… in-depth dependencies ( afferent couplings ).
Aa ... outgoing dependencies ( efferent couplings ).

where and are calculated as follows:

  • = Classes outside the module, which depend on classes within the module
  • = Classes of the module, which depend on classes outside the module

The instability is in the range from 0 to 1, an instability of 0 indicates a maximally stable module, one of 1 indicates a maximally unstable module.

Stable Abstractions Principle

The stable abstractions principle requires that the abstractness of a module must be directly proportional to its stability.

“Packages that are maximally stable should be maximally abstract. Instable packages should be concrete. The abstraction of a package should be in proportion to its stability. "

“Packages that are as stable as possible should be as abstract as possible. Unstable packages should be specific. The abstractness of a package should be proportional to its stability. "

- Robert C. Martin : Stability

The more abstract a module is - d. H. the more interfaces, abstract classes, and methods it has - the more stable it should be. In general, the abstractness of a module is calculated as follows:

A… abstractness of a module
Ka… number of abstract classes in a module
K… total number of classes in a module

For each module, the distance to the ideal line - engl. Called Main Sequence - calculate between maximum stability and abstractness and maximum instability and concreteness. This ranges from 0 to ~ 0.707:

D… distance to the ideal line
A… abstractness of a module
I… instability of a module

The greater the distance, the worse the stable abstraction principle is fulfilled.

See also

literature

  • Robert C. Martin : Agile Software Development. Principles, Patterns, and Practices . Pearson Education, Upper Saddle River, NJ 2002, ISBN 0-13-597444-5 .
  • Robert C. Martin: Design Principles and Design Patterns . objectmentor.com, 2000 ( objectmentor.com (PDF; 162 kB)).
  • Bertrand Meyer : Object-Oriented Software Construction . Prentice Hall, New York et al. a. 1988, ISBN 0-13-629049-3 .
  • Richard Pawson, Robert Matthews: Naked Objects . John Wiley & Sons, Chichester et al. a. 2002, ISBN 0-470-84420-5 .

Web links

Individual evidence

  1. ^ Robert C. Martin: Agile Software Development: Principles, Patterns, and Practices . Prentice Hall, 2002, ISBN 978-0-13-597444-5 , pp. 149–153 ( objectmentor.com (PDF)).
  2. ^ Bertrand Meyer: Object Oriented Software Construction . Prentice Hall, 1988, ISBN 978-0-13-629155-8 , pp. 57-61 .
  3. Barbara H. Liskov, Jeannette M. Wing: Family Values: A Behavioral Notion of Subtyping . Pittsburgh 1993.
  4. Barbara H. Liskov, Jeannette M. Wing: Behavioral Subtyping Using Invariants and Constraints . Ed .: MIT Lab. for Computer Science, School of Computer Science, Carnegie Mellon University. Prentice Hall, Pittsburgh July 1999 ( adm.cs.cmu.edu (Postscript)).
  5. Lahres, Rayman: Practical book object orientation . Pages 153-189, see literature
  6. ^ Robert C. Martin: The Interface Segregation Principle . Object Mentor, 1996 ( objectmentor.com (PDF)).
  7. ^ Robert C. Martin: Object Oriented Design Quality Metrics . an analysis of dependencies. In: C ++ Report . September / October 1995 edition. October 28, 1994 (English, objectmentor.com (PDF) [accessed July 26, 2010]).
  8. ^ Robert C. Martin: The Dependency Inversion Principle . Object Mentor, May 1996 ( objectmentor.com (PDF)).
  9. ^ Karl J. Lieberherr, I. Holland: Assuring good style for object-oriented programs . In: IEEE software . S. 38-48 (English, ist.psu.edu [accessed February 27, 2010]).
  10. ^ Bertrand Meyer: Object Oriented Software Construction . Prentice Hall, 1988, ISBN 978-0-13-629155-8 , pp. 18 .
  11. ^ Bertrand Meyer: Object Oriented Software Construction . Prentice Hall, 1988, ISBN 978-0-13-629155-8 , pp. 53-54 .
  12. ^ Bertrand Meyer: Object Oriented Software Construction . Prentice Hall, 1988, ISBN 978-0-13-629155-8 , pp. 54-55 .
  13. ^ Bertrand Meyer: Object Oriented Software Construction . Prentice Hall, 1988, ISBN 978-0-13-629155-8 , pp. 55-57 .
  14. ^ Bertrand Meyer: Object Oriented Software Construction . Prentice Hall, 1988, ISBN 978-0-13-629155-8 , pp. 61-63 .
  15. ^ Bertrand Meyer: Object Oriented Software Construction . Prentice Hall, 1988, ISBN 978-0-13-629155-8 , pp. 252-253 .
  16. ^ Robert C. Martin: Agile Software Development - Principles, Patterns and Practices . Pearson Education, ISBN 0-13-597444-5 , pp. 255 .
  17. ^ A b Robert C. Martin: Granularity . In: IEEE software . December 1996, p. 6 (English, objectmentor.com (PDF) [accessed April 24, 2010]).
  18. ^ Robert C. Martin: Granularity . In: IEEE software . December 1996, p. 5 (English, objectmentor.com (PDF) [accessed April 24, 2010]).
  19. ^ Robert C. Martin: Granularity . In: IEEE software . December 1997, p. 8–11 (English, objectmentor.com (PDF) [accessed April 24, 2010]).
  20. ^ Robert C. Martin: Granularity . In: IEEE software . December 1997, p. 11–14 (English, objectmentor.com (PDF) [accessed April 24, 2010]).