21

I am learning DDD development for few days, and i start to like it.

I (think i) understand the principle of DDD, where your main focus is on business objects, where you have aggregates, aggregates roots, repositories just for aggregates roots and so on.

I am trying to create a simple project where i combine DDD development with Code First approach.

My questions are: (I am using asp.net MVC)

  1. DDD Business Objects will be different than Code First objects? Even if they will probably be the same, for example i can have a Product business object which has all the rules and methods, and i can have a Product code first (POCO) object which will just contain the properties i need to save in database.

  2. If answer to question 1 is "true", then how do i notify the Product POCO object that a property from business object Product has been changed and i have to update it? I am using an "AutoMapper" or something like this? If the answer is "no", i am completely lost.

Can you show me the most simple (CRUD) example of how can i put those two together?

Thank you

Catalin
  • 11,503
  • 19
  • 74
  • 147
  • this question might give you additional insights :http://stackoverflow.com/questions/8556365/ef-4-2-code-first-and-ddd-design-concerns/8560328#8560328 – Arthis Nov 05 '12 at 10:14

5 Answers5

8

Update I no longer advocate for the use of "domain objects" and instead advocate a use of a messaging-based domain model. See here for an example.

The answer to #1 is it depends. In any enterprise application, you're going to find 2 major categories of stuff in the domain:

Straight CRUD

There's no need for a domain object here because the next state of the object doesn't depend on the previous state of the object. It's all data and no behavior. In this case, it's ok to use the same class (i.e. an EF POCO) everywhere: editing, persisting, displaying.

An example of this is saving a billing address on an order:

public class BillingAddress {
  public Guid OrderId;
  public string StreetLine1;
  // etc.
}

On the other hand, we have...

State Machines

You need to have separate objects for domain behavior and state persistence (and a repository to do the work). The public interface on the domain object should almost always be all void methods and no public getters. An example of this would be order status:

public class Order { // this is the domain object  
  private Guid _id;
  private Status _status;

  // note the behavior here - we throw an exception if it's not a valid state transition
  public void Cancel() {  
    if (_status == Status.Shipped)
      throw new InvalidOperationException("Can't cancel order after shipping.")
    _status = Status.Cancelled;
  }

  // etc...
}

public class Data.Order { // this is the persistence (EF) class
  public Guid Id;
  public Status Status;
}

public interface IOrderRepository {
  // The implementation of this will:
  // 1. Load the EF class if it exists or new it up with the ID if it doesn't
  // 2. Map the domain class to the EF class
  // 3. Save the EF class to the DbContext.
  void Save(Order order); 
}

The answer to #2 is that the DbContext will automatically track changes to EF classes.

Rustom Aburas
  • 17
  • 1
  • 5
Josh Kodroff
  • 27,301
  • 27
  • 95
  • 148
2

The Pluralsight course: Entity Framework in the Enterprise goes into this exact scenario of Domain Driven Design incorporated with EF Code First.

For number 1, I believe you can do it either way. It's just a matter of style. For number 2, the instructor in the video goes through a couple ways to account for this. One way is to have a "State" property on every class that is set on the client-side when modifying a value. The DbContext then knows what changes to persist.

YeahStu
  • 4,032
  • 5
  • 48
  • 69
  • thank you, but unfortunately i can't download the tutorials from there. (i don't have a credit card to sign up) – Catalin Nov 04 '12 at 13:43
  • 4
    this Pluralsight course is a bit messy, Julie will teach you how to use generic repository antipattern and how to build lots of useless abstractions to make your code more complicated – IlliakaillI Feb 22 '13 at 19:21
  • 9
    hey I've learned plenty in the past 2 years and am no longer a fan of generic repos except for the most simple CRUD scenarios! I'll be updating that EF Enterprise course with the DDD stuff I've been learning since I built that prev. course. Plus EF now supports mocking much more smoothly ergo less abstraction. Hope you will be more fond of the udpate, ILICH. :) – Julie Lerman Jun 30 '14 at 22:59
2

The answer is No. One of the best things about EF code-first is that it fits nicely with DDD since you have to create your business objects by hand so do use your EF models to be equivalent to DDD entities and value objects. No need to add an extra layer of complexity, I don't think DDD recommends that anywhere.

You could even have your entities to implement an IEntity and you value objects to implement IValue, additionally follow the rest of DDD patterns namely Repositories to do the actual communication to the database. More of these ideas you can find this very good sample application in .NET, even though it doesn't use EF code first, it's still very valuable: http://code.google.com/p/ndddsample/

kabaros
  • 5,083
  • 2
  • 22
  • 35
  • 8
    It's true that Code First allows you to create the classes without worrying about the DB, but i don't think they can be replaced with Domain Objects, which has a lot of private properties, methods, readonly fields, all of them which can't be properly mapped by EF. That's why i think you should have two objects – Catalin Nov 05 '12 at 08:11
  • 2
    you can have all the stuff you mentioned, and you can ignore them in the mapping or map them to different column names etc... the mapping is part of an IRepository implementation and becomes an implementation detail that won't pollute your model. In all cases, good design is about managing complexity so even if you're not following DDD to the letter, you still better off with managing one business object layer. The only time where you might need such a mapping if you had a legacy database that you're hooking to and want to have a clean model then map it to another model that matches your db – kabaros Nov 05 '12 at 09:50
  • +1 agreed on the first paragraph but in the context of DDD, I also agree with OP that EF entities can't be treat as domain model because I just realize EF does not support mapping one db table to multiple entities. Domain model require to be created/mapped manually (using AutoMapper/ValueInjecter). This have to be done in business object. It gain framework complexity but I think reduce business development. – CallMeLaNN Jun 04 '13 at 16:18
  • The info above is not correct regarding value objects. Value objects do not have IDs by definition and entity framework (and relational databases in general) do not support this. – Josh Kodroff Mar 27 '14 at 15:05
  • 1
    EF6 does support Value Objects/ComplexTypes – Chazt3n Jan 07 '15 at 18:36
2

Recently I've done similar project. I was following this tutorial: link And I've done it this way: I've created Blank solution, added projects: Domain, Service and WebUI.

Simply said in domain I've put model (for example classes for EF code first, methods etc.) Service was used for domain to communicate with world (WebUI, MobileUI, other sites etc.) using asp.net webapi WebUi was actually MVC application (but model was in domain so it was mostly VC)

Hope I've helped

hyperN
  • 2,674
  • 9
  • 54
  • 92
1

Late question on this topic. Reading Josh Kodroff's answer confirms my thoughts about the implementation of a Repository to, for instance, Entity Framework DAL.

You map the domain object to an EF persistance object and let EF handle it when saving. When retrieving, you let EF fetch from database and map it to your domain object(aggregate root) and adds it to your collection.

Is this the correct strategy for repository implementation?

  • If you don't mind some compromise on domain models. Persistence infrastructure usually have some side effects on domain models making them suitable for persistence(but sometimes redudant for domain or totally change your models). – Yugang Zhou Sep 13 '13 at 09:50
  • This answer is more suitable as a comment or as a separate question. – ukliviu Sep 13 '13 at 10:07
  • Yes. Sorry, but I just registered and doesnt have 50 rep-points allowing me to comment on Josh's answer. Thanks for your comments though and thanks Hippoom, my thoughts exactly. – user2775864 Sep 13 '13 at 11:13