Search code examples
ruby-on-railsactiverecorddomain-driven-designanti-patternsdomain-model

Rails Domain model decoupling of Activerecord


I have been reading the book "SQL Antipatterns: Avoiding the Pitfalls of Database Programming" especially around the magic beans anti pattern. In it shows a diagram decoupling activerecords by using a domain model and has example in PHP, but not Rails, it refers to this as HAS-A aggregation between domain models and views/controllers and HAS-A composition between domain models and activerecords (I presume this is UML speak).

In Rails it seems to be common place to make thin controllers fat models by using model methods, these methods may manipulate other associated models so that only one model can be used in any given controller. However, I wonder if there is a practice which includes total decoupling in Rails?

That is, to create a tableless model or other class to be used as a domain model acting as a layer between controllers and activerecord objects (which in turn are mapped to tables) so that controllers have better isolation and don't need to know anything about the underlying database and its structure. It also gives the option to move away from CRUD methods which don't explain the application requirements which they apply, another criticism in the book.


Solution

  • My comments come from utilizing DDD together with ASP.NET MVC. The recommended approach to binding controllers to domain entities is through view models, which are DTOs purposed specifically toward binding to a specific view. The view model provides a much needed buffer between the binding mechanisms and the domain model. Often times a given view may be a composition of multiple domain entities or even reporting objects and therefore does not correspond directly with any given domain entity. Having the attributes required for a view declared in a view model makes those data requirements explicit and does not lead one into trying to adjust the domain model to fulfill the needs of a view.

    The downside of course is the potential emergence of a dual-class hierarchy, where you may have a view model which corresponds to many of your domain entities. In practice however, I find that maintaining the dual class hierarchy is much easier than worrying about the ramifications of changing a domain entity. Take a look at The Fallacy of ReUse.

    In an SOA system, the objects which view models 'wrap' may not be domain entities but instead DTOs representing those domain entities. This does not violate the structure of the view models, since they are themselves DTOs and don't have behavioral aspects, only data. Take a look at this article which discusses the nature of data at application boundaries.

    To answer your question, I believe that creating a layer of view models would be advantageous for a Rails application, given all the caveats above. The view models would be populated with data from either an active record object or any other object containing data to be presented, and then when the user inputs data, the view model would update the active record object or domain model entity. Though I would avoid calling this view model layer a domain model.