Object orientation has been the dominant paradigm of professional software development for 20 years. The days when “Data Structure + Algorithms = Programs” was a sensible book title are long gone. Instead of algorithms, we have networks of cooperating objects through which control flow bounces like a ball in a pachinko machine. And instead of data structures that slice up the abstract geometries of time and computational order into perfect crystals, we have dictionaries of strings to dictionaries of dictionaries of Accounts to dictionaries of Orders to floats (to strings? I got lost in there).
OOP’s greatest benefit may well be that it has a good learning curve: from the “objects are nouns, verbs are methods” of Object 101 to design and architectural patterns, to tying it back to universal principles like coupling and cohesion. Most of today’s professional software developers learned object-oriented programming either by being taught it or teaching themselves, and, for all the difficulty of hiring a new developer, the world of professional software developers has managed to grow from perhaps 3-5 million in the early 1990s to about 18 million, with another 8 million coming online in the next six years, according to Evans Data.
I know only two other paradigms that have similarly gentle early learning curves: block-oriented imperative languages from Fortran to Flash, and the declarative programming of spreadsheets. Both those paradigms have organizational trouble as application scope scales from individuals to departments to businesses to enterprises. In contrast, object orientation logically scales toward the service orientation that has proved most effective at the enterprise level.
Professional developers quickly move past the “objects are nouns, verbs are methods” concept. But the success of OOP relies, in important ways, on that simple mapping between concepts in the user’s mental model and concepts in the solution. In the 1979 document in which he introduced Model-View-Controller, Trygve Reenskaug said, “There should be a one-to-one correspondence between the model and its parts on the one hand, and the represented world as perceived by the owner of the model on the other hand.”
Forty years on, we know things are rarely that simple. I was programming a ChromeCast the other day, and there wasn’t a “Television” object in sight. Instead I had a “GCKMediaProtocolMessageStream” and half a dozen other equally cryptic classes. Reenskaug, for whom retirement is apparently distasteful, has diagnosed the problem as a loss of a proper mapping between the user’s mental model and software components. In “The DCI Architecture: A New Vision of Object-Oriented Programming,” Reenskaug and James Coplien present “Data, context and interaction,” which proposes that classic OOP does a poor job capturing the use-case-specific relationships between the particular objects that are cooperating.
Coplien’s book “Lean Architecture: for Agile Software Development” goes into much more detail on DCI, and Jim Gay’s “Clean Ruby” discusses it in the context of that language. The DCI vision substantially revises object orientation: traditional classes still define the data of “what objects are,” but the behavior of “what objects do” is defined elsewhere. In the context of a particular use case, objects adopt “roles” (subsets of their potential behavior); are brought together into a recognizable, but limited, network of cooperating objects; and the use-case behavior is triggered.
I was initially drawn to DCI because it seemed to capture some techniques that I’d had success with in the Scala world. (Scala’s “traits” feature is perfectly suited to DCI.) Lately I’ve been working with DCI in C# and F#, using extension methods as an implementation technique. A challenge with DCI is that it only makes sense in more complex applications; in a sample I wrote, I defined 13 types! That’s absurd for a trivial application, but in an enterprise application that’s fulfilling dozens or hundreds of use cases, it makes perfect sense to have a use case serviced by a few custom types and then have a large number of reused data objects.
I think DCI needs refinement (specifically, I think it overburdens the Controller component in an MVC application), but I’ve found myself drawn to it even in relatively small apps, because it makes algorithms look like algorithms again. Sometimes you only realize how much you miss something when it returns to you.
Larry O’Brien is a developer evangelist/advocate for Xamarin. Read his blog at www.knowing.net.