Gdzie wyznaczamy granicę między delegowaniem a enkapsulacją logiki biznesowej? Wydaje mi się, że im więcej delegujemy, tym bardziej stajemy się anemiczni . Delegacja promuje jednak również ponowne użycie i zasadę SUCHEGO. Co zatem należy przekazać i co powinno pozostać w naszych modelach domen?
Weź jako przykład następujące obawy:
Autoryzacja . Czy obiekt domeny powinien być odpowiedzialny za utrzymanie swoich reguł kontroli dostępu (takich jak właściwość CanEdit), czy powinien być delegowany do innego komponentu / usługi odpowiedzialnej wyłącznie za zarządzanie dostępem, np. IAuthorizationService.CanEdit (obiekt)? A może powinna to być kombinacja tych dwóch? Być może obiekt domeny ma właściwość CanEdit, która deleguje do wewnętrznej IAuthorizationService, aby wykonać rzeczywistą pracę?
Validation . Ta sama dyskusja jak powyżej dotyczy walidacji. Kto przestrzega zasad i kto jest odpowiedzialny za ich ocenę? Z jednej strony stan obiektu powinien należeć do tego obiektu, a ważność jest stanem, ale nie chcemy przepisywać kodu używanego do oceny reguł dla każdego obiektu domeny. My mogli używać dziedziczenia w tym przypadku ...
Tworzenie obiektów . Klasa fabryczna a metody fabryczne kontra „nowe” wystąpienie. Jeśli użyjemy oddzielnej klasy fabryki, jesteśmy w stanie izolować i hermetyzować logikę tworzenia, ale kosztem otwarcia stanu naszego obiektu na fabrykę. Można to zarządzać, jeśli nasza warstwa domeny znajduje się w osobnym zestawie, odsłaniając wewnętrznego konstruktora używanego przez fabrykę, ale staje się to problemem, jeśli istnieje wiele wzorców tworzenia. A jeśli cała fabryka zajmuje się wezwaniem właściwego konstruktora, to po co mieć fabrykę?
Metody fabryczne w klasie eliminują problem z otwarciem stanu wewnętrznego obiektu, ale ponieważ są one statyczne, nie jesteśmy w stanie przełamać zależności poprzez wstrzyknięcie interfejsu fabrycznego, tak jak możemy to zrobić przy pomocy osobnej klasy fabrycznej.
Trwałość . Można argumentować, że jeśli nasz obiekt domeny zamierza ujawnić CanEdit podczas delegowania odpowiedzialności za wykonanie kontroli autoryzacji na inną stronę (IAuthorizationService), dlaczego nie zastosować metody Save na naszym obiekcie domeny, która robi to samo? Umożliwiłoby to nam ocenę stanu wewnętrznego obiektu w celu ustalenia, czy operację można wykonać bez przerywania enkapsulacji. Oczywiście wymaga to, abyśmy wstrzyknęli instancję repozytorium do naszego obiektu domeny, który trochę pachnie, więc czy zamiast tego wywołujemy zdarzenie domeny i pozwalamy programowi obsługiwać wykonanie operacji utrwalania?
Widzisz, gdzie idę z tym?
Rockford Lhotka ma świetną dyskusję na temat powodów, dla których zdecydował się pójść drogą Class-in-Charge dla swojego frameworka CSLA, a ja mam trochę historii z tym frameworkiem i mogę zobaczyć jego pomysł na obiekty biznesowe równoległe do obiektów domeny na wiele sposobów. Ale starając się bardziej przyłączyć do dobrych ideałów DDD, zastanawiam się, kiedy współpraca staje się zbyt duża.
Jeśli skończę z usługą IAuthorizationService, IValidator, IFactory i IRepository dla mojego zagregowanego katalogu głównego, co pozostanie? Czy posiadanie metody publikowania, która zmienia stan obiektu z wersji Roboczej na Opublikowaną, wystarcza, aby uznać klasę za obiekt domeny nieanemicznej?
Twoje myśli?