next up previous
Next: Determining the System Boundary Up: Essential Use Cases and Previous: System Responsibility

Essential Use Cases and Design

 

In object-oriented design, the term ``responsibility'' already holds a special role. In particular, responsibility is the pivotal concept in CRC cards, and in Responsibility-Driven Design.

In the CRC technique [4], responsibilities are associated with objects, and identify problems to be solved. Objects may send messages to other objects in the course of satisfying responsibilities, and these other objects are designated as collaborators. The arrangement and delegation of responsibilities and collaborators is then iteratively adjusted through many versions until a satisfactory structure emerges. In this way, responsibility guides the articulation of a system by partitioning classes to distribute responsibility. While CRC may have been originally cast as a pedagogical tool, it is now seen as useful in the context of practical system development [24, 5].

In responsibility-driven design [25, 26], the idea of responsibility is used more thoroughly and on a larger scale. Responsibilities are associated with objects, and represent knowledge an object maintains, or actions an object can perform. Responsibilities thus emphasize abstract behavior while being silent about possible implementation structure. However, objects may fulfill responsibilities by collaborating with other objects through message sending, and responsibilities may also be factored to higher level abstract classes. Together, such principles lead to designs where responsibilities are apportioned at high levels of abstraction, without any mention of object implementation.

The basic idea of ``responsibility'' seems to be the same in both CRC and responsibility-driven design, and the ways in which it is used seem consistent. Both techniques suggest that every object should have a coherent and well-understood set of responsibilities, and involve the concept of distributing responsibility sensibly as a guide to making design decisions. In essence, both use responsibility as a design heuristic. A basic principle of object-oriented design is that objects involve behavior and information that work together. Responsibility is good heuristic for determining this, because the word ``responsibility'' suggests both a duty to do something, and the resources with which to do it. Responsibility also allows delegation, allowing large responsibilities to be managed by delegating smaller responsibilities to others. Responsibility involves both abstraction and encapsulation, as Wirfs-Brock et al.[25] explain:

The responsibility-driven approach emphasizes the encapsulation of both the structure and behavior of objects. By focusing on the contractual responsibilities of a class, the designer is able to postpone implementation considerations until the implementation phase.

In essential use cases, the idea of a responsibility is to identify what the system must do to support the use case, without making commitments as to how it will actually be done. This resembles object encapsulation, where the internals of an object cannot be directly accessed from outside, and has similar benefits.

This role of responsibility in use cases is entirely consistent with the role of responsibility in design. Both describe behavior without describing implementation. This commonality presents valuable opportunities to link the way we work when determining requirements and the way we work when determining design.