Event sourcing: making it functional (5)

TL;DR

After defining events of the Payment aggregate it’s time to move on and work on applying these events.

State

To apply events, the state of Payment will be extracted to a separate class. This should be a familiar pattern to all event sourcing practitioners, but let me show the code for clear understanding of our approach

paymentstate

How to construct the state

  1. There are no public setters. The state has readonly properties.
  2. All events are applied with an Apply method.
  3. The only way to change the state is to apply an event.
  4. No Apply throws an exception. The event has already happened and the state is just an accumulator of the changes.

New Payment Aggregate

The Payment aggregate now can be transformed to use this state, by removing all the state changes and raising/applying events in these places:

paymentstate

Summary

We know how to extract a state from the aggregate and apply all the events. Although Payment uses events, it does not store them in any form nor allows accessing them for processing. In the current shape the Payment isn’t much different from the previous version. We extracted a few event classes and the state, but we still can’t treat events as the first class citizen. we need to move one step further and we will do it in the next blog post.

Event sourcing: making it functional (4)

TL;DR

In the last entry we defined the aggregate implementation that we’ll work on. Let’s move forward and make it an event sourced aggregate.

Events

The first and the most important event, is the fact of issuing the payment itself. Let’s define it in the following way:

paymentissued

The event contains all the data provided to the constructor of the payment aggregate in the past.

The next one is raised and applied when the payment is processed successfully. Let’s make it a class without any members. We just want to record a notion of success.

paymentissued

The last but not least is the one raised in case of the error. We make the errors explicit in here as we’d like to react to payments failure. One could model it in a different way, providing one event class, but then again, just follow this take on the payment problem.

paymentissued

Summary

We discovered three meaningful events:

  1. PaymentIssued
  2. PaymentProcessedSuccessfully
  3. PaymentProcessedWithFailure

In the next entry we will start rewriting the aggregate to use these.

Event sourcing: making it functional (3)

TL;DR

We’re on our journey to move from event sourcing oriented on the aggregates to a more functional approach. In the first entry, we went through some of the DDD building blocks. In the second, we defined an interface of the aggregate that we’ll work with. Before, going to the event sourced approached, let’s go through the aggregate’s implementation, somehow related to the Blue Book approach, without event sourcing.

Payment aggregate!

Let’s dive straight into the code

paymentapi

We can see that a payment is issued for a user, with a specified payment method and a given amount of money. Yes, it’s simplistic, but bear with me, and follow its implementation for a while.

The other method is responsible for receiving the gateway response and applying it onto the aggregate. The status and the description are updated accordingly.

So far so good? In the next entry we’ll make this aggregate event sourced!

Event sourcing: making it functional (2)

TL;DR

In the last post we covered the basic concept of DDD, the aggregate and its root. Before we move on with the non-functional approach, let’s try to define at least one aggregate, that could be used as an example for future posts and code samples.

A payment

For sake of providing an aggregate example let me reuse the payment example I introduced for the service kata purposes. The aggregate boundary is handling a single payment. This includes:

  • selecting payment method
  • registering an answer from the payment gateway
  • storing status

Having this we can easily imagine that the API of this aggregate could be similar to:

paymentapi

As you can see, there are no dummy setters or meaningless primitive properties. We exposed meaningful methods and properties for showing the part of the state we want to show. Additionally, the payment constructor shows all the parameters that are required to issue a payment.

With this example we can move forward and provide more insight into its initial implementation and refactoring it towards more functional design.

Event sourcing: making it functional (1)

TL;DR

This article starts a series of entries that will guide you through my experiences with making event sourcing functional. There are a few existing entries about a functional approach to event sourcing, but I want to share my path and a story behind migrating from one approach to another. I’ll start with some fundamentals. This will show from where I started, as well as it may help you to learn some basics of DDD and event sourcing if you’re not into the topic.

The Blue Book51szw87slrl-_sx258_bo1204203200_

There’s a book that is a must read, Domain-Driven Design by Eric Evans. It’s quite old and a lot of has changed in our industry. Still, the basic need of having developers understanding the domain they work on, the strategies and tactics they could use to embrace it, they are the same. Eric covers a lot of topics in there, one of them which is a really low level concept (and not the most important one) is the aggregate.

The aggregate

Let me quote Eric’s descriptions of the aggregate first:

An AGGREGATE is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each AGGREGATE has a root and a boundary. The boundary defines what is inside the AGGREGATE. The root is a single, specific ENTITY contained in the AGGREGATE. The root is the only member of the AGGREGATE that outside objects are allowed to hold references to, although objects within the boundary may hold references to each other. ENTITIES other than the root have local identity, but that identity needs to be distinguishable only within the AGGREGATE, because no outside object can ever see it out of the context of the root ENTITY.

The vital part of this description is the boundary. That’s what aggregate is for – to distill boundaries existing in a domain you work on. So once you set a boundary of data changed together, you ensure that they stay together. Additionally, you operate on this data only via the Aggregate Root, which might be treated as the public API of an aggregate, something that others interacts with.

The aggregate boundaries

If an aggregate is defined by its boundaries, one could design a system, that would be just one aggregate. This would enable to access all the data and still have a defined boundary, right? Wrong. What you want to do is to define aggregates following these two simple rules:

  1. aggregates are as big as there have to
  2. aggregates are as small as possible

Aggregates are as big as there have to

The very first rule says that the size of an aggregate is determined by a domain and a model. A domain can require some consistency across different entities, making an aggregate bigger. The same with model. Frequently it’s up to the modeller (a model’s creator) to create bigger or smaller aggregate, but not bigger than needed.

Aggregates are as small as possible

Distilling just one aggregate would mean, that a system can execute one action at a time (when optimistic concurrency applied). This isn’t enough for the majority of applications. Making aggregates small improves your system’s scalability and performance, not to mention your ability to design and model in small chunks.

Summary

This ends the first entry of this series. We recalled the aggregate’s definition and discussed briefly two rules of modelling an aggregate. Still, there’s more to come on our way of making the event sourcing functional. First, we need to visit a non-functional approach.

Service kata with Business Rules

TL;DR

In the previous post we started working on a code kata and discovered that instead of creating a new monolithic giant we could tackle the complexity of a process by modelling it right in its natural boundaries: contexts. It this post we continue this journey.

Requesting payment

Let’s spend some time on modelling a process of ordering a membership. It’s been said that it requires a payment and as soon as the payment is done, the membership is activated. We introduced the PaymentReceived event as an asynchronous response to the payment request.

Consider a membership order with the following identifier

11112222-3333-4444-5555-666677778888

When accepting the request for a membership, Membership sends a request to the Payments with the following information

payment_request

It is important to see, that the caller generates identifier, which has following properties:

  • In this case it reuses it’s own identifier for a different context to use snowy identifiers to create snowflake entities
  • As the caller generates id and stores it, in case of the failure when requesting a payment, it can be POSTed again as it’s idempotent (any http status indicating that it already exists means that the previous call was accepted and processed).

Using approach in a service oriented architecture enables idempotence (everyone knows the id upfront).

Events strike back

The result of the payment, after receiving money is an event PaymentReceived which is published to all the interested parties. One of them will be Membership, which would simply take the paymentId and check if there’s an order for a membership with the same identifier. It there is, it can be checked as paid. Simple and easy. The same will apply to other rules in other contexts.

There’s really no point of making this ONE BIG APP TO RULE THEM ALL. You can separate services according to business units and design towards integrating them.

Again, depending on the used tools, you can have events delivered by a bus to all the subscribers all use ATOM feed to publish events in there, and consume them by polling from other services.

Summary

These two posts show that raising modelling questions is important and that it can help to reuse existing structures and applications in creating new robust systems. They do not cover transactions, retries and more. You can use tools that solve it for you like a messaging bus or you’ll need to handle it on your own. Whatever path you choose, the modelling techniques will be generally the same and you can use them to bring real value into the existing ecosystem instead of creating the single new shiny application that will rule them all.

 

Code kata with Business Rules

TL;DR

How many times you were given an implicit requirements that you’d create one application or two services? How many times the architecture and design were predetermined before any modelling with business stake holders? Let’s take a dive into a code kata, that will reveal much more than code.

Kata

The kata we’ll be working on is presented here. It covers writing a tool for a set of business rules gathered across the whole company. The business rules depends on the payment (the fact that it is done) and some other conditions, for example:

  • If the payment is for a physical product, generate a packing slip for shipping.
  • If the payment is for a book, create a duplicate packing slip for the royalty department.
  • If the payment is for a membership, activate that membership.

The starting point for every rule is a payment that is accepted. Another observation is that these rules are scattered across the whole company (as the author mentions Carol on the second floor handles that kind of order). Do you think that having a new single application that gathers all the rules is the way to go?

Contexts

If a mythical Carol is responsible for some part of the rules, maybe another department/team is responsible for membership? What about the payments? Is the bookstore part of your organization really interested if a payment was done with a credit card or a transfer? Is a membership rule really valid outside of the membership context? Is it needed to anyone without membership specific knowledge should be able to say when the membership is activated?

I hope you see the way through these questions. There are multiple contexts that are somehow dependent but that are not a truly one:

  • payments – a part responsible for accepting money and making them transferred to the company’s account
  • membership – taking care of (possibly) accounts, monitoring activity, activating/disactivating accounts
  • bookstore/videostore or simply store – the sales part
  • shipping – for physical products

Are these areas connected? Of course they are!

PaymentReceived

The first visible connector is the payment. To be precise, the fact of receiving it, which can be described in a passive tense PaymentReceived. You can imagine, when requesting a membership, a payment is required. This can be perceived as a whole process, but could be split into following phases:

  • gathering membership data
  • requesting a payment
  • receiving a payment
  • completing the membership order

This is the Membership point of view. As you can see it requests a payment but does not handle it. We will see in the next post how it can be solved.