GRASP – General Responsibility Assignment Software Patterns Explained

Introduction

I recently noticed that a lot of attention is paid to SOLID principles. And this is very good thing because it is the total basis of Object-Oriented Design (OOD) and programming. For developers of object-oriented languages, knowledge of the SOLID principles is a requirement for writing code which is characterized by good quality. There are a lot of articles and courses on these rules, so if you do not know them yet, learn them as soon as possible.

On the other hand, there is another, less well-known set of rules regarding object-oriented programming. It’s called GRASP – General Responsibility Assignment Software Patterns (or Principles). There are far fewer materials on the Internet about this topic, so I decided to bring it closer because I think the principles described in it are as important as the SOLID principles.

Disclaimer: This post is inspired and based on awesome Craig Larman’s book: Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development. Although the last edition was released in 2004, according to me, the book is still up-to-date and explains perfectly how to design systems using object-oriented languages. It’s hard to find the better book about this subject, believe me. It is not book about UML, but you can learn UML from it because it is good explained too. Must-have for each developer, period.

The Responsibility in Software

Responsibility in software is a very important concept and not only concerns classes but also modules and entire systems. Thinking in terms of responsibilities is popular way to think about design of the software. We can always ask questions like:

– What is the responsibility of this class/module/component/system?
– Is it responsible for this or is it responsible for that?
– Is Single Responsibility Principle violated in this particular context?

But to answer these kind of questions we should ask one, more fundamental question: what does it mean that something is responsible in the context of the software?

Doing and Knowing

As it is proposed by Rebecca Wirfs-Brock in Object Design: Roles, Responsibilities, and Collaborations book and her RDD approach a responsibility is:

an obligation to perform a task or know information

As we see from this definition we have here a clear distinction between behavior (doing) and data (knowing).

Doing responsibility of an object is seen as:
a) doing something itself – create an object, process data, do some computation/calculation
b) initiate and coordinate actions with other objects

Knowing responsibility of an object can be defined as:
a) private and public object data
b) related objects references
c) things it can derive

Let’s see an example:

If you want more information about responsibilities in software and dig into Responsibility-Driven Design you can read it directly from Rebecca’s Wirfs-Brock book or this PDF.

Ok, now we know what the responsibility in context of software is. Let’s see how to assign this responsibility using GRASP.

GRASP

GRASP is set of exactly 9 General Responsibility Assignment Software Patterns. As I wrote above assignment of object responsibilities is one of the key skill of OOD. Every programmer and designer should be familiar with these patterns and what is more important – know how to apply them in everyday work (by the way – the same assumptions should apply to SOLID principles).

This is the list of 9 GRASP patterns (sometimes called principles but please, do not focus on naming here):

1. Information Expert
2. Creator
3. Controller
4. Low Coupling
5. High Cohesion
6. Indirection
7. Polymorphism
8. Pure Fabrication
9. Protected Variations

NOTE: All Problem/Solution paragraphas are quotes from Craig Larman’s book. I decided that it would be best to stick to the original.

1. Information Expert

Problem: What is a basic principle by which to assign responsibilities to objects?
Solution: Assign a responsibility to the class that has the information needed to fulfill it.

In following example Customer class has references to all customer Orders so it is natural candidate to take responsibility of calculating total value of orders:

This is the most basic principle, because the truth is – if we do not have the data we need, we would not be able to meet the requirement and assign responsibility anyway.

2. Creator

Problem: Who creates object A?
Solution: Assign class B the responsibility to create object A if one of these is true (more is better)
– B contains or compositely aggregates A
– B records A
– B closely uses A
– B has the initializing data for A

Going back to the example:

As you can see above Customer class compositely aggregates Orders (there is no Order without Customer), records Orders, closely uses Orders and has initializing data passed by method parameters. Ideal candidate for “Order Creator”. 🙂

3. Controller

Problem: What first object beyond the UI layer receives and coordinates “controls” a system operation?
Solution: Assign the responsibility to an object representing one of these choices:
– Represents the overall “system”, “root object”, device that the software is running within, or a major subsystem (these are all variations of a facade controller)
– Represents a use case scenario within which the system operation occurs (a use case or session controller)

This principle implementation depends on high level design of our system but general we need always define object which orchestrate our business transaction processing. At first glance, it would seem that the MVC Controller in Web applications/API’s is a great example here (even the name is the same) but for me it is not true. Of course it receives input but it shouldn’t coordinate a system operation – it should delegate it to separate service or Command Handler:

4. Low Coupling

Problem: How to reduce the impact of change? How to support low dependency and increased reuse?
Solution: Assign responsibilities so that (unnecessary) coupling remains low. Use this principle to evaluate alternatives.

Coupling is a measure how one element is related to another. The higher the coupling, the greater the dependence of one element to the another.

Low coupling means our objects are more independent and isolated. If something is isolated we can change it not worrying that we have to change something else or wheter we would break something (see Shotgun Surgery). Use of SOLID principles are great way to keep coupling low. As you see in example above between CustomerOrdersController and AddCustomerOrderCommandHandler coupling remains low – they need only agree on command object structure. This low coupling is possible thanks to Indirection pattern which is described later.

5. High Cohesion

Problem: How to keep objects focused, understandable, manageable and as a side effect support Low Coupling?
Solution: Assign a responsibility so that cohesion remains high. Use this to evaluate alternatives.

Cohesion is a measure how strongly all responsibilities of the element are related. In other words, what is the degree to which the parts inside a element belong together.

Classes with low cohesion have unrelated data and/or unrelated behaviors. For example, the Customer class has high cohesion because now it does only one thing – manage the Orders. If I would add to this class management of product prices responsibility, cohesion of this class would drop significantly because price list is not directly related to Customer itself.

6. Indirection

Problem: Where to assign a responsibility to avoid direct coupling between two or more things?
Solution: Assign the responsibility to an intermediate object to mediate between other components or services so that they are not directly coupled.

This is where Mediator Pattern comes in to play. Instead of direct coupling:

we can use the mediator object and mediate between objects:

One note here. Indirection supports low coupling but reduces readability and reasoning about the whole system. You don’t know which class handles the command from the Controller definition. This is the trade-off to take into consideration.

7. Polymorphism

Problem: How handle alternatives based on type?
Solution: When related alternatives or behaviors vary by type (class), assingn responsibility for the behavior (using polymorphi operations) to the types for which the behavior varies.

Polymorphism is fundamental principle of Object-Oriented Design. In this context, principle is strongly connected with (among others) Strategy Pattern.

As it was presented above constructor of Customer class takes ICustomerUniquenessChecker interface as parameter:

We can provide there different implementations of this interface depending on the requirements. In general, this is very useful approach when we have in our systems different algorithms that have the same input and output (in terms of structure).

8. Pure Fabrication

Problem: What object should have the responsibility, when you do not want to viloate High Cohesion and Low Coupling but solutions offered by other principles are not appopriate?>
Solution: Assign a highly cohesive set of responsibilites to an artifical or convenience class that does not represent a problem domain conecept.

Sometimes it is realy hard to figure it out where responsibility should be placed. This is why in Domain-Driven Design there is a concept of Domain Service. Domain Services hold logic which are not related with one, particular Entity.

For example, in e-commerce systems we often have need to convert one currency to another. Sometimes it is hard to say where this behavior should be placed so the best option is to create new class and interface:

This way we support both High Cohesion (we are only converting currencies) and Low Coupling (client classes are only dependent to IForeignExchange interface). Additionally, this class is reusable and easy to maintain.

9. Protected Variations

Problem: How to design objects, subsystems and systems so that the variations or instability in these elements does not have an undesirable impact on other elements?
Solution: Identify points of predicted variation or instability, assign responsibilities to create a stable interface around them.

In my opinion, this is the most important principle which is indirectly related to the rest GRASP principles. Currently, one of the most important software metrics is the ease of change. As architects and programmers we must be ready for ever-changing requirements. This is not optional and “nice to have” quality attribute – it is “must-have” and our duty.

Fortunately, we are armed with a lot design guidelines, principles, patterns and practices to support changes on different levels of abstraction. I will mention only a few (already beyond the GRASP):

– SOLID principles, especially the Open-Close principle (but all of them supports change)
– Gang of Four (GoF) Design Patterns
Encapsulation
Law of Demeter
Service Discovery
– Virtualization and containerization
– asynchronous messaging, Event-driven architectures
Orchestration, Choreography

As iterative software development process is more suitable today because even we are forced to change something once, we can draw conclusions and be prepared for future changes at a lower cost.

Fool me once shame on you. Fool me twice shame on me.

Summary

In this post I described one of the most fundamental Object-Oriented Design set of patterns and principles – GRASP.

Skilful management of responsibilities in software is the key to create good quality architecture and code. In combination with others patterns and practices is it possible to develop well-crafted systems which supports change and do not resist it. This is good, because the only thing that is certain is change. So be prepared.

Related posts

10 common broken rules of clean code

Company, don’t waste your programmers time

Introduction

In this post I would like to raise the subject of wasting programmers time which can be easily saved. What’s more, it is said time is money so we can save both! This post is especially for management people (managers, directors, CTOs) but developers should also think about whether they use their potential one hundred percent.

These days it is very hard to hire good-skilled and experienced programmer because there are few of them (comparing the demand on the market) and they cost a lot. So when the company finally manages to hire a programmer, what he can do to use this valuable resource effectively for the benefit of both sides (win-win rule)?

1. Provide him with the right equipment

There is nothing more annoying than a situation where you can’t honestly carry out your duties not because of you. I will mention only a few examples:
– slow, unstable or even not working internet connection.
– not working, not efficient computer.
– small, old, low resolution monitor.
– broken accessories like mouse, keyboard.

Nowadays, IT equipment compared to people’s earnings is very, very cheap. So one of the best thing company can do is investing in high performance hardware. Programmers need this, especially today when we need a lot of applications which have high requirements (not to mention all containerization and virtualization). I think high performance computer with at least 16GB RAM, 256-500GB SSD, i7 CPU and two FULL HD monitors should be a standard hardware for programmer. Trust me, this investment will return very quickly.

2. Provide him with the right tools

This is another misunderstanding for me. There are a lot of amazing applications which can boost people productivity, so why people do not use them? From ignorance, lack of money, maybe both?

I will give you an example of the best .NET extension tool – Resharper. This is plugin for Visual Studio which makes programming easier and more automatic in some cases. In my opinion it can save from 10% to 20% percent of programming time. At the time when I am writing this post it costs 299 euro (lifetime subscription without upgrades). You know the rate for the programmer’s hour so calculation of ROI I will left up to you. 😉

3. Provide him with the right environment

Does your work environment look like this?
The Ford assembly line in 1913. Source.

Work can be divided into two types: algorithmic and heuristic. An algorithmic work is one that is governed by procedures, schemes, standards and repeatability. You know what you need to do, how and with what. For example: work on the assembly line or the work of a cashier in a supermarket is just algorithmic. At the other end of the spectrum there is a heuristic work, one during which there is no clearly defined path, only you have to experiment, demonstrate your imagination and creativity to come up with a solution to a problem.

It’s not hard to guess what type of work is programming. So why companies try to put their employees in environments in which they are ineffective, for example big open spaces? I think something have gone wrong recently. They want to save on space but this is only illusory saving. People who mainly use their mind during their work need:
– quiet.
– peace.
– enough space at the desk.
– daylight.
– own place.
– coffee machine. 😉

If they don’t have the conditions I mentioned above, they will have a problem with concentration, creativity and effectiveness. Summarizing they will be less productive so work will take them a lot more time.

4. Create a development process

Every programmer should know:
– what are his tasks and what are the priorities.
– for what he is responsible, accountable, what should he consult and what to inform. See RACI matrix.
– what he can do and what can not.
– the Big Picture of current project.

Without well-defined process developers will not know these things (certainly not everything). None of the them should wonder what to do now, who to assign the task to or who to consult. It should be defined clear and understandable workflow.

On the other hand, development process should be automated as much as possible. From the management perspective, you should use project management software and try to eliminate ineffective communication channels like emails. For technical reasons, you should use continuous integration/deployment/delivery practices because machines are much better in repetitive tasks (and they cost less as I mentioned earlier), while people should focus on creative and difficult to automate tasks.

5. Organize only useful meetings

A lot of time can be lost at meetings. Meetings are usually too long, they have too many participants and there are often off-topics that are not related to our work. I am not suggesting abandoning meetings now but organizing them in a thoughtful way, i.e. meeting should:
– have a reason.
– be as short as possible.
– have earlier prepared agenda.
– only have interested participants who will give value to this meeting.
– start and end on time.

So remember, one useless half-hour meeting per day with 4 participants and on Thursday whole man-day is lost. Think about it the next time you organize a meeting.

6. Let the programmer to rest

The one of the famous personal development coach, Stephen Covey, described in his book The 7 Habits of Highly Effective People the formula for effectiveness:

Effectiveness lies in the balance – what I call the P/PC Balance. P stands for production of desired results, the golden eggs. PC stands for production capability, the ability or asset that produces the golden eggs.

From this quote follows: you can produce more either by work more or work better/smarter but you have to keep balance. If person is tired because of constant overtimes his production capability (PC) will be very low as well as his efficiency. So it is better in this situation let him to rest to charge the batteries.

7. Give him opportunity to grow

We can constantly improve our production capability through learning and training. But when programmer can do it? Does it always have to be time out of work?

I think it should not be like this. This industry is growing so fast that if programmer want to be up to date he should train himself AND his efforts should be supported by his company. Supporting can be in different ways: sending to courses, buying books, organizing workshops, giving time to research and develop new things. It should be something, I think it is fair for both parties.

Summary

In conclusion, if you, company, don’t want to waste your programmer’s time at all, you must provide him with good hardware and tools, create appropriate supporting environment and development process and you must take care of his development and rest. Are there a lot of requirements? Of course! 🙂 But you do not have to do it right away, you can do it gradually. This is an investment but changes will be noticed quickly.

Start today, not tomorrow.