Refactoring to Microservices – Using a Document as State

In a previous installment of our Microservice refactoring effort, I’ve introduced a ShopManager and a Clerk to implement the shopping process (see this blog). I ended up with a JSON document transferred between services. To make life easy for myself I just parsed all of the document using Spring magic. This time I will discuss the downside of this strategy and show an alternative.

If you’re interested in details, you can find the code I’m referring to here: 

git clone git@github.com:xebia/microservices-breaking-up-a-monolith.git

git checkout tags/document_v2

The code can be found in the services/messages folder.

So, last time I ended up with a JSON document sent around from one service to the next, looking like [this]:

{

  "uuid": "a89a65ae-6d1a-42e5-a8f1-11b6d190286e",

  "status": 0,

  "webUser": {

    "uuid": "f7871043-9224-4ac7-8f5b-67976ff54137",

    "username": "webuser051dcde5-43d7-434d-b363-3dee6dc137ce",

    "password": "password"

  },

  "orderr": {

    "uuid": "662dbb25-cf36-440b-998a-93bac6abbdaf",

    "ordered": 1456001059094,

....

    "total": 0.0

  }

}

In order to parse this document, I created classes for each concept and a Clerk class as a container. While working on this version I frequently had to change some part of the domain classes and ended up making the same change in all of my services. This seemed to go against the general microservices idea of independent components. And of course it’s a lot of rather boring work.

To improve the design I implemented an idea inspired by Greg Young’s CQRS/DDD course. The idea is to store the JSON document as is and use only the parts that are needed. Marshalling and unmarshalling is done by domain classes.

As an example, let’s look at the [payment component].

The sequence diagram below shows the interaction between classes.

The version of Clerk in the payment service holds a reference to a Payment as well as the full text of the document it receives from the shopManager service (in [EventListener]). You can imagine that during the payment process a customer will add details to the payment that are stored in the payment data store. When the payment is finalized, an updated version of everything we know about the shopping session (as represented by a Clerk) is sent back to the shopManager service.

In the example updating and sending the resulting document is handled by [PaymentController] when it receives a PUT message with the customer’s credit card data. PaymentController updates the Payment with card number and date, stores this updated information in its database and then sends a new Clerk JSON message on its way to the shopManager service. There’s some implicit processing going on here (I’m not really happy with this but haven’t found a better solution yet): Clerk’s getDocument() method updates the document attribute by inserting a new version of the Payment data and then converting this to JSON. In a future version of this code I hope to find a better way. Maybe by storing the document separately from clerk in its own table and making the update-before-send more explicit.

This version of the domain code is smaller because the domain classes in each service are more focused on a single problem. This means it will be easier to make changes because a change in, say, the Shipment class in the fulfillment service will not impact payment or shopManager.

 

To view or add a comment, sign in

More articles by Jan Vermeir

  • Easy lambdas with Netlify

    Over the past years I've tried working with lambda functions on and off a couple of times. Each time I got stuck…

  • A/B Testing with Netlify

    While browsing the Netlify configuration site for my account (in a more or less panicky attempt to find some config…

  • Unlimited versions of your site with Netlify

    Remember when we used to have a production, acceptance testing, integration and development version of a site? And that…

    3 Comments
  • Burst your bubble: using machine learning to change the world

    Social media has been blamed for locking people in a bubble, only showing them news that is in line with their beliefs.…

    3 Comments
  • Mutation testing with Pitest

    Mutation testing promises to help ensure quality tests. It does this by making changes to a code base and running all…

    2 Comments
  • How to if?

    While trying to upgrade my programming skills, I ran into a new-fangled way to do ifs. The example below is taken from…

    9 Comments
  • Uncle Bob and my personal programming Kata

    My first [Uncle Bob] event was the 2017 [GoTo conference] in Amsterdam, where Robert Martin delivered a talk like he…

    3 Comments
  • Have we made no progress in software engineering since 1968?

    Friday I was at [Joy of Coding] in Rotterdam, an excellent conference about software development. I especially enjoyed…

  • Refactoring to Microservices – Introducing Docker Swarm

    In my [previous blog] I used local images wired together with a docker-compose.yml file.

  • Refactoring to Microservices – Using Docker Compose

    In the previous version of the shop landscape (see tag 'document_v2' in this [repository]) services were started with a…

Others also viewed

Explore content categories