Saturday, May 19, 2007

Responsibility Driven Design

The classical approach to object based analysis and design is the process of taking your problem or solution statement and picking out the nouns (objects) and verbs (methods). The objects that emerge are considered as data, with a bunch of associated methods to operate on those data members.

As a method of organising your problem into code this works; but it can make the code more cumbersome that it could be. A common point at which this sort of problem arises is the point where two or more objects interact through a given verb, and it's not obvious where to put the verb. And then when it comes to implement, side effects or necessary pre-conditions for doing whatever verb have to be considered.

And finally, when we are coding a verb -- an algorithm -- associated with one object, we are working at a level below the object design, where things start to become purely procedural again -- this can lead to code (which I am sure that we have all seen examples of) such as :

class ObjectUser {
    void doSomethingWithData() { // return and argument lists immaterial
        // do some stuff
        bool switch = someObject->getSomeState();
        if(switch)
            // do something not involving this
        else
            // do something else also not involving this
        // do some more
    }
}

where we inspect the state of one object to do something without making any reference to the calling object's state.

This sort of code, once it exists, is amenable to refactoring, moving the if/else code into a new method on the class to which someObject belongs. You may even find that after doing this, the whole need for the public getSomeState() method may vanish. Even if someObject is of a class we don't own, specialising or wrapping it can still be a good move. We have a whole book (and web-site) on how to do that with code.

But, wouldn't it be nice to get the same effect ahead of time, during the analysis and design stages?

Responsibility driven design is one technique that can help with this.  Rather than the historic data+algorithm approach for looking at objects, the approach is to look at objects for their roles within the system and their responsibilities in making it work. It also helps us focus not on the static anatomy of the system (such as inheritance paths), but rather on the dynamic behaviour of the objects in their context, and emphasises the encapsulation part of object design.

In this approach an object is defined by what it knows, and what services it performs. Those services may be performed by passing parts of the tasks to other objects that this first object knows about; but the clients need not know about that. All they need to see is an interface, describing the services.

Thinking about or objects this way, we can take a rough partition of the system into objects -- perhaps a noun and verb model -- and start to assign roles : does this object know things? coordinate activities? perform services? interface with things beyond the system? Then we can perform what is in effect a dry run through the model, based upon known use cases. This will show up those cases where an object may actually need to know things not initially available to it.  It will also reveal where objects are being asked to do too many different things (and occasionally, those doing too little to justify themselves).

Objects that have more than one focus of responsibility are candidates for being broken up. Tasks that are not strictly related to their responsibility should be moved to objects for whom they are better suited.

After a couple of iterations -- which may be done on the fly, while running through the use cases -- the changes should settle down; and the web of interactions simplified.

With your objects defined by their roles (interfaces), and the unnecessary interactions untangled, the design is also readied for test driven development -- you have interfaces for mock objects to follow, and have reduced the amount of work that a mock will have to perform.

Related links

http://www.wirfs-brock.com/Design.html -- Rebecca Wirfs-Brock's site, pretty much the last word on the subject

http://www.cs.colorado.edu/~kena/classes/6448/s05/lectures/lecture04.pdf and http://www.cs.colorado.edu/~kena/classes/6448/s05/lectures/lecture05.pdf -- two lectures (presentations in .pdf form) as a high-level overview of Responsibility Driven Design

No comments :