SQLAlchemy and DDD – Developing a Unique Pattern

domain-driven-designsqlalchemy

While reading "Patterns, Principles, and Practices of Domain-Driven Design" by Nick Tune; Scott Millett (certainly not the first book on DDD I've read) I started to understand usage of Martin Fowler's EAA patterns with DDD and with that there came a question.

A single SQLAlchemy model is like Active Record (if I understand it correctly), however, a set of SQLAlchemy models is very good at abstracting persistence mechanism away, so I always thought following Domain Model, degrading in some places to Anemic Domain Model.

In many cases there still are Transaction Scripts, touching several Entities. I am trying to keep these in actions / services (Service Layer?) because it feels wrong to have actions touching multiple models in the model classes themselves (circular dependencies can occur) unless they are subordinate (lay lower in the aggregate structure).

The result is not quite a pure pattern (as business logic is between "actions" and "active records") – more like some kind of hybrid of those mentioned above – but it is working in practice, captures domain knowledge (both verbs and nouns) well, fits naturally with SQLAlchemy persistence.

What pattern SQLAlchemy models (in ORM mode) naturally represent and how operations, which touch several models, can be fit into DDD way? Is there anything I can improve on the described above?

To clarify more, this question and it's answers deals with another, similar in spirit, dilemma: whether to use ORM classes directly for the domain model or add one more layer (and the favorite answer is not to overarchitect).

In this question, I am trying to find a good way to place multi-entity behaviors. My take is that "action" / "service" modules with function per action is the right place (in Python it is usual to use module level functions when there is no shared state).

Best Answer

This is a common issue, and the cause is usually related to a shallow understanding of DDD. The purpose of DDD is to model the functional requirements of your system such that the result is a useful abstraction of the core rules of your business domain. Often developers fail to understand why this is important and create a domain model almost directly mapped from their persistence model. Because data is usually a poor starting point for modeling the functional requirements of a system, this usually will result in a highly-coupled system where rules are devoid of context (and are therefore useless).

When creating a domain model, the business requirements should be the absolute focus. This often means that the most useful domain models are created before a physical model is made to store/relate/normalize the data involved. You should seek to keep your persistence layer (physical model) as loosely coupled to your domain model as possible. That's the entire point of a layered architecture right?

While I agree with the sensibilities put forth in the link you provided, it is simply a poor design choice to give your necessarily anemic persistence model (ORM) the responsibility of being your domain model. An ORM is a tool not a solution, and not something your domain should be aware of in any way, shape, or form (it needn't know nor care if/how it's persisted).

You, yourself, have already started running into the problems of mixing the two. By using your persistence model as your domain model, it is preventing you from properly modeling business processes that are dependent on data from two entities (clearly the data in this case should be combined into a single domain entity). This is precisely the reason mixing the two doesn't work. Your application is going to devolve into a system where your "models" are simply bags of data being passed around as arguments to "rules/processes". That separation of data and behavior is fundamentally procedural in nature, not OOP, and certainly not DDD.

Related Topic