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:
SimpleOrder.ConsoleClient (prezentacja) - chcę wstrzykiwać. konkretne wdrożenie domeny stąd jak stosowanie
SimpleOrder.ApplicationFacade (usługi aplikacyjne) - masywny wyższego szczebla, grubsze drobnoziarnisty metody o rchestrating metod niższego poziomu w domenie
SimpleOrder.Contracts - zajęcia DTO używany do komunikacji między prezentacji i aplikacji usług
SimpleOrder.Domain (domena/bil) - domeny klasy modelu klienta, Order, OrderItem, Product
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?
Po bliższym przyjrzeniu się ... opcje 3 i 4 są w zasadzie takie same. Ups. Powinienem mieć dowód - dokładniej przeczytać. –