Responsibility-driven design

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 functions should be finely grained, such as in Eiffel. Even finer control of the visibility of even classes is available in the Newspeak programming language.

Building blocks

In their book Object Design: Roles, Responsibilities and Collaborations,[1] the authors describe the following building blocks that make up responsibility-driven design.

Objects

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]

Roles

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]

Control style

An important part in the responsibility-driven design process is the distribution of control responsibilities that results in developing a control style.

Centralized control style

This control style inflicts a procedural paradigm on the structure of the application and places major-decision making responsibilities in only a few objects.

Advantages
Disadvantages
When to use

When decisions to be made are few, simple, and related to a single task.

Clustered control style

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]

Advantages
Disadvantages
When to use

When decisions to be made are few, simple, and related to a single task.

Delegated control style

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 significant role to play.

Advantages
Disadvantages
When to use

When one wants to delegate work to objects that are more specialized.

Dispersed control style

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]

Advantages
Disadvantages
When to use

Never.

Preferred control style

The inventors of responsibility-driven design recommend using a delegated control style because no one object knows or does too much.[20]

Conflict with the Law of Demeter

According to Wirfs-Brock and Wilkerson, there is a conflict between the Law of Demeter and responsibility-driven design. The law says that messages can be sent only to the following: message argument, instance variable, new objects, and 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."

References

Bibliography