Rozumiem koncepcję DI, ale dopiero uczę się, co mogą zrobić różne kontenery IoC. Wygląda na to, że większość ludzi opowiada się za używaniem kontenerów IoC do łączenia usług bezstanowych, ale co z używaniem ich do obiektów stanowych, takich jak encje?
Niezależnie od tego, czy jest to dobre, czy złe, zwykle napycham swoje byty zachowaniem, nawet jeśli to zachowanie wymaga zewnętrznej klasy. Przykład:
public class Order : IOrder
{
private string _ShipAddress;
private IShipQuoter _ShipQuoter;
public Order(IOrderData OrderData, IShipQuoter ShipQuoter)
{
// OrderData comes from a repository and has the data needed
// to construct order
_ShipAddress = OrderData.ShipAddress; // etc.
_ShipQuoter = ShipQuoter;
}
private decimal GetShippingRate()
{
return _ShipQuoter.GetRate(this);
}
}
Jak widać, zależności są wstrzykiwane przez konstruktor. A teraz kilka pytań.
Czy uzależnienie podmiotów od zewnętrznych klas, takich jak ShipQuoter, jest uważane za złą praktykę? Wydaje się, że wyeliminowanie tych zależności prowadzi mnie do domeny anemicznej, jeśli dobrze rozumiem definicję.
Czy używanie kontenera IoC do rozwiązywania tych zależności i konstruowania jednostki w razie potrzeby jest złą praktyką? Czy da się to zrobić?
Dzięki za wgląd.
źródło
Odpowiedzi:
Najtrudniej odpowiedzieć na pierwsze pytanie. Czy to zła praktyka, gdy jednostki są zależne od zewnętrznych klas? Z pewnością nie jest to najczęstsza rzecz.
Jeśli, na przykład, wstrzykniesz Repozytorium do swoich Encji, masz efektywną implementację wzorca Active Record . Niektórzy ludzie lubią ten wzór ze względu na wygodę, którą zapewnia, podczas gdy inni (jak ja) uważają go za zapach kodu lub anty-wzór, ponieważ narusza on zasadę pojedynczej odpowiedzialności (SRP).
Możesz argumentować, że wstrzyknięcie innych zależności do jednostek pociągnie cię w tym samym kierunku (z dala od SRP). Z drugiej strony z pewnością masz rację, że jeśli tego nie zrobisz, pociągnie się w kierunku modelu domeny anemicznej .
Walczyłem z tym wszystkim przez długi czas, dopóki nie natknąłem się na ( porzucony ) artykuł Grega Younga na temat DDDD, w którym wyjaśnia, dlaczego stereotypowa architektura n-warstwowa / n-warstwowa zawsze będzie CRUDy (a zatem raczej anemiczna).
Przeniesienie naszej uwagi na modelowanie obiektów domeny jako poleceń i zdarzeń zamiast rzeczowników wydaje się umożliwiać nam zbudowanie odpowiedniego, zorientowanego obiektowo modelu domeny.
Na drugie pytanie łatwiej odpowiedzieć. Zawsze możesz użyć Abstract Factory do tworzenia instancji w czasie wykonywania . Z Castle Windsor możesz nawet skorzystać z Fabryki Typów, zwalniając cię z ciężaru ręcznego wdrażania fabryk.
źródło
Wiem, że to stary post, ale chciałem dodać. Jednostka domeny nie powinna zachowywać się sama, nawet jeśli przekazujesz abstrakcyjne repozytorium w ctor. Sugeruję, że to nie tylko narusza SRP, ale także jest sprzeczny z agregacją DDD. Pozwólcie, że wyjaśnię, DDD nadaje się do złożonych aplikacji z nieodłącznie głębokimi wykresami, dlatego używamy korzeni zbiorczych lub kompozytowych, aby utrwalić zmiany w podstawowych „dzieciach”, więc kiedy wstrzykujemy wytrwałość poszczególnym dzieciom, naruszamy ich relacje z złożony lub zagregowany rdzeń, który powinien „odpowiadać” za cykl życia lub agregację. Oczywiście złożony pierwiastek lub agregat również nie zachowuje swojego własnego wykresu. Innym jest to, że wstrzykiwanie zależności obiektów DDD polega na tym, że wstrzyknięty obiekt domeny faktycznie nie ma stanu, dopóki nie nastąpi inne zdarzenie w celu uwodnienia jego stanu. Każdy konsument kodu będzie zmuszony najpierw zainicjować lub skonfigurować obiekt domeny, zanim będzie mógł wywołać zachowanie biznesowe, które narusza hermetyzację.
źródło