2009-10-04 8 views
16

Zaimplementowałam stronę poleceń DDD przy użyciu modelu domeny i repozytoriów, ale jak zaimplementować stronę zapytania?Jak wdrożyć stronę zapytań CQRS w DDD?

Czy mogę utworzyć całkowicie nowy model domeny dla interfejsu użytkownika i gdzie jest przechowywany w strukturze projektu ... w warstwie domeny, warstwie interfejsu itp.?

Ponadto, co używam jako mechanizmu zapytań, czy tworzę nowe repozytoria specjalnie dla obiektów domeny UI, coś innego niż repozytoria lub coś innego?

+3

Właśnie natknąłem się na blogu przez JAK Charlton, który opisuje, dlaczego nie zdecydował się użyć DDD dla zapytań w ogóle: „Bok Zapytanie o CQS nie musi silnie typami jednostek, ani nie wymaga silnie wpisane DTOs - ponieważ w dużej mierze dane ad-hoc utrzymują te jednostki, a DTO pochłaniają nieproporcjonalnie długi czas opracowywania czegoś, co DataTable może poradzić sobie z więcej niż odpowiednio " http://devlicio.us/blogs/casey/archive/2009/ 06/22/my-are-not-doing-ddd-part-dwa-cqs.aspx – rohancragg

Odpowiedz

6

Z mojego rozumienia CQRS stworzysz zestaw DTO spełniających wymagania ekranów interfejsu użytkownika lub aplikacji, które mogą wymagać ich użycia.

Jeśli istnieje w projekcie, opiera się na wymaganiach, ponieważ byłoby to uzależnione od ujawnienia tych DTO za pośrednictwem usług internetowych. W takim przypadku nie umieszczałbym go w warstwie WWW, lecz w warstwie aplikacji lub w specjalnej warstwie fasady.

Następnie można mieć repozytorium tylko do odczytu lub warstwę dostępu do danych, która bezpośrednio zapełnia DTO. Myślę, że strona Query rzeczy powinna być zoptymalizowana pod kątem wydajności odczytu, w którym to przypadku zadania bezpośrednie/procedury przechowywane na widokach baz danych lub tabelach i SqlDataReaders wykonałyby tutaj najlepszą robotę. Ale zdecydowanie warto byłoby wyodrębnić ten dostęp za interfejsem, aby można było dodać buforowaną implementację w dalszej części ścieżki.

Jeśli korzystasz z ORM i chcesz zmapować z Twoich Jednostek Domeny do DTO, możesz mieć ogólny QueryRepository, który ma metody, które wymagają ISpecification lub podobnej konstrukcji do zdefiniowania twoich zapytań, a następnie obiektu DtoAssembler do tworzenia Dtos z twoich obiektów domeny. Następnie implementacja ma obiekt pierwszej klasy dla każdego z zapytań, które zamierzasz wykonać.

Oto dość wymyślny przykład, ale mam nadzieję, że da ci to pomysł.

 public interface ISpecification<T> 
     { 
      Expression<Func<T, bool>> Predicate { get; } 

     } 

     public class ActiveCustomersSpecification : ISpecification<Customer> 
     { 
      private Expression<Func<Customer, bool>> predicate; 
      public ActiveCustomersSpecification() 
      { 
       predicate = c => c.IsActive; 
      } 
      #region ISpecicfication<Customer> Members 

      public Expression<Func<Customer, bool>> Predicate 
      { 
       get { return predicate; } 
      } 

      #endregion 
     } 

     public interface IQueryRepository<T> 
     { 
      IQueryable<T> GetQuery(ISpecification<T> specification); 

      IEnumerable<T> FindAllBy(ISpecification<T> specification); 
     } 



public class CustomerDtoAssembler 
    { 
     public CustomerDto AssembleFrom(Customer customer) 
     { 
      var customerDto = new CustomerDto 
      { 
       Id = customer.Id 
      }; 

      return customerDto; 
     } 
    } 
+0

Znalazłem to interesujące, czy możesz wyjaśnić jedną rzecz? repozytorium zapytań i interfejs specyfikacji, oba są wyraźnie powiązane z technologią ORM, nie jest? W tej sprawie odgaduję strukturę podmiotu. Czy nie powinno być abstrakcyjne? –

3

myślę willbt dał wam naprawdę dobry starting point.

Dodam, że jeśli zdecydujesz się na używanie ORM jako strategii dostępu do danych dla zapytań, dobrze byłoby rozważyć zdefiniowanie strategii pobierania dostosowanej do danych, których spodziewasz się, że będziesz potrzebować dostępu (Tak przy okazji myślę o NHibernate tutaj). Oznacza to, że możesz zdecydować, czy chcesz wczytać lub załadować obiekty i kolekcje związane z konkretnym obiektem Aggregate Root.

Urządzenie NCommon project firmy Ritesh Rao oferuje doskonałą (w toku) demonstrację sposobu definiowania różnych strategii pobierania w różnych celach.

Ritesh explains it really również na swoim blogu.

Śmiało i spojrzeć na źródła:

w 'Repository_For_Uses_Registered_Fetching_Strategies' test połączenia do

NHRepository<Order>().For<NHRepositoryTests>() 

... powoduje fe Strategie tnące są rejestrowane w klasie NHRepositoryTests, a zatem elementy OrderItem i Produkty będą ładowane bez problemów z konfiguracjami mapowania NHibernate.

+1

To jest poprawny punkt. Jednak ma to zastosowanie tylko wtedy, gdy zwrócisz swoje jednostki do warstwy elewacji, a następnie mapujesz do DTO. Moją sugestią byłoby wykorzystanie zwróconego produktu IQueryable i projektu bezpośrednio do DTO. W ten sposób unikasz wszelkich FetchStrategies. Możesz także wykonywać projekcje na poziomie mapowania NHibernate. – willbt

+0

Oczywiście! Tak, dziękuję. Nadal pogodzę się z tym, jak zmiana NHibernate.Linq zmienia grę, ale jeśli spojrzysz na to, jak Ritesh obejmuje IQueryable, zobaczysz, że on certyfikuje "dostaje to" i buduje wokół siebie dobre rzeczy (tj. Wyrażenie w ich konstruktorze). – rohancragg

+0

linki zostały teraz zaktualizowane do lokalizacji GitHub – rohancragg