Jarosław Kuchta Wzorce projektowe warstwy biznesowej
Wzorce projektowe dotyczące danych, obiektów i logiki biznesowej Transfer Object Assembler Łączy dane pochodzące z różnych komponentów biznesowych Composite Entity Łączy trwałe komponenty encji z obiektami zależnymi Business Delegate Działając po stronie klienta pośredniczy między komponentami warstwy prezentacji a obiektami biznesowymi Wzorce projektowe warstwy usług 2
Transfer Object Assembler
Transfer Object Assembler - motywacje Stosowanie wielu obiektów biznesowych powoduje: Ścisły związek między warstwą aplikacji a rozproszonym modelem obiektowym. Zmniejszenie wydajności sieci w przypadku licznych komponentów rozproszonych. Konieczność wbudowania logiki biznesowej do warstwy aplikacji ( gruby klient). Trudne zarządzanie zmianami logiki biznesowej w przypadku różnych typów klientów. Wzorce projektowe warstwy usług 4
Rozwiązanie Zbiorczy obiekt transferowy (Transfer Object Assembler) reprezentuje dane pochodzące z różnych komponentów biznesowych. Pobiera obiekty transferowe od wielu komponentów i łączy je w jeden. Przenosi dane do klienta przez wywołanie pojedynczej metody. Zbiorczy obiekt transferowy nie powinien być modyfikowalny. Wzorce projektowe warstwy usług 5
Struktura wzorca uses Transfer Object * 1 contains creates Client requests «session» Transfer Object Assembler 1 uses * Business Object «entity» Business Entity «session» Business Session Data Access Object Wzorce projektowe warstwy usług 6
Współdziałanie komponentów Client Transfer Object Assembler Business Entity Business Session DAO 1: Get Data 2: Create Transfer Object 3a: Get Data 3b: Get Data 3c: Get Data 4: Set Data 5: Return Object Wzorce projektowe warstwy usług 7
Strategie implementacyjne dla komponentu asemblera implementacja przez dowolny obiekt implementacja przez komponent sesji Wzorce projektowe warstwy usług 8
Implementacja przez dowolny obiekt Asembler obiektów transferowych jest implementowany przez dowolny obiekt. Uruchamiany w warstwie biznesowej. Zapobiega odwoływaniu się do źródłowych obiektów biznesowych pomiędzy warstwami. Wzorce projektowe warstwy usług 9
Implementacja przez komponent sesji Zbiorczy obiekt transferowy zawiera zdjęcie danych modelu. Przy zmianie modelu staje się nieaktualny. Preferowana sesja bezstanowa. Przy rzadkich zmianach modelu można zastosować sesję ze stanami (przechowuje zbiorczy obiekt transferowy) mechanizm rozpoznawania zmian. Wzorce projektowe warstwy usług 10
Przykład Aplikacja zarządzania projektem. Klient żąda zbiorczej informacji o projekcie, która zawiera: Dane identyfikacyjne projektu Dane osobowe kierownika projektu Listę zadań w tym projekcie Zasoby dla każdego zadania Wzorce projektowe warstwy usług 11
Kod zbiorczego obiektu transferowego public class ProjectDetailsData { public ProjectTO projectdata; public ProjectManagerTO projectmanagerdata; public Collection listoftasks;... } Wzorce projektowe warstwy usług 12
Kod asemblera (1) public class ProjectDetailsAssembler { public ProjectDetailsData getdata (String projectid) { // tworzenie zbiorczego obiektu transferowego ProjectDetailsData pdata = new ProjectDetailsData(); // pobieranie danych identyfikacyjnych projektu ProjectEntity project = projecthome.findbyprimarykey(projectid); ProjectTO projto = project.getdata(); pdata.projectdata = projto; // pobieranie danych osobowych kierownika projektu ProjectManagerEntity projectmanager = projectmanagerhome.findbyprimarykey(projto.managerid); ProjectManagerTO projmgrto = projectmanager.getdata(); pdata.projectmanagerdata = projmgrto; Wzorce projektowe warstwy usług 13
Kod asemblera (2) // pobieranie listy zadań dla projektu Collection projtasklist = project.gettaskslist(); ArrayList listoftasks = new ArrayList(); // wynikowa lista obiektów transferowych dla zadań Iterator taskiter = projtasklist.iterator(); while (taskiter.hasnext()) { TaskTO task = (TaskTO) taskiter.next(); // pobranie informacji o zasobach dla każdego zadania ResourceEntity resource = resourcehome.findbyprimarykey(task.assignedresourceid); ResourceTO resto = resource.getresourcedata(); // utworzenie obiektu transferowego dla zadania i jego zasobów TaskResourceTO trto = new TaskResourceTO( task.projectid, task.taskid, task.name, task.description, task.startdate, task.enddate, resto); listoftasks.add(trto); // i dodanie do listy wynikowej } // dodanie listy obiektów transferowych do zbiorczego obiektu transferowego i zwrot danych pdata.listoftasks = listoftasks; return pdata; Wzorce projektowe warstwy usług 14
Zalety i wady Oddzielenie logiki biznesowej od logiki aplikacji Rozluźnienie powiązań pomiędzy klientami i modelem obiektowym Zwiększenie wydajności sieci Zwiększenie wydajności klienta Zwiększenie wydajności transakcji Mogą pojawiać się nieaktualne obiekty transferowe Wzorce projektowe warstwy usług 15
Composite Entity
Composite Entity - motywacje Każde wywołanie przez klienta potencjalnie przechodzi przez sieć, nawet jeśli serwer znajduje się na tym samym komputerze. Im mniejsza ziarnistość obiektów, tym większy ruch w sieci i tym większy narzut sieciowy na wykonanie operacji. Komponenty encji powinny reprezentować gruboziarniste, trwałe obiekty zależne. Jednak nawet wtedy mogą być powiązane z wieloma obiektami zależnymi Bezpośrednie odwzorowanie modelu klas w komponenty encji nie uwzględnia ziarnistości. Wzorce projektowe warstwy usług 17
Composite Entity - problemy Konieczność walidacji referencji zdalnych do komponentów encyjnych Problemy z zarządzaniem i pielęgnowaniem systemu Problemy z wydajnością sieci Zależność aplikacji od schematu bazy danych Konieczność zarządzania relacjami przez klienta przeglądanie wielu tabel Wzorce projektowe warstwy usług 18
Rozwiązanie Wzorzec Composite Entity łączy gruboziarnisty obiekt trwały i jego obiekty zależne w złożony komponent encyjny. Klient wykonuje operacje get/set na obiekcie gruboziarnistym. Ten obiekt decyduje o pobieraniu lub modyfikowaniu obiektów zależnych. Wzorce projektowe warstwy usług 19
Strategie implementacyjne 1. Złożony komponent encyjny zawierający obiekt gruboziarnisty 2. Złożony komponent encyjny implementujący obiekt gruboziarnisty 3. Strategia "leniwego" ładowania 4. Zastosowanie markera modyfikacji 5. Zastosowanie złożonego obiektu transferowego Wzorce projektowe warstwy usług 20
Strategia 1 struktura komponentów «entity» Composite Entity contains Coarse Grained Object 1 contains * Dependent Object 1 * contains Wzorce projektowe warstwy usług 21
Strategia 1 - współdziałanie Client «entity» Composite Entity Coarse Grained Object Dependent Object 1 Dependent Object 2 Dependent Object 3 1: Get/Set Data 2: Get/Set Data 3a: Get/Set Data 3b: Get/Set Data 3b.1: Get/Set Data Wzorce projektowe warstwy usług 22
Strategia 2 struktura komponentów «entity» Composite Entity 1 * contains Dependent Object * 1 contains Wzorce projektowe warstwy usług 23
Strategia 2 - współdziałanie Client «entity» Composite Entity Dependent Object 1 Dependent Object 2 Dependent Object 3 1: Get/Set Data 1.1: Get/Set Data 1.1.1: Get/Set Data 1.1.2: Get/Set Data 1.1.2.1: Get/Set Data Wzorce projektowe warstwy usług 24
Wykorzystanie ładowania "leniwego" Komponent encyjny może być złożony na wiele poziomów w głąb. Ładowanie wszystkich obiektów zależnych na raz może być nieefektywne. Za pierwszym razem ładuje się tylko obiekty zależne pierwszego poziomu. Kiedy klient żąda dostępu do obiektu, który nie jest jeszcze załadowany, to obiekt ten jest ładowany na żądanie. Jeśli obiekt zależny został załadowany, to przy kolejnych wołaniach metody ładowania trzeba uwzględnić ten obiekt w aspekcie synchronizacji z pamięcią trwałą. Wzorce projektowe warstwy usług 25
Zastosowanie markera modyfikacji «interface» Dirty Marker setdirty(): void isdirty(): boolean resetdirty(): void setnew(): void isnew(): boolean resetnew(): void setdeleted(): void isdeleted(): boolean resetdeleted(): void «entity» Composite Entity 1 * contains Dependent Object * 1 contains Wzorce projektowe warstwy usług 26
Client Wykorzystanie złożonego obiektu «entity» Composite Entity transferowego Dependent Object 1 Dependent Object 2 Dependent Object 3 1: Get/Set Data 2a: Get/Set Data 2a.1: Get/Set Data 2b: Get/Set Data 2b.1: Get/Set Data 3: Create Transfer Object Assembler 4: Return Object Wzorce projektowe warstwy usług 27
Przykład implementacja obiektu gruboziarnistego public class ResourceEntity implements EntityBean { // dane o zasobie osobowym public String employeeid; public String lastname; public String firstname; public String departmentid; public String practicegroup; public String title; public String grade; public String email; public String phone; public String cell; public String pager; public String managerid; // kolekcje obiektów zależnych public Collection blockouttimes; public Collection skillsets; Wzorce projektowe warstwy usług 28
Tworzenie encji obiektu gruboziarnistego // utworzenie encji z obiektu transferowego public String ejbcreate(resourceto resource) throws CreateException { try { this.employeeid = resource.employeeid; setresourcedata(resource); getresourcedao().create(resource); } catch(exception ex) { throw new EJBException("Reason:" +...); } return this.employeeid; // funkcja zwraca identyfikator pracownika } Wzorce projektowe warstwy usług 29
Metody encji (prosta logika wewnętrzna) public String ejbfindbyprimarykey (String primarykey) throws FinderException {... } public void ejbremove() {... } public void setentitycontext(entitycontext context) {... } public void unsetentitycontext() {... } public void ejbactivate() {... } public void ejbpassivate() {... } public void ejbload() {... } public void ejbstore() {... } public void ejbpostcreate(resourceto resource) {... } Wzorce projektowe warstwy usług 30
Metody związane z obiektami transferowymi i zależnymi public ResourceTO getresourceto() {... } public void setresourcedata(resourceto resourceto) {... } public Collection getskillsetsdata() {... } // ta metoda implementuje strategię "lazy loading" Wzorce projektowe warstwy usług 31
Metody gruboziarniste (złożona logika wewnętrzna) public void addblockouttimes (Collection morebots) throws BlockOutTimeException // morebots to kolekcja obiektów transferowych BlockOutTimeTO {... } public void updateblockouttime(collection updbots) throws BlockOutTimeException {... } public void updateskillset(collection updskills) throws CommitmentException {... } Wzorce projektowe warstwy usług 32
Implementacja strategii leniwego ładowania public Collection getskillsetsdata() throws SkillSetException { checkskillsetload(); return skillsets; } private void checkskillsetload() throws SkillSetException { try { // ładowanie wówczas, gdy obiekt nie został jeszcze pobrany z DAO if (skillsets == null) skillsets = getskillsetdao(resourceid).loadall(); } catch(exception exception) { throw new SkillSetException(...); } } Wzorce projektowe warstwy usług 33
Zalety i wady stosowania wzorca Zmniejszenie liczby relacji między komponentami encyjnymi. Ułatwienie zarządzania klasami przez zmniejszenie liczby komponentów encyjnych. Zmniejszenie liczby wywołań między warstwą aplikacji a warstwą biznesową Zwiększenie wydajności sieci Zmniejszenie zależności aplikacji od schematu bazy danych Zmniejszenie gadatliwości w sieci Wymaga dodatkowego kodu przy zarządzaniu drzewem zależności wewnątrz obiektu. Wzorce projektowe warstwy usług 34
Business Delegate
Business Delegate - problemy Komponenty warstwy prezentacji mogą być wrażliwe na zmiany implementacji usług. Komponenty warstwy prezentacji wysyłają wiele wywołań przez sieć. Bezpośrednie korzystanie z API usług zmusza klienta do zajmowania się zagadnieniami sieciowymi. Wzorce projektowe warstwy usług 36
Rozwiązanie Delegat biznesowy jest abstrakcją usług po stronie klienta. Ukrywa implementację usług biznesowych. Chroni klienta przed możliwą zmianą implementacji API usług biznesowych. Wzorce projektowe warstwy usług 37
Struktura komponentów Client uses Business Delegate uses Business Service Service Locator lookups/ creates Wzorce projektowe warstwy usług 38
Współdziałanie komponentów Client Service Locator Business Service 1: Create Business Delegate 1.1: Get Service 1.1.1: Lookup 2: Invoke 2.1: Invoke 3: Get ID 3.1: Get ID for Business Service 3.1.1: Get Handle 3.1.2: Convert Handle to string ID Wzorce projektowe warstwy usług 39
Wykorzystanie identyfikatora usług Client Service Locator Business Service 4: Create (ID) Business Delegate 4.1: Get Service (ID) 4.1.1: Convert ID to Handle Handle 4.1.2: Get Service 4.1.2.1: Connect 5: Invoke 5.1: Invoke Wzorce projektowe warstwy usług 40
Strategie implementacyjne Delegat biznesowy jako klasa proxy Udostępnia funkcje proxy do przekazywania metod klienta do komponentu sesyjnego. Może lokalnie buforować dane, w tym referencje zdalne do komponentów. Może przetwarzać takie referencje na identyfikatory tekstowe. Delegat biznesowy jako adapter Dla środowiska B2B przy komunikowaniu się z usługami opartymi o J2EE Oddzielne systemy mogą wykorzystywać język XML, co wymaga wzorca Adapter (GoF) Wzorce projektowe warstwy usług 41
Integracja systemów B2B Client B2B Adapter Business Service 1: Invoke (XML) 1.1: Parse (XML) 1.2: Create 1.3: Invoke Business Delegate 1.3.1: Invoke 1.4: Prepare (XML) 1.5: Return (XML) Wzorce projektowe warstwy usług 42
Przykład implementacja delegata biznesowego w postaci proxy (1) public class ResourceDelegate { // zdalna referencja do usługi Session Facade private ResourceSession session; // konstruktor łączący z poprzednią sesją usług poprzez jej identyfikator public BusinessDelegate(String id) super(); reconnect(id); } public void reconnect(string id) { session = (ResourceSession)ServiceLocator.getService(id); } Wzorce projektowe warstwy usług 43
Metody lokalne przekazywane przez wywołania zdalne do sesji usługi public ResourceTO setcurrentresource(string resourceid) throws ResourceException { try { return session.setcurrentresource(resourceid); } catch (RemoteException ex) { throw new ResourceException(...); } } public ResourceTO getresourcedetails() throws ResourceException {... } public void setresourcedetails(resourceto vo) throws ResourceException {... } Wzorce projektowe warstwy usług 44
Korzyści ze stosowania wzorca Ukrycie szczegółów wywołania usług biznesowych. Zmniejszenie wrażliwości komponentów warstwy prezentacji na zmiany implementacji usług. Możliwość obsługiwania wyjątków od warstwy usług. Możliwość lokalnego buforowania wyników i referencji do zdalnych usług biznesowych. Wzorce projektowe warstwy usług 45
Literatura Rysunki i przykłady pochodzą z następujących źródeł: http://java.sun.com/blueprints/corej2eepatterns/patterns/transferobjectassemble r.html http://java.sun.com/blueprints/corej2eepatterns/patterns/compositeentity.html http://java.sun.com/blueprints/corej2eepatterns/patterns/businessdelegate.html Literatura uzupełniająca: Gamma et al: Wzorce projektowe, WNT Warszawa 2005 http://student.agh.edu.pl/~zegarow/filez/wzorce/wzorce_projektowe.pdf Buschman et al: Pattern-Oriented Software Architecture Volume 1: A System of Patterns, Wyd. Wiley, Schmidt et al: Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects, Wyd. Wiley, Wzorce projektowe warstwy danych 46