10

TłoGdzie zdefiniować interfejsy dla repozytorium w architekturze warstwowej?

Próbuję utworzyć prostą aplikację, aby naprawdę zrozumieć cały stos DDD + TDD + itd. Moim celem jest dynamiczne wstrzykiwanie klas repozytorium DAL w czasie wykonywania. Dzięki temu można przetestować warstwy usługi domenowej i usług aplikacji . Planuję za pomocą „Di biednych”, aby osiągnąć to teraz ... więc chciałbym to zrobić w prosty uruchamiania aplikacji konsoli w pobliżu:

 

    // Poor man's DI, injecting DAL repository classes at runtime 
    var productRepository = new SimpleOrder.Repository.ProductRespository(); 
    var customerRepository = new SimpleOrder.Repository.CustomerRepository(); 
    var orderRepository = new SimpleOrder.Repository.OrderRepository(); 

    // Constructor injection into this class in the Application Services layer, 
    // SimpleOrder.ApplicationFacade 
    OrderEntry oe = new OrderEntry(customerRepository, orderRepository, productRepository); 

Aby osiągnąć ten zastrzyk zależnościach, jakie stworzył trzy repozytorium interfejsy:

 
-- ICustomerRepository 
-- IOrderRepository 
-- IProductRespository 

typowa implementacja:

 

    namespace SimpleOrder.Domain.Interfaces 
    { 
     public interface ICustomerRepository 
     { 
      Customer GetCustomerById(int customerId); 
      void SaveCustomer(Customer customer); 
     } 
    } 

** Zauważ, że SaveCustomer odwołuje klasę modelu klienta zdefiniowaną w doma w warstwie. Jest to typowe dla innych repozytoriów.

jednak nie jestem pewien projekt, który powinien/warstwa one być realizowane w Mam 5 projektów w roztworze:

  1. SimpleOrder.ConsoleClient (prezentacja) - chcę wstrzykiwać. konkretne wdrożenie domeny stąd jak stosowanie

  2. SimpleOrder.ApplicationFacade (usługi aplikacyjne) - masywny wyższego szczebla, grubsze drobnoziarnisty metody o rchestrating metod niższego poziomu w domenie

  3. SimpleOrder.Contracts - zajęcia DTO używany do komunikacji między prezentacji i aplikacji usług

  4. SimpleOrder.Domain (domena/bil) - domeny klasy modelu klienta, Order, OrderItem, Product

  5. SimpleOrder.Repository (dAL) - realizuje repo sitory interfejsy

Oto moje opcje jak ja to widzę:

Wariant 1: Define repozytorium interfejsów w SimpleOrder.Contracts ...

PRO: to gdzie ja myśleć powinny należeć, ponieważ stworzyłem to, aby dzielić się umowami pomiędzy różnymi problemami/warstwami. np., DTO są zdefiniowane tutaj.

CON: jednak sygnatury metod w każdym interfejsie odnoszą się do klas modeli domen.
Oznacza to, że będę musiał dodać odniesienie do SimpleOrder.Domain, ale kiedy SimpleOrder.Kontrakty są przywoływane w innym projekcie, będą musiały przenosić SimpleOrder.Domain razem na przejażdżkę. To nie jest w porządku.

Opcja 2: sam scenariusz jak powyżej, ale także zdefiniować interfejsy dla każdej domeny modelu klasa w SimpleOrder.Contracts więc mogę przerwać sprzężenie repozytorium interfejsów do rzeczywistych klasach modelowych.

Przykład:

 

    namespace SimpleOrder.Domain.Interfaces 
    { 
     public interface ICustomerRepository 
     { 
      ICustomer** GetCustomerById(int customerId); 
      void SaveCustomer(ICustomer customer); 
     } 

     public interface ICustomer 
     { 
      int CustomerId { get; set; } 
      string Name { get; set; } 
      System.Collections.Generic.List Orders { get; } 
     } 
    } 

IMPACT: Każda klasa modelu domeny musiałby wykonywać swój powiązany interfejs. tj.,

 

    public class Customer : SimpleOrder.Domain.Interfaces.ICustomer 
    { 
     public Customer() 
     { 
      _orders = new List(); 
     } 

     public int CustomerId { get; set; } 
     public string Name { get; set; } 

     private List _orders; 
     public virtual List Orders { 
      get { return _orders; } 
     } 
    } 

PRO: Naprawiono problem z Opcją 1.

CON: To powoduje eksplozję liczby plików (i postrzeganej złożoności) w projekcie, ponieważ każda klasa domeny ma teraz powiązany interfejs.

Wariant 3: zdefiniować repozytorium intefaces w SimpleOrder.Domain

oddziaływania: W celu wstrzyknięcia konkretnych zajęć repozytorium usług w warstwie aplikacji (projekt SimpleOrder.ApplicationFacade) od SimpleOrder.ConsoleClient przy starcie SimpleOder.ConsoleClient będzie również wymagać odwołania do SimpleOrder.Domain.

PRO: Rozwiązuje to również opcja 1

CON: Starałem się unikać odwoływania się do warstwy domeny z warstwy prezentacji bezpośrednio ponieważ teraz warstwa prezentacji może wiedzieć zbyt wiele o warstwie domeny. Kiedy w przyszłości zastępuję aplikację konsoli aplikacją WPF lub ASP.NET MVC, ryzykuję drugą i następną implementację warstwy prezentacji przed próbą wywołania metod w Modelu zamiast warstwy Usługi aplikacji. (Jednak ja rozważyć to w wariancie 4.)

Wariant 4: Put interfejsy w SimpleOrder.Domain, a następnie odwołać SimpleOrder.Domain z SimpleOrder.ConsoleClient.

PRO: Naprawiono wszystkie powyższe problemy.

CON: nie czuję się dobrze, bo byłoby zapewnienie dostępu od warstwy prezentacji bezpośrednio do metod niższego poziomu w warstwie Domain kiedy powinien tylko być zapewnienie dostęp do wyższego poziomu masywny metody w SimpleOrder.ApplicationFacade.

PYTANIE Próbowałem każdego z nich, ale rozliczane w wariancie 4, jednak, że pozostawia nieprzyjemny smak w ustach o nim. Czy jest lepsza opcja? Czy jestem na dobrej drodze?

+0

Po bliższym przyjrzeniu się ... opcje 3 i 4 są w zasadzie takie same. Ups. Powinienem mieć dowód - dokładniej przeczytać. –

Odpowiedz

9

Z tego, co rozumiem na twoje pytanie, zgadzam się, że opcja 4 jest najlepsza. Interfejsy repozytorium powinny być zadeklarowane w warstwie domeny obok wszystkich obiektów domeny. Implementacja wspomnianych interfejsów powinna być częścią warstwy infrastruktury - warstwy łączącej twoją warstwę domeny ze światem. Spójrz na Hexagonal Architecture, aby zobaczyć jakąś motywację do tego.

Aby rozwiązać problem związany z opcją 4, nie należy uważać aplikacji konsoli za warstwę prezentacji. Ma również inne obowiązki, takie jak bycie gospodarzem aplikacji i composition root w warunkach DI. Może istnieć składnik prezentacji aplikacji konsoli, który komunikuje się tylko z usługami aplikacji. Możesz również zamknąć usługę aplikacji za open host service zaimplementowaną za pomocą interfejsu ASP.NET WebAPI. Następnie warstwa prezentacji będzie odwoływać się tylko do tej usługi i będzie ukryta przed podstawową warstwą domeny.

+0

Na podstawie twojej odpowiedzi na moje poprzednie pytanie, a teraz ta, wygląda na to, że będę ci winien kawę lub stek, czy coś takiego. :) Mam jedną szybką kontynuację ... napisałeś "Z tego, co rozumiem twoje pytanie" ... co prawda, było to długo zdyszane. Czy była tam też jakaś terminologia lub proces myślenia, który również brzmiał krzywo? DZIĘKUJĘ za twoją wspaniałą odpowiedź ... znowu. –

+0

Chodzi mi o to, że nie jestem świadomy wszystkich szczegółów twojego projektu, więc mogłem pominąć ograniczenie. Ale mimo to bardzo dobrze zadeklarowane pytanie! – eulerfx

0

Zgadzam się z eulerfx. Dodam tylko, że nie jest w porządku, ponieważ tradycyjna architektura N-ty sprawiłaby, że wszystko zależałoby od bazy danych i używałaby abstrakcji do zerwania tych zależności.

Powinieneś spojrzeć na Onion Architecture, który jest przykładem sposobu, w jaki organizujesz swoje zależności w opcji 4. Ja osobiście uważam, że jest to najbardziej skalowalny model architektury. Jeśli połączysz tę architekturę z praktykami DDD, zyskasz największą elastyczność przy najmniejszym wysiłku.

Na marginesie, wiele wdrożeń, jakie widziałem, rozbija umowy dla repozytoriów i usług domenowych na swój własny projekt. Jest to jednak decyzja czysto organizacyjna. Jest całkowicie poprawne, aby mieć je w projekcie modelu domeny.

+0

FYI architektura cebuli może być uważana za zasadniczo taką samą, jak sześciokątna; niektórzy uważają to za zgwałcenie, ponieważ sześciokąt był zarysowany jakiś czas przed cebulą. – eulerfx

+0

Widzę, co masz na myśli, dziękuję za informacje. Dlaczego żaden model architektury nie opisuje zależności między interfejsem/aplikacją/infrastrukturą? Odwołując się do twojej odpowiedzi, aplikacja ma obowiązek wybrać, z jakiej implementacji infrastruktury korzystać, więc czy to jest poza zakresem tego, co próbują wyrazić za pomocą tych modeli, czy też jest jeszcze jeden powód, dla którego nie ma tego w modelach architektonicznych? Zdaję sobie sprawę, że nie stworzyłeś modeli; Zastanawiam się tylko nad twoją opinią na ten temat. –

+0

W układzie sześciokątnym interfejs użytkownika to kolejna przejściówka, którą można uznać za infrastrukturę. Być może źle zrozumiałem to, o co prosiłeś? Jaką zależność masz na myśli między interfejsem/aplikacją/infrastrukturą? Jest na to kilka perspektyw, które widzę. – eulerfx

Powiązane problemy