DDD (Domain Driven Design) + wzorzec MVC + ORM

4

Witam.
Jednym z głównych założeń DDD jest to, że obiekty domeny nie powinny być tylko zwykłymi kontenerami na dane, zawierającymi gettery i settery. Prowadzi to do tzw. 'anemic domain model' czyli stanu gdy, obiekty domeny posiadają tylko stan (są kontenerami na dane), nie posiadają zachowania (metod) a logika biznesowa obsługiwana jest przez specjalne obiekty-serwisy, które operują na właściwościach obiektów.
Obiekty domeny również powinny być zawsze w stanie poprawnym i spójnym (przykład: jeżeli mam obiekt klasy Uzytkownik z polem string Email, to do tego pola nie można przypisać wartości, która nie jest zgodna z wyrażeniem regularnym obsługującym tego emaila)
Obiekty są tworzone często przez konstruktor i występują typy złożone jak np typ Address dla Uzytkownika.

Pytanie dla tych, którzy stosują DDD jest następujące - jak sobie radzicie z tym problemem i zastosowaniem poszczególnych ORM'ów (np Entity Framework Code First). Czy stosujecie encje, które mają publiczne gettery i prywatne settery? Czy może tworzycie drugą warstwę z obiektami domeny, które są następnie konwertowane na Encje (wtedy niestety, w przypadku wzorca MVC mamy dużo konwersji - ViewModel -> Domain Object -> ORM Entity). Czy może pomijacie ten aspekt DDD?

W wielu projektach, których autorzy twierdzą są zgodne z DDD obiekty domeny są to encje z publicznymi właściwościami i są obsługiwane przez Serwisy, więc tak naprawdę nie są one zgodne z podstawowymi założeniami DDD (oczywiście podział na warstwy i zasady SOLID są zachowane.)

Mamy wtedy do czynienia z taką architekturą Controller->ViewModel->Service (operacje biznesowe) ->Repository->DB
Przykład:

public JakisController : Controller {
   private IProductService productservice;
   public JakisController(IProductService productservice) {
       this.productservice=productservice.
   }
   [HttpPost]
   public ActionResult ModifyProduct(ProductModifyViewModel model) {
        var result = productservice.Modify(model);
        return View(result)
   }
}

gdzie:

public class ProductService : IProductService {
     private IProductRepository productrepository;
     public ProductService(IProductRepository productrepository) {
          this.productrepository=productrepository;
     }
     public ProductModifyResult Modify(ProductModifyViewModel model) {
         .....operacje biznesnowe na encji.......
         .....zapis w repozytorium.....
     }
}
public class ProductRepository : IProductRepository, Repository<Product> {
     .........operacje na bazie danych..............
}

Czy Wasze ORM-owskie klasy-encje spełniają jednocześnie rolę obiektów domeny i zawierają metody? Jeżeli tak to jak je testujecie? Czy dodatkowo wprowadzacie dla tych encji-obiektów-domeny interfejsy?

3
micc napisał(a):

Czy stosujecie encje, które mają publiczne gettery i prywatne settery?

Aby być zgodnym z DDD, tak należałoby robić. Ponadto, kolekcje powinny być tylko do odczytu, tak aby nikt nie mógł sobie zrobić np. faktura.Pozycje.Dodaj(...), tylko musiał użyć faktura.DodajPozycję(...).

Czy może tworzycie drugą warstwę z obiektami domeny, które są następnie konwertowane na Encje (wtedy niestety, w przypadku wzorca MVC mamy dużo konwersji - ViewModel -> Domain Object -> ORM Entity).

Utworzenie dodatkowego zestawu klas nic nie daje, poza koniecznością utrzymywania niepotrzebnego kodu.
Najpierw tworzymy encje domeny, a potem mapujemy je ORMem i to wystarczy.

Czy może pomijacie ten aspekt DDD?

Jeśli mam być szczery, to jeszcze nigdy nie widziałem prawidłowego DDD w żadnym projekcie, i coraz bardziej wątpię w to, że takie coś w Polsce istnieje. Zawsze jest ADM z publicznym wszystkim co się da i niekiedy zestawem pomocniczych metod biznesowych.

Mamy wtedy do czynienia z taką architekturą Controller->ViewModel->Service (operacje biznesowe) ->Repository->DB

To jest raczej dobra architektura, bo serwisy również są częścią DDD. Moim zdaniem złe (właściwie c****, ale forum tego słowa nie przepuści) jest korzystanie z repozytorium (czy innej formy dostępu do danych) bezpośrednio z kontrolera.

Czy Wasze ORM-owskie klasy-encje spełniają jednocześnie rolę obiektów domeny i zawierają metody? Jeżeli tak to jak je testujecie? Czy dodatkowo wprowadzacie dla tych encji-obiektów-domeny interfejsy?

Jeśli chodzi o testy, to testuję jednostkowo. ;) Trochę mało konkretne to pytanie.
Interfejsy dla encji? Brzmi hardcorowo, a po co?

1 użytkowników online, w tym zalogowanych: 0, gości: 1