Posts tagged domain events

Really Simple Architecture

As you know, I’ve been experimenting with event sourcing for quite some time. My latest experiments are  based on Rinat Abdullin’s post (ideas) and on Greg Young’s Event Store and Ayende’s RavenDB (technology).

The idea is very simple. Because a picture is worth thousand words, take a look at this diagram:

As you can see, a system is broken down into services. Services communicate only via events. Each service contains a user interface and/or API which can be mashed up with other services’ UIs and APIs to in order to implement complex use cases. A service consists of following kinds of components:

  • receptors which react on other services’ events and send commands to command handlers within the service
  • command handlers which process commands. As a result, new events are generated within the service
  • view projections which process events generated within the service populating views
  • resources which return their representations based on data contained in views and/or transform representations sent by a client into commands

What’s interesting about this architecture is, using some experimental code I’ve written I can easily achieve 250 transaction per second on my 2 year old laptop. And by transaction I mean a proper and-to-end transaction, including

  • fetching an event by the receptor,
  • sending a command,
  • fetching the command by the handler,
  • loading an aggregate,
  • calling a business method on the aggregate
  • saving the aggregate (using optimistic concurrency)
  • updating a view

There is quite a lot of space for further optimization. The goal is to be able to run a complex SOA/EDA solution for a big enterprise on a hardware that fits in one rack. Downsizing is the next big thing!

    VN:F [1.9.22_1171]
    Rating: 4.9/5 (7 votes cast)

    Dependency inversion patterns and the domain model

    Inversion of control is constantly a hot topic. So are domain model and domain-driven design. How about combining these into one hot post? Yeah, combining posts is easy compared to combining the patterns. I will focus on particular type of inversion of control — the dependency inversion.

    The problem

    You are building a system. One day you encounter a new requirement stating that customers with unpaid dues should be notified by e-mail.

    As a careful designer, you had decided that your business logic will be structured according to domain model pattern. When the new requirement comes, you instantly know how to implement it — just add CheckUnpaidDues method to the Customer entity.

    On the other hand, as a conscious developer, you recognize that abstract concepts should not depend upon details. Put it another way, business logic (the Customer entity) should not depend upon infrastructure (the e-mail sending library). So you decide to make use of Uncle Bob’s dependency inversion principle.

    Here is the initial solution.

    public interface IEmailSender
    {
       void SendEmail(string address);
    }
    
    public class Customer
    {
       public string Name { get; set;}
       public string EmailAddress { get; set;}
       public IEmailSender EmailSender { get; set; }
    
       public void CheckUnpaidDues()
       {
          //...
          HasUnpaidDues = true;
          EmailSender.SendEmail(EmailAddress);
       }
    }
    

    Dependency injection

    It solution uses dependency injection pattern. Dependencies are being ‘injected’ into a domain model object using specialized framework — the Inversion of Control (IoC) container. This causes at least two problems.

    First of all, injecting dependencies into domain objects is a technically challenging task. You have to deal with your object/relational mapping (O/RM) framework, plug into it’s instance creation process and make it use your container instead of simply new-ing up objects. This, however, can be accomplished with most O/RMs, given a skillful developer and reasonable amount of time.

    The far worse problem is degradation of the model. Can you spot it right away? By adding an EmailSender field/property to the Customer entity we stated that e-mail sending mechanism is a part of customer model. It is ridiculous. Real world customers don’t carry SMTP servers in a backpack, so why should we model them that way? It is obvious that other, non domain-related, concepts are creeping into the model. We should do something to prevent this.

    Double dispatch

    The are some doubts (see comments under this Jimmy Bogard’s blog post) about concerning the name of this pattern, but that’s not the point. What does matter is the idea of passing a dependency as an argument to the method of domain object.

    public class Customer
    {
       public string Name { get; set;}
       public string EmailAddress { get; set;}
    
       public void CheckUnpaidDuesAndNotifyUsing(IEmailSender sender)
       {
          //...
          sender.SendEmail(EmailAddress);
       }
    }
    

    What we gain here by using this pattern is a clear message stating that e-mail sending mechanism is not a part of Customer’s model, but Customer-representing entity can use it in order to send notifications.

    Service Locator

    We can achieve a quite similar effect using service locator pattern:

    public class Customer
    {
       public string Name { get; set;}
       public string EmailAddress { get; set;}
    
       public void CheckUnpaidDues()
       {
          //...
          ServiceLocator.Current.GetInstance<IEmailSender>()
             .SendEmail(EmailAddress);
       }
    }
    

    There is a difference, however. A very big one, actually. This code hides the dependency instead of exposing it. This is what makes service locator an anti-pattern in majority of cases. As Krzysztof recently said (and I remembered)

    service locator dependency is the worst of static class dependencies because it makes out class depend on possibly anything

    There is, at least in case of dependency inversion, a third way (I don’t consider a service locator a solution anymore).

    Domain Events

    One again I will build upon great blog post series by Udi Dahan introducing a pattern called domain events. This pattern describes a solution to the problem of pushing information out of domain model without breaking it’s encapsulation. Sounds pretty useful, isn’t it? Will it enable us to send out e-mails (push data out) without introducing dependency on e-mail sender (without breaking encapsulation). Let’s try it out.
    First, the pushing data out part.

    public class Customer
    {
       public string Name { get; set;}
       public string EmailAddress { get; set;}
       public bool HasUnpaidDues { get; set; }
    
       public void CheckUnpaidDues()
       {
          //...
          HasUnpaidDues = true;
          DomainEvents.Publish(new CustomerHasUnpaidDuesEvent(this));
          return true;
       }
    }
    

    This model tells us that Customer entity is able to check whether there are any unpaid dues and, if so, publish that information for others to use. What are these others? An e-mail notifier, for example.

    public class SendEmailIfCustomerHasUnpaidDues : IEventHandler<CustomerHasUnpaidDuesEvent>
    {
       public IEmailSender EmailSender { get; set; }
       public void Handle(CustomerHasUnpaidDuesEvent @event)
       {
          EmailSender.SendEmail(@event.Subject.EmailAddress);
       }
    }
    

    It is obvious that this solution is slightly more complicated that a double dispatch one. Apart from the additional event handler class, users must also include the domain events infrastructure (I use the one Udi published, almost unmodified). Why pay the price of additional complexity?

    I think that the benefit of having really clear and focused model is worth its price. Customer model no longer cares about the notification process which is not essential to the model. It focuses on that’s important — checking whether there are any unpaid dues.

    This solution has, however, a downside. It can be used only in case of one-way communication. Attempts to use the event to carry the result back to the model (I have seen some) negate the publish semantics of the operation and make the whole model unreadable.

    Summary

    My own rule of thumb is to use domain events wherever possible (communication is, or can be, one way) and double dispatch in all the other cases. What’s yours?

    VN:F [1.9.22_1171]
    Rating: 5.0/5 (6 votes cast)

    Słowniczek pojęć bliskoznacznych

    Moja żona zainspirowała mnie do tego, aby przerwać strumień notek opisujących jakieś techniczne nowinki, tricki i sztuczki i pochylić się na moment nad tematami bardziej podstawowymi. Czym właściwie jest Domain-Driven Desing? Czym design (projektowanie) różni się od architektury? I czy w ogóle można to w jakiś sensowny sposób wytłumaczyć nie-programiście?

    Ostrzegam na wstępie, że niniejsza notka jest wyrazem moich osobistych opinii i nie należy ją traktować jako prawdę objawioną — nie znajduję się w tym momencie w proroczym transie:-)

    Architektura

    Zacznijmy od wysokiego poziomu abstrakcji. Co rozumiem pod pojęciem architektura? Przede wszystkim dla mnie jest to skrót myślowy prowadzący do architektury oprogramowania. Podczas, gdy istnieje wiele innych dziedzin architektury (jak enterprise architecture), ja ograniczam się w moim blogopisarstwie do tej jednej. Podoba mi się określenie znalezione na tym blogu:

    architektura jest rodzajem projektowania, ale nie każde projektowanie to architektura

    Architektura oprogramowania, jako zajęcie, to ten podzbiór aktywności projektowych o największym znaczeniu — takich, których skutki są trudne i kosztowne do zmiany.

    Jeszcze bardziej jednak podoba mi się inne określenie, zainspirowane artykułem Martina Fowlera. Pomysł polega na tym, że w tworzeniu oprogramowania nie ma narzuconej z góry ważności decyzji: to, czy dana decyzja jest trudna do zmiany,czy nie wynika ze sposobu w jaki budujemy nasz system. Architektura w takim ujęciu jest zestawem metadecyzji: decyzji o tym, które kwestii związanych z projektowaniem systemu mają być trudne do zmiany, a które nie. Wszystko inne (w tym same decyzje) są już  “jedynie” projektowaniem.

    Service-Oriented Architecture

    SOA to chyba najbardziej chwytliwy trzyliterowy skrót ostatniej dekady. Wszystko, co produkuje nasza branża musi mieć plakietkę “SOA”, aby się sprzedało. Ale czym właściwie jest to całe SOA? Ja mam przynajmniej dwie równoległe teorie. Każda z nich odwołuje się do abstrakcyjnej definicji, zgodnie z którą SOA to architektura, w której centralnym punktem są usługi — autonomiczne (jedna z 4 zasad SOA) byty udostępniające pewne funkcjonalności dla innych podobnych bytów.

    SOA “klasyczne”

    SOA “wg Thomasa Erla” to dla mnie kwintesencja klasycznego podejścia do usług. W tym rozumieniu katalog usług podzielony jest na warstwy, w obrębie których dominującym wzorcem jest definiowania funkcjonalności usług jest CRUD. Dominującym mechanizmem komunikacji jest zaś synchroniczna komunikacja WS-*. Nie jestem fanem tej definicji. Abstrahując od kwestii technicznych (nie wierzę w efektywność komunikacji synchronicznej), głównym problemem z tak rozumianym SOA są wymagania i założenia organizacyjne.

    Pierwsze z nich mówi, że aby SOA było zrealizowane efektywnie, całe przedsiębiorstwo musi być przeanalizowane pod kątem odkrywania usług, które mają się składać na implementację SOA, zanim rozpocznie się jakakolwiek implementacja. Bardzo brzydko pachnie mi to procesami wodospadowymi.

    Drugie, jeszcze bardziej problematyczne, założenie sugeruje, że wszystkie usługi powinny posługiwać się tym samym modelem danych w celu zminimalizowania transformacji. Nie zgadzam się z dwóch powodów. Po pierwsze modelowanie danych (a nie zachowania) jest wg mnie mało użyteczne. Po drugie jestem przekonany (a moje przekonanie zbudowane jest na własnym doświadczeniu i lekturze publikacji związanych z DDD), że model powinien rozwiązywać dokładnie jeden problem, dla którego powstał. Model do wszystkiego jest do niczego. Kropka.

    Pozostawmy na chwilę SOA i rozważmy inny sposób definiowania architektury…

    Event-Driven Architecture

    EDA nie jest pomysłem nowym. Nigdy jednak nie zyskała takiego uznania, jak jej siostra, SOA. Architektura oparta o zdarzenia nie jest aż tak napakowana różnymi standardami, wzorcami, dobrymi radami. Jedyne co mówi to, że poszczególne komponenty wchodzące w jej skład porozumiewają się za pomocą zdarzeń mających dobrze określone znaczenie w domenie rozwiązywanego problemu. Żeby nie szukać daleko przykładów, Java-owy Swing posiada architekturę EDA.

    SOA wg Udiego Dahana

    Wracamy do SOA aby przyjrzeć się wersji, którą proponuje nam Udi Dahan. Jest to architektura spełniająca założenia SOA (tenets), jednak jest także architekturą EDA. Kluczowym elementem tak zdefiniowanej architektury są autonomiczne (a jakże by inaczej) usługi komunikujące się poprzez publikowanie zdarzeń. Zainteresowanych odsyłam do prezentacji “How to avoid failed SOA”, którą Udi prezentował na zeszłorocznym C2C oraz (a może przede wszystkim) do bloga Udiego.

    Domain-Driven Design

    Schodząc z abstrakcyjnego poziomu architektury na ziemię, stwierdzamy, że coś musi sterować naszym projektowaniem. Na przykład domena — stąd Domain-Driven Design. W odróżnieniu od tego, co się zwykle sądzi, DDD nie jest czymś, co można zrealizować w konkretnym systemie jedynie poprzez wykorzystanie kilku technicznych tricków. DDD jest sposobem pracy zespołów produkcyjnych, który jest zorientowany na modelowanie domeny. To, co zwykle rozumie się pod pojęciem DDD, czyli wszystkie kwestie techniczne, to jedynie wzorzec projektowy Domain Model.

    Domain-Driven Design to wiele więcej niż ten wzorzec. Praktyki DDD obejmują sposób rozdziału zadań programistycznych, sposób projektowania implementacji, sposób współpracy między zespołami. DDD wpływa także na architekturę poprzez definiowania map kontekstów i struktur wielkoskalowych wpływających nie tylko na jeden budowany system.

    Domain Model

    To wzorzec projektowy sugerujący implementację logiki biznesowej w specjalnej warstwie nazywanej modelem domeny. Z modelem związanych jest wiele dobrych praktyk oraz mniejszych wzorców dotyczących m.in. organizacji kodu (na agregaty, encje oraz obiekty ValueObject). Model domeny zwykle składa się z klas reprezentujących jeden-do-jednego byty z przestrzeni biznesowej. Także zwykle jego stan jest trwale przechowywany, za zwyczaj przy pomocy narzędzia mapowania obiektowo-relacyjnego (O/RM).

    Domain Events

    To jeden z wzorców projektowych związanych z modelem domeny. Dlaczego go wyróżniłem i postanowiłem omówić osobno? Po pierwsze dlatego, że bardzo często się do niego odwołuję w swoich postach. Po drugie, zaś, dlatego, że zdarzenia domenowe często bywają mylone ze zdarzeniami Event-Driven Architecture. Domain Events to sposób na wypychanie informacji z modelu domeny konkretnego systemu. Informacje te mogą, ale nie muszą, zostać później przetransformowane na postać zdarzeń EDA. Równie dobrze mogą zostać przetransformowane na, bardziej klasyczne, asynchroniczne komunikaty. Nic nie stoi temu na przeszkodzie, ponieważ decyzje o użyciu Domain Events i EDA są zupełnie niezależne. Więcej o Domain Events możecie dowiedzieć się tutaj.

    To wszystko na dziś. Jeśli macie jakieś pytania lub sugestię co jeszcze w moich postach jest niejasne i wymaga zdefiniowania, zostawcie komentarz.

    VN:F [1.9.22_1171]
    Rating: 4.0/5 (2 votes cast)

    NetMX, domain events i logowanie

    Co łączy te trzy, z pozoru zupełnie ze sobą nie związane, pojęcia? Wszystkie trzy zastosowane razem pozwalają uzyskać bardzo dobry wgląd w to, co dzieje się z systemem podczas jego pracy. Za chwilę pokażę jak.

    NetMX (jeśli ktoś jeszcze nie wie :-) ) jest stworzonym przeze mnie portem JMX dla .NET. Jego główną zaletą jest możliwość udostępniania informacji o stanie aplikacji zdalnie, w formie tzw. MBean-ów — obiektów zarządzalnych. Każdy MBean posiada zestaw swoich atrybutów oraz operacji. Te pierwsze pozwalają dowiedzieć się czegoś na temat jego stanu, te drugie zaś — zmodyfikować zachowanie systemu. Oczywiście zdalnie.

    Domain events to swego rodzaju wzorzec, opisany przez Udiego Dahana, a wielokrotnie cytowany przeze mnie na tym blogu. Tak naprawdę, to chyba najczęściej wspominana przeze mnie koncepcja:-) Idea zdarzeń domenowych  jest bardzo prosta: obiekty domenowe mogą emitować zdarzenia, aby poinformować świat zewnętrzny o zmianie swojego stanu.

    Spróbujmy to teraz połączyć. Obiekty domenowe emitują zdarzenia, kiedy chcą poinformować świat o czymś interesującym. Możemy przechwycić te zdarzenia i wyświetlić w formie liczników w ramach MBean-ów. Możemy też zalogować ich wystąpienie, aby pomóc sobie z debugowaniu. Na koniec, jak pokazał Erich, możemy wykorzystać NetMX do sterowania poziomem logowania w aplikacji, czyli np. włączać i wyłączać logowanie wszystkich (lub tylko niektórych) domain events.

    Jeśli chodzi o modyfikację poziomu logowania, to Erich opisał tę kwestię świetnie, więc nie będę się tym zajmował. Logowanie zdarzeń domenowych to kwesta rozbudowy mechanizmu Udiego:

    • albo o dodanie interfejsu niegenerycznego IEventHandler, który pozwala obsługiwać wszystkie zdarzenia,
    • albo zmianę sposobu wyszukiwania handler-ów tak, aby dla typu T sprawdzane były obiekty obsługujące wszystkie typy bazowe i interfejsy implementowane przez T.

    Dzięki temu będziemy mogli napisać uniwersalnego handler-a logującego. Ja osobiście wybrałem to pierwsze rozwiązanie, ponieważ wydaje mi się dużo prostsze. To drugie, jest za to dużo potężniejsze, ale przecież YAGNI! :-)

    Integracja z NetMX jest dosyć prosta i można do niej podejść na kilka sposobów. Ja wybrałem sposób z klasą bazową i konfiguracją w konstruktorze a’la FluentNHibernate — w przyszłości być może rozbuduję ją o możliwość konfigurowania przez konwencje. Póki co mam klasę bazową EventDrivenDynamicMBean, która udostępnia metodę

    EventDrivenAttribute<T>(string attributeName, Predicate<T> filter)
    

    przy czym parametr “filter” jest opcjonalny. Przykładowy MBean wygląda tak:

    public TransactionProcessingMBean : EventDrivenDynamicMBean
    {
       public TransactionProcessingMBean() : base("Przetwarzanie transakcji") //Przyjazna nazwa MBean-a
       {
          EventDrivenAttribute<TransactionProcessed>("Przetworzone");
          EventDrivenAttribute<InsufficientFunds>("Brak środków");
       }
    }
    

    Jeśli uważacie, że podejście jest interesujące, mogę spróbować wydzielić ten kod i wrzucić go tu, na bloga. Mnie  pozwoliło ono zaoszczędzić całą masę kodowania. Poprzednia implementacja monitorowania (także korzystała z NetMX) oparta była na MBean-ach standardowych (statycznych). Każdy taki MBean wymagał napisania interfejsu (eksponowanego zdalnie), klasy go implementującej oraz poutykania tu i ówdzie w modelu domeny odwołań inkrementujących odpowiednie liczniki MBean-a. Szczególnie to ostatnie bardzo mi się nie podobało i było głównym powodem to poszukiwania alternatywnych rozwiązań.

    VN:F [1.9.22_1171]
    Rating: 0.0/5 (0 votes cast)