GRASP - General Responsibility Assignment Software Patterns Explained
![general responsibility assignment software principles general responsibility assignment software principles](https://www.kamilgrzybek.com/images/blog/posts/grasp-explained/GRASP_image.png)
![](http://writinghelp.online/777/templates/cheerup/res/banner1.gif)
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
![general responsibility assignment software principles general responsibility assignment software principles](https://www.kamilgrzybek.com/images/blog/posts/10-common-broken-clean-code-rules/hero.jpg)
- 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
GRASP Design Principles 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.
![general responsibility assignment software principles grasp-banner](https://media.geeksforgeeks.org/wp-content/uploads/20240318095439/grasp-banner.webp)
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:
![general responsibility assignment software principles GRASP-Principles](https://media.geeksforgeeks.org/wp-content/uploads/20240318095503/GRASP-Principles.webp)
- 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.
- System Design
- OOAD - Object Oriented Analysis and Design
- How to Get a Free SSL Certificate
- Best SSL Certificates Provider in India
- Elon Musk's xAI releases Grok-2 AI assistant
- What is OpenAI SearchGPT? How it works and How to Get it?
- Content Improvement League 2024: From Good To A Great Article
Improve your Coding Skills with Practice
What kind of Experience do you want to share?
![general responsibility assignment software principles](https://miro.medium.com/v2/resize:fill:64:64/1*dmbNkD5D-u45r44go_cf0g.png)
GRASP Principles: Object-Oriented Design Patterns
General responsibility assignment software patterns.
![general responsibility assignment software principles Patrick Karsh](https://miro.medium.com/v2/resize:fill:88:88/1*At8qKZ9BMc379IPmy_Al6Q.jpeg)
Patrick Karsh
Object-oriented design is a crucial aspect of software development, and creating robust and maintainable systems requires a systematic approach. GRASP (General Responsibility Assignment Software Patterns) is a set of guidelines that helps designers make informed decisions during the object-oriented design process. In this article, we will explore the key principles of GRASP and understand how they contribute to the creation of flexible and extensible software solutions.
The Creator principle guides the allocation of responsibility for creating objects. According to this principle, a class should be responsible for creating objects of other classes if the first class aggregates, contains, or has a composition relationship with the second class. This principle promotes low coupling between classes, enabling better maintainability and reusability.
Information Expert
The Information Expert principle focuses on assigning responsibilities to classes that possess the most information required to fulfill them. A class should be responsible for a particular task if it has the necessary information to perform that task effectively. By adhering to this principle, we can design systems where responsibilities are distributed efficiently among classes, improving cohesion and reducing dependencies.
How Object-Oriented Design Enhances Code Readability and Maintainability
Best practices for implementing object-oriented design.
patrickkarsh.medium.com
Low Coupling
The Low Coupling principle emphasizes designing classes with minimal dependencies on other classes. By reducing the interconnections between classes, we create a more flexible and modular system. Achieving low coupling improves maintainability, as changes to one class are less likely to affect other classes. The use of interfaces and abstractions can help minimize coupling and promote code reusability.
High Cohesion
High Cohesion is a principle that advocates designing classes with a clear and focused purpose. A class should have a single responsibility and encapsulate related behaviors and data. Cohesive classes are easier to understand, test, and maintain. They promote code reuse and minimize the impact of changes within the system.
The Controller principle suggests that an entity responsible for handling a system operation should be a separate class. Controllers act as intermediaries between the user interface and the business logic, orchestrating the flow of information and managing the interaction between objects. By encapsulating the control logic in dedicated controller classes, we achieve better separation of concerns and improve the overall flexibility of the system
Polymorphism
Polymorphism is a fundamental principle in object-oriented design that enables objects of different classes to be treated uniformly through a common interface. By leveraging polymorphism, we can design systems that are extensible and adaptable to new requirements. Polymorphic behavior allows for code reuse and promotes loosely coupled systems.
A Dive Into Inheritance, Polymorphism, and Encapsulation: The Pillars of Object-Oriented Design
A deep dive into inheritance, polymorphism, and encapsulation: the pillars of object-oriented design, slap: single layer of abstraction principle, in the realm of software development, where complexity often abounds, finding effective ways to manage and simplify…, pure fabrication.
The Pure Fabrication principle suggests the creation of artificial classes to improve system design. These classes are not directly tied to the domain or problem being solved but serve as helpers or connectors between other classes. Pure Fabrication aids in achieving low coupling and high cohesion by encapsulating complex operations or providing an interface to external systems.
GRASP principles provide a set of guidelines that help designers make informed decisions when designing object-oriented systems. By adhering to these principles, developers can create software that is modular, flexible, and maintainable. Applying GRASP principles ensures a clear distribution of responsibilities, promotes low coupling, and high cohesion among classes. Moreover, these principles enable the development of systems that are adaptable to change and support future extensions. Mastering GRASP principles is crucial for every software designer aiming to create well-structured and scalable object-oriented systems.
![general responsibility assignment software principles Patrick Karsh](https://miro.medium.com/v2/resize:fill:144:144/1*At8qKZ9BMc379IPmy_Al6Q.jpeg)
Written by Patrick Karsh
NYC-based Ruby on Rails and Javascript Engineer leveraging AI to explore Engineering. https://linktr.ee/patrickkarsh
Text to speech
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.
![](http://writinghelp.online/777/templates/cheerup/res/banner1.gif)
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!
![general responsibility assignment software principles Author Yannic Schröer](https://assets.blog.code-specialist.com/yannic_162aa36780.webp)
![general responsibility assignment software principles Fluent C++](https://www.fluentcpp.com/wp-content/uploads/2016/11/c10318_fluent_cpp_logo_jc1-1-e1479715436541.png)
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
![general responsibility assignment software principles](https://www.fluentcpp.com/wp-content/uploads/2019/01/banner_book.jpg)
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 :
![general responsibility assignment software principles Applying UML and Patterns](https://i0.wp.com/www.fluentcpp.com/wp-content/uploads/2019/04/51gVLEtrCNL._SX398_BO1204203200_.jpg?resize=400%2C500&ssl=1)
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
![Follow me on twitter twitter](https://i0.wp.com/www.fluentcpp.com/wp-content/plugins/social-media-feather/synved-social/image/social/regular/96x96/twitter.png?resize=48%2C48&ssl=1)
- Programming
GRASP (General Responsibility Assignment Software Patterns)
![general responsibility assignment software principles TechTarget Contributor](https://cdn.ttgtmedia.com/rms/onlineImages/contributor_avatar_140X180.jpg)
- TechTarget Contributor
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. The design pattern sets responsibilities for objects and classes in object-oriented program design.
GRASP with object-oriented programming classifies problems and their solutions together as patterns. With these problems and solutions well defined, they can be applied in other similar instances. GRASP assigns seven types of roles to classes and objects in order to make for clear delineation of responsibilities. These roles are:
- Information Expert
- High Cohesion
- Low Coupling
- Polymorphism
- Protected Classes
GRASP is occasionally coupled with other design patterns such as SOLID . This combination makes for the convincing moniker of SOLID GRASP. Design patterns such as these help keep code simpler, more organized, more comprehensible, analyzable and reusable.
Continue Reading About GRASP (General Responsibility Assignment Software Patterns)
- Discover the role of smart endpoints in microservices
- Awakening the potential of IoT with programming languages
- What can I do to gain Java skills and leave mainframe programming?
- Understanding the grasp design patterns
Related Terms
A URL (Uniform Resource Locator) is a unique identifier used to locate a resource on the internet.
File Transfer Protocol (FTP) is a network protocol for transmitting files between computers over TCP/IP connections.
A virtual private network (VPN) is a service that creates a safe, encrypted online connection.
Cloud computing requires a security approach that is different than traditional protections. Where does cloud detection and ...
An endpoint protection platform (EPP) is a security technology that safeguards endpoint devices.
Endpoint security is the protection of endpoint devices against cybersecurity threats.
Data monetization is the process of measuring the economic benefit of corporate data.
C-level, also called the C-suite, is a term used to describe high-ranking executive titles in an organization.
Value-sensitive design is a concept that advocates the consideration of human principles and standards when planning technology.
Employee self-service (ESS) is a widely used human resources technology that enables employees to perform many job-related ...
Diversity, equity and inclusion is a term used to describe policies and programs that promote the representation and ...
Payroll software automates the process of paying salaried, hourly and contingent employees.
Voice or speaker recognition is the ability of a machine or program to receive and interpret dictation or to understand and ...
Customer segmentation is the practice of dividing a customer base into groups of individuals that have similar characteristics ...
Customer experience (CX) is the sum total of customers' perceptions and feelings resulting from interactions with a brand's ...
Scientific Applications & Development News
Grasp: 9 must-know design principles for code.
- Published at : https://www.fluentcpp.com/2021/06/23/grasp-9-must-know-design-principles-for-code/
- Author: Jonathan Boccara
- Publication date: June 23, 2021
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 :
![general responsibility assignment software principles Applying UML and Patterns](https://www.fluentcpp.com/wp-content/uploads/2019/04/51gVLEtrCNL._SX398_BO1204203200_.jpg)
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.
Leave a Reply Cancel reply
Your email address will not be published. Required fields are marked *
- 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)
Principles | |||||
---|---|---|---|---|---|
Patterns |
Discuss this wiki article and the collection on the corresponding talk page .
Instantly share code, notes, and snippets.
dimabory / gist:56e36474a1bb5573c08f26805a978fb5
- Download ZIP
- Star ( 7 ) 7 You must be signed in to star a gist
- Fork ( 2 ) 2 You must be signed in to fork a gist
- Embed Embed this gist in your website.
- Share Copy sharable link for this gist.
- Clone via HTTPS Clone using the web URL.
- Learn more about clone URLs
- Save dimabory/56e36474a1bb5573c08f26805a978fb5 to your computer and use it in GitHub Desktop.
General Responsibility Assignment Software Patterns
http://www.it.uu.se/edu/course/homepage/asd/ht14/Lecture%204.pdf https://web.cs.dal.ca/~jin/3132/lectures/dp-13.pdf https://www.cs.cmu.edu/~aldrich/214/slides/design-grasp.pdf https://dzone.com/articles/solid-grasp-and-other-basic-principles-of-object-o
A collection of patterns/principles for achieving good design – patterns of assigning responsibility. Refer to software objects not domain objects.
Low coupling
High cohesion, information expert, polymorphism, indirection, pure fabrication, protected variations.
Read more here: https://gist.github.com/dimabory/140223715fe24025eeacc78251f063b0
Problem : How to reduce the impact of change? Advice : Assign responsibilities so that (unnecessary) coupling remains low.
Use this principle to evaluate alternatives. Focus on points of realistic instability or evolution.
Drawback : may add additional layers of indirection.
Problem : How to keep objects focussed, understandable, and manageable, and as a side effect, support Low Coupling? Advice : Assign responsibilities so that cohesion remains high.
Use this to evaluate alternatives.
Problem : Who creates an A? Advice : Assign class B the responsibility to create an instance of class A if one of these is true (the more the better):
- B “contains” or compositely aggregates A.
- B records A.
- B closely uses A.
- B has the initialising data for A.
Problem : What is the basic principle by which to assign responsibilities/functionality to objects? Advice : Assign a responsibility to a class that has the information needed to fulfil it.
Problem : What first object beyond the UI layer receives and coordinates (“controls”) a system operation? Advice : Assign the responsibility to an object representing one of these choices:
- Represents the overall “system”, a “root object”, a 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.
Avoid bloated controllers.
Problem : How to handle alternatives based on type? How to create pluggable software components? Advice : When related alternatives or behaviours vary by type (class), assign responsibility for the behaviour — using polymorphic operations— to the types for which the behaviour varies.
Avoid adding flexibility just because you can.
Problem : Where to assign a responsibility, to avoid direct coupling between two (or more) classes? How to decouple objects so that low coupling is supported and reuse potential remains higher? Advice : Assign the responsibility to an intermediate object to mediate between other components or services so that they are not directly coupled.
Problem : What object should have the responsibility, when you do not want to violate High Cohesion and Low Coupling, or other goals, but solutions offered by Information Expert (for example) are not appropriate? Advice : Assign a highly cohesive set of responsibilities to an artificial or convenience class that does not represent a domain concept—sometimes invented to support high cohesion, low coupling, and reuse.
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? Advice : Identify points of predicted variation or instability; assign responsibilities to create a stable interface around them.
Interface is used in broadest sense – not just Java interfaces.
![general responsibility assignment software principles DZone](https://dz2cdn1.dzone.com/themes/dz20/images/dz_logo_2021_cropped.png)
- Manage Email Subscriptions
- How to Post to DZone
- Article Submission Guidelines
- Manage My Drafts
A Decade of Kubernetes: Tell us how K8s has impacted your dev journey (and enter for a chance to win $$).
Database Systems: In 2024, the focus around databases is on their ability to scale and perform in modern data architectures. See why.
Data Pipeline Essentials: Dive into the fundamentals of data pipelines and the problems they solve for modern enterprises.
Natural Language Processing: Learn all of the cutting-edge NLP techniques! * Affiliate
- 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
- Why You Should Use Buildpacks Over Docker
- A Complete Guide To Implementing GraphQL for Java
- How To Achieve High GC Throughput
- A Comparative Exploration of LLM and RAG Technologies: Shaping the Future of AI
- 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..
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.
IMAGES
COMMENTS
General Responsibility Assignment Software Patterns (or Principles), abbreviated GRASP, is a set of "nine fundamental principles in object design and responsibility assignment" [1]: 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 ...
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 ...
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.
GRASP (General Responsibility Assignment Software Patterns) is a set of guidelines that helps designers make informed decisions during the object-oriented design process. In this article, we will explore the key principles of GRASP and understand how they contribute to the creation of flexible and extensible software solutions. Creator
The General Responsibility Assignment Software Principles list nine principles: 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.
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.
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 ...
TechTarget Contributor. 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 ...
•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
GRASP. •Acronym for General Responsibility Assignment Software Patterns. •Has 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. •Can be applied during the creation of sequence diagrams. Information Expert.
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.
GRASP Stands for "General Responsibility Assignment Software Principles" Grasp principles can help you understand the fundamentals behind the GOF design patterns or in fact any other object ...
The GRASP (General Responsibility Assignment Software Patterns) principles are a set of guidelines in object-oriented design that help assign responsibilities to objects and classes in a system.
Responsibility: Responsibility can be: - accomplished by a single object. - or a group of object collaboratively accomplish a responsibility. GRASP helps us in deciding which responsibility should be assigned to which object/class. Identify the objects and responsibilities from the problem domain, and also identify how objects interact with each other.
General Responsibility Assignment Software Patterns (GRASP) Craig Larman describes how to assign responsibilities to classes using the following principles and patterns: Controller. Creator. High Cohesion. Indirection. Information Expert. Low Coupling. Polymorphism.
This playlist contains video sessions on all nine General Responsibility Assignment Software Principle (GRASP). These principles are very useful for creating...
Advice: Assign the responsibility to an object representing one of these choices: Represents the overall "system", a "root object", a 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. Avoid bloated controllers.
Jan 6, 2024. 50. GRASP. GRASP is a set of guidelines and patterns that help developers make informed decisions about assigning responsibilities to objects and classes within object-oriented design ...
A developer discusses the principles of object-oriented design, such as SOLID and GRASP and how to achieve maintainability, ... (General Responsibility Assignment Software Principles) published by ...
GRASP, or general responsibility assignment software principles, help guide object-oriented design by clearly outlining who does what: which object or class is responsible for what action or role ...
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]
GRASP stands for General Responsibility Assignment Software Patterns. It is a set of principles applied to Object Oriented Programming. There are nine principles or "patterns" which help ...
GRASP - General Responsibility Assignment Software Patterns (or Principles) - Free download as PDF File (.pdf), Text File (.txt) or read online for free. Grasp
ADOBE WORKFRONT Plan, assign, and execute work from one place. Build a marketing system of record by centralizing and integrating work across teams and applications with the industry-leading enterprise marketing work management application.