Sunday, April 10, 2011

Data, Context, and Interaction (DCI) Architecture

I started reading about DCI last year, and it sounded interesting, but the more I've thought about it, the more enthusiastic I've become.

DCI is the creation of Trygve Reenskaug, the inventor of MVC.  James Coplien is also very involved in advancing DCI, and it is one of the main topics of his latest book, "Lean Architecture".

DCI could have as much impact as MVC on the way we build software.

I did a presentation on DCI last November. In preparation, I wrote up an introduction and posted it on the DCI (object composition) mailing list, asking for comments. Here's the revised version (with great thanks to James Coplien and the others who provided feedback):

Data-Context-Interaction (DCI)

Although the concept of roles is not new in software development, DCI promotes roles to a critical level of importance. Domain objects are not reduced in importance, but are set free from all of the baggage typically dumped on them to support all of the roles they are expected to fill. The objects are distilled to their basic essence, still encapsulating their data, but only providing the methods essential to what the object “is”, not everything it “does”.

Roles are the home for all of the things an object "does". ("Is" and "does" are the authors' terms for distinguishing between an object's core responsibilities and its roles.) Obviously each object can fill many roles, with each role cleanly separating what would otherwise be mashed into one of the many personalities of the object. In addition, the role / object separation opens up the possibility of having roles that support many types of objects – as long as the underlying object supports the interface required by the role, everything’s good.

In DCI, roles are not standalone objects; they don't even have to be implemented as classes. A role is a set of methods to be dynamically added to an object. In Ruby, roles can be implemented as modules, simply extending the appropriate domain objects. (It’s a bit more complicated in crustier languages ;-)

The linking of roles to domain objects is the responsibility of the Contexts. Each user / system interaction scenario is represented by a context, typically initiated by a controller. The context not only assembles the roles and objects, but also orchestrates any high-level interaction that does not cleanly fit within the object roles nor the controller (for example, a sequence of steps specific to the implementation of a story).  Contexts can be nested and reused, but should be stacked, so that only one is active at any time.