Responsibility-driven design

From Wikipedia, the free encyclopedia
Jump to: navigation, search

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[edit]

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

  • Application : A software application is referred to as a set of interacting objects[2]
  • Candidates : 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]
  • Collaborations : A collaboration is defined as an interaction of objects or roles (or both).[2]
  • CRC Cards : 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.
    • Content of lined side : On this side the candidate's name, its responsibilities and its collaborators are recorded.[4]
    • Content of unlined side : On this side the candidate's name, its purpose in the application, stereotype roles and anything worthwhile such as the names of roles in patterns it participates in are recorded.[4]
  • Hot Spots : Hot Spots are points in the application where variations occur. They are recorded using Hot Spot Cards.[5]
  • Hot Spot Cards : 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:
    • Hot Spot Name
    • General description of the variation
    • At least two specific examples where the variation occurs

Objects[edit]

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]

  • Object Neighborhoods : Another term for subsystem.[6] It is a logical grouping of collaborators.[6]
  • Responsibilities : A responsibility is an obligation to perform a task or know information.[2] These are further categorized according to their usage scenario.
  • Public Responsibilities : Public responsibilities are the responsibilities an object offers as services to others and the information it provides to others.[7]
  • Private Responsibilities : Private responsibilities are the actions an object takes in support of public responsibilities[7]
  • Subresponsibilities : 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.
    • Subordinate Responsibilities : These are the major steps of the subresponsibility.[8]
    • Sequencing Responsibility : This responsibility refers to the sequencing of the execution of subordinate responsibilities.[8]

Roles[edit]

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 : Role stereotypes are simplified roles that come with predefined responsibilities.[10] There are several categories.
  • Controller : Objects implementing this role make decisions and closely direct the action of other objects.[10]
  • Coordinator : This role reacts to events by delegating tasks to others.[10]
  • Information Holder : Information holder know and provide information.[10]
    • Information Provider : 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]
  • Interfacer : This role transforms information and requests between distinct parts of an application.[10] It is further divided into more specific roles.
    • External Interfacer : 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]
    • Internal Interfacer : Also called intersystem interfacers.[11] These interfacers act as a bridge between object neighborhoods.[12]
    • User Interfacer : These interfacers communicate with users by responding to events generated in the UI and then passing them on to more appropriate objects.[11][12][13]
  • Service Provider : This role performs work and offers computing services.[11]
  • Structurer : This role maintains relationships between objects and information about those relationships.[11]

Control style[edit]

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

  • Concept of Control : Control styles rely 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]
  • Control Centers : 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]
  • Control Style Variations : 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.

Centralized control style[edit]

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
  • Application logic is in one place.
Disadvantages
  • Control logic can get overly complex
  • Controllers can become dependent on information holders' contents
  • Objects can become coupled indirectly through the actions of their controller
  • The only interesting work is done in the controller
When to use

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

Clustered control style[edit]

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
  • Application logic is in one place.
Disadvantages
  • Control logic can get overly complex
  • Controllers can become dependent on information holders' contents
  • Objects can become coupled indirectly through the actions of their controller
  • The only interesting work is done in the controller
When to use

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

Delegated control style[edit]

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
  • It is easy to find out how something works since only few objects are involved[18]
  • It is reusable because each object is largely capable of fulfilling its own responsibilities[18]
  • System functions can be used in relative isolation since they are organized into pools of responsibilities[18]
  • Delegating coordinators tend to know about fewer objects than dominating controllers
  • Dialogs are higher-level
  • Changes typically affect fewer objects
  • It is easier to divide design work among team members
Disadvantages
  • Too much distribution of responsibility can lead to weak objects and weak collaborations
When to use

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

Dispersed control style[edit]

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
  • None
Disadvantages
  • When you want to find out how something works, you must trace the sequence of requests for services across many objects
  • Not very reusable because no single object contributes much
When to use

Never.

Preferred control style[edit]

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[edit]

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[edit]

Bibliography[edit]