8 comments

[ 2.5 ms ] story [ 38.6 ms ] thread
I've been applying DCI with my team for the past few months and have found it allows for much greater flexibility in design. We can keep our classes small and cohesive and in turn we find the code easier to understand in a lot of ways. Specifically, the fact that design can be driven by scenarios centered around the contexts gives a clear flow of logic from the controller to the domain.

In a lot of ways DCI will almost seem a bit like having a meta-MVC within your MVC application. I like to think of it as a MVC-like pattern for the domain, decoupling your domain from the infrastructure of the web-tier.

If you are unfamiliar with DCI, I'd recommend checking out the Oredev videos where it was first introduced:

http://vimeo.com/8235574

http://vimeo.com/8235394

Also Jim Gray is currently working on a book (I've pre-ordered and get the chapters as they are being written) http://clean-ruby.com/

I'm not sure I can consider it a meta MVC pattern however. They way I use it is a completely separate pattern in a completely different application.

By decoupling the business layer from the delivery mechanism (the web), I can use DCI as a pattern the effectively organizes my business application and use MVC specifically for my display/web application. Although, the MVC pattern sort of breaks down when you abstract out your business layer and your infrastructure layers. It turns into something more like VC where your controllers interact with your interactors and push the data to the views depending on the interactor logic.

Does anybody else see similarity between this

  authenticate = SApp::AuthenticateUser.authenticate(...
  action = authenticate.action
  if action != :login_error
    redirect_to "/#{action}"
  ...
  def find_account
    @account = SApp::FindAccount.find(@account_subdomain)
  end
and this http://en.wikipedia.org/wiki/Inner-platform_effect http://thedailywtf.com/Articles/Soft_Coding.aspx
Do you have any better way of approaching this?

I mainly posted code examples to show the general idea of what I'm trying to describe. My actual code base has a lot of logic locked behind the authentication and which action to take after the user is authenticated (there are about 4 different places they could land).

4 other use cases are then discovered in the underlying app depending on which action they are taken to.

> Do you have any better way of approaching this?

No, but frankly speaking I don't get the idea from the keynote speech.

2012 and there are no example apps of that concept. I don't get it.

This is an interesting approach.

One change I would make is in the testing of the lib directory. I've found it best to separate the testing of the lib directory contents from the unit and functional tests that are baked into Rails. It requires a bit of custom setup, but it's easy to reuse in other applications.

1. Create a test/lib directory

2. Create a lib/tasks/test_libs.rake file

3. Put the following into the Rake file[1]:

    namespace :test do
      desc "Test libraries"
      Rake::TestTask.new(:libs) do |t|
        t.libs << "test"
        t.pattern = 'test/lib/**/*_test.rb'
        t.verbose = false
      end
    end

    lib_task = Rake::Task["test:libs"]
    test_task = Rake::Task[:test]
    test_task.enhance { lib_task.invoke }
4. Run `rake test:libs` to test just your lib directory.

[1] Credit goes to http://stackoverflow.com/a/1588496 for this Rake task.

Just to be clear, the code inside of the lib and test directories is not actually inside of our rails application. They're inside of a different git repository and are packed as a separate gem. It makes more sense to me once you've isolated the code this way that you would then write "use case tests" and then role tests (which I haven't gotten into yet.. next post :))