Pokazywanie postów oznaczonych etykietą CqRS. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą CqRS. Pokaż wszystkie posty

wtorek, 9 października 2012

ORM - "The Vietnam of Computer Science"

...cytat Teda Newarda rozbawił mnie szczerze - ale to śmiech przez łzy. Martin Fowler natomiast pyta: Ale co w zamian?

Możemy uciec się do rozwiązań typu Datoms (Encja, Atrybut, Wartość, Timestamp) lub bardziej "semantycznego" Event Sorcingu.

Jednak są to rozwiązania specyficznych klas problemów (podróże w czasie, wektory uczące dla Sztucznych Sieci Neuronowych) lub problemów skali Googl/Twitter/Facebbok - mimo, że nie pracujemy w tych firmach, to lubimy się na nie powoływać w swych elaboratach architektonicznych:)

Natomiast w typowych systemach biznesowych wystarczy przyjęcie prostych i racjonalnych zasad doboru odpowiedniego młotka do odpowiedniej klasy problemu:
  • Obiekty persystentne to Agregaty, których granice są wyznaczane wg dobrych praktyk DDD: np. modelowanie niezmienników oraz modelowanie jednostki zmiany biznesowej
  • Do persystencji Agregatów używamy ORM, ponieważ dobrze zakreślone granice agregatów (w tym unikanie zbędnych połączeń) rozwiązują większość problemów
  • Do wydajnego odczytu danych przekrojowych nie używamy ORM - nie służą do tego typu zadań 
Proste, łatwe i... przyjemne:)
W razie problemów z wydajnością warto spróbować różnych form separacji z podejścia: Command-query Responsibility Segregation.

//==========================

Więcej w archiwalnym poście, natomiast rozwinięcie w najbliższym numerze programistamag.pl



czwartek, 19 lipca 2012

Implementing Domain-Driven Design

Dziś ukazała się elektryczna wersja najnowszej książki autorstwa Vaughna Vernona poświęconej praktycznym aspektom implementacji DDD: "Implementing Domain-Driven Design", którą możecie zakupić na safari books online.

Recenzję opublikuję zaraz po tym jak skończę ją czytać (ale w kolejce priorytetowej znajduje się ok 10 pozycji "miękkich").

Już teraz mogę napisać, że mając wcześniej dostęp do pewnych jej części, śmiało mogę polecić nawet zaawansowanym praktykom DDD.


//====================================

Nieskromnie dodam (po przejrzeniu spisu treści), że książka stworzona pod nadzorem elity współczesnej inżynierii oprogramowania (M. Fowler, E. Evans, G. Young, U. Dahan) tylko nieznacznie wychodzi merytoryką poza nasz projekt DDD-CqRS Leaven:]

piątek, 2 marca 2012

Racjonalne wykorzystanie JPA

W poprzednim poście opisałem klasyczny problem wydajnościowy N+1 Select Problem występujący podczas korzystania z Java Persistence API, wraz z kilkoma podejściami do zabezpieczenia się przed jego powstawaniem.

W komentarzach pojawił się pewien wątek, który chciałbym teraz rozwinąć...

Zastanowimy się nad racjonalnym wykorzystaniem narzędzia jakim jest maper relacyjno-obiektowy. Jak to zwykle z racjonalnym myśleniem bywa - niesie ono ze sobą zwykle dodatkowe skutki uboczne w postaci nieoczekiwanych korzyści. W tym wypadku będzie to dodatkowa poprawa wydajności.

Co? Po co? Dlaczego tak?

W jakim celu mapujemy świat relacyjny na obiektowy?
Być może po to aby:
  • Pobierać w wygodny sposób obiekty biznesowe - wraz z wygodnymi mechanizmami typu Lazy Loading
  • Wykonywać na nich operacje biznesowe zmieniające ich stan - możemy tutaj tworzyć zarówno anemiczne encje modyfikowane przez serwisy jak również projektować prawdziwe obiekty modelujące reguły i niezmienniki biznesowe (styl Domain Driven Design)
  • Utrwalać stan obiektów biznesowych - stan, który zmienił się w poprzednim kroku (korzystając z wygodnych mechanizmów wykrywania "brudzenia" i mechanizmu kaskadowego zapisu całych grafów obiektów)
Jeżeli używasz JPA do tych klas problemów, to używasz odpowiedniego młotka do odpowiedniej klasy problemu. Czyli pobieram obiekt (JEDEN, no dwa, góra cy;) biznesowy, zmieniam jego stan, zapisuję go.

Pisząc zmieniam stan nie mam na myśli "edytuję podpinając pod formularz". Mam na myśli logikę aplikacji (modelującą Use Case/User Story), która modyfikuje mój obiekt biznesowy (uruchamiając jego metody biznesowe lub settery jeżeli jest on anemiczny). Przykład gdzie Order i Invoice to obiekty persystentne:

 public void approveOrder(Long orderId) {
        Order order = orderRepository.load(orderId);

        //sample: Specification Design Pattern
        Specification<Order> orderSpecification = generateSpecification(systemUser);
        if (!orderSpecification.isSatisfiedBy(order))
            throw new OrderOperationException("Order does not meet specification", order.getEntityId());

        // sample: call Domain Logic
        order.submit();
        // sample: call Domain Service (Bookkeeper)
        Invoice invoice = invoicingService.issuance(order, generateTaxPolicy(systemUser));

        invoiceRepository.save(invoice);
        orderRepository.save(order);
    }

Link do kodu.


Zawsze?

Jeżeli natomiast chcę wyświetlić na ekranie dane, np. dane przekrojowe, np w postaci tabelki (ludzie biznesu uwielbiają tabelki, najlepiej aby dało się przestawiać kolejność ich kolumn;) to narzędzie pod tytułem JPA nie jest odpowiednim młotkiem do tego problemu. W tym wypadku na każdym etapie postępuję nieracjonalnie:
  • Pobieram z mapera listę obiektów (zamapowanych na całe tabelki w bazie) gdy potrzebuję na ekranie jedynie kilku kolumn z każdej tabelki (dla bazy nie robi to różnicy, ale gdy maszyna serwująca bazę lub klient je zdalna to wówczas zaznamy odczuwać skutki tej decyzji)
  • Mam możliwość korzystania z mechanizmu Lazy Loadingu, który nie ma sensu dla operacji typu "pobierz dane do wyświetlenia"
  • Silnik mapera wykonuje niepotrzebne operacje związane z LL i wykrywaniem "brudzenia" - przecież nie będę modyfikował tych obiektów, chcę jedynie coś wyświetlić
  • Zdradzam model biznesowy warstwie prezentacji. Być może w prostych aplikacjach z prezentacją w technologii webowej (ta sama maszyna pobiera i prezentuje dane) nie jest to problem - dodatkowo zyskujemy produktywność w pracy. Ale jeżeli klienty (nie klienci) są zdalne (np Android)? Zdradzanie modelu domenowego wiąże się z drastycznym spadkiem bezpieczeństwa (wsteczna inżynieria) oraz z koniecznością koordynacji prac zespołów pracujących nad "klientem" i "serwerem", że o zapewnianiu kompatybilności starszych wersji klientów nie wspomnę. Niby banały, jednak w niektórzy ewangelizatorzy EE zachęcają do zwracania encji ponad warstwę serwisów (sic!)


Klasa problemu <=> Klasa rozwiązania

W każdym systemie mamy wyraźnie rozróżnienie na odczyt danych i modyfikację danych. Pisałem już jakiś czas temu o paradygmacie Command-query Seapration, z którego wyłoniła się architektura Command-query Responsibility Segregation.

Nie chcę się powtarzać, zatem w materiałach bloga (link na górze po prawej) znajdziecie prezentację na ten temat, polecam też artykuł samego mistrza: Martina Fowlera.

Separacja

Tak więc donosząc się do pytania Andrzeja z poprzedniego posta: Jak najbardziej konstrukcja SELECY NEW MyDTO(encja.pole1, ecnja.pole2) FROM Encja encja jest na miejscu. W przypadku gdy chodzi o zwrócenie danych do prezentacji (modelowanych jako DTO) a nie pobranie obiektów biznesowych do wykonania na nich operacji biznesowych.

Separację możemy poprowadzić jeszcze "głębiej" i dokonać projekcji modelu domenowego, który utrzymujemy w III postaci normalnej do postaci płaskiej, odpowiedniej do odczytu. W tym celu możemy zastosować Widoki Zmaterializowane lub np. odświeżać model Read przy pomocy zdarzeń domenowych.

Najmniej racjonalną rzeczą jaką możemy zrobić to pobierać encje JPA i przepakowywać je na DTO. Po co pobierać te dane (ryzykując N+1SP) skoro i tak musimy wykonać pracę (kodowanie, załączenie automatu) przepakowania?

Wydajność ++

Ale zostawmy zaawansowane architektury przygotowane do skalowania...

Jeżeli już decydujemy się na pobieranie poszczególnych kolumn z bazy, to dlaczego nie użyć czystego SQL zamiast HQL (konstrukcji SELECT NEW)? Przecież skoro wiem, że pewnych miejscach pobieram dane jedynie do odczytu, to być może warto zestawić osobną pulę połączeń z bazą - połączeń read-only. Być może baza, której używasz będzie wówczas działać nieco lepiej...:)

W takim wypadku warto użyć lekkiego mapera typu myBatis, którego użyję w celu mapowania Result Set na paczki danych (DTO) a nie na obiekty biznesowe służce do wykonywania operacji biznesowych!

//======================================

Pracując z Hibernate (od 2003r, od wersji 2.0) zawsze, w każdym jednym projekcie - małym i dużym (1200 tabel) dochodziło do sytuacji przepisania pewnych zapytań na czysty SQL z powodu wydajności. MyBatis na prawdę działa:)

Przykłady architektury, która wyraźnie rozdziela operacje odczytu i zapisu: Domain Driven Design & Command-query Responsibility Segregation sample project - Java, Spring, JPA

środa, 14 grudnia 2011

DDD na platformie Java EE 6

Dzisiaj coś dla miłośników Enterprise Edition.

Nieustannie rozwijamy projekt ilustrujący implementację zaawansowanych technik Domain Driven Design i architektury Command-query Responsibility Segregation.
Dotychczasowa implementacja oparta na Springu doczekała się swego lustrzanego odbicia na platformie Java EE6
W projekcie znajdziecie między innymi kilka sztuczek w CDI oraz przykłady wykorzystania silnika zdarzeń w modelowaniu biznesowym (dowiecie się również dlaczego budowany Events<> jest nieco ułomny:).

Więcej szczegółów na blogu projektu.

//===========================

W najbliższych planach aplikacja kliencka na Androidzie w architekturze Eventually Connected Client.

niedziela, 9 października 2011

Konferencja Warsjawa - kolejny warsztat DDD&CqRS Leaven

Zapraszam na konferencję Warsjawa, która odbędzie się w najbliższą sobotę (15 października) w Warszawie.

Warto dodać, że konferencja jest całkowicie darmowa:)

Podczas konferencji będziecie mogli uczestniczyć między innymi w naszych warsztatach, poświęconych projektowi DDD&CqRS Leaven.

Szczegółowy program warsztatów: https://github.com/warszawajug/warsjawa2011/wiki/Warsztaty-DDD-i-CqRS.

środa, 5 października 2011

Persystentny Multi-Listener, czyli... Saga

Persystentny multi-listener... jak to pięknie brzmi...:)

Cóż to takiego?

Listener - czy obiekt słuchający zdarzeń,
mulit - czyli chodzi o wiele zdarzeń,
persystentny - czyli posiadający trwały stan.


Podczas ostatnich warsztatów z zakresu projektu DDD-CqRS Leaven wspomniana wyżej technika modelowania czasu spotkała się z zainteresowaniem wielu osób. Nic dziwnego, jest to dosyć nowy pattern; również na szkoleniach wzbudza zawsze największe emocje. Głównie dlatego, że ciężko pogodzić się z myślą, że coś tak złożonego można modelować i implementować w tak prosty i przyjemny sposób:P

Pattern ma swoją oficjalną nazwę, brzmi ona Saga. Jeżeli saga kojarzy się senior developerom z sagą rodziny Carringtonów, to dobrze się Wam kojarzy. Saga to coś co może rozciągać się w czasie niczym telenowela. Saga jest patternem służącym do orkiestracji wielu zdarzeń, które mogą zajść w rozproszonym systemie w nieokreślonej kolejności. Czas pomiędzy zajściem zdarzeń może być relatywnie długi, dlatego należy persystować jej stan w czasie oczekiwania na kolejne zdarzenie.

Przykład:
Wyobraźmy sobie system, w którym mamy moduły: sprzedaży, płatności i magazynu.
W module sprzedaży możemy zatwierdzić obiekt biznesowy Zamówienie. Zamówienie rzuca wówczas zdarzenie biznesowe ZatwierdzonoMnie zawierające id tegoż zamówienia.
W module płatności możemy dokonać wpłaty. Być może jest to przedpłata dokonana wcześniej niż zatwierdzenie zamówienia... Moduł ten rzuca zdarzenie niosące informację o zajściu faktu dokonania wpłaty.
Oba zdarzenia są orkiestrowane przez sagę Zakupy. Jeżeli otrzyma ona oba zdarzenia (pasujące po id biznesowym) i stwierdzi, że jesteśmy "kwita" wówczas może wysłać sygnał do modułu magazynowego aby przygotować paczkę do wysyłki.

Oczywiście możemy tego typu proces zaimplementować w inny sposób niż zdarzeniowy, ale jeżeli zależy nam na decouplingu modułów systemu (wraz z wszystkimi konsekwencjami: skalowanie, testowanie, rozszerzalność, otwartość na dodawanie pluginów, redukcja architektury Speaghetti na poziomie modułów) to warto posłużyć się Sagą.


Udi Dahan dosyć dobrze wyjaśnia motywację oraz szczegóły koncepcyjne: Saga Persistence and Event-Driven Architectures dlatego nie chcę powtarzać, tego co zostało napisane ponad 2 lata temu.

Jak widać w powyższym linku technicznie Saga to złożenie 2 wzorców: Observer i Memento. O ile observera każdy zna choćby z bibliotek graficznych i wszechobecnych tam onClickListenerów, o tyle Memento jest mniej znanym patternem. Jeżeli ktoś oglądał film pt. Memento o człowieku, który miał problem z transferem danych z pamięci podręcznej (kora przed-czołowa) do pamięci długotrwałej (hipokamp) to skojarzenie jest również poprawne. Memento to pattern służący obiektom na wysyłanie do siebie informacji na przyszłość. Tak jak bohater filmu, który zapisywał i tatuował sobie na rękach informacje o tym co należy zrobić w przyszłości:)

Natomiast zainteresowanych szczegółami implementacji Sagi odsyłam do przykładu w projekcie DDD&CqRS Leaven:



//=============================================

Jako ciekawostkę dodam, że niektóre szyny komunikatów w .NET wspierają mechanizm Sagi niejako "z pudełka"...
Techniczny komunikat (message) jest traktowany na poziomie logicznym jak zdarzenie (event). Ichnie "Message Driven Beany" reagaujące na wiele zdarzeń to po prostu Sagi. Do tego automatyczne ładowanie i zapisywanie Memento, kończenie albo usypianie sagi oraz drobny szczegół: obsługa współbieżności...
Natomiast my w swym świecie Javy wciąż szukamy uber-frameworka webowego, który daje złudzenie, że każdy system jest CRUDem...

środa, 28 września 2011

Zapraszamy na warsztaty z "wypiekania zaczynu" (DDD, BDD, CqRS)

W najbliższą sobotę (1 października) organizujemy w ramach lubelskiego JUGa otwarte warsztaty z zakresu:
- modelowania z wykorzystaniem Domain Driven Design
- procesu Behavior Driven Development (w tym wykorzystanie JBehave, Selenium i Agentów)
- architektury Command-query Responsibility Segregation

Warsztaty będą przeprowadzone na podstawie materiałów z otwartego i darmowego projektu DDD+CqRS Leaven.

Szczegóły wydarzenia na stronie JUGa.


//============================

Dla zainteresowanych z innych zakątków Polski informacja: planujemy tego typu inicjatywy podczas zbliżających się konferencji branżowych - szczegóły wkrótce.

wtorek, 30 sierpnia 2011

Zaczyn DDD+CqRS

Jak pewnie zauważyliście, częstotliwość publikowania postów spadła ostatnio dosyć znacznie. A to za sprawą mocnego zaangażowania w nowy projekt - projekt ilustrujący techniki modelowania Domain Driven Design oraz wybrane podejścia do implementacji architektury Command-query Responsibility Segreation.

Projekt osiągnął poziom wersji Beta pierwszego Milestonea, tak więc już oficjalnie możemy go upublicznić: http://code.google.com/p/ddd-cqrs-sample/.



Zaczyn?
Nazwa ociekająca folklorem jest ilustracją idei: projekt to coś więcej niż Sample ale zdecydowanie nie jest to kolejny Framework - więcej na ten temat na wiki.
Gwoli wyjaśnienia: zaczyn to coś z czego powstaje chleb.

Odeszliśmy od formy frameworka przekonani przez samego Grega Younga (twórcę CqRS i propagatora DDD). Greg przekonał mnie podczas prywatnych rozmów, że framework dla CqRS delikatnie mówiąc nie ma sensu:)



Zawartość projektu odpowiada na pytania techniczne, które pojawiają się tak często, że uznaliśmy, że czas stworzyć sampla ilustrującego nasze podejście. Do tej pory istnieją dwa takie Sample napisane w Javie - my jednak chcieliśmy pójść nieco dalej. Tak więc projekt jest sumą doświadczeń jego twórców.

Co w nim znajdziecie:
- ilustracja wszystkich Builiding Blocków DDD (bez uproszczeń technicznych)
- ilustracja zaawansowany technik DDD (Bounded Context to nie są akademickie rozważania)
- ewolucyjne podejście do architektury warstwowej, różne poziomy separacji CqRS (na tym etapie nie wprowadzamy Event Sourcingu - wyjaśnienie powodów na wiki)
- pragmatyczne podejście do CqRS
- część bardzo specyficznej wiedzy wyniesioną przez nas z wiosennego szkolenia Grega Younga
- modelowanie czasu poprzez zdarzenia i dosyć nową technikę modelowania czasu: Sagi
- kilka eleganckich trików z wykorzystaniem Springa i Hibernate:)
- techniki testowania: jednostkowe, integracyjne i akceptacyjne
- połączenie JBehave (Behavior Driven Development) z Selenium
- już niedługo: nasz własny pomysł na uogólnienie historyjek tak by wspierały zarówno testowanie przez GUI jak i przez API



Zainteresowanych zapraszamy do:
- wiki - kilkadziesiąt stron A4 plus trzy wizualizacje w Prezi
- SVN - aktualnie ok 150 klas platformy zaczynu oraz przykładów DDD
- grupy dyskusyjnej
- bloga


//====================================

Teksty techniczne z zakresu DDD i CqRS będę publikował na nowym blogu. Natomiast niniejszy będzie wciąż prowadzony jako miejsce na tematy pozostałe.

piątek, 15 lipca 2011

Fowler o CqRS

Koncepcja architektury CqRS doczekała się oficjalnego błogosławieństwa przez samego guru współczesnej inżynierii oprogramowania - Martina Fowlera.

/*
*Pamiętam jak jeszcze w kwietniu Greg Young opowiadał mi
* o swojej pierwszej prezentacji na temat CqRS,
* gdzie w pierwszych rzędach siedzieli: Uncle Bob, Eric Evans i Martin Fowler.
* Po prezentacji Evans podszedł i powiedział:
*bardzo słaba prezentacja, zrozumiałem tylko 30%:)
*/

Tak więc możemy uznać, że CqRS wchodzi do kanonu stylów architektonicznych - z zastrzeżeniem jednak co do zakresu stosowalności: okiełznanie chaosu w złożonych częściach systemu i potrzeba skalowania. Czyli w sumie otrzymujemy pogodzenie dwóch skrajnych interesów: elegancki model (np. DDD) z wysoką wydajnością.
"So while CQRS is a pattern I'd certainly want in my toolbox, I wouldn't keep it at the top."

Warto zwrócić też uwagę, że Fowler wyraźnie rozróżnia CqRS, który jest stylem architektonicznym od Event Sourcingu, który jest jedną z możliwych technik persystencji. Z obserwacji mogę powiedzieć, że często jest to zbyt silnie utożsamiane, ale należy pamiętać, że zawsze można mieć jedną z tych rzeczy bez drugiej.

Z ciekawych kontekstów, w których Event Sourcing zaczyna mieć sens oraz mocno się opłaca, jest wykorzystanie porcji zdarzeń jako wektorów uczących dla Sztucznych Sieci Neuronowych. Nie mówi się o tym zbyt wiele w mainstreamie, ale ES jest naturalną i od dawna stosowaną techniką w tych klasach systemów. Próba przeniesienia ES na systemy gdzie nie ma takich zastosowań na pewno się powiedzie, pytanie tylko jakim kosztem w stosunku do jakich zysków...?


//==========================================

Wiele osób pyta o postępy w przygotowywaniu naszego DDD-CqRS Sampla w Javie.
Pierwszy milestone zbliża się dużymi krokami. Mamy trzy małe konteksty domen z przykładami każdego Building Blocku. Stos biznesowy jest ilustrowany zarówno klasycznie serwisami jak i commandami, gdzie mamy kilka ciekawych technik takich jak asynchroniczność i filtrowanie duplikatów. Sagi docelowo będą działać na JMS. Stos prezentacji ilustruje kilka typowych optymalizacji odczytu.

Chętnych, którzy chcieliby ocenić projekt przez jego upublicznieniem zapraszam do kontaktu.

środa, 4 maja 2011

DDD i CqRS w Toruniu i Lublinie

Dziś post czysto ogłoszeniowy.

Lublin: 9. maja
Zapraszam na prezentację poświęconą CqRS, która przedstawię na lubelskich dniach informatyki (szczegóły).

Toruń: 13. maja
Zapraszam czytelników bloga z Torunia i okolic na dwie prezentacje poświęcone DDD i CqRS, które wygłoszę 13 maja w ramach toruńskiej grupy .NET (szczegóły).


//============================

Jeżeli ktoś widział te prezentacje na konferencjach NYAC, 4Develoeprs lub 33rd Degree to zapewniam, że pojawi się kilka nowych szczegółów:)