Często moje obiekty biznesowe mają sytuacje, w których informacje zbyt często przekraczają granice obiektów. Kiedy robimy OO, chcemy, aby informacje były w jednym obiekcie i w miarę możliwości cały kod zajmujący się tymi informacjami powinien znajdować się w tym obiekcie. Jednak reguły biznesowe nie są zgodne z tą zasadą, co sprawia mi kłopoty.
Jako przykład załóżmy, że mamy Zamówienie, które ma wiele OrderItems, które odnoszą się do InventoryItem, który ma cenę. Wywołuję Order.GetTotal (), który sumuje wynik OrderItem.GetPrice (), który zwielokrotnia ilość przez InventoryItem.GetPrice (). Na razie w porządku.
Ale potem dowiadujemy się, że niektóre przedmioty są sprzedawane za dwie za jedną ofertę. Możemy sobie z tym poradzić, każąc OrderItem.GetPrice () zrobić coś takiego jak InventoryItem.GetPrice (ilość) i pozwalając InventoryItem sobie z tym poradzić.
Potem jednak dowiadujemy się, że umowa typu „dwa za jednego” trwa tylko przez określony czas. Ten okres musi być oparty na dacie zamówienia. Teraz zmieniamy OrderItem.GetPrice () na InventoryItem.GetPrice (quatity, order.GetDate ())
Ale potem musimy obsługiwać różne ceny w zależności od tego, jak długo klient był w systemie: InventoryItem.GetPrice (ilość, zamówienie.GetDate (), zamówienie.GetCustomer ())
Ale potem okazuje się, że oferty dwa w jednym dotyczą nie tylko zakupu wielu takich samych przedmiotów w ekwipunku, ale wielu dla dowolnego przedmiotu w kategorii InventoryCategory. W tym momencie podnosimy ręce i po prostu przekazujemy InventoryItem element zamówienia i pozwalamy mu poruszać się po wykresie odniesienia obiektu za pośrednictwem akcesoriów, aby uzyskać potrzebne informacje: InventoryItem.GetPrice (this)
TL; DR Chcę mieć niskie sprzężenie w obiektach, ale reguły biznesowe często zmuszają mnie do uzyskiwania dostępu do informacji z całego miejsca w celu podejmowania konkretnych decyzji.
Czy istnieją dobre techniki radzenia sobie z tym? Czy inni znajdują ten sam problem?
źródło
Odpowiedzi:
Mieliśmy w zasadzie to samo doświadczenie, w którym pracuję i rozwiązaliśmy ten problem, mając klasę OrderBusinessLogic. W przeważającej części opisany układ działa w większości naszych firm. Jest ładny, czysty i prosty. Ale w sytuacjach, w których kupiłeś dowolne 2 z tej kategorii, traktujemy to jako „wykonanie biznesowe” i każemy klasie OrderBL przeliczyć sumy, przechodząc przez potrzebne obiekty.
Czy to idealne rozwiązanie, nie. Nadal mamy jedną klasę o wiele za dużo znającą inne klasy, ale przynajmniej przenieśliśmy tę potrzebę z obiektów biznesowych do klasy logiki biznesowej.
źródło
Wygląda na to potrzebny jest oddzielny obiekt dyskontowa (lub ich listę), który śledzi wszystkie te rzeczy, a następnie zastosowanie dyskonta (ów) do Zakonu, coś
Order.getTotal(Discount)
lubDiscount.applyTo(Order)
lub podobny.źródło
Dostęp do danych z innych klas jest całkowicie w porządku. Jednak chcesz, aby była to relacja jednokierunkowa. Załóżmy na przykład, że ClassOrder uzyskuje dostęp do CallItem. Idealnie, ClassItem nie powinien mieć dostępu do ClassOrder. To, co myślę, że brakuje ci w klasie zamówień, to logika biznesowa, która może uzasadniać taką klasę, jak sugerował Walter.
Edycja: Odpowiedź na komentarz Winstona
Nie wydaje mi się, że w ogóle potrzebujesz przedmiotu z ekwipunku ... przynajmniej w sposób, w jaki go używasz. Zamiast tego miałbym klasę zasobów, która zarządzała bazą danych zasobów.
Odniosę się do przedmiotów magazynowych według identyfikatora. Każde zamówienie zawierałoby listę identyfikatorów zapasów i odpowiednią ilość.
Następnie obliczyłem sumę zamówienia za pomocą czegoś takiego.
Inventory.GetCost (Items, nazwa klienta, data)
Wtedy możesz mieć inną funkcję pomocnika, taką jak:
Inventory.ItemsLefts (int itemID)
Inventory.AddItem (int itemID, int ilość)
Inventory.RemoveItem (int itemID, int ilość)
Inventory.AddBusinessRule (...)
Inventory.DeleteBusinessRule (...)
źródło
Po zastanowieniu się nad tym wymyśliłem własną alternatywną strategię.
Zdefiniuj klasę cenową.
Inventory.GetPrice()
zwraca obiekt cenyTeraz klasa Price (i ewentualnie niektóre klasy pokrewne) zawierają logikę wyceny, a porządek nie musi się o to martwić. Price nie wie nic o Order / OrderItem, zamiast tego po prostu wprowadza do niego informacje.
źródło