Especially for the start of a new set for the course “Architecture and Design Patterns” I continue my series of publications about GRASP templates.
Described in Craig Larman’s book “Applying UML and patterns, 3rd edition”, GRASP patterns are generalizations of GoF patterns, as well as a direct consequence of the principles of OOP. They complement the missing step in the logical ladder that allows you to derive GoF patterns from OOP principles. GRASP patterns are not design patterns (like GoF’s), but the fundamental principles of allocating responsibility between classes. As practice shows, they are not very popular, but the analysis of the designed classes using the full set of GRASP patterns is a prerequisite for writing good code.
The complete list of GRASP templates consists of 9 elements:
- Information Expert
- Low coupling
- High cohesion
Different behaviors should be handled based on type, allowing for replacement of system parts.
It is proposed to distribute responsibilities between classes using polymorphic operations, leaving each external system with its own interface. As an example, we can cite standardized libraries, or application configuration by connecting certain plugins for different customers according to their needs.
The presence of a switch construction in the code is a violation of this principle, switches and are subject to refactoring.
Overuse of polymorphism leads to over-complication of the code and is generally discouraged.
Low coupling and high cohesion must be ensured. For this purpose, it may be necessary to synthesize an artificial essence. The Pure Fabrication pattern suggests that you shouldn’t hesitate to do this. As an example, consider the facade to the database. This is a purely artificial object that has no analogues in the subject area. In general, any facade is Pure Fabrication (unless it is, of course, an architectural facade in the corresponding application).
It is necessary to distribute responsibilities between objects, avoiding direct binding. To do this, you can assign responsibilities for communication between components or services to an intermediate object.
Translated into Russian, the pattern implies the following: any object in the code must be called through its interface (the same intermediate object).
Indirection is the most key pattern listed in this article. First, it is very simple in terms of security. Second, it gives the code tremendous flexibility without being premature optimizations due to the first point. If all classes call each other through interfaces, then this leads to the ability to “rip” any piece from the system and reuse it elsewhere. Moreover, the use of Indirection allows you to add almost any template of a gang of four without too much straining or refactor classes.
It is necessary to design the system so that changes in some of its elements do not affect others. As a solution, it is proposed to identify points of possible changes or instability and assign responsibilities in such a way as to ensure the stable operation of the system.
In fact, this is not a pattern, but a goal achieved by following the rest of the patterns.
GRASP templates consist of 8 patterns:
- Information Expert – we process information where it is contained.
- Creator – we create objects where they are needed.
- Controller – we move the multithreading logic into a separate class or component.
- Low Coupling 5) High Cohesion – we design classes with homogeneous business logic and a minimum number of connections between themselves.
- Polymorphism – we arrange various options for the system’s behavior in the form of polymorphic calls, if necessary.
- Pure Fabrication – do not hesitate to create classes that have no analogue in the subject area, if it is necessary to comply with Low Coupling and High Cohesion.
- Indirection – we call any class through its interface.
- Protected Variations – applying all of the above, we get a code resistant to changes.
- Architecture for developers and admins: who needs what skills?