Kiedy użyłem IoC Container w moim ostatnim projekcie, skończyłem z anemicznymi podmiotami i większością mojej logiki biznesowej w Stateless Services.
Widziałem projekty napisane przez innych programistów, które wykorzystują „Inversion of Control” i zawsze są one „anemiczne”.
Skoro „Anemic Domain Model” ma anty-wzorzec, czy można korzystać z IoC i Rich Domain? Czy są jakieś dobre przykłady, które to robią?
dependency-injection
Mag20
źródło
źródło
Odpowiedzi:
Na początek: DI i IoC nie są synonimami. Przykro mi, ale muszę to zaznaczyć (wydaje mi się, że tak myślisz).
Jeśli chodzi o twoje zapytanie ... Cóż, wstrzykiwanie zależności jest tylko narzędziem. Sposób korzystania z tego narzędzia jest całkowicie odrębną sprawą. Istnieją również inne narzędzia (wzorce projektowe), które mogą przyczynić się do rozwiązania problemu. Na przykład uważam, że szerokie zastosowanie wzorca MVC jest jednym z kluczowych składników w tworzeniu anty-wzorca Anemic Domain Model: kontrolery (w prostszych aplikacjach, w bardziej skomplikowanych, które byłyby dodatkową warstwą usług) przejmują odpowiedzialność za sprawdzanie reguł biznesowych , wymuszając je, a także przekształcając jednostki DB w coś użytecznego, podczas gdy warstwa biznesowa zamienia się w prostą warstwę dostępu do danych, która jest zwykłym ORM z mapowaniem jeden-do-jednego do jednostek bazy danych.
Z pewnością to sposób projektowania aplikacji - jeśli chcesz, możesz stworzyć poprawny model domeny, a wszystkie te IoC, DI, MVC Cię nie zatrzymują. To, co może Cię zatrzymać, to Twój zespół. Musisz w jakiś sposób przekonać ich, aby wybrali właściwą ścieżkę, co może być trudne, ponieważ wielu programistów nie ma silnego zaplecza architektonicznego.
źródło
Większość (jeśli nie wszystkie) aplikacji to mieszanka problemów związanych z infrastrukturą i domenami. Po osiągnięciu pewnego poziomu złożoności łatwiej będzie zarządzać, jeśli domena zostanie oddzielona od infrastruktury, dzięki czemu łatwiej będzie się zastanowić i będzie mogła rozwijać się niezależnie.
Oczywiście model domeny nadal musi komunikować się z resztą systemu i zwykle będzie to dotyczyło usług bezstanowych (które są częścią domeny), które mają problemy z infrastrukturą (takie jak dostęp do bazy danych). Używanie kontenera IoC nie usuwa tej zależności, przenosi jego konfigurację do oddzielnego obszaru - ponownie ułatwiając rozumowanie i utrzymanie.
Podmioty przechowują stan i powinny być odpowiedzialne za reguły biznesowe. Jeśli Twoje usługi wymuszają wszystkie niezmienniki i inne reguły biznesowe, prawdopodobnie logika jest w niewłaściwym miejscu.
Teraz, jeśli masz logikę we właściwych miejscach, a mimo to nadal masz do czynienia z usługami, które są niczym więcej niż owijaniem wokół elementów infrastruktury i podmiotów, które są tylko torbami nieruchomości, to jest bardzo prawdopodobne, że domena nie jest wystarczająco złożona, aby uzasadnić koszty własne modelu. Prawie wszystko, co przeczytasz o DDD, będzie zawierało oświadczenie, że tak naprawdę jest ono przeznaczone tylko dla złożonych domen, ale wydaje się, że zbyt często jest o tym zapominany.
źródło
Idź do źródła. Zacznij od fragmentu Fowlera w Anemic Domain Models . Jako przykład dobrej praktyki odwołuje się do projektu opartego na domenach Erica Evana. Kod źródłowy tego jest tutaj . Pobierz to.
Zauważ, że używa Inversion of Control (szukaj @Autowired) i ma klasy usług (BookingService) oraz klasy „procesów biznesowych” (np. ItineraryUpdater).
Oryginalny artykuł Fowlera rozpoczyna szlak do szukanego przykładu.
źródło
VoyageRepositoryHibernate
klasa, która została umieszczona w warstwie infrastruktury, ale w rzeczywistości zależy od warstwy domeny.save(foo)
kod, który może ulec zmianie, gdy zmienia się model domeny (na przykład, jeśli dodawany jest nowy atrybutMyDomainObject
), wówczas (z definicji) musi należeć do warstwy domeny; w przeciwnym razie nie możesz już mówić o „warstwach”.Zakładam, że masz na myśli DI zamiast IoC, a projekt, nad którym pracowałeś, wykorzystuje pojemnik DI, taki jak Spring. IoC ma dwa główne smaki: DI i wzór lokalizatora. Nie rozumiem, dlaczego wzór Lokalizatora powinien być problemem, więc skupmy się na DI.
Nie sądzę, żeby to było możliwe, a przynajmniej byłoby bardzo niepraktyczne. Głównym aspektem kontenerów DI jest to, że kontrolują tworzenie obiektów, gdy wstrzykują je innym („obiektom zarządzanym”). Zestaw zarządzanych obiektów, który żyje podczas uruchamiania projektów, jest niezależny od tego, które elementy domeny istnieją w projekcie, ale zależy od tego, w jaki sposób obiekty są okablowane i jakie zakresy (singleton, prototyp) są do nich przypisane.
Dlatego nie chcesz, aby kontener DI zarządzał obiektami domeny. Ale jeśli tworzysz obiekty ręcznie (z nowym), nie możesz wstrzykiwać innych obiektów do obiektów domeny. (Pozostawiając potencjalne obejścia z ręcznym okablowaniem na bok.) Ponieważ te zastrzyki są potrzebne do zastąpienia implementacji innymi, nie można zastąpić funkcjonalności bogatych obiektów domeny za pomocą DI. W związku z tym nie będziesz chciał umieszczać funkcji w obiektach domeny lub utracisz funkcje DI.
Nie rozumiem, jak mógłby działać hipotetyczny kontener DI, który nie zarządza twoimi obiektami, i żadna z istniejących implementacji na to nie pozwala. Można więc śmiało twierdzić, że DI polega na zarządzaniu obiektami. Dlatego zawsze kusi cię do podzielenia potencjalnych obiektów Rich Domain na jedną klasę anemiczną i jedną lub kilka klas skryptów transakcyjnych.
źródło