Przyszedł czas na opisanie najbardziej złożonego wzorca warstwy biznesowej – modelu domeny (DM). Jeśli nie znacie dobrze wzorca opisanego w poprzednich postach (aktywny rekord) nie zaczynajcie nawet próbować zrozumieć DM ponieważ jest on po prostu rozszerzeniem AR.
Na początek kilka faktów. DM jest wzorcem w pełni obiektowym, wykorzystującym wszelkie dobrodziejstwa programowania obiektowego (dziedziczenie, polimorfizm itp.). DM w przeciwieństwie do AR nie jest wzorcem zorientowanym na bazę danych. Scenariusz wykorzystania AR często wyglądał tak, że programista tworzył najpierw bazę danych dla danego problemu biznesowego a dopiero potem obiekty biznesowe AR. W przypadku DM podejście wygląda zupełnie inaczej. Problem biznesowy kompletnie abstrahuje od bazy danych. Programista tworzy najpierw klasy rozwiązujące problem biznesowy a baza danych jest już potem tylko dodatkiem.
Podobnie jak AR, klasy DM przechowują informacje na poziomie wiersza. Przykładową klasą DM może być więc:
public class Client: Person { public string FirstName {get;set;} public string LastName {get;set;} public abstract int GetDiscount(); }
Sama klasa wygląda tak jak AR. Jednak trzeba być świadomym kilku faktów:
-
Klasa nic nie wie o docelowej bazie danych. Obiekt takiej klasy po prostu reprezentuje kawałek logiki biznesowej. Kwestia zapisu jest już tylko sprawą techniczną i jak to zostanie zrobione nie należy to do kompetencji DM,
-
Klasa jest typu POCO. Klasy POCO muszą spełniać kilka warunków m.in nie mogą zawierać atrybutów czy z góry narzuconych interfejsów zdefiniowanych przez ORM. Innymi słowy jest to po prostu czysta klasa c#,
-
Klasa Client dziedziczy po Person. Jest to jak najbardziej wskazane w DM,
-
Zawiera abstrakcyjną metodę – tak jak wspomniałem DM ze względu na pełną niezależność od bazy danych może wykorzystywać pełen zestaw dobrodziejstw programowania obiektowego,
-
Klasa Client nie musi odpowiadać jednej tabeli w bazie danych. Często pojedyncza klasa DM mapowana jest na wiele tabel. Występuje tu pełna niezależność ze względu na fakt, że zapisem do bazy nie zajmują się już obiekty biznesowe.
Zalety:
-
Zapobiega duplikacji logiki,
-
Rozłożenie problemu na obiekty biznesowej powoduje wzrost czytelności kodu,
-
Niezależność od źródła danych,
-
Obiekty są typu POCO, zatem mogą korzystać z rozszerzeń OOP,
-
Znacznie ułatwienia w wykonywaniu testów jednoskokowych ze względu na oddzielenie obiektów odo źródła danych.
Wady:
-
Bardzo czasochłonna implementacja,
-
Rozdrobniony interfejs,
-
Potrzeba wykorzystania dodatkowego wzorca (remote facade) w celu wyeksponowania logiki przez web service.
Nie będę pisać konkretnego kodu ponieważ wartość metod zależy już od budowanego systemu. Zamiast tego uważam, że lepszym wyjściem jest pokazanie diagramu klas. W końcu nie ważne co znajduje się w środku tylko jaka jest relacjami pomiędzy klasami. Poniżej krótki przykład DM w akcji dla systemu sprzedaży: