GRASP Design Patterns A.A. 2018/2019
Objectives Introducing design patterns Introduzione ai design pattern Designing objects and responsibilities GRASP design patterns
A long corridor
A passage room Does this room seem cozy? Would you like to stay there? Why? Light Proportions Symmetry Furnitures...
Example In the bedroom it might be helpful to have a armchair, perhaps near the window for reading. When spaces are more regular, the solution is to put the armchair in the corner. If the window is far, you need to provide a lamp.
An interior design pattern Descripting schema of a design pattern Context: genera situation in which we are carrying on a design project Problem: set of forces that are active in the context Solution: rule to apply in order to solve such forces Example: light point Forces We would like to sit up and be comfortable in a room We will be attracted by the light Solutions In the living room at least a window must be the light point If an armchair is far from a light point we must create one
Design patterns in architecture Each 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) A pattern is a recurrent solution to a certain known design problem, which occurs in a certain context Do you think patterns are relevant for software?
Benefits of Patterns Shared language of design Increases communication bandwidth Decreases misunderstandings Learn from experience Becoming a good designer is hard Understanding good designs is a first step Tested solutions to common problems Where is the solution applicable? What are the tradeoffs?
Design patterns in software A pattern describes a problem that occurs frequently, along with a recommended and well accepted solution to the problem Each pattern in software describes the relations among classes or objects needed to solve the design problem in a specific context Example: adapter, a pattern that enables the interaction among objects with are incompatibles
Example: Adapter Participants Adaptee: it defines the interface that requires to be adapted Target: it defines the interface we want to use Adapter: it adapts the interface Adaptee to the interface Target.
Antipatterns An antipattern is a common response to a recurring problem that is usually ineffective and risks being highly counterproductive. Example: interface bloat, when a interface incorporates too many operations on some data into an interface, only to find that most of the objects cannot perform the given operations.
Interface bloat
GRASP General Responsibility Assignment Software Patterns (or Principles), abbreviated GRASP, consist of guidelines for assigning responsibility to classes and objects in objectoriented design. Computer scientist Craig Larman states that "the critical design tool for software development is a mind well educated in design principles. It is not UML or any other technology." Thus, GRASP are really a mental toolset, a learning aid to help in the design of objectoriented software.
List of GRASP patterns Information Expert Creator Low Coupling High Cohesion Controller Polymorphism Pure Fabrication Indirection Protected variations (Law of Demeter)
Pattern Information expert Information expert (also expert or the expert principle) is a principle used to determine where to delegate responsibilities. These responsibilities include methods, computed fields, and so on. Using the principle of information expert, a general approach to assigning responsibilities is to look at a given responsibility, determine the information needed to fulfill it, and then determine where that information is stored. Information expert will lead to placing the responsibility on the class with the most information required to fulfill it.
Information expert as problem/solution Problem: What is the principle to follow for assigning a responsibility to a class? Solution: The responsibility must be assigned to the class that owns the information required to get the responsibility
Information expert example Which class should compute the total sum of a receipt provided by a POS application?
Information expert example (contd.) We need all SalesLineItem instances and subtotals. Sales knows that, hence Sales is the expert class
Sale as a CRC cards Class name: Sale Superclass: Subclasses: Class name: SaleLineItem Superclass: Subclasses: Responsibilities Collaborations Responsibilities Collaborations Knows the total amount of a sale SaleLineItem Knows the subtotal amount of a sale ProductDescription Class name: ProductDescription Responsibilities Knows the price of a product Superclass: Subclasses: Collaborations
Information Expert: pros and cons Pros: Preserve encapsulation hide the values or state of a structured data object inside a class, preventing unauthorized parties' direct access to them Foster decoupling and cohesion coupling is the degree of interdependence between software modules. Coupling is usually contrasted with cohesion. Low coupling often correlates with high cohesion, and vice versa. Low coupling is often a sign of a wellstructured computer system and a good design, and when combined with high cohesion, supports the general goals of high readability and maintainability cohesion refers to the degree to which the elements inside a module belong together. In one sense, it is a measure of the strength of relationship between the methods and data of a class and some unifying purpose or concept served by that class. In another sense, it is a measure of the strength of relationship between the class s methods and data themselves. Cons: it might introduce unnecessary complexity
Pattern Creator Creation of objects is one of the most common activities in an objectoriented system. Which class is responsible for creating objects is a fundamental property of the relationship between objects of particular classes.
Creator as problem/solution Problem: What is responsible for creating a class? Solution: B should be responsible for creating instances of class A if one, or preferably more, of the following apply: Instances of B contain or compositely aggregate instances of A Instances of B record instances of A Instances of B closely use instances of A Instances of B have the initializing information for instances of A and pass it on creation
Creator example Who creates squares?
Creator example (contd.)
Creator discussion Creating objects is a very common responsibility An object becomes a creator when one or more of the following situations hold. The object aggregates multiple parts The object is a container of contents The object is a recorder The object is able to communicate creation data
Creator: contraindications It might complicate the project Performance might decrease Inappropriate for creating instances of a family of similar classes conditionally
Pattern LowCoupling Coupling is a measure of how strongly one element is connected to, has knowledge of, or relies on other elements. Low coupling is an evaluative pattern that dictates how to assign responsibilities to support lower dependency between the classes change in one class having lower impact on other classes higher reuse potential.
Lowcoupling as problem/solution Problem: How to reduce modification by fostering reuse? Solution: Assigning responsibilities so that the degree of coupling is kept low
This scenario violates lowcoupling
LowCoupling: pros and cons Pros: Comprehensibility: classes can be understood more easily Maintainability: classes are not affected by changes to other components Reusability: classes can be reused in different systems more easily Cons: it is better to keep already tested and stable classes coupled (e.g. software libraries, legacy systems)
Controller: problem Who is responsible for handling events coming from an external UI?
Controller: solution The responsibility of handling the events generated by an external UI can be assigned to: A single representative of the system (i.e. a façade) A session controller for each use case an object representing the coordinator should be identified
Pattern Controller A controller object is a nonuser interface (UI) object responsible for receiving or handling a system event. The controller is defined as the first object beyond the UI layer that receives and coordinates ("controls") a system operation. The controller should delegate the work that needs to be done to other objects; it coordinates or controls the activity. It should not do much work itself.
Controller: example In a use case scenario named Buy Items the following events should be managed: enteritem() endsale() makepayment() Who is responsible for the event enteritem()?
Controller: example (contd.)
Bloated Controllers Controller class is called bloated, if The class is overloaded with too many responsibilities. Solution: add more controllers The Controller class is performing many tasks instead of delegating to other class. Solution controller class has to delegate things to others
Who is the controller?
High cohesion: problem Cohesion is the measure of the correlation among the responsibility assigned to a class How to design classes with a high cohesion degree?
High cohesion: solution How are the operations of any element are functionally related? Related responsibilities in to one manageable unit Prefer high cohesion Clearly defines the purpose of the element Benefits Easily understandable and maintainable Code reuse Low coupling
High cohesion pattern High cohesion is an evaluative pattern that attempts to keep objects appropriately focused, manageable and understandable. High cohesion is generally used in support of low coupling. High cohesion means that the responsibilities of a given element are strongly related and highly focused. Breaking programs into classes and subsystems is an example of activities that increase the cohesive properties of a system. Alternatively, low cohesion is a situation in which a given element has too many unrelated responsibilities. Elements with low cohesion often suffer from being hard to comprehend, hard to reuse, hard to maintain and averse to change.
Is this object associated with high cohesion?
Is this object associated with high cohesion? Canonical example of low cohesion NO! Can we design it better?
High cohesion: example
High cohesion: pros and cons Pros: Comprehensibility and reusability Complementary with low coupling as it suggests designers to avoid putting a large number of unrelated responsibilities within a single class Maintainability Cons: Sometimes it might be desirable to have a single object (e.g. a server) with lower cohesion. In this case the objective is to design such an object as a interface for many operations in order to boost efficiently, i.e. to many communications among objects can decrease performance.
Polymorphism: problem How to handle related but varying elements based on element type? Example: Modelling geometric different shapes that a UI might present
Polymorphism: solution When alternatives behaviours change with type (i.e. class) the responsibilities are assigned to those types that alternatives or behaviours change for. This mechanism is enabled by polymorphic operations
Polymorphism: example
Pure Fabrication: problem In case we use Information Expert and high cohesion and/or low coupling are violated is there any way for assigning responsibilities?
Pure Fabrication: solution We introduce an artificial class for convenience, which is highly cohesive and lowly coupled
Pure Fabrication Fabricated class/ artificial class assign set of related responsibilities that doesn't represent any domain object. Provides a highly cohesive set of activities. Behavioral decomposed implements some algorithm. Benefits: High cohesion, low coupling and reuse
Pure Fabrication: example Suppose we have a Shape class and we must store the shape data in a database. If we put this responsibility in Shape class, there will be many database related operations thus making Shape incohesive. So, create a fabricated class DBStore which is responsible to perform all database operations Similarly LogInterface which is responsible for logging information is also a good example for Pure Fabrication
Pure fabrication: example Participants Adaptee: it defines the interface that requires to be adapted Target: it defines the interface we want to use Adapter: it adapts the interface Adaptee to the interface Target.
Indirection: problem How can we avoid a direct coupling between two or more elements.
Indirection: solution Indirection introduces an intermediate unit to communicate between the other units, so that the other units are not directly coupled. Benefits: low coupling
Indirection: bad example Any possible improvement?
Indirection: good example
Protected Variations: problem How to avoid impact of variations of some elements on the other elements?
Protected Variations: solution It provides a well defined interface so that the there will be no side effect on other units. It provides flexibility and protection from variations. It provides more structured design. Note: it is a generalisation of the Law of Demeter
Law of Demeter The Law of Demeter (LoD) or principle of least knowledge is a design guideline for developing software, particularly objectoriented programs. Each unit should have only limited knowledge about other units: only units "closely" related to the current unit. Each unit should only talk to its friends; don't talk to strangers. Only talk to your immediate friends.
Characteristics of a good pattern Provides a solution to a problem Describes a relation The solution is not trivial Both problem and solution are well known and accepted by the community Useful and elegant Follows general design principles
SOLID principles Single responsibility principle a class should have only a single responsibility (high cohesion) Open/closed principle software entities should be open for extension, but closed for modification. Liskov substitution principle objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. Interface segregation principle many clientspecific interfaces are better than one generalpurpose interface. Dependency inversion principle one should depend upon abstractions, not concretions.
Questions