Objects are responsible for their state and behavior. Assigning responsibilities to objects effectively makes maintenance of a program less cumbersome.
This post summarizes the GRASP patterns and SOLID principles. They may be thought as the principles and patterns underlying the design patterns described in Design Patterns: Elements of Reusable Object-Oriented Software.
General Responsibility Assignment Principles or GRASP patterns were popularized by Craig Larman in his book Applying UML and Patterns (2001). They help with identifying objects required by a program, and their responsibilities.
Assign responsibility of creation to object that contains, or has the information required to create, a given object.
Assign responsibility to object representing a module’s facade, or a handler of a use case. Beware of a fat controller.
High Cohesion (HC)
Assign responsibility to object with closely related state and behavior. Don’t Repeat Yourself (DRY) rule helps maintain HC.
Assign responsibility to an intermediary object so that coupling is low.
Information Expert (IE)
Assign responsibility to object that has related information.
Low Coupling (LC)
Creation, inheritance, type reference, and message passing, all result in coupling. Assign responsibility such that coupling is low between objects that are not closely related in state and behavior.
Assign behavior to subclass when related behavior varies by type. Prefer aggregation and composition to inheritance.
Protected Variations (PV)
Assign responsibility to new object that provides a stable interface around known instabilities.
Pure Fabrication (PF)
Assign responsibility to a new object not derived from the domain to ensure LC and HC.
SOLID are more generalized principles popularized by Robert Martin aka Uncle Bob in his book Agile Software Development: Principles, Patterns, and Practices (2002).
Single-Responsibility Principle (SRP)
A class or module does one thing well. See HC.
Open-Closed Principle (OCP)
A class, module, or function, should be closed for modification but open for extension.
Liskov Substitution Principle (LSP)
Subclasses must be substitutable by their base (super) classes.
Interface Segregation Principle (ISP)
Avoid situation where clients depend on a fat interface. Changes to fat interface due to any client will affect all the other clients.
Dependency Inversion Principle (DIP)
Prevent modules in higher (more abstract) layers of an architecture from being impacted by changes in modules in lower layers. Abstractions should not depend on concrete implementations.