SalesLineItems, so it has the information necessary for total
SalesLineItemknows the quantity, so it has the information necessary for subtotal
ProductDescriptionknows the price
«General Responsibility Assignment Software Principles»
After identifying your requirements and creating a domain model, add methods to the appropriate classes and define the messaging between the objects to fulfill the requirements.”
A responsibility an obligation to perform a task or know information
doing something itself: create an object, process data, do some computation/calculation
initiate and coordinate actions with other objects
private and public object data
related objects references
things it can derive
a single object or
a group of object collaboratively accomplish a responsibility.
What is a general principle for assigning responsibilities to objects?
Assign a responsibility to the information expert, that is, the class that has the information necessary to fulfill the responsibility.
They have all the information needed to perform operations, or in some cases they collaborate with others to fulfill their responsibilities.
SalesLineItems, so it has the information necessary for total
SalesLineItem knows the quantity, so it has the information necessary for subtotal
ProductDescription knows the price
knows sale total
knows line item subtotal
knows product price
Basic Object-Oriented principle
Objects know things related to the information they have
The information necessary may be spread across several objects
Just because an object has information necessary does not mean it will have responsibility for action related to the information
Who should be responsible for creating a new instance of a class?
B the responsibility to create an instance of class
A if one or more of the following is true:
B records instances of
B closely uses
B has the initializing data that will be passed to
A when it is created (thus
B is an Expert wrt creating
If more than option applies, prefer class
B which aggregates or contains class
SalesLineItem objects, it should be responsible for creating Items.
The association is a composite aggregation.
When creating requires complexity, such as using existing instances of a class, conditionally creating an instance from one class or another based upon some external property, etc.
In these cases, delegate creation to a helper class called a Concrete Factory or Abstract Factory
Related Design Patterns: Concrete Factory, Abstract Factory
Who should be responsible for handling a system event? (Or, what object receives and coordinates a system operation?)
Assign the responsibility for receiving and/or handling a system event to one of following choices:
Object that represents overall system, device or subsystem (façade controller)
Object that represents a use case scenario within which the system event occurs (a «UseCase»x Handler)
vent generated by an external actor associated with a system operation
a non-UI object responsible for receiving or handling a system event
During analysis, we can assign system operations to a class
That does not mean there will be a
System class at time of design
During design, a controller class is given responsibility for system operations
Controller is a façade into domain layer from interface layer
Often use same controller class for all system events of one use case so that one can maintain state information, e.g. events must occur in a certain order
Normally controller coordinates activity but delegates work to other objects rather than doing work itself
represents the overall system — use when there are not many system events
use different controller for each use case
Single class receiving all system events and there are many of them
Controller performs many tasks rather than delegating them
Controller has many attributes and maintains significant information about system which should have been distributed among other objects
Related Design Patterns: Command, Façade, Layers
How to support low dependency, low change impact, and increased reuse?
Assign responsibilities so that (unnecessary) coupling remains low. Use this principle to evaluate alternatives.
Coupling is measure of how strongly one element is connected to, has knowledge of, or depends on other elements
The greater the coupling, the greater the dependence between objects
Coupling is avoided because it goes against OO principles
It reduces time, effort and defects involved in modifying software
A class with high coupling relies on many other classes and leads to different problems:
Changes in related classes force local changes
Harder to understand in isolation
Harder to reuse
Sale. Who should be responsible for creating a
Paymentand associating it with a
Since a Register records a Payment it should have this responsibility (cf Creator)
p then sends
p to a
Sale (coupling of Register class to Payment class)
Sale to create a
In both cases a
Sale needs to know about a
Register needs to know about a
Payment in the first but not in the second solution
The second alternative leads to less coupling:
Avoids an association between
Payment are already related
High coupling to stable or pervasive elements is not a problem (e.g. Java libraries)
High coupling is a problem only in areas where change is likely (e.g. Domain Classes)
classes are easier to understand in isolation
changes in other components do not affect the class
it is easy to reuse a single class than several intricate classes
How to keep complexity manageable?
Assign the responsibility so that cohesion remains high. Use this principle to evaluate alternatives.
Cohesion is a measure of how strongly related and focused the responsibilities of an element (class, subsystem, etc.) are
Easy to understand/comprehend
Easy to reuse
Easy to maintain
In isolation, there is no problem
But if we start assigning additional system operations to
Register then will violate high cohesion
Register delegates Payment creation to the Sale:
This second approach leads to higher cohesion for the
Note: this design supports both, low coupling and high cohesion
High cohesion, like low coupling, is an evaluative principle
a class is responsible for many things in different functional areas
a class has sole responsibility for a complex task in one functional area
a class has lightweight and sole responsibilities in a few different areas that are logically related to the class concept but not to each other
a class has moderate responsibilities in one functional area and collaborates with other classes to fulfill tasks
Typically high cohesion leads to few methods with highly related functionality
these two principles are closely related, often low cohesion leads to high coupling and vice-versa
classes/components are simpler, having fewer operations.
logical changes in the domain affect fewer modules, and changes in one module require fewer changes in other modules.
application developers will find the component they need more easily among the cohesive set of operations provided by the module.
where to assign a responsibility to avoid direct coupling between two or more things?
assign the responsibility to an intermediate object to mediate between other components or services so that they are not directly coupled.
⇒ The intermediate object creates an indirection between the other components
Adapter acts as a level of indirection to external systems
Main benefit: lower coupling between components
Related Design Patterns: Adapter, Bridge, Façade, Observer, Mediator.
How to handle alternatives based on element type? How to create pluggable software components?
When alternatives or behaviors vary by type (class), assign responsibility for the behavior—using polymorphic operations—to the types for which the behavior varies.
Corollary: Do not test for the type of an object and use conditional logic to perform varying alternatives based on type
How to handle multiple external third-party tax calculators?
a design based on assigning responsibilities by polymorphism is easily extend (by the addition of new classes).
Related Design Patterns: Several Design Patterns rely on polymorphism: Adapter, Command, Composite, Proxy, State, and Strategy
What object should have the responsibility, when you do not want to violate High Cohesion and Low Coupling but solutions offered by other principles are not appropriate?
Assign a highly cohesive set of responsibilities to an artificial or convenience class that does not represent a problem domain concept.
Salein a relational database?
According to Information Expert, it should be
this task requires database-oriented operations (reduces cohesion)
the class becomes highly coupled to the database interface (increases coupling)
Persisting objects is a common task that should be more generic
Pure Fabrication usually takes on responsibilities from the domain class that would be assigned those responsibilities based on Information Expert
Several Design Patterns are Pure Fabrications: Adapter, Command, Strategy, etc.
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?
Identify points of predicted variation or instability, assign responsibilities to create a stable interface around them.
Core Protected Variations Mechanisms: data encapsulation, interfaces, polymorphisms, standards, etc.
Service Lookup: JNDI, UDDI, etc.
Reflective or Meta-Level Designs
Uniform Access: Ada, Eiffel, C# support properties
Standard Languages: SQL
The Liskov Substitution Principle
Structure-Hiding Designs: Law of Demeter
Caution: Speculative PV and Picking Your Battles
Two points of change are worth defining: variation point and evolution point
See also: Information hiding and the Open-Closed Principle