Responsibility-driven design is a design technique in Object-oriented programming. It was proposed by Rebecca Wirfs-Brock and Brian Wilkerson who defined it as follows:
Responsibility-driven design is inspired by the client/server model. It focuses on the contract by asking:
- What actions is this object responsible for?
- What information does this object share?
Responsibility-driven design is in direct contrast with Data-driven design, which promotes defining the behavior of a class along the data that it holds. Data-driven design is not the same as Data-driven programming which is concerned with using data to determine control flow not class design.
The client/server model they refer to assumes that a software client and a software server exchange information based on a contract that both parties commit to adhere to. The client may only make the requests specified, the server must answer them. Thus, responsibility-driven design tries to avoid dealing with details, such as the way in which requests are carried out, by instead only specifying the intent of a certain request. The benefit is increased encapsulation, since the specification of the exact way in which a request is carried out is private to the server.
To further the encapsulation of the server, Wirfs-Brock and Wilkerson call for language-features that limit outside influence to the behavior of a class. They demand that visibility of members and function should be finely grained, such as in Eiffel. Even finer control of the visibility of even classes is available in the Newspeak programming language.
Contents
|
In their book Object Design: Roles, Responsibilities and Collaborations[1] the authors describe the following building blocks that make up Responsibility-Driven Design.
A software application is referred to as a set of interacting objects[2]
Candidates or candidate objects are key concepts in the form of objects described on CRC cards. They serve as initial inventions in the process of object design.[3]
A collaboration is defined as an interaction of objects or roles (or both)[2].
CRC stands for Candidates, Responsibilities, Collaborators. They are index cards used in early design for recording candidates[4]. These cards are split up into an unlined and a lined side.
On this side the candidate's name, its responsibilities and its collaborators are recorded[4].
On this side the candidate's name, its purpose in the application, stereotype roles and anything worthwile such as the names of roles in patterns it participates in are recorded[4].
Hot Spots are points in the application where variations occur. They are recorded using Hot Spot Cards[5].
Hot Spot Cards are used for recording variations, so called hot spots. They are similarly to CRC cards low-level tools in the form of index cards[5]. These cards consist of:
Objects are described as things that have machinelike behaviors that can be plugged together to work in concert. These objects play well-defined roles and encapsulate scripted responses and information[2].
Another term for subsystem[6]. It is a logical grouping of collaborators[6].
A responsibility is an obligation to perform a task or know information[2]. These are further categorized according to their usage scenario.
Public responsibilities are the responsibilities an object offers as services to others and the information it provides to others[7].
Private responsibilities are the actions an object takes in support of public responsibilities[7]
These responsibilities come into existence whenever a large or complicated responsibility is split up into smaller ones[8]. They are further categorized by what they do.
These are the major steps of the subresponsibility[8].
This responsibility refers to the sequencing of the execution of subordinate responsibilities[8].
A role is a set of related responsibilities[2]. They can be implemented as classes and interfaces. Interfaces, however, are the preferred implementation as they increase flexibility by hiding the concrete class which ultimately does the work[9].
Role stereotypes are simplified roles that come with predefined responsibilities[10]. There are several categories.
Objects implementing this role make decisions and closely direct the action of other objects[10].
This role reacts to events by delegating tasks to others[10].
Information holder know and provide information [10].
A slight variation of an information holder is the information provider, which takes a more active role in managing and maintaining information. This distinction can be used if a designer needs to get more specific[11].
This role transforms information and requests between distinct parts of an application[10]. It is further divided into more specific roles.
These interfacers communicate with other applications than your own.[11]. They are mainly used for encapsulating non-object-oriented APIs and do not collaborate a lot.[12].
Also called intersystem interfacers[11]. These interfacers act as a bridge between object neighborhoods[12].
These interfacers communicate with users by responding to events generated in the UI and then passing them on to more appropriate objects. [11][13][12]
This role performs work and offers computing services[11].
This role maintains relationships between objects and information about those relationships[11].
An important part in the Responsibility-Driven Design process is the distribution of control responsibilities that results in developing a control style.
Control styles relie heavily on the concept of Control. Therefore it makes sense to properly define the term. It is defined as decision making and selection of paths through an application[14].
An important aspect of developing a control style is the invention of so called control centers. These are places where objects charged with controlling and coordinating reside.[15].
A control style comes in three distinct variations. These are not precise definitions though since a control style can be said to be more centralized or delegated than another.
This control style inflicts a procedural paradigma on the structure of the application and places major-decision making responsibilities in only a few objects.
When decisions to be made are few, simple, and related to a single task.
This control style is a variation of the centralized control style wherein control is factored among a group of objects whose actions are coordinated[16]. The main difference between a clustered and delegated control style is that in a clustered control style, the decision making objects are located within a control center whereas in a delegated control style they are mostly outside[17].
When decisions to be made are few, simple, and related to a single task.
A delegated control style lies in between a centralized and dispersed control style. It passes some of the decision making and much of the action to objects surrounding a control center. Each neighboring object has a signifcant role to play.
When you want to delegate work to objects that are more specialized.
A dispersed control style does not contain any control centers. The logic is spread across the entire population of objects, keeping each object small and building in as few dependencies among them as possible[19].
Never.
The inventors of Responsibility-Driven Design recommend using a delegated control style because no one object knows or does too much[20].
According to Wirfs-Brock and Wilkerson, there's a conflict between the Law of Demeter and Responsibility-driven design. The law of Demeter says that messages can be sent only to the following: message argument, instance variable, new objects, global variables. Therefore, sending a message to the result of a previous message send isn't allowed. However, "returned values are part of the client/server contract. There need be no correlation between the structure of an object and the object returned by the message."