Idiomatic Ruby port of the DDD sample application
Ruby CSS Other
Latest commit b673943 Sep 19, 2014 @drsharp drsharp Merge pull request #63 from thomasvincent/patch-1
Updated URL's to reflect current

Thanks, Thomas!

README.adoc

Ruby DDD Sample App

Goal

The goal of this sample app is to provide an idiomatic Ruby port of the DDD sample application. It should remain faithful to the intention of the purposes of the original DDD sample application.

Why a Ruby port?

Because Paul wanted to learn Ruby and see how well it supports DDD. Also, interested in questions like:

  • How does the choice of Ruby affect the implementation of the DDD building block patterns?

  • How well does an opinionated MVC framework like Rails support doing DDD?

  • What are implications of choosing a document store like MongoDB for aggregate design and eventual consistency?

Why a DDD Sample App?

  1. Provide a how-to example for implementing a typical DDD application

    • Descriptive, not prescriptive

    • Idiomatic

    • Update sample app with latest ideas

  2. Support discussion of implementation practices

    • Engage Ruby community in dialog and learning about DDD

    • Show design and implementation tradeoffs

    • Teach DDD (tend to be Java & .NET) community more about Ruby

  3. Lab mouse for controlled experiments

    • Learn Ruby as a language and ecosystem

    • Can Rails + MongoDB carry the weight of a complex domain model?

    • Tradeoffs between Sinatra vs Rails for Ruby web apps

Problems with Sample Apps

DDD Sample Application

History

  • Sep 2008 First public release: 1.0.

  • Jan 2009 Sample application tutorial at the JFokus conference in Stockholm.

  • Mar 2009 Sample application tutorial at the QCon conference in London.

  • Mar 2009 New public release: 1.1.0. See changelog for details.

  • 2010/2011 Ported to .NET in several flavors.

  • May 8, 2013 Begin porting to Ruby at https://github.com/paulrayner/ddd_sample_app_ruby

  • May 13, 2013 Presentation of early work on port of sample app to Ruby at DDD Denver. Slides are available online.

The .NET port is being used as the primary basis for this Ruby port.

Implementation Stack

  • Persistence: MongoDB

  • Data access: Mongoid-backed repositories

  • Domain model: Plain Ruby objects

  • UI: Rails stack (w/ Twitter bootstrap)

  • Aggregate eventual consistency: Wisper-async leveraging Celluloid

  • GOAL: Before DDDx London - June 14 DONE!

_The focus of this version is to see how implementing a domain model within Rails affects the implementation.

Aggregates

The aggregate roots are:

  • Cargo

  • HandlingEvent

  • Location

  • Voyage

Design Decisions

Here you’ll find information on design choices made, and the relative tradeoffs. Plus resources for further reading. Actually, mostly resources right now.

Persistence

MongoDB

Mongo ORMs

  • Mongoid - Object-Document-Mapper (ODM) for MongoDB written in Ruby. Has Echo sample app - take a look at application.rb - it’s using Sidekiq and Kiqstand (not sure what for…​maybe could be used for aggregate updates?)

  • Mongomatic - A MongoDB super-set that adds nice features over the traditional Ruby Driver. Map your Ruby objects to Mongo documents. It is designed to be fast and simple.

  • MongoMapper - ODM for MongoDB written in Ruby.

Repository Pattern in Ruby

Have not yet found a repository implementation that supports aggregates. Rather, each implementation follows a repository-per-object approach, which is not what we need.

There is an on issue for Curator regarding supporting foreign keys and embedded objects, and some experimentation in a branch with adding a mapping API which may do what I need.

Entrepot looks promising. It uses Virtus for the objects and has this kinda weird approach of referencing a repository from a repository:

class Address
  include Virtus
  include Entrepot::Model

  attribute :street,  String
  attribute :city,    String
  attribute :country, String
end

class Person
  include Virtus
  include Entrepot::Mongo::Model

  attribute :name,     String
  attribute :address,  Address
end

class PersonRepository
  include Entrepot::Repository

  has_many :articles, :repository => :ArticleRepository
end

Aggregates

Concurrency in Ruby

Eventual Consistency

Resources for implementing eventual consistency (i.e. performing asynchronous updates) between aggregate instances.

DDD and Rails

Contributing

This is a learning experiment, pull requests are welcome! Bonus points for feature branches.

To get started, see milestones and issues. Use the vanilla .NET port version as the basis for any work.

Progress and learning will be shared after the DDD Exchange on June 14 through posts on Paul Rayner’s blog.

Copyright © 2013 Paul Rayner. See LICENSE for details.