2

Looking into incorporating ideas of Domain Driven Design into an application however our data model is not really a good fit for ORM like Hibernate. Very old database / data model, lots of compound / natural keys, lack of foreign keys, etc.

The item I am struggling with is how to design the domain layer without ORM since ORM would handle fetching items lazy or eager depending on how mappings are configured. I don't see how to avoid that without having DI framework (Spring in my case) inject the repository into the Domain objects, or have the repository fully initialize the domain object, which in itself may be overly wasteful.

  • 2
    Why don't you use a NoSQL database? – Constantin Galbenu May 4 '17 at 16:09
  • I work an enterprise environment, we are never going to switch to from Oracle or migrate off the current database, way to much time and cost. – greyfox May 4 '17 at 16:55
  • Your domain data model don't need to be the same model you persist in DB. You could add another layer of abstraction between the domain data model and the ORM – Laiv May 4 '17 at 18:16
  • Check out this blog post by Bob Martin. He reasons that our OO abstractions are too database-centric, and ORMs perpetuate it. That's not to say that ORMs are to blame, but they tend to reinforce designing everything around the database. – Scott Hannen May 4 '17 at 20:15
  • How much refactoring on the db could you do? – JeffO May 5 '17 at 17:10
4

The item I am struggling with is how to design the domain layer without ORM since ORM would handle fetching items lazy or eager depending on how mappings are configured.

Typically, the domain components operate on in memory state, without integrating with the ports and adapters in your system. Think onion architecture.

A second important idea is to make sure that the domain model is as explicit as possible about the information that is needed. This is usually done with the abstraction of a repository, but one where the contract is specific to the domain use case. Udi Dahan (2007) touched on the idea.

So the domain asks the repository for the absolute minimum that it needs to satisfy its own requirements, and the implementation under the covers figures out how to retrieve the necessary state and from it create an in memory model of that state.

Yes, in the pathological case, you might end up with a lot of repository implementations that carve specific data out of Oracle. It happens.

DI framework really doesn't figure into it unless you are intending to run the domain model in a lot of different environments; you just need repository discovery, which is to say a factory that provides the correct implementation of the repository on demand (aka the "repository" repository).

1

If you don't use an ORM tool, then you have to do the ORM yourself. Unfortunately, ORM adds a high level of complexity. There are some strategies to deal with the challenges, which you've alluded to.

Include the Repository in the Domain Object

Pro: Allows for lazy loading. The domain model keeps the data manipulation pretty simple while letting the repository component do the persistence layer.

Con: You might cause multiple database calls in some cases where one would have been enough. It can be more difficult to use the database to do the filtering for you. That means increased memory usage, and object manipulation.

Serialize everything from the Repository

Pro: You are in full control of the persistence process without triggering later calls to the database. You can use the database to apply filters, etc. much more easily.

Con: Can be very expensive when all you need is a summary of data in a large list.

Something In-Between

Some lessons I've learned when designing an app around a NoSQL database made me think a bit differently about how I was separating the data. I know that for the time being that solution is off the table. However, some of the same strategies apply to DDD:

  • Think about where the separation needs to be. I found that some light weight "reference" objects were great for supplying the summary information for lists, without getting everything from the children. Getting the parent and the reference child objects was pretty quick and let me populate the screen completely.
  • Don't add anything you don't need until you need it. If you choose to get everything at once, and that starts slowing down the app, you can add the complexity of lazy loading then.
  • Add tests as you go along.

DDD is both powerful and different from the current understanding of how to build applications. I find DDD favors environments where everything is in one layer like a desktop app. With web applications, you need to be able to serialize objects to and from JSON and have the screen react appropriately. The logic you painstakingly apply in the web application layer doesn't automatically convey to the web browser. I think that's why the anemic domain model is a bit more popular these days.


I will say that using a NoSQL database does solve a number of the woes surrounding the complexity that is ORM. If/when you can take a look at it, you'll see how it solves a number of the problems for you.

0

I'm confused by the implication that not using an ORM would be a challenge for domain-driven-design. If anything using an ORM makes it more challenging to build a proper domain model, in my experience.

So really the question here is how do you create the objects from the data, right? I cringe to think that working with databases is such a lost art that people think ORM is a necessity. The question is what tools you use to query and update. There are tools such as MyBatis that can help you manage connections etc. and use real SQL. Lazy/eager loading isn't difficult to implement. Are you looking for help with design/techniques for that?

0

I'd expect the domain objects to have minimal-to-no logic in them while the repository simply uses them and, possibly, some DTOs to go from your repository to domain objects.

In the project I'm working on, we have things like "CoffeeCup" and "CoffeeCupRo", where the latter is a repository object that understands the repository layout and has methods for converting to and from domain objects. This seems like it would solve your problem as well.

Comments taught me that this is a bad idea and you shouldn't repeat our mistake.

  • 1
    "I'd expect the domain objects to have minimal-to-no logic in them while the repository simply uses them and, possibly, some DTOs to go from your repository to domain objects." - Isn't the whole premise of DDD encapsulating the business logic into the domain objects? Seems like you are referring to anemic domain design, or maybe I misunderstood – greyfox May 4 '17 at 16:08
  • @greyfox - Not as I understand it. Domain objects should have very little logic in them, but be referenced by services that contain business logic and interact the the repository using the domain objects. I could be wrong, but that's my understanding. – William - Rem May 4 '17 at 16:40
  • 1
    martinfowler.com/bliki/AnemicDomainModel.html In regards to DDD itself, @greyfox is correct. That said, the service/data model that is more popular today is another good way of tackling the design. – Berin Loritsch May 4 '17 at 17:26
  • For hundreds of years, surgeons would bleed people to treat various illnesses because that was what other surgeons did. I know from painful experience that the anemic domain model has a necrotic effect on a code base. You might as well code in COBOL at that point. – JimmyJames May 4 '17 at 18:29
  • Huh. Well, my answer is patently wrong then, but I think our discussion in the comments has significant value for others, so I'm not going to delete it unless someone has a good reason to. – William - Rem May 4 '17 at 19:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.