Grube modele vs. Logika biznesowa, gdzie wyróżniasz?

16

Dzisiaj wdałem się w gorącą debatę z innym programistą w mojej organizacji na temat tego, gdzie i jak dodawać metody do klas odwzorowanych w bazie danych. Używamy sqlalchemyi główna część istniejącej bazy kodu w naszych modelach baz danych to niewiele więcej niż worek mapowanych właściwości o nazwie klasy, prawie mechaniczne tłumaczenie z tabel bazy danych na obiekty python.

W moim argumencie moja pozycja była taka, że ​​podstawową wartością użycia ORM było to, że możesz dołączyć zachowania i algorytmy niskiego poziomu do mapowanych klas. Modele są najpierw klasami, a następnie trwałymi (mogą być trwałe przy użyciu xml w systemie plików, nie musisz się tym przejmować). Jego zdaniem każde zachowanie jest „logiką biznesową” i koniecznie należy do dowolnego miejsca, ale nie w modelu trwałym, który ma być używany tylko do trwałości bazy danych.

I na pewno sądzę, że istnieje różnica między tym, co jest logika biznesowa i powinny być rozdzielone, ponieważ ma jakąś izolację od niższego poziomu, jak to zostanie zrealizowane, a logika domeny, które wierzę, jest abstrakcją dostarczone przez klasach modelowych spierałem się w poprzednim akapicie, ale ciężko mi wskazać, co to jest. Mam lepsze pojęcie o tym, co może być interfejsem API (którym w naszym przypadku jest HTTP „ReSTful”), ponieważ użytkownicy wywołują interfejs API z tym, co chcą robić , niezależnie od tego, co wolno im robić i jak to zrobić robi się.


tl; dr: Jakie rzeczy mogą lub powinny iść w metodzie klasy odwzorowanej przy użyciu ORM i co należy pominąć, aby żyć w innej warstwie abstrakcji?

SingleNegationElimination
źródło
Wydaje mi się, że były to dwie kwestie omawiane w tym samym czasie, kwestia trwałości Modele to najpierw klasy, a po drugie trwałe (mogą być trwałe przy użyciu xml w systemie plików, nie musisz się tym przejmować). i przyczynę kodu. Zwykle wszystko się wyjaśnia , przynajmniej dla mnie, kiedy zadaję sobie pytanie, dlaczego kod jest napisany, jakie wymagania wymuszają ten kod. Czy jest to wymóg klientów co do tego, jak program będzie działał, czy też w jaki sposób zdecydujemy się go wdrożyć. Dla mnie pierwsza to logika biznesowa, a druga to, co nazywacie logiką domeny. Jak to pomaga.

Odpowiedzi:

10

Jestem głównie z tobą; wydaje się, że twój kolega opowiada się albo za anemicznym modelem domeny antywirusowej, albo za duplikowaniem modelu w „modelu trwałości” bez wyraźnych korzyści (pracuję nad projektem Java, w którym to zostało zrobione, i jest to ogromny problem z utrzymaniem, ponieważ oznacza to trzykrotność pracy przy każdej zmianie modelu).

Jakie rzeczy mogą lub powinny znaleźć się w metodzie klasy odwzorowanej przy użyciu ORM, a co należy pominąć, aby żyć w innej warstwie abstrakcji?

Ogólna zasada: klasa powinna zawierać logikę opisującą podstawowe fakty dotyczące danych, które są prawdziwe we wszystkich okolicznościach. Logika specyficzna dla przypadku użycia powinna być gdzie indziej. Przykładem jest walidacja, ciekawy artykuł Martina Fowlera, w którym podkreśla, że ​​należy go uznać za zależny od kontekstu.

Michael Borgwardt
źródło
+1 za drugą część odpowiedzi. Jeśli chodzi o pierwszą część, jestem pewien, dlaczego twierdzisz, że anemiczny model domeny wymaga tak dużej „dodatkowej” pracy w przypadku zmiany. Rozumiem, że zmiana nastąpi w jakikolwiek sposób, ale w kilku różnych klasach (co jest trochę złe), ale jest to prawie taka sama ilość zmian; Zgaduję?
NoChance
1
@Emmad Kareem: Komentarz dotyczył spearate trwałości i modeli domen. Dodanie właściwości do modelu wymaga następnie dodania jej do dwóch klas modeli (zamiast jednej), a także do dowolnych map między nimi (co teoretycznie może być automatyczne, ale zwykle dla tego, kto uważał, że dobrym pomysłem jest posiadanie oddzielnej „model trwałości” decyduje się uzasadnić to rozdzielenie, czyniąc je różnymi, np. mają typy danych, które bardziej pasują do modelu typu DB), więc jest to 2 + X razy więcej niż zmiana, przy czym X zmienia się między 0 a godzinami utraty wydajności z powodu niejasności problemy z mapowaniem.
Michael Borgwardt
3

Jest to wezwanie do osądu, które naprawdę zależy od przewidywanego rozmiaru i skali tego, co rozwijasz. Najbardziej sztywnym podejściem jest ograniczenie typów ORM do komponentu dostępu do danych i stosowanie POCO we wspólnej bibliotece jako typów, do których odwołują się i których używają wszystkie warstwy. Umożliwiłoby to w przyszłości fizyczną separację, a także logiczną separację. Możesz także zdecydować, że między interfejsem użytkownika a warstwą logiki biznesowej powinna istnieć dodatkowa warstwa. Zwykle jest to nazywane warstwą fasadową lub biznesową. W tej dodatkowej warstwie znajduje się „kod przypadku użycia”. Indywidualny luźno powiązany kod jest wywoływany przez warstwę Facade / BI (np. Facade ma funkcję ProcessOrder (), która wywołuje logikę biznesową 1: M razy, aby wykonać wszystkie kroki konieczne do faktycznego przetworzenia zamówienia).

Jednak wszystko to powiedziane: wielokrotnie ta ilość architektury jest po prostu niepotrzebnym przesadą. Na przykład, kod specjalnie dla prostej witryny sieci Web, w której nie masz zamiaru pakować jej komponentów do ponownego użycia. Tworzenie witryny internetowej MVC i używanie obiektów EF dla tego typu rozwiązania jest całkowicie poprawne. Jeśli witryna będzie musiała zostać później skalowana, możesz przyjrzeć się tworzeniu klastrów lub procesowi często tracącemu nazwę „refaktoryzacji”.

Sean Chase
źródło
3

Przypomnij tylko swojemu współpracownikowi, że nie musisz nadarchitagować modeli, jakby to był projekt Java. Chodzi mi o to, że porównywanie dwóch utrwalonych obiektów jest zachowaniem, ale nie jest ono określone przez warstwę trwałości. Pytanie 6 piwa brzmi: dlaczego zupełnie niepowiązane zajęcia opisują coś o tym samym? Oczywiście, wytrwałość jest wystarczająco dużym aspektem modelu, aby traktować go osobno, ale niewystarczająco uzasadniającym, aby traktować go inaczej niż wszystko inne. Jeśli prowadzisz samochód, myjesz go lub bijesz, cały czas manipulujesz samochodem.

Dlaczego więc nie połączyć wszystkich tych różnych aspektów w jedną klasę modeli? Potrzebujesz kilku klasowych metod radzenia sobie z utrwalonymi obiektami - umieść je w jednej klasie; masz wiele metod instancji zajmujących się sprawdzaniem poprawności - umieść je w innej. Wreszcie, zmieszaj dwa i voila! Masz tutaj inteligentną, samoświadomą iw pełni ograniczoną reprezentację modelu.

Filip Dupanović
źródło
1

Oprócz innych odpowiedzi, zwracaj uwagę na ukryte zastrzeżenia, używając bogatych modeli domen z ORM.

Miałem problemy z wstrzykiwaniem usług polimorficznych w klasach modeli utrwalonych, gdy próbowałem osiągnąć coś takiego jak następujący pseudokod:

Person john = new Person('John Doe')
Organisation company = organisation_repository.find('some id')
Employee our_collegue_john = company.hire(john)

W takim przypadku organizacja może wymagać HRServicezależności konstruktora (na przykład). Zwykle nie można łatwo kontrolować instanacji klas modeli podczas korzystania z ORM.

Korzystałem z Doctrine ORM i kontenera usług firmy Symfony. Musiałem śledzić ORM w niezbyt elegancki sposób i nie miałem wyboru, musiałem rozdzielić modele uporczywości i biznesowe. Nie próbowałem jeszcze z sqlachemy, pomyślałem. Python może okazać się bardziej elastyczny niż PHP dla tych rzeczy.

abstrus
źródło