A recent debate with a co-worker about different approaches to design and code the models in a Rails application brought me across DCI in the context of Rails.
However, I just can't seem to wrap my head around that entire concept, even after going over this example application.
Currently, I tend to just go more or less "by the book" when writing a Rails app.
So there are a few things I'd like to ask --
- What is DCI and what are its advantages when implemented alongside MVC over plain old MVC (and vanilla ActiveRecord in Rails) ?
- And how can it be implemented in Rails (or in other words, what's with all the modules) ?
Edit
I'd like to even further expand my question in the context of RoR - is another level of abstraction between the models and the controllers in Rails recommended? How widespread is it in different-scale applications?
For the people who are wondering whats DCI stands for..
DCI stands for
Data Context Interaction
At the heart of DCI is the cognitive tools it provides the developer. I'm not sure if you've seen all the great James Coplien/Trygve Reenskaug lectures, but I will try to distill the gist of it for anyone new to the concepts. It is about moving system behavior out of the systems' interacting domain objects(data entities, or what the system is), and into behavior objects(what the system does) as first class citizens which mediate the collaboration between objects by injecting them with functionality in the context of a use case just-in-time.
Think BDD. We code the behavior not across many objects like particulates of functionality spread out all over our data objects which are highly coupled to the persistence layer, but within cohesive objects that exist solely for a use case(story), and which inject capabilities into and coordinate the interactions of these dumb data objects. Like sheer layers of a physical architecture, slowly changing data objects are not loaded up with rapidly changing feature implementation that they carry around all the time. Rather, Ruby provides us the ability to easily inject the behavior into the objects at runtime when/if needed only in the context of a use case.
As an example in ROR, if you have a controller action involved in a use case in which there is an event probability matrix where most entries may be triggered in only a small percentage of requests, then instantiating a network of bloated behavior-heavy objects with the knowledge to execute every event for every possible use case of the data is unnecessary. Also, not having to dig through 18 files in my text editor to understand how that interaction works vs. having all the logic cleanly abstracted to patterns in an interface provided by the context object is a definite plus as well.
Regarding your question about 'another' layer of abstraction between controllers and models in rails, I'm not sure which other one your referring to. Regardless, Yes. By all means. No problem. Design patterns and Uncle Bobs' SOLID principles are pretty much generally accepted best practices in OO design. Both of these strongly encourage loosely coupled abstractions between policy and implementation. They both help avoid catostrophic brain dumps of roman empire demolishing magnitude, because they provide a common framework everyone understands. DCI, for me, provides the same type of cognitive framework, but for making a system easier to comprehend and deal with effectively, and this is the holy grail for any object oriented designer.
DCI is a paradigm and hence much more than a way to design an application. It's a way to think about modelling as well as structuring code. One of the important parts of DCI is keeping what the system is (the domain model) and what the system does (functionality) apart. DCI is not a different approach to solving the same problem as MVC so your first question can't really be answered. You can use MVC and DCI simultaneously which is no coincidence since Trygve Renskaug is the father of both MVC and DCI. He recently answered a similar question to this on the google group 'object-composition'.
The example you've linked to violates some of the basic ideas such as keeping roles private to the contexts and I couldn't actually find a single context either but that could be due to spending only a short time browsing the code.
I don't know RoR my self so I can't give you an RoR example but if you go to fullOO you'll find examples written in different languages including both Ruby and Marvin the first language designed for DCI.
EDIT There's no simply answer to the question "What is DCI" DCI is a paradigm, just like OOP is a paradigm. They both have the same roots and answering the above question is as complicated as answering "What is object orientented programming". Things are even more complicated by the fact that DCI is object oriented and OOP in all the major OO languages is actually class oriented and not object oriented. DCI aims at producing code where the interaction between objects at run time is visible in the code at compile time and in more general terms tries to mkae it easier to reason about the run time behavior from reading the code. The site I've linked to above is devoted to explaining what DCI is all about and also lists examples in a number of languages. Ruby being one of them
EDIT There's a book on ruby and DCI on it's way. The author is pretty active on object-composition and insightfull
There's a book (currently in progress) on using DCI in Ruby/Rails: Clean Ruby. I highly suggest putting yourself on the notification list - I've read parts of this book and it looks really good.
DCI is gaining acceptance in the Rails world - there's been a number of interesting blog posts about it over the last 3 months or so.