Code Monkey home page Code Monkey logo

domainevents's Introduction

Domain Events: A clean approach

Prequisites

  • JDK 11
  • Docker v. 19+
  • Docker-Compose v. 1.26+
  • make

Why Domain Events

Design for scalability

Most of times, even in average-complex applications, we need to implement complex workflows where a user action can impact on multiple aspects of the domain. Think about an e-commerce app, where a cart checkout involeves order creation, inventory check for products, scheduling shipments and so on. Some of this updates are performed with atomic transactions*, to make sure to leave the system in a consistent overall state. This of course affects performance as well as user experience. For this reason, DDD doctrine recommends to split up the domain implementation in "aggregates" which define what data are updated under atomicity contstraints, and every request should involve a single aggregate update, while the additional impacted aggregates are eventually updated

*Notice, here "atomicity" and "consistency" are not referred to the data level

Managing side-effects

Flexible Consistency Semantics

Sometimes we are led to think that domain events === async stuff that flies back and forth into our process and eventually consistent distributed transactions. Actually this is not took for granted: it really depends on the undelying technology. Therefore, domain events give developers the freedom to choose how to deal with consistency. With Spring Boot we can implement

  • Synchronous, in-thread local events
  • Asynchronous, multithreaded local events
  • Asychronous, multiprocess remote events

Other ecoystems offer different tools and implementations: think about Akka or Vertx and their Actor Model. Nodejs, Python's asyncio based on event-loops. Goroutines/channels and so on...

Adding Logging/Tracing capabilities

In this example is shown how it's possible -in some extent- to decorate event listeners in Spring Boot in order to address cross-cutting concerns. if the latter statements makes you think about AOP, you should know that it's very tricky to develop an Aspect that joins Spring's ApplicationEventPublisher, since this is also the ApplicationContext.

An even more trvial approach would just be to wrap ApplicationEventPublisher into a custom decorator and define the wrapper as a Primary Bean: this works indeed, but there is no way to inject it into AbstractAggregateRoot inheriting objects

So I came out with another approach: define a "catch-all" event listener that listens to all Events that implement the DomainEvent interface. This means that devs declare that certain events are also domain events, and domain events should be treated in a specific way; for instance, logging each occourrence and generating a new span

How to publish remote (cross-domain) events

When you split an event-driven, monolithic app into multiple microservices, one of the operation that should be done is to replace local domain events with "remote events" sent over the wire (in this example, the "wire" is RabbitMQ) it would be nice if we are able to do it without any modification to the core logic. That's why this example defines a specific EventAdapter that listens for CrossDomainEvents, a specialization of DomainEvents. Every CrossDomainEvent is serialized an associated to a specific topic (routing key) declared from the dev. Thus, to publish an event as a RabbitMQ message, is sufficent to make your event POJO to implement the CrossDomainEvent interface and implementing declared methods

Best Practices for beautiful domains

How to run it

You need to start the local "dev environment" in order to execute tests sudo make run-infra

Then you run tests from you favouire IDE or from command line with mvn clean test

Finally, shut down the infrastructure with sudo make stop-infra

domainevents's People

Contributors

cingaldi avatar

Stargazers

Will Chang avatar

Watchers

 avatar

Forkers

bellmit

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.