GRASP - General Responsibility Assignment Software Patterns Explained

grasp general responsibility assignment

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 is set of exactly 9 G eneral R esponsibility A ssignment S oftware P atterns. 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):

  • Information Expert
  • Low Coupling
  • High Cohesion
  • Indirection
  • Polymorphism
  • Pure Fabrication
  • 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.

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 concept .

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 Protected Variations principle says, first step is to identify points of predicted variation or instability . This is often very difficult because we sometimes don’t really know what would change and when. This is why 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.

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 See all blog posts

grasp general responsibility assignment

  • System Design Tutorial
  • What is System Design
  • System Design Life Cycle
  • High Level Design HLD
  • Low Level Design LLD
  • Design Patterns
  • UML Diagrams
  • System Design Interview Guide
  • Crack System Design Round
  • System Design Bootcamp
  • System Design Interview Questions
  • Microservices
  • Scalability
  • Object-Oriented Analysis and Design(OOAD)
  • OOAD Full Form
  • Object Oriented Analysis in Object Oriented Analysis & Design
  • Object Oriented Paradigm in Object Oriented Analysis & Design(OOAD)
  • Object Oriented System | Object Oriented Analysis & Design
  • Object Model | Object Oriented Analysis & Design
  • Object Oriented Principles in OOAD
  • What are the Object Oriented Analysis and Design(OOAD) Phases?
  • Booch Methodology in Object-Oriented Analysis and Design(OOAD)

GRASP Design Principles in OOAD

  • Aggregation in OOAD
  • Unified Process in OOAD

In Object-Oriented Analysis and Design (OOAD) , General Responsibility Assignment Software Patterns (GRASP) play a crucial role in designing effective and maintainable software systems. GRASP offers a set of guidelines to aid developers in assigning responsibilities to classes and objects in a way that promotes low coupling, high cohesion, and overall robustness. By understanding and applying GRASP principles, developers can create software solutions that are flexible, scalable, and easier to maintain over time.

grasp-banner

Important Topics for GRASP Design Principles in OOAD

What are GRASP Principles?

Importance in ooad, grasp principles and their examples, benefits of grasp, challenges of grasp.

GRASP, which stands for General Responsibility Assignment Software Patterns, includes several principles that guide the allocation of responsibilities in object-oriented design. These principles include:

GRASP-Principles

  • Creator: Assign the responsibility of creating instances of a class to the class that has the most knowledge about when and how to create them.
  • Information Expert: Assign a responsibility to the class that has the necessary information to fulfill it, promoting high cohesion and minimizing coupling.
  • Low Coupling: Aim for classes to have minimal dependencies on each other, facilitating easier maintenance and flexibility in the system.
  • High Cohesion: Ensure that the responsibilities within a class are closely related and focused, enhancing readability, maintainability, and reusability.
  • Controller: Assign the responsibility of handling system events or coordinating activities to a controller class, promoting centralized control and avoiding cluttered classes.
  • Pure Fabrication: Introduce new classes to fulfill responsibilities without violating cohesion and coupling principles, promoting cleaner and more maintainable designs.
  • Indirection: Use intermediaries or abstractions to decouple classes and promote flexibility in design.
  • Polymorphism: Utilize inheritance and interfaces to enable multiple implementations of behaviors, allowing for flexible and extensible systems.

By applying these GRASP principles, developers can create object-oriented designs that are robust, maintainable, and adaptable to changing requirements.

In Object-Oriented Analysis and Design (OOAD), GRASP principles hold significant importance as they provide a framework for designing systems with clarity, flexibility, and maintainability. Here’s why they are essential:

  • Clarity of Design: GRASP principles help in organizing classes and responsibilities in a way that makes the design more understandable. Clear responsibilities assigned to classes make it easier for developers to comprehend the system’s architecture.
  • Low Coupling, High Cohesion: GRASP encourages low coupling between classes, meaning that classes are less dependent on each other. This leads to more modular and reusable code. Additionally, high cohesion ensures that each class has a clear and focused purpose, making the system easier to maintain and modify.
  • Flexible Design: By following GRASP principles such as Indirection and Polymorphism, the design becomes more flexible and adaptable to changes. Indirection allows for the introduction of intermediaries, which can simplify complex interactions, while Polymorphism enables the use of multiple implementations for behaviors, facilitating extensibility.
  • Scalability : GRASP principles contribute to the scalability of the system by promoting a design that can accommodate future changes and enhancements without significant refactoring. This scalability is vital as systems evolve and grow over time.
  • Ease of Maintenance: With clear responsibilities assigned to classes and well-defined relationships between them, maintaining the system becomes more straightforward. Developers can quickly identify where changes need to be made and can do so without inadvertently affecting other parts of the system.

General Responsibility Assignment Software Patterns (GRASP) are a set of guidelines used in Object-Oriented Analysis and Design (OOAD) to assign responsibilities to classes and objects effectively. Let’s explore each principle in depth with an example scenario:

Assign the responsibility for creating instances of a class to the class itself or to a related factory class.

For Example:

Consider a scenario where you are designing a system for managing a library. In this system, when a new book is added to the library, a `Book` object needs to be created. The responsibility for creating `Book` objects should lie with a class like `Library` or a separate `BookFactory` class. This ensures that the logic for creating `Book` objects is centralized and encapsulated, making it easier to manage.

2. Information Expert

Assign a responsibility to the class that has the necessary information to fulfill it.

Continuing with the library management system, when a user wants to borrow a book, the responsibility of checking if the book is available should lie with the `Book` class itself. The `Book` class contains information about its availability and can perform the necessary checks without needing to rely on other classes. This promotes high cohesion and reduces coupling between classes.

3. Low Coupling

Aim for classes to have minimal dependencies on each other.

In the library management system, suppose there is a `LibraryCatalog` class responsible for managing the catalog of books. Instead of directly accessing the `Book` class to check availability, the `LibraryCatalog` class can rely on an interface, such as `Searchable`, implemented by `Book`. This way, `LibraryCatalog` remains loosely coupled with `Book`, allowing for easier maintenance and changes.

4. High Cohesion

Ensure that responsibilities within a class are closely related and focused.

In the library management system, the `Book` class should have cohesive responsibilities related to managing book details, such as title, author, and availability. Responsibilities unrelated to book management, such as user authentication, should be handled by separate classes. This ensures that each class is focused on a specific aspect of the system, promoting clarity and maintainability.

5. Controller

Assign the responsibility of handling system events or coordinating activities to a controller class.

In a web application for a library, when a user requests to borrow a book, the responsibility of handling this request and coordinating the necessary actions should lie with a `BorrowBookController` class. This controller class would interact with other classes, such as `Book`, `User`, and `Library`, to facilitate the borrowing process. By centralizing control logic in a controller class, the system becomes more organized and easier to manage.

6. Pure Fabrication

Introduce new classes to fulfill responsibilities without violating cohesion and coupling principles.

Suppose the library management system needs to send email notifications to users when they borrow or return books. Instead of adding email sending logic directly to the `Book` or `User` classes, a separate `NotificationService` class can be created. This `NotificationService` class acts as a pure fabrication responsible for sending email notifications, maintaining low coupling and high cohesion in the system.

7. Indirection

Use intermediaries or abstractions to decouple classes and promote flexibility in design.

In the library management system, if multiple classes need to access book information, an `BookRepository` interface can be introduced. Classes that need access to book data can depend on the `BookRepository` interface rather than directly on the `Book` class. This allows for flexibility in how book information is retrieved, facilitating easier changes and adaptations in the future.

8. Polymorphism

Utilize inheritance and interfaces to enable multiple implementations of behaviors.

Continuing with the library management system, suppose there are different types of books, such as `FictionBook` and `NonFictionBook`, each with its own borrowing rules. By defining a common interface, `Book`, and implementing it in the `FictionBook` and `NonFictionBook` classes, polymorphism allows the borrowing process to be handled uniformly regardless of the book type. This promotes code reuse and simplifies the handling of different book types within the system.

GRASP (General Responsibility Assignment Software Patterns) offers several benefits in Object-Oriented Analysis and Design (OOAD), contributing to the development of robust and maintainable software systems such as:

  • Clarity and Understandability: GRASP principles provide a clear and structured approach to assigning responsibilities to classes and objects. This clarity enhances the overall understandability of the system’s design, making it easier for developers to grasp the architecture and functionality.
  • Flexibility and Adaptability: By adhering to GRASP principles such as Low Coupling, High Cohesion, and Polymorphism, designs become more flexible and adaptable to changes in requirements. The modular and loosely coupled nature of the system allows for easier modification and extension without causing widespread ripple effects.
  • Promotion of Best Practices: GRASP encapsulates best practices and design guidelines derived from years of experience in software engineering. By following these principles, developers can ensure that their designs adhere to industry standards and best practices, leading to higher-quality software.
  • Maintainability and Scalability : GRASP promotes designs that are easier to maintain and scale. Clear responsibilities assigned to classes and objects facilitate maintenance activities such as debugging, refactoring, and adding new features. Additionally, the modular nature of GRASP designs allows for seamless scalability as the system grows and evolves over time.
  • Enhanced Reusability: GRASP principles encourage the creation of classes and objects with well-defined responsibilities and interfaces. This promotes code reusability, as components can be easily reused in different parts of the system or in entirely new projects, leading to increased productivity and reduced development time.

While GRASP (General Responsibility Assignment Software Patterns) offers numerous benefits, it also presents some challenges that developers may encounter during the design and implementation phases of software development:

  • Complexity: Applying GRASP principles effectively requires a deep understanding of object-oriented design concepts and practices. For developers who are new to these principles or lack experience in OOAD, grasping and implementing GRASP patterns can be challenging, leading to potential design complexities and errors.
  • Subjectivity: Determining the most appropriate responsibility assignment for classes and objects can be subjective and open to interpretation. Different developers may have varying perspectives on how to apply GRASP principles to a given problem, which can result in inconsistencies or disagreements within a development team.
  • Trade-offs: While GRASP aims to promote desirable design qualities such as low coupling, high cohesion, and flexibility, achieving these qualities often involves making trade-offs. For example, optimizing for low coupling may increase the complexity of communication between classes, while optimizing for high cohesion may lead to larger and more tightly coupled classes.
  • Context Sensitivity: GRASP principles are not one-size-fits-all solutions and must be adapted to the specific context of each software project. What works well for one project may not be suitable for another, depending on factors such as project size, domain complexity, team expertise, and development constraints.
  • Maintenance Overhead: While GRASP designs aim to enhance maintainability, poorly applied patterns or overly complex designs can actually increase maintenance overhead. Developers may struggle to understand and modify intricate designs, leading to higher costs and effort associated with maintenance tasks.

Please Login to comment...

Similar reads.

author

  • OOAD - Object Oriented Analysis and Design
  • System Design

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

Fluent C++

About Jonathan Boccara

Hello, my name is Jonathan Boccara, I'm your host on Fluent C++. I have been a developer for 10 years. My focus is on how to write expressive code . I wrote the book The Legacy Code Programmer's Toolbox . I'm happy to take your feedback, don't hesitate to drop a comment on a post, follow me or get in touch directly !

Jonathan Boccara's blog

Recent Posts

  • Usage First, Implementation After: A Principle of Software Development
  • Design Patterns VS Design Principles: Factory method
  • How to Store an lvalue or an rvalue in the Same Object
  • Copy-Paste Developments
  • Design Patterns VS Design Principles: Abstract Factory
  • How to Generate All the Combinations from Several Collections

grasp general responsibility assignment

GRASP: 9 Must-Know Design Principles for Code

In order to write code that is understandable, maintainable and that stands the test of time, one of the crucial skills that we all need to have is design .

What does code design mean? In my definition, doing code design means deciding which class (or more generally which component) is in charge of which responsibility.

The reason why this is so crucial is because, according to the above definition, code that is well designed is consistent and well organised, and code that is poorly designed is essentially a mess.

And understanding, adding or fixing something in a well organised structure is, as you can imagine, easier that in a mess.

The need for Patterns

Being able to decide where to assign any given responsibility is a make-or-break skill for your code. But how do we do that?

With Experience, of course!

After years of trials and errors, after paying the high prices of your design mistakes, after living in a messy code, you will end up realizing that some design choices tend to work better than others.

Or there is an easier way: capitalizing on the experience of others.

The question of choosing where to assign a responsibility in code has been around for decades, and has been thought over by thousands and thousands of developers in their day-to-day code. Probably thousands and thousands of mistakes have been made, and as many lessons have been drawn from those mistakes.

If we could benefit from this std::accumulate d experience, then we would stand on the shoulders of giants.

Luckily for us, a lot of this wisdom is available to us, and what’s more, synthesized into manageable bits that we can apply in our everyday life while coding: design principles .

Design principles are guidelines that help us take the right decisions when assigning responsibilities in our code.

There is a set of 9 such design principles: the GRASP principles .

The book where I learnt the design principles

GRASP stands for General Responsibility Assignment Software Principles. I think the words that carry the most meaning in this acronym are RA: Responsibility Assignment . This is exactly what we’re talking about.

I learnt those principle in Craig Larman’s book Applying UML and Patterns :

Applying UML and Patterns

Even though the book title mentions UML, the book is about object-oriented design in general, as Martin Fowler praised (this is on the book cover): “People often ask me which is the best book to introduce them to the world of OO design. Ever since I came across it, Applying UML and Patterns has been my unreserved choice.”

I recommend that you read at least the parts about the GRASP patterns in this book, if not all of it.

Let me go further: even if you should read both, I think that GRASP principles are a more useful reading than the popular GoF design patterns .

Why such a bold statement?

  • The GRASP principles will let you understand the rationale behind the GoF design patterns,
  • Some GoF design patterns are obscure and not used often (at least in my experience, take the “Bridge” pattern for example),
  • Some GoF patterns should be avoided most of the time (for example the “Singleton” pattern, which is essentially a global variable with no copy constructor),
  • You can apply the GRASP pattern to other things than classes. And with free functions being idiomatic to C++, this is particularly relevant for C++ developers.

Ssome of the GoF design patterns are indeed necessary to know (“Strategy” for example), so you should also read the GoF book (especially since it contains more than just a design patterns catalogue). But to me, GRASP is a more fundamental topic to read about.

The GRASP patterns

Let’s see what the 9 GRASP patterns are. I’ll make a brief summary of each one, and you can refer to the above book for more detailed discussions and examples.

  • Information expert

Let’s start by one that is quite natural: information expert . This principle recommends that if you have an operation to do, and this operations needs inputs, then you should consider putting the responsibility of carrying out this operation in the class that contains the inputs for it.

This helps keeping the data local, because if you put the operation somewhere else then the inputs will have to be carried over there, creating a relationship between the class that holds the input data (the “information expert”) and that new place. This would create coupling and be detrimental for encapsulation, thus creating complexity.

Granted, it’s a natural thing to do. But formalizing this as a principle still has several benefits. For example, if you feel that a design is not quite right, thinking about the information expert principle can help you pinpoint what was disturbing you in it. Also, it helps expressing your remarks in a code review.

The Creator principle gives guidelines as to which class B should be in charge of creating a certain type of objects A. The principle contains a set of rules, such as:

  • B contains or aggregates instances of A
  • B closely uses A
  • B has the inputs to construct A

The more rules are fulfilled, the better B is suited to instantiate objects of type A.

This goes a further than Information expert: it’s not just about having the input of the operation of construction, it’s about being “close” to the operation.

If you put together two part of the code that are semantically close (the construction of A, and the code that works a lot with A), then they become easier to reason about than if they were far apart.

  • Low coupling

Coupling happens between two parts of the code when one depends on the other. Coupling introduces complexity, if only because the code can then no longer be understood isolation.

Such dependencies can be explicit, in terms of a function call for example, and that’s unavoidable and often OK.

But other types of coupling are less sane and less visible, for example when a part of the code expects that another part has set a data member to a certain value.

The design principle of low coupling encourages to keep coupling low, and it can help in particular to choose between two designs: select the one that introduces the lower amount of coupling.

For more details about the various types of coupling and the various types of problems that coupling generates, refer to this dedicated article on coupling .

  • Protected variations

The principle of Protected variations is related to the one of Low coupling, because it helps reducing the impacts of the changes of the code of one part A on another part B. The code of part B is protected against the variations of the code of part A, hence the name of the pattern.

How do you achieve such a protection? By organizing the responsibilities around stable interfaces .

This is particularly relevant for code that tends to change often. Introducing an interface between this unstable part of the code and the rest of the codebase helps limiting the rippling effects of those frequent changes.

The principle of protected variations is, according to my understanding, very close to the concept of “anti-corruption layer” from Domain Driven Design .

  • Indirection

The Indirection pattern is another way to reduce coupling by creating an intermediary class (or any kind of component) between two classes A and B. This way, the changes in each one of A and B don’t affect the other one. The intermediary class absorbs the impact by adapting its code rather than A or B (or more other classes).

This relates a lot to the Adapter design pattern, even though the Adapter design pattern is rather made to connect two existing incompatible interfaces. But it also has the effect of protecting each one against the changes of the other.

Indirection looks a bit like Protected variations, as they both introduce a layer between components in order to reduce coupling.

According to my understanding, the difference between Protected variations and Indirection is that Protected variations is about designing interfaces in the existing components, whereas Indirection is about introducing a new component in the middle.

  • Polymorphism

The Polymorphism principle is an exhortation to use… polymorphism in your code.

Polymorphism is often seen as having a base class with virtual methods that defines an interface, and derived classes implementing this interface, but this is only one type of polymorphism. There are plenty of types of polymorphism (including templates for example) and I hope we’ll get to dive into this topic at some point on Fluent C++.

The usage for polymorsphism is when there are several ways to accomplish a task, and you want to decouple the clients of this task from the various pieces of code that implement the various ways to perform it.

The Polymorphism principle is very close to the GoF Strategy pattern, if not identical. It contributes to the Low Coupling principle.

  • High cohesion

The principle of High cohesion encourages to focus classes around one responsibility, and to have all its components oriented towards achieving this responsibility. This is the principle of “do one thing and do it well”.

The principle of high cohesion also applies to other elements of the code, such as functions, and also modules and systems.

This ties back well with the idea of having a well-organized code: a highly cohesive component lets you label it in your mind with “this is the part of the code that does X”. This allows better mental abstractions as well as code abstractions .

  • Pure fabrication

It is natural to represent in our code objects that map the reality of the domain that we’re trying to model. For example, if you’re working on a financial application, you can probably expect to encounter some classes called Transaction  or Portfolio in the code.

But sometimes you have a responsibility to assign, and it seems to not fit well in any domain class. And according to the principle of High cohesion above, you shouldn’t force a responsibility into a class that is already doing something else.

That’s when the principle of Pure fabrication comes into play: create a class that does not map to a domain object, and let it achieve this new responsibility in a cohesive way.

This principle is probably one of the hardest to guess, because it goes against our natural tendency to write code that represents the problem we’re trying to solve.

Here is an example of a pure fabrication: a UI Controller . This is such a common pattern that it was included in the 9 GRASP principles. Personal opinion: I would have kept this as an example of pure fabrication and not made a principle out of it.

The controller is the first non-UI component that receives the UI event and organizes the operations to react to this event. Indeed, that doesn’t map to any domain object, even if the UI itself can display domain concepts.

There are also other examples of pure fabrications in the GoF design patterns: for example, a Facade object is a pure fabrication.

Some principles are more fundamental than others

These were the 9 GRASP principles:

Those principles are not all of the same type. Some of those are overarching principles of good design. Some are techniques to put those principles into practice. Some are merely examples.

Also, they relates to some GoF design patterns, sometimes closely and sometimes the GoF patterns are implementations of the GRASP patterns.

In the next post, we will try to relate the GRASP patterns together.

You will also like

  • It all comes down to respecting levels of abstraction
  • How to Insulate a Toxic Api from the Rest of Your Code
  • To DRY or not to DRY?
  • Functional Programming Is Not a Silver Bullet
  • The Dangers of Coupling and How to Avoid Them

twitter

Do you know GRASP? Part 1 - Controller and Creator

Do you know GRASP? Part 1 - Controller and Creator

Mateusz Gajda's photo

Due to the fact that shorter posts are much better read, I decided to divide this topic into about 4 separate entries. Each concerning two or three patterns. Here is part one.

What is it?

GRASP - General Responsibility Assignment Software Patterns are 9 patterns, which will help you with adding a new responsibility to your current codebase. It could be very helpful because sometimes we don't know if this component is suitable for this functionality. Maybe we should create a new one? These 9 patterns can help us.

Problem: What the first object beyond the UI layer receives and coordinates “controls” a system operation?

Controllers image

In the software world, everything should have its responsibility. Models contain data, views present the data, repositories talk with databases, etc. Our systems are consistent with a lot of different objects and components. Very often they have to talk with each other, but we should take care of who's talking to whom. We do not want to let our objects talk directly to the database or other external services. We need something which takes this responsibility.

By simplifying our systems, we can say that they consist of many different use cases. Each use case needs to talk with a lot of different objects. We need to talk with the database, execute some operations on the domain object or retrieve some data from an external API. We need also a layer that will be responsible for handling user input.

That is why we a controller. An object which will be an entry point for our use case or system. It will be the first object beyond the UI layer. Very often it will be an application service or command handler if we are talking in the CQRS case. But, be careful! It isn't a controller such as in MVC. In MVC the controller is still part of a UI. In our case, it is the first object in the system. Let's take a look:

We have our application service called OrderService. Here we talk to our database through repositories. We retrieve a product which next is passed to our static factory method, which is part of our domain model Order. Next, we save a new order to the database. Thanks to that, the domain model doesn't know anything about the database. Additionally, the separation of the application code from the UI allows us to test our service more easily. In the case of the unit tests, we need only to mock our repositories. Here is how it looks like in our router:

Problem: Who creates object Y?

Lego creator

A common problem is definitely which object should be responsible for creating a class Y instance. Creating an object is an important process, so it is good to have defined rules that will make it easier to decide who should create a Y-instance. So let's take a look at these rules. Object X can create Y if the following conditions are true:

  • X aggregate/contains Y.
  • X has all the data required to create Y
  • X closely use Y

Thanks to these rules, it may turn out that we don't have to create a special factory to create the Y object. We can simply create it in object X. Why? Because X object needs Y object, it knows everything about how to create Y object so a new factory, in this case, will be useless.

Assume that we have a diary class that contains our notes. We can easily create our note inside the Diary , because it contains the list of Notes .

That's only 2 out of 9 patterns. In the next few parts, I'll introduce you to the next ones. I hope you'll find them useful and use them. If you have some question, feel free to write a comment :)

Software Modelling and Design

Table of contents, grasp: overview and interrelationship, responsibilities, information expert, low coupling, high cohesion, polymorphism, pure fabrication, indirection, protected variations, liskov substitution principle, don’t talk to strangers.

  • General Responsibility Assignment Software Patterns
  • pattern : named and well-known problem and solution that can be applied to new contexts, providing guidance for assessing trade-offs

Relationship between grasp principles

Benefits of patterns

  • capture expertise in an accessible, standardised manner
  • facilitate reuse of applying expertise
  • improve understandability and communication, by operating in a common language
  • inspiration for new solutions based on modifying existing patterns
  • responsibility : contract/obligation
  • do something itself, e.g. create an object, perform a calculation
  • initiate action in other objects
  • control/coordinate activities in other objects
  • know about private encapsulated data
  • know about related objects
  • know about things it can derive/calculate
  • low representational gap : domain model can be used to inspire knowing responsibilities
  • granularity : big responsibilities may take hundreds of classes/methods, while small ones may take a single method
  • responsibilities are distinct from methods: responsibilities are an abstraction, but methods fulfill responsibilities

collaboration : responsibiilities may involve multiple objects working together to fulfill a responsibility

  • Responsibility Driven Design: way to think about assigning responsibilities in OO software design, where the design comprises a community of collaborating responsible objects

Problem: who should be responsible for object creation?

Solution: Assign class B responsibility to create class A if:

  • B contains/aggregates A
  • B records A
  • B closely uses A
  • B has initialising data for A

The more of these that hold, the stronger the implication.

Benefits: Low coupling

Contraindications:

  • complex object creation, e.g. from a family of classes. Instead delegate to Factory

Problem: How to decide which class to assign a responsibility to?

  • Assign X the responsibility if X has the necessary information

Benefits: classes are

  • understandable
  • maintainable
  • the solution suggested by Information Expert may introduce problems with coupling and cohesion

Problem: how to support low dependency, low change impact, and increased reuse?

  • assign responsibilities such that coupling remains low.
  • use this to differentiate alternatives
  • coupling: degree of connection to other elements (whether knowledge/reliance on)

Benefits: code becomes

  • high coupling can be okay with stable code, e.g. standard libraries

Problem: How to keep objects focused, understandable, manageable, while suppporting low coupling?

  • functional cohesion: how strongly related and focused the responsibilities of an element are
  • low cohesion: class performs too many unrelated tasks. Code is hard to comprehend, reuse, maintain
  • choose between alternatives by assigning the reponsibility to X for maximum cohesion
  • easy to comprehend
  • non-functional requirements may require low cohesion, e.g. reduce processing overheads in high- performance computing

Cohesion in Monopoly

Problem: What first object beyond the UI layer receives and coordinates (i.e. controls) system operation?

  • facade controller: assign responsibility to a class representing the overall system
  • use case/session controller: assign responsibility to a class representing a use case scenario that deals with the event, named something like <UseCaseName><Handler|Coordinator|Session>

Benefits: prevent coupling between UI and application logic

  • break facade controller into multiple use case controllers
  • delegate work to other objects: only handle control in the controller itself

Facade vs Use Case Controller

  • Bad coupling of UI to domain layer

UI Coupling

  • Better UI coupling with controller

Better UI Coupling

  • conditional variation using switch-case statements requires heavy modification when new alternatives are added
  • viewing components in a client-server relationship, how can you replace a server component without affecting the client?

Solution: when related alternatives/behaviours vary by type (class), assign responibility for the behaviour using polymorphic operations to the types (classes) for which the behaviour varies.

  • i.e. give the same name to services in different objects
  • i.e. inheritance with generalisation/specialisation, or interfaces

Corollary: avoid testing the type of an object as part of conditional logic to perform varying alternatives based on type (class).

Guideline: unless there is a default behaviour in the superclass, declare a polymorphic operation in the superclass to be abstract .

Guideline: when should you consider using an interface?

  • introduce one when you want to support polymorphism without being committed to a class hierarchy
  • easy extension of code: you can introduce new implementations without affecting clients
  • avoid premature optimisation: consider future proofing with respect to realistic likelihood of variability before investing time in increased flexibility.

Problem: what object should have a responsibility, where you don’t want to violate high cohesion/low coupling, etc., but guidance from Expert etc. is not appropriate?

Solution: assign a highly cohesive set of responsibilities to an artificial/convenience class that doesn’t exist in the problem domain.

  • high cohesion
  • reuse potential
  • overuse where each class is basically a single function: produces high coupling and lots of message passing
  • where to assign responsibility to avoid direct coupling between 2+ things?
  • how to decouple to support low coupling and reuse potential?
  • assign responsibility to an intermediary, creating indirection between components
  • e.g. Adapter to protect inner design against external variation
  • “Most problems in computer science can be solved by another layer of indirection”
  • reduced coupling
  • high performance may need to reduce amount of indirection
  • “Most problems in performance can be solved by removing another layer of indirection”

Problem: How to design objects/systems so that variation in these elements doesn’t impact other elements?

  • identify points of predicted variation/instability
  • assign responsibilities to create a stable interface (in the broad sense of an access view) around them
  • variation point: variation in existing system/requirements
  • evolution point: speculative variations that may arise in the future
  • equivalent to Open-Closed principle : objects should be open for extension, and closed to modification that affects clients
  • equivalent to Information Hiding
  • new implementations don’t affect clients
  • low coupling
  • low cost of change
  • cost of future-proofing can outweigh benefits
  • reworking a brittle design as needed may be easier
  • novice developers produce brittle designs
  • intermediate developers produce overly fancy/flexible, generalised designs that never get used
  • expert developers choose with insight, balancing the cost of changing a simple/brittle design against its likelihood
  • software (methods, classes, …) referring to a type T (interface, abstract superclass) should work properly with any substituted implementation or subclass of T

Avoid creating designs that traverse long object structure paths and/or send messages to distant, indirect (stranger) objects. doing so makes designs fragile with respect to changes in object structures.

Within a method, messages should only be passed to:

  • this object ( self )
  • parameter of the method
  • attribute of this , (or element of collection that is an attribute of this )
  • object created in the method

Intent: : avoid coupling between client and knowledge of indirect objects, and connections between objects.

Guideline: The farther along a path one traverses, the more fragile it will be. Instead add a public operation to direct objects that hides how the information is obtained.

Edit this page .

GRASP - General Responsibility Assignment Software Principles

GRASP is an acronym for General Responsibility Assignment Software Principles. In this article, we want to point out these principles and how they work.

About GRASP #

This collection of object-oriented design rules goes back to Craig Larman and his book Applying UML and Patterns from 2004. Larman didn't invent any of these principles and ideas. He simply collected them.

GRASP is a pretty fancy name, but it somehow feels more like he wanted GRASP as the acronym and linked random words to reach it. Even though it is about to become an oldie, most rules collected under the GRASP banner are still helpful, and they should be essential to every developer's toolkit.

The General Responsibility Assignment Software Principles list nine principles:

  • Indirection
  • Information Expert
  • Low Coupling
  • High Cohesion
  • Polymorphism
  • Protected Variations
  • Pure Fabrication.

Though they are tailored to object-oriented design, some also apply for general software development as well.

I write about some things that are not from Larman's book but my own opinion and personal note. If you don't want the unaltered version, I suggest you read the original book: Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development

Controller #

The controller pattern is a common tool in object-oriented software design. Though most people might only associate the controller with the ancient architecture of the MVC (Model-View-Controller - Which is far too often used for cases it absolutely doesn't fit, but that's a story for a different day), the controller is a construct of itself.

As the name implies, the controller's work is to 'control' any events that are not directly related to the user interface. But controlling does not mean implementing. The controller consists of barely any logic. It is merely a mediator between the presentation layer and the (core) logic.

For example, if we imagine a simple web-shop application with the use case of "User X bought item A"; The controller's job would be to receive the signal of the pressed button from the UI and then run the necessary functions in the correct order. In the example at hand that could be to certify the payment and then initialize the shipment of the item.

Applying the principle of a controller can hugely improve your software's lifetime as it naturally creates a resilient layer regarding the interchangeability of code. If your UI or logic (unlikely, but possible), you can adjust your mappings instead of having to rewrite large chunks of code.

Also, it becomes incredibly easier to add other layers, such as an app at the overlaying presentation layer that uses a different UI but wants the same responses.

You can also think of a controller as a driver. It knows both parts it connects with one another but it acts merely as a broker. It consists of just a few and essential parts of code.

The creator is another pattern, but to me, it's more like an abstract idea than a real pattern. I must admit I rarely use this pattern intentionally.

A creator is a class that is responsible for creating instances of objects. Larman defines the following cases as B is the creator of A :

  • B aggregates A objects
  • B contains A objects
  • B records instances of A objects
  • B closely uses A Objects
  • B has the initializing data that will be passed to A when it is created

So an example for a creator could be a library that contains books. In that case, the library would be the creator of books, even though this sounds syntactically weird as natural language.

Indirection #

Indirection isn't a pattern but an idea. It is also of no use of its own, only in combination with other ideas such as low coupling. The goal behind indirection is to avoid direct coupling.

To pick up an earlier example the controller for example is a kind of indirection between the UI and the logic. Instead of coupling the UI directly to the logic, the controller decouples this layer and thereby comes with all the advantages of indirection.

Information Expert #

Another principle that falls into that area is the information expert. Sometimes it is just called the expert or the expert principle. The problem that should be solved with the information expert is the delegation of responsibilities. The information expert is a class that contains all the information necessary to decide where responsibilities should be delegated to.

You identify the information expert by analyzing which information is required to fulfill a certain job and determining where the most of this information is stored.

Low Coupling #

Low or loose coupling is the idea of creating very few links between modules. In GRASP it is an inter-module concept. Meaning it describes the flow between different modules, not the flow inside the modules.

Together with cohesion, it is the main reason upon which you make global design decisions such as "Where do we pack this module or function to?".

Low coupling is another concept that supports interchangeability. By making very few dependencies, very few code must be changed in case of a change.

High Cohesion #

in GRASP high (functional) cohesion is an intra-module concept. Meaning it describes the flow inside a certain module not the flow between modules.

The main reason behind high cohesion is the idea of reducing complexity. Instead of building large classes that have many functions that have few in common and are hard to maintain, the goal should be to create classes that fit exactly their defined purpose.

It's kind of hard to understand these abstract ideas but I also wasn't able to come up with a simple example, which is why I will write an extra article on the topic of low cohesion combined with high cohesion that is more detailed.

Polymorphism #

Polymorphism: πολυ ( polús )= many/multi, μορφή ( morphé ) = shape/form, ισμός ( ismós ) = imitation of.

Meaning, Polymorphism could be frankly translated as "something that imitates many forms". And that might be a concise but useless explanation to someone who has never heard of polymorphism.

Anyone who ever took a programming class is most likely familiar with polymorphism. But, it can be a tricky question to define it sensefully.

The idea again is to reduce complexity by imagining that objects follow simple and similar rules. Consider the following example: You have three objects A, B and C. B has the same methods and attributes but has an additional method X. C has the same methods and attributes as B, but an additional method Y.

The non-developer approach to this problem would be: "Great, as you said, we have 3 objects, so we have A, B, and C. Problem solved. You little stinky moron.". Yes, non-developers are insanely evil creatures.

But as a programmer, you instinctively know that we need the concept of inheritance here. A is an object, B is an object that inherits from A, and C is an object that inherits from B. Caution: Inheritance is not polymorphism - inheritance is an application that is allowed due to polymorphism.

To wrap it up: polymorphism is the concept of disassembling objects and ideas into their most atomic elements and abstracting their commonalities to build objects that can act like they were others. Not only to reduce complexity but also to avoid repetitions.

Protected Variations #

The protected variations pattern is a pattern used to create a stable environment around an unstable problem. You wrap the functionality of a certain element (class, interfaces, whatever) with an interface to then create multiple implementations by using the concept of polymorphism. Thereby you are able to catch specific instabilities with specific handlers.

An example of the protected variations pattern is working with sensory data, such as a DHT22, a common temperature and humidity sensor often used for Raspberry Pi or Arduino). The sensor is doing its job pretty well, but sometimes it will say the temperature just rose by 200 celsius or won't return any data at all. These are cases you should catch using the protected variations pattern to avoid false behavior of your program.

Pure Fabrication #

To reach low coupling and high cohesion, it is sometimes necessary to have pure fabrication code and classes. What is meant by that is that this is code that does not solve a certain real-world problem besides ensuring low coupling and high cohesion. This is often achieved by using factor classes.

Some last words #

Often when I look into programming principles, I feel mildly overwhelmed and discouraged. That's in part because some of these concepts are very hard to grasp if you never heard of them or got no practical use case in mind. But with a growing set of programming principles and best practices, you will see that all these principles refer to the same key statements and follow the same rules.

Unfortunately, in my opinion, there's also no substitution for learning it the hard way. Memorizing merely the key statements will eventually lead to greater school and university scores, but it will still be useless incoherent information without any practical use. Thereby, my advice is to learn as much as possible about code and its principles but also get as much hands-on experience as possible to abstract the key statements by yourself.

If you liked this post or are of any different opinion regarding any of the written, please let us know via mail or comment. Happy coding!

Author Yannic Schröer

DZone

  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
  • Manage My Drafts

Modern API Management : Dive into APIs’ growing influence across domains, prevalent paradigms, microservices, the role AI plays, and more.

Where and how does low code fit into the engineering experience? Share your opinions and help shape DZone's June report (+ enter a raffle!).

Programming in Python: Dive into the Python ecosystem to learn about popular libraries, tools, modules, and more.

Vector databases: Learn all about the specialized VDBMS — its initial setup, data preparation, collection creation, data querying, and more.

  • JSON-Based Serialized LOB Pattern
  • Data Software Design Pitfalls on Java: Should We Have a Constructor on JPA?
  • Introduction to Couchbase for Oracle Developers and Experts: Part 2 - Database Objects
  • How to Perform Object Level Recovery in SQL Server
  • How To Get Started With New Pattern Matching in Java 21
  • The Case for Choosing Between TCP and UDP for Data Transmission
  • A Guide to Vector Embeddings for Product and Software Engineers
  • Analyze Your ALB/NLB Logs With ClickHouse
  • Data Engineering

SOLID, GRASP, and Other Basic Principles of Object-Oriented Design

Learn principles of object oriented design, and get a firm hold on the ideas behind the solid and grasp languages in this article..

Muhammad Umair user avatar

Join the DZone community and get the full member experience.

I will start with a cliché. Code should depict the following qualities:

  • Maintainability
  • Extensibility

You may find yourself in a difficult situation when you ask a question about whether any particular code depicts the above average qualities or not.

A technique that helps is to look at the development timeline of any piece of software. If the code remains easy to maintain, extend, and modularize over its lifetime then it means that the code is above average in terms of the qualities listed above.

I have written difficult to read, hard to extend, and rotten code. I only knew after six months into the development when a change happened. Hence the development timeline is important in understanding quality factors.

Senior developers, who know about quality, don't have this problem. They feel proud when they see their code has the quality factors which junior developers only dream about. Hence senior developers and experts have distilled a set of principles down to junior developers which they can apply to write quality code and to show off in front of other developers.

In this post, I will cover SOLID principles. These principles are given by Uncle Bob (Robert C. Martin). I will also cover GRASP (General Responsibility Assignment Software Principles) published by Craig Larman and a few other basic object-oriented design principles. I have included examples from my personal experience, therefore you will not find any 'Animal' or 'Duck' examples.

The code examples shown are closer to Java and C#, but they are helpful to any developer who knows the basics of object-oriented programming.

Here is the complete list of principles covered in this post:

  • Single Responsibility Principle (SOLID)
  • High Cohesion (GRASP)
  • Low Coupling (GRASP)
  • Open Closed Principle (SOLID)
  • Liskov Substitution principle (SOLID)
  • Interface Segregation Principle (SOLID)
  • Dependency Inversion Principle (SOLID)
  • Program to an Interface, not to an Implementation

Hollywood Principle

  • Polymorphism (GRASP)
  • Information Expert (GRASP)
  • Creator (GRASP)
  • Pure Fabrication (GRASP)
  • Controller (GRASP)
  • Favor composition over inheritance
  • Indirection (GRASP)

One mistake that I made early in my career is that I tried to apply all the above principles at one time. That was a big mistake. I don’t want you to do that. I have designed a very simple process that allows you to apply basic design skills, and then build up from there. I compiled that process here.

Single Responsibility Principle

The Single Responsibility Principle (SRP) states:

     A class should have only one responsibility.

A class fulfills its responsibilities using its functions or contracts (and data members help functions).

Take the following example class:

This class handles two responsibilities. First, this class is loading simulation data, and, second, it is performing the simulation algorithm (using the  Simulate  and  ConvertParams   functions).

A class fulfills a responsibility using one, or more than one, function. In the example above, loading the simulation data is one responsibility, and performing the simulation is another responsibility. One function is needed to load simulation data (i.e LoadSimulationFile). The remaining two functions are needed to perform the simulation.

How do I know how many responsibilities my class has? Consider the phrase "reason to change" as analogous to responsibility . Hence, look for all the reasons a class has to change. If there is more than one reason to change a class then it means this class does not follow the single responsibility principle.

In our example class above, this class should not contain the  LoadSimulationFile   function (or loading simulation data responsibility). If we create a separate class for loading simulation data then this class will not violate SRP.

A class can only have a single responsibility. How would you design software with such a hard rule?

Let’s consider another principle which is closely related to SRP: High Cohesion. High cohesion gives you a subjective scale and not an objective one as in the case of SRP. Very low cohesion means a class is fulfilling many responsibilities. For example, there are more than 10 responsibilities for which a class is responsible. Low cohesion means a class is fulfilling around 5 responsibilities and moderate cohesion means a class fulfilling 3 responsibilities. High cohesion means a class is fulfilling a single responsibility. Hence, the rule of thumb while designing is to strive for high cohesion.

Another principle which should be discussed here is Low Coupling. This principle states that one should assign a responsibility so that the dependency between the classes remains low. Again consider the above example class. After applying the SRP and the high cohesion principle, we have decided to make a separate class which will handle simulation files. In this way, we have created two classes which are dependent on each other.

It looks like as if applying high cohesion is causing us to violate the principle of low coupling. This level of coupling is allowed as the goal in order to minimize the coupling, but not to zero the coupling. Some degree of coupling is normal to create an object-oriented design in which tasks are completed by a collaboration of objects.

On the other hand, consider a GUI class which connects to a database, handles remote clients over HTTP and handles screen layout. This GUI class is dependent upon too many classes. This GUI class clearly violates the low-coupling principle. This class cannot be re-used without involving all the related classes. Any change to database component cause changes to GUI class.

Open-Closed Principle

The Open-Closed principles states:

A software module (it can be a class or method ) should be open for extension but closed for modification.

In other words, you cannot update the code that you have already written for a project, but you can add new code to the project.

There are two methods by which you can apply the open-closed principle. You can apply this principle either through inheritance or through composition.

Here is the example of applying the open-close principle using inheritance:

In this example, the client read data ( ds.Read() ) comes from the network stream. If I want to extend the functionality of the client class to read data from another stream, e.g. PCI data stream, then I will add another subclass using the  DataStream  class, as shown in the listing below:

In this scenario, the client code will function without any error. The client class knows about the base class, and I can pass an object of any of the two subclasses of  DataStream . In this way, the client can read data without knowing the underlying subclass. This is achieved without modifying any existing code.

We can apply this principle using composition, and there are other methods and design patterns to apply this principle. Some of these methods will be discussed in this post.

Do you have to apply this principle to every piece of code that you write? No. This is because most of that code will not change. You will only have to apply this principle strategically in those conditions where you suspect a piece of code will change in the future.

Liskov Substitution Principle

The Liskov Substitution Principle states:

Derived classes must be substitutable for their base classes.

Another way to look at this definition is that abstraction (interface or abstract class) should be enough for a client.

To elaborate, let’s consider an example, here is an interface whose listing is given below:

This code represents data acquisition device abstraction. Data acquisition devices differ based upon their interface types. A data acquisition device can use a USB interface, Network Interface (TCP or UDP), PCI express interface, or any other computer interface. Clients of iDevice, however, do not need to know what kind of device they are working with. This gives programmers an enormous amount of flexibility to adapt to new devices without changing the code which depends upon the iDevice interface.

Let’s go into a little history when there were only two concrete classes that implemented iDevice interface shown below:

These three methods ( open ,  read , and  close ) are sufficient to handle data from these devices. Later, there was a requirement to add another data acquisition device which was based upon USB Interface.

The problem with a USB device is that when you open the connection, data from the previous connection remains in the buffer. Therefore, upon the first read call to the USB device, data from the previous session is returned. That behavior corrupted data for that particular acquisition session.

Fortunately, a USB-based device driver provides a refresh function which clears the buffers in the USB-based acquisition device. How can I implement this feature into my code so that the code change remains minimal?

One simple, but unadvised, solution is to update the code by identifying if you are calling the USB object:

In this solution, client code is directly using the concrete class as well as the interface (or abstraction). It means abstraction is not enough for the client to fulfill its responsibilities.

Another way to state the same thing is to say that the base class cannot fulfill the required behavior (refresh behavior), but the derived class does, in fact, have this behavior. Hence, the derived class is not compatible with the base class and thus the derived class cannot be substituted. Therefore, this solution violates the Liskov Substitution Principle.

In the example above, the client is dependent upon more entities (iDevices and USB Devices) and any change in one entity will cause a change in other entities. Therefore, violation of the LSP causes dependency between the classes.

Below I give a  solution to this problem that follows the LSP:

Now the client of iDevice is:

Now the client does not depend upon the concrete implementation of iDevice. Hence, in this solution, our interface (iDevice) is enough for the client.

There is another angle to look at the LSP principle within the context of object-oriented analysis. To get an introduction and a simple method to apply object-oriented analysis read this. In summary, during OOA, we think about the classes and their hierarchies that could be part of our software.

When we are thinking about the classes and hierarchies we can come up with classes which violate the LSP.

Let’s consider the classic example of the rectangle and the square. When looking from the outset it looks like that square is a specialized version of the rectangle and a happy designer would draw the following inheritance hierarchy:

What happens next is you cannot substitute a square object in place of a rectangular object. Since the square inherits from the rectangle, therefore, it inherits its method  setWidth()  and  setHeight() . A client of the square object can change its width and height to different dimensions. But width and height of a square are always identical, hence we get a failing of the normal behavior of the software.

This can only be avoided by looking at classes according to different usage scenarios and conditions. Therefore, when you are designing classes in isolation there is a probability that your assumptions may fail. As in the case of Square and Rectangle, a relationship looks good enough during initial analysis, but as we look at different conditions this relationship failed to work with the correct behavior of the software.

Interface Segregation Principle

The Interface Segregation Principle (ISP) states:

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

Again consider the previous example:

There are three classes that implement this interface:  USBDevice ,  NetworkDevice , and  PCIDevice . This interface is good enough to work with the network and PCI devices. But the USB device needs another function ( Refresh() ) to work properly.

Similar to the USB device, there can be another device which may require a refresh function to work properly. Due to this, iDevice is updated as shown below:

The problem is now each class that implements iDevice has to provide the definition for the refresh function.

For example, I have to add the following lines of code to the  NetworkDevice  class and  PCIDevice   class to work with this design:

Hence, iDevice represents a fat interface (too many functions). This design violates the Interface Segregation Principle because the fat interface is causing unnecessary clients to depend upon it.

There are numerous ways to solve this problem, but I will tackle this problem while staying within our predefined range of object-oriented solutions.

I know that refresh is directly called after the open function. Hence, I moved the logic of refresh from the client of iDevice to the specific concrete class. In our case I moved the call to refresh logic to the  USBDevice   class as shown here:

In this way, I have reduced the number of functions in the iDevice class and made it less fat.

Dependency Inversion Principle (DIP)

This principle is a generalization of the other principles discussed above. 

Before jumping to the textbook definition of DIP, let me introduce a closely related principle which will help understand DIP.

The principle is:

Program to an interface, not to an implementation.

This is a simple one. Consider the following example:

The above example violates the “program to an interface" principle because we are working with the reference of the concrete class PCI Device. The below listing follows this principle:

Hence it’s very easy to follow this principle. The Dependency Inversion Principle is similar to this principle, but DIP asks us to do one more step.

High-level modules should not depend upon low-level modules. Both should depend upon abstractions.

You can easily understand the line “both should depend upon abstractions,” as it is saying each module should program to an interface . But what are high-level modules and low-level modules?

To understand the first part we have to learn what high-level modules and low-level modules actually are.

See the following code:

In this code, there are three classes. The TransferManager class represents a high-level module. This is because it is using two classes in its one function. Hence the other two classes are low-level modules.

The high-level module function (TransferData) defines logic based upon how data is transferred from one device to another device. Any module which is controlling the logic, and uses the low-level modules in doing so, is called the high-level module.

In the code above, the high-level module is directly (without any abstraction) using the lower-level modules, hence violating the dependency inversion principle.

Violation of this principle makes the software difficult to change. For example, if you want to add other external devices you will have to change the higher-level module. Hence your higher-level module will be dependent upon the lower-level module, and that dependency will make the code difficult to change.

The solution is easy if you understand the principle above: "program to an interface." Here is the listing:

In the code above both high-level module and low-level modules depend upon abstractions. This code follows the Dependency Inversion Principle.

This principle is similar to the Dependency Inversion Principle. This principle states:

Don’t call us, we will call you.

This means a high-level component can dictate low-level components (or call them) in a manner so that neither one is dependent upon the other.

This principle helps to prevent dependency rot. Dependency rot happens when each component depends upon every other component. In other words, dependency rot is when dependency happens in each direction (upward, sideways, downward). The Hollywood Principle allows us to only make dependency in one direction.

The difference between the Dependency Inversion Principle and the Hollywood Principle is that the DIP gives us a general guideline: “Both higher-level and lower-level components should depend upon abstractions and not on concrete classes.” On the other hand, the Hollywood Principle specifies how higher-level component and lower-level components interact without creating dependencies.

You want to learn more about object oriented programming then visit here.

Polymorphism

What -- polymorphism is a design principle? Yes, it's the basic requirement for any OOP language to provide a polymorphism feature where derived classes can be referenced through parent classes.

It’s also a design principle in GRASP. This principle provides guidelines about how to use this OOP language feature in your object-oriented design.

This principle restricts the use of run-time type identification (RTTI). We implement RTTI in C# in the following manner:

In Java, RTTI is accomplished using the function getClass() or instanceOf()  

If you have written this type code in your project then now is the time to refactor that code and improve it using the polymorphism principle.

Look at the following diagram:

Here I have generalized the read method in the interface and delegated the device specific implementation to their classes (e.g ReadUART32() in USBDevice).

Now, I just use the method Read .

Where will the implementation of getDeviceObject() come from? This we will discuss in the Creator Principle and Information Expert Principle below, where you will learn about assigning the responsibilities to classes.

Information Expert

This is a simple GRASP principle and it gives guidelines about giving responsibilities to classes. It states that you should assign a responsibility to the class which has the information necessary to fulfill that responsibility.

Consider the following classes:

In our scenario, a simulation is performed at full speed (600 loops per second), whereas the user display is updated at a reduced speed. Here, I have to assign a responsibility to determine whether to display the next frame or not.

Which class should handle this responsibility? I have two options: either the Simulation class or SpeedControl class.

Now the  SpeedControl class has the information about which frames have been displayed in the current sequence, thus according to the Information Expert SpeedControl should have this responsibility.

Creator is a GRASP principle which helps to decide which class should be responsible for creating a new instance of a class. Object creation is an important process, and it is useful to have a principle in deciding who should create an instance of a class.

According to Larman, a class, B, should be given the responsibility to create another class, A, if any of the following conditions are true.

a) B contains A

b) B aggregates A

c) B has the initializing data for A

d) B records A

e) B closely uses A

In our example of polymorphism, I have used Information Expert and Creator principles to give the DeviceManager class the responsibility to create a Device Object (dm.getDeviceObject()). This is because DeviceManger has the information to create a Device Object.

Pure Fabrication

In order to understand Pure Fabrication, you must first understand object-oriented analysis (OOA).

Object Oriented Analysis is a process through which you can identify the classes in your problem domain. For example, the domain model for a banking system contains classes like Account, Branch, Cash, Check, Transaction, etc. In this example, the domain classes need to store information about the customers. In order to do that one option is to delegate data storage responsibility to domain classes. This option will reduce the cohesiveness of the domain classes (more than one responsibility). Ultimately, this option violates the SRP principle. To learn more about object oriented analysis  visit here .

Another option is to introduce another class which does not represent any domain concept. In the banking example, we can introduce a class called, “PersistenceProvider.” This class does not represent any domain entity. The purpose of this class is to handle data storage functions. Therefore “PersistenceProvider” is a pure fabrication.

When I started developing software, I wrote most of my programs using Java's swing components and most of my logic behind listeners .

Then I learned about domain models. So, I moved my logic from listeners to   Domain models. But I directly called the domain objects from listeners. This creates a dependency between the GUI components (listeners)   and the domain model. Controller design principles helped in minimizing the dependency between GUI components and the Domain Model classes.

There are two purposes of the Controller. The first purpose of the Controller is to encapsulate a system operation . A system operation is something that your user wants to achieve, e.g. buying a product or entering an item into the cart. This system operation is then accomplished by calling one or more method calls between the software objects.The second purpose of the Controller is to provide a layer between the UI and the Domain Model.

A UI enables users to perform system operations. A Controller is the first object after the UI layer that handles the system operations requests, and then delegates the responsibility to the underlying domain objects.

For example, here is a MAP Class which represents a Controller in one of our software codes.

From the UI we delegate the responsibility of "moving cursor" to this Controller and then this calls the underlying domain objects to move the cursor.

By using the Controller principle you will have the flexibility to plug in another user interface like a command line interface or a web interface.

Favor Composition Over Inheritance

Primarily there are two tools in object oriented programming to extend the functionality of existing code. The first one is inheritance.

The second method is composition. In programming words, by having a reference to another object you can extend that object’s functionality. If using composition, add a new class create its object and then use that object using its reference where you want to extend the code.

A very helpful feature of the composition is that behavior can be set at run-time. On the other hand, using inheritance you can only set the behavior at compile time. This will be shown in the example below.

When I was a newbie and used inheritance to extend the behavior, these are the classes that I designed:

Initially, I only know about processing an incoming stream of data, and there were two kinds (Stream A and Stream B) of data. After a few weeks, I figured out that endianness of the data should be handled. Thus, I came up with the class design shown below:

Later on, another variable was added to the requirements. This time I have to handle the polarity of the data. Imagine how many classes I have to add? Two types of polarity for Stream A, StreamB, a stream with endianness, and so on. A class explosion! Now I will have to maintain a large number of classes.

Now, if I handle the same problem using composition, the following will be the class design:

I added new classes and then used them in my code by using their references. See the listing below:

Hence I can provide the instances of the classes according to the behavior that I want. This feature reduced the total number of classes and ultimately the maintainability issues. Hence favoring composition over inheritance will reduce maintainability problems and give you the flexibility to set behavior at run-time.

Indirection

This principle answers one question: How do you cause objects to interact in a manner that makes bond among them remain weak?

The solution is: Give the responsibility of interaction to an intermediate object so that the coupling among different components remains low.

For example, a software application works with different configurations and options. To decouple the domain code from the configuration a specific class is added - which shown in the following listing:

In this way, if any domain object wants to read a certain configuration setting it will ask the Configuration class object. Therefore, the main code is decoupled from the configuration code.

If you have read the Pure Fabrication Principle, this Configuration class is an example of pure fabrication. But the purpose of indirection is to create de-coupling. On the other hand, the purpose of pure fabrication is to keep the domain model clean and represent only domain concepts and responsibilities.

Many software design patterns like Adapter, Facade, and Observer are specializations of the Indirection Principle.

Published at DZone with permission of Muhammad Umair . See the original article here.

Opinions expressed by DZone contributors are their own.

Partner Resources

  • About DZone
  • Send feedback
  • Community research
  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone
  • Terms of Service
  • Privacy Policy
  • 3343 Perimeter Hill Drive
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and the Unified Process, Second Edition by Craig Larman

Get full access to Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and the Unified Process, Second Edition and 60K+ other titles, with a free 10-day trial of O'Reilly.

There are also live events, courses curated by job role, and more.

16.4. GRASP: Patterns of General Principles in Assigning Responsibilities

To summarize the preceding introduction:

The skillful assignment of responsibilities is extremely important in object design.

Determining the assignment of responsibilities often occurs during the creation of interaction diagrams, and certainly during programming.

Patterns are named problem/solution pairs that codify good advice and principles often related to the assignment of responsibilities.

Understanding and being able to apply these principles during the creation of interaction diagrams is important because a software ...

Get Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and the Unified Process, Second Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.

Don’t leave empty-handed

Get Mark Richards’s Software Architecture Patterns ebook to better understand how to design components—and how they should interact.

It’s yours, free.

Cover of Software Architecture Patterns

Check it out now on O’Reilly

Dive in for free with a 10-day trial of the O’Reilly learning platform—then explore all the other resources our members count on to build skills and solve problems every day.

grasp general responsibility assignment

Chapter: Object Oriented Analysis and Design

Grasp - general responsibility assignment software patterns (or principles).

        General Responsibility Assignment Software Patterns (or Principles), abbreviated

GRASP,  consists of guidelines for assigning responsibility to classes and objects in object-oriented design.

       The different patterns and principles used in GRASP are: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations. All these patterns answer some software problem, and in almost every case these problems are common to almost every software development project. These techniques have not been invented to create new ways of working but to better document and standardize old, tried-and-tested programming principles in object oriented design.

       It has been said that "the critical design tool for software development is a mind well educated in design principles. It is not the UML or any other technology". Thus, GRASP is really a mental toolset, a learning aid to help in the design of object oriented software.

       Creation of objects is one of the most common activities in an object-oriented system. Which class is responsible for creating objects is a fundamental property of the relationship between objects of particular classes.

       In general, a class B should be responsible for creating instances of class A if one, or preferably more, of the following apply:

1.       Instances of B contains or compositely aggregates instances of A

2.       Instances of B record instances of A

3.       Instances of B closely use instances of A

4.       Instances of B have the initializing information for instances of A and pass it on creation.

3.  Information Expert

       Information Expert 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.

4. Low Coupling

       Low Coupling is an evaluative pattern, which dictates how to assign responsibilities to support:

1.       low dependency between classes;

2.       low impact in a class of changes in other classes;

3.       high reuse potential

5. Controller

       The Controller pattern assigns the responsibility of dealing with system events to a non-UI class that represent the overall system or a use case scenario. A Controller object is a non-user interface object responsible for receiving or handling a system event. A use case controller should be used to deal with all system events of a use case, and may be used for more than one use case (for instance, for use cases Create User and Delete User, one can have one UserController, instead of two separate use case controllers).

       It is defined as the first object beyond the UI layer that receives and coordinates ("controls") a system operation. The controller should delegate to other objects the work that needs to be done; it coordinates or controls the activity. It should not do much work itself. The GRASP Controller can be thought of as being a part of the Application/Service layer (assuming that the application has made an explicit distinction between the App/Service layer and the Domain layer) in an object-oriented system with common layers.

6. High Cohesion

       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 adverse to change.

Polymorphism

According to Polymorphism, responsibility of defining the variation of behaviors based on type is assigned to the types for which this variation happens. This is achieved using polymorphic operations.

Pure Fabrication

       A pure fabrication is a class that does not represent a concept in the problem domain, specially made up to achieve low coupling, high cohesion, and the reuse potential thereof derived (when a solution presented by the Information Expert pattern does not). This kind of class is called "Service" in Domain-driven design.

Indirection

       The Indirection pattern supports low coupling (and reuse potential) between two elements by assigning the responsibility of mediation between them to an intermediate object. An example of this is the introduction of a controller component for mediation between data (model) and its representation (view) in the Model-view-controller pattern.

Protected Variations

       The Protected Variations pattern protects elements from the variations on other elements (objects, systems, subsystems) by wrapping the focus of instability with an interface and using polymorphism to create various implementations of this interface.

7. Visibility

Creational Design Patterns

       In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation. The basic form of object creation could result in design problems or added complexity to the design.

       Creational design patterns solve this problem by somehow controlling this object creation. In object-oriented design, there is a notation of visibility for attributes and operations. UML identifies four types of visibility: public, protected, private, and package.

       The UML specification does not require attributes and operations visibility to be displayed on the class diagram, but it does require that it be defined for each attribute or operation.

       To display visibility on the class diagram, you place the visibility mark in front of the attribute's or operation's name. Though UML specifies four visibility types, an actual programming language may add additional visibilities, or it may not support the UML-defined visibilityies

Mark          Visibility

+       Public

#        Protected

-        Private

~        Package

A BankAccount class that shows the visibility of its attributes and operations

grasp general responsibility assignment

       Visibility -  the ability of one object to “see” or have a reference to another object.

Visibility is required for one object to message another.

8. Applying GOF Design Patterns:

       Design patterns represent common software problems and the solutions to those problems in a formal manner. They were inspired by a book written by architect Christopher Alexander. Patterns were introduced in the software world by another book: "Design Patterns: Elements of Reusable Object-Oriented Software", by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. These people were nicknamed the "Gang of Four" for some mysterious reason. The Gang of Four describes 23 design patterns.

       With patterns you don't have to reinvent the wheel and get proven solutions for frequently encountered problems. Many books and articles have been written on this subject. This means that design patterns are becoming common knowledge, which leads to better communication. To summarize design patterns save time, energy while making your life easier.

8.1. Singleton

       The singleton pattern deals with situations where only one instance of a class must be created. Take the case of a system administrator or superuser. This person has the right to do everything in a computer system. In addition we will also have classes representing normal users. Therefore we must ensure that these classes have no access to the super

user constructor. The solution to this problem in C++ and Java is to declare the superuser constructor private.

       The super user class itself has a private static attribute sysadmin, which is initialised using the class constructor. Now we get an instance of the super user class with a public static method that returns sysadmin. Here is the class diagram:

grasp general responsibility assignment

8.2. Factory Method

       The Factory Method pattern deals with situations where at runtime one of several similar classes must be created. Visualise this as a factory that produces objects. In a toy factory for instance we have the abstract concept of toy.

       Every time we get a request for a new toy a decision must be made - what kind of a toy to manufacture. Similarly to the Singleton pattern the Factory Method pattern utilises a public static accessor method. In our example the abstract Toyfactory class will have a getInstance() method, which is inherited by its non abstract subclasses.

grasp general responsibility assignment

8.3. Adapter

       Sometimes it will have two classes that can in principle work well together, but they can't interface with each other for some reason. This kind of problem occurs when travelling abroad and you carry an electric shaver with you.

       Although it will work perfectly when you are at home. There can be problems in a foreign country, because of a different standard voltage. The solution is to use an adapter. Let's turn our attention back to the software domain. Here we will have an interface which defines new methods for example getElectricity2.

       An adapter class will wrap around the Shaver class. The adapter class will implement the interface with the new method.

grasp general responsibility assignment

       The Proxy pattern deals with situations where you have a complex object or it takes a long time to create the object. The solution to this problem is to replace the complex object with a simple 'stub' object that has the same interface.

       The stub acts as a body double. This is the strategy used by the Java Remote Method Invocation API. The reason to use the proxy pattern in this case is that the object is on a remote server causing network overhead. Other reasons to use the proxy can be restricted access (Java applets for example) or time consuming calculations.

grasp general responsibility assignment

8.5. Decorator

       The Decorator is usually a subclass, that is a body double for its superclass or another class with identical interface. The goal of the Decorator pattern is to add or improve the capabilities of the super class.

grasp general responsibility assignment

8.6. Composite

       The composite is often encountered in GUI packages like for instance the Java Abstract Windwing Toolkit (AWT) or Microsoft Foundation (MFC) classes. All objects in this pattern have a common abstract superclass that descibes basic object conduct. The base class in the MFC hierarchy is CObject. It provides functions for debugging and serialization. All the MFC classes even the most basic ones inherit these facilities.

grasp general responsibility assignment

8.7. Observer and MVC

       An application with Model - View - Controller setup usually uses the Observer Pattern. In a Java webserver environment the model will be represented by Java classes encompassing the business logic, the view is represented by Java Server Pages which display HTML in the client's browser and we will have a Servlets as Controllers.

       The observer pattern strategy is to have view components take subscriptions for their model. This ensures that they will get notified if the model changes.

grasp general responsibility assignment

8.8. Template

       In the good old days before OOP writing functions was the recommended thing to do. A sort algorithm would be implement by half dozen of functions, one sort function for integers, one sort function for floating points, one sort function for doubles etc.

       These functions are so similar that nobody in their right mind will type them letter by letter. Instead a programmer will write a template and copy the template several times. After that it's just a matter of writing down datatypes as appropriate. Thanks to OOP and the Template Design Pattern less code is required for this task.

       Define an abstract Template class let's call it SortTemplate and it will have methods sort, compare and process (performs one cycle of the algorithm). Then we define  classes for each datatype. These classes are subclasses of SortTemplate and implement the compare and process methods.

grasp general responsibility assignment

8.9. Strategy

       The Strategy Design Pattern makes it possible chooses an implementation of an algorithm at run time. The implementation classes implement the same interface. In the case of the Java AWT Layout classes, the common interface is Layout Manager.

grasp general responsibility assignment

10. Summary

       Design patterns are a hot research item. New patterns are emerging every day. In the future design patterns will be integrated in development tools. The main advantages of design patterns:

1.       Provide proven solutions

2.       Simplify complex problems

3.       Improve communication

Classification and list

       Design patterns were originally grouped into the categories: creational patterns, structural patterns, and behavioral patterns, and described using the concepts of delegation, aggregation, and consultation.

       For further background on object-oriented design, see coupling and cohesion, inheritance, interface, and polymorphism. Another classification has also introduced the notion of architectural design pattern that may be applied at the architecture level of the software such as the Model-View-Controller pattern.

       In software engineering, creational design patterns are design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation.

       The basic form of object creation could result in design problems or added complexity to the design. Creational design patterns solve this problem by somehow controlling this object creation

Related Topics

Privacy Policy , Terms and Conditions , DMCA Policy and Compliant

Copyright © 2018-2024 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.

  • skip to content

Principles Wiki

  • Recent Changes
  • Media Manager

Table of Contents

Further reading, general responsibility assignment software patterns (grasp).

Craig Larman describes how to assign responsibilities to classes using the following principles and patterns:

  • High Cohesion
  • Indirection
  • Information Expert
  • Low Coupling
  • Polymorphism
  • Protected Variations
  • Pure Fabrication

He calls GRASP “patterns of general principles in assigning responsibilities” 1) . Some of these are really patterns but others are principles.

Craig Larman: Applying UML and Patterns

  • GRASP (object-oriented design)

Discuss this wiki article and the collection on the corresponding talk page .

404 Not found

U.S. flag

An official website of the United States government

Assistant Insider Threat Program Coordinator (A/CITPC)

Department of homeland security.

This assignment is a 1-year non-reimbursable assignment. This assignment is within U.S. Customs and Border Protection, Office of Intelligence, Insider Threat and Counterintelligence Services Division (ITCSD) We encourage you to read the entire announcement prior to submitting your application. Position Title: Assistant Insider Threat Program Coordinator This is not a Virtual/Remote JDA Series: Requested: 0340,0343,1801 and 0132 Security Clearance: TS/SCI Assignment Location: Washington, DC

  • Accepting applications

Open & closing dates

02/20/2024 to 08/01/2024

$99,200 - $153,354 per year

Pay scale & grade

1 vacancy in the following location:

  • Washington, DC

Telework eligible

Travel required.

Not required

Relocation expenses reimbursed

Appointment type, work schedule.

Competitive

Promotion potential

Job family (series).

0132 Intelligence

0340 Program Management

0343 Management And Program Analysis

1801 General Inspection, Investigation, Enforcement, And Compliance Series

Supervisory status

Security clearance.

Sensitive Compartmented Information

Announcement number

JDP-12325359-24-KJ

Control number

This job is open to, federal employees - competitive service.

Current or former competitive service federal employees.

Federal employees - Excepted service

Current excepted service federal employees.

Clarification from the agency

This detail opportunity is for current competitive and excepted service employees only. If you are not a current federal civilian employee you will not be eligible for this position. DHS Joint Duty Assignments do not apply to members of the Military service or contractors.

This position is with the Department of Homeland Security, within U.S. Customs and Border Protection, Office of Intelligence, Insider Threat and Counterintelligence Services Division (ITCSD), located in Washington, DC. This position is non-reimbursable and will be used to staff a key position within the Insider Threat Branch. This is a one year non-reimbursable position with the option to extend an additional year.

Requirements

Conditions of employment.

  • Must be a current permanent Federal employee
  • Must have supervisory approval to apply to the Joint Duty Assignment. DHS 250-2 Application Form under "required documents" section.
  • Must NOT have any pending/outstanding disciplinary actions
  • Must have achieved a minimum of "meet expectations/proficiency" on latest performance appraisal/evaluation
  • Must be currently at the grade level of the detail. *No Temporary Promotion Opportunity*
  • The program does not apply to members of the Military service or contractors.

Qualifications

  • Ability to effectively communicate, both orally and in writing, and an ability to grasp conceptual ideas and exercise original thought where there is an established time limit for deliberation, consultation, and evaluation, and to present well-considered and sound suggestions.
  • Ability to plan, organize, and direct team/task force efforts across organizational lines, including the ability to monitor progress to ensure that realistic objectives and milestones are established, to clearly assign responsibilities, and to accomplish mission requirements in a timely manner.
  • Ability to plan, organize, develop, coordinate, and represent the ITP in briefings with both internal and external senior stakeholders to inform them of the progress of important initiatives to ensure the success of OI's ITP priority objectives, and secure additional and necessary resources to ensure the success of ITP's programmatic initiatives.
  • Highly proficient in Microsoft Office Suite, particularly Microsoft Excel, Microsoft PowerPoint, and Visio.
  • Perform other duties as assigned or required.
  • Job Title (Include series and grade of Federal Job)
  • Duties (Be specific in describing your duties)
  • Name of Federal agency
  • Supervisor name, email, and phone number
  • Start and end dates including month and year (e.g. June 2007 to April 2008)

EDUCATIONAL SUBSTITUTION: There is no educational substitution for this position.

Additional information

  • Complete the DHS Training Course 15 days prior to the arrival to the JDA.
  • Phase 1: Establish assignment objectives within the first 30 days of the JDA.
  • Phase 2: Complete a self-assessment of the duties performed at the mid-point of the JDA.
  • Phase 3: Complete a final review within the last 30 days of the JDA.

A career with the U.S. government provides employees with a comprehensive benefits package. As a federal employee, you and your family will have access to a range of benefits that are designed to make your federal career very rewarding. Opens in a new window Learn more about federal benefits .

Eligibility for benefits depends on the type of position you hold and whether your position is full-time, part-time or intermittent. Contact the hiring agency for more information on the specific benefits offered.

How You Will Be Evaluated

You will be evaluated for this job based on how well you meet the qualifications above.

We will review your resume and supporting documentation to ensure you meet the basic qualification requirements. If you meet the minimum qualifications, your experience, education, and training will be rated using a job questionnaire based on the competencies or knowledge, skills, and abilities needed to perform this Joint Duty Assignment. If you are among the best qualified, you may be referred to the hiring manager for consideration and may be called for an interview. After reviewing your resume and supporting documentation, a determination will be made. You must submit the supporting documents listed under the required documents section of this announcement. Note: DHS continues to take necessary steps to keep our workforce safe amid the COVID-19 pandemic. If you receive a final Joint Duty Assignment offer to onboard, please complete the onboarding requirements and/or forms and submit them electronically in an expeditious manner. Your start date may be delayed if the action above is not completed.

As a new or existing federal employee, you and your family may have access to a range of benefits. Your benefits depend on the type of position you have - whether you're a permanent, part-time, temporary or an intermittent employee. You may be eligible for the following benefits, however, check with your agency to make sure you're eligible under their policies.

  • Your appointment in the Federal service
  • Grade and Step
  • Full performance level
  • To begin, click Apply Online to create a USA JOBS account or log in to your existing account. Follow the prompts to select your USA JOBS resume and other supporting documents, and complete the questionnaire.
  • Click Submit My Answers to submit your application package. NOTE : It is your responsibility to ensure your responses and appropriate documentation is submitted prior to the closing date.

Agency contact information

Dhs joint duty program.

[email protected]

Once you submit your application, we will assess your experience and training, identify the best qualified applicants, and refer those applications to the selecting official for further consideration and a possible interview. We will notify you by email at various stages in the process. Your status will also be updated on USAJOBS throughout the process. To check your status, log on to your USAJOBS account, click on "Application Status," and then click "More Information." We expect to make a final JDA offer within 90 days after the deadline for applications. If you are selected, we will conduct a suitability/security background investigation. Telework: Telework eligibility is based on the needs of the office and is subject to change. Additional information pertaining to your interest and availability for this position may be needed after the closing date of the Joint Duty Assignment vacancy announcement; therefore, a timely response to these requests must be adhered to in order to remain in consideration.

The Federal hiring process is set up to be fair and transparent. Please read the following guidance.

  • Equal Employment Opportunity (EEO) Policy
  • Criminal history inquiries
  • Reasonable accommodation policy
  • Financial suitability
  • Selective Service
  • New employee probationary period
  • Signature and false statements
  • Privacy Act
  • Social security number request

Required Documents

How to apply, fair & transparent.

This job originated on www.usajobs.gov . For the full announcement and to apply, visit www.usajobs.gov/job/777936600 . Only resumes submitted according to the instructions on the job announcement listed at www.usajobs.gov will be considered.

Please wait while map is being generated.

Learn more about

Department of Homeland Security - Agency Wide

DHS is calling on those who want to help protect American interests and secure our Nation. DHS Components work collectively to prevent terrorism; secure borders and our transportation systems; protect the President and other dignitaries; enforce and administer immigration laws; safeguard cyberspace; and ensure resilience to disasters. The DHS Joint Duty Program (JDP) is an intra- and inter-departmental program which offers civilian personnel professional and developmental opportunities. Joint Duty Assignments (JDAs) enhance operations and mission execution through unity of effort and collaboration. The DHS JDP is a human capital program initiative which is managed by OCHCO at DHS headquarters. The DHS JDP's purpose is two-fold: to encourage and to facilitate assignments of DHS personnel to other DHS components as well as outside agencies. The purpose of JDAs is to gain multi-component, multi-faceted experience focused on cross-cutting DHS and Federal-wide operations to enhance performance of the individual, the organizations, and the Department. JDAs are for a period not to exceed 1 year and do not qualify for Joint Duty credit. The DHS JDP covers current Federal employees at the GS-13 through GS-15 grade levels and equivalent. The DHS JDP does not apply to members of the military service or contractors. JDAs do not offer Temporary Promotions.

Visit our careers page

Learn more about what it's like to work at Department of Homeland Security - Agency Wide, what the agency does, and about the types of careers this agency offers.

https://www.dhs.gov/employee-resources/joint-duty-program/

Your session is about to expire!

Your USAJOBS session will expire due to inactivity in eight minutes. Any unsaved data will be lost if you allow the session to expire. Click the button below to continue your session.

COMMENTS

  1. GRASP (object-oriented design)

    General Responsibility Assignment Software Patterns (or Principles), abbreviated GRASP, is a set of "nine fundamental principles in object design and responsibility assignment": 6 first published by Craig Larman in his 1997 [citation needed] book Applying UML and Patterns.. The different patterns and principles used in GRASP are controller, creator, indirection, information expert, low ...

  2. GRASP

    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 ...

  3. GRASP Design Principles in OOAD

    GRASP, which stands for General Responsibility Assignment Software Patterns, includes several principles that guide the allocation of responsibilities in object-oriented design. These principles include: Creator: Assign the responsibility of creating instances of a class to the class that has the most knowledge about when and how to create them.

  4. GRASP (General Responsibility Assignment Software Patterns)

    GRASP (General Responsibility Assignment Software Patterns) is a design pattern in object-oriented software development used to assign responsibilities for different modules of code.. As a tool for software developers, GRASP provides a means to solve organizational problems and offers a common way to speak about abstract concepts.

  5. Object-Oriented Design with GRASP

    GRASP (General Responsibility Assignment Software Pattern) is a set of nine fundamental principles in object-oriented design, that emphasize defining tasks or obligations that objects must fulfill ...

  6. Mastering GRASP Design Principles for Better Software Design

    GRASP, which stands for General Responsibility Assignment Software Patterns (or Principles), is a collection of nine best practices that assist in assigning responsibilities to classes and objects.

  7. Understanding the GRASP Design Patterns

    GRASP (General Responsibility Assignment Software Patterns) GRASP is a set of guidelines and patterns that help developers make informed decisions about assigning responsibilities to objects and ...

  8. PDF GRASP Design Principles

    GRASP stands for General Responsibility Assignment Software Patterns guides in assigning responsibilities to collaborating objects. 9 GRASP patterns Creator Information Expert Low Coupling Controller High Cohesion Indirection Polymorphism Protected Variations Pure Fabrication

  9. GRASP: 9 Must-Know Design Principles for Code

    GRASP stands for General Responsibility Assignment Software Principles. I think the words that carry the most meaning in this acronym are RA: Responsibility Assignment. This is exactly what we're talking about. I learnt those principle in Craig Larman's book Applying UML and Patterns: Even though the book title mentions UML, the book is ...

  10. GRASP

    GRASP - General Responsibility Assignment Software Patterns are 9 patterns, which will help you with adding a new responsibility to your current codebase. It could be very helpful because sometimes we don't know if this component is suitable for this functionality. Maybe we should create a new one?

  11. GRASP · Notes

    GRASP Table of Contents. GRASP: Overview and Interrelationship; Responsibilities; Creator; Information Expert; Low Coupling; High Cohesion ... General Responsibility Assignment Software Patterns; pattern: named and well-known problem and solution that can be applied to new contexts, providing guidance for assessing trade-offs; Benefits of ...

  12. GRASP

    Even though it is about to become an oldie, most rules collected under the GRASP banner are still helpful, and they should be essential to every developer's toolkit. The General Responsibility Assignment Software Principles list nine principles: Pure Fabrication. Though they are tailored to object-oriented design, some also apply for general ...

  13. PDF CS130 Software Engineering

    The GRASP Principles/Patterns •The GRASP principles are a set of principles that direct the design of software systems •GRASP = General Responsibility Assignment Software Principles/Patterns •(There are other useful sets of software design principles, e.g.SOLID) •All programming is basically the task of breaking down a larger, more

  14. PDF Object Analysis & Design in the textbook Introduction to GRASP

    GRASP Patterns GRASP •General Responsibility Assignment Software Patterns. •These are well-known best principles for assigning responsibilities. •Nine core principles that object-oriented designers apply when assigning responsibilities to classes and designing message interactions. We will look at 5 of these 9 principles

  15. Chapter No- 6 : GRASP General Responsibility Assignment Software

    This video contains the introduction about GRASP(General Responsibility Assignment Software Patterns).It include patterns like Expert, Creator, and Low Coupl...

  16. PDF Presentation Duncan C

    Presentation Duncan C. GRASP Patterns. David Duncan November 16, 2012. Introduction. • GRASP (General Responsibility Assignment Software Patterns) is an acronym created by Craig Larman to encompass nine object‐oriented design principles related to creating responsibilities for classes • These principles can also be viewed as design ...

  17. GRASP (General Responsibility Assignment Software Patterns)

    GRASP (General Responsibility Assignment Software Patterns) GRASP is a set of guidelines and patterns that help developers make informed decisions about assigning responsibilities to objects and ...

  18. SOLID, GRASP, and Other Basic Principles of Object-Oriented Design

    These principles are given by Uncle Bob (Robert C. Martin). I will also cover GRASP (General Responsibility Assignment Software Principles) published by Craig Larman and a few other basic object ...

  19. GRASP: Patterns of General Principles in Assigning Responsibilities

    16.4. GRASP: Patterns of General Principles in Assigning Responsibilities To summarize the preceding introduction: The skillful assignment of responsibilities is extremely important in object design. Determining the assignment of responsibilities … - Selection from Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and the Unified Process, Second Edition [Book]

  20. GRASP

    1. GRASP. General Responsibility Assignment Software Patterns (or Principles), abbreviated. GRASP, consists of guidelines for assigning responsibility to classes and objects in object-oriented design. The different patterns and principles used in GRASP are: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure ...

  21. PDF Object Analysis & Design in the textbook

    GRASP. • General Responsibility Assignment Software Patterns. • These are well-known best principles for assigning responsibilities. • Nine core principles that object-oriented designers apply when assigning responsibilities to classes and designing message interactions. We will look at 5 of these 9 principles.

  22. General Responsibility Assignment Software Patterns (GRASP)

    High Cohesion. Indirection. Information Expert. Low Coupling. Polymorphism. Protected Variations. Pure Fabrication. He calls GRASP "patterns of general principles in assigning responsibilities" 1). Some of these are really patterns but others are principles.

  23. GRASP

    Ok, now we know thing the responsibility in context of browse is. Let's see how to assign which responsibilities using GRASP. GRASP. GRASP is set out exactly 9 General ROENTGENesponsibility ONEssignment Software Patterns. As I note above assignment of object responsibilities can one for the lock skill of OOD. Every programmer the designer ...

  24. USAJOBS

    Phase 1: Establish assignment objectives within the first 30 days of the JDA. Phase 2: Complete a self-assessment of the duties performed at the mid-point of the JDA. Phase 3: Complete a final review within the last 30 days of the JDA. A career with the U.S. government provides employees with a comprehensive benefits package.