Autonomous Services

Autonomous Services

In my previous post, I explored how words and language used by users of our system in our domain space can have different meaning based on their context. This establishes which services own which behavior and data. In this post, I’m going to explore why services are autonomous and how we can communicate between them

This blog post is in a series. To catch up check out these other posts:

Autonomy

Autonomy is the capacity to make an informed, uncoerced decision. Autonomous services are independent or self-governing. 

What does autonomy mean for services? A Service is the authority of a set of business capabilities. It doesn’t rely on other services.

We are constantly in a push/pull battle between coupling and cohesion. High coupling ultimately leads to the big ball of mud.

What’s unfortunate is the move to (micro)services with non-autonomous services that rely on RPC (usually via HTTP) hasn’t reduced coupling at all. It’s actually made the problem worse by introducing an unreliable network turning the big ball of mud into a distributed big ball of mud.

Prefer Messaging over RPC

We want services to be autonomous and not rely on other services over RPC to reduce coupling. One way to do this is to communicate state changes between our services with events.

When Service A has a state change, we publish that event to our message broker. Any other service can subscriber to that event and perform whatever action it needs to internally. The producer of the event (Service A) doesn’t care about who may consume that event.

Services that don’t Serve

This may seem completely counter-intuitive since the definition of a service is an act of assistance. However, an autonomous service does not want to assist other services synchronously via behaviors, rather exposing to other services things that have happened to it via asynchronous messaging.

An example of this in our distribution domain is in the form of Sales services and the quantity on hand of a product.

Does Sales need the quantity on hand of a product?

Sort of. You could assume without knowing this domain that you do not want to oversell. However, in my experience in distribution, overselling isn’t really a sales problem as it is a purchasing problem.

Sales want to know the quantity on hand of a product, as well as what has purchasing ordered from the vendor but has not yet been received. This is called Available to Promise (ATP) and is used by sales to determine if they can fulfill an order for a customer.

Another interesting point is related to Quantity on Hand. The quantity on hand that is owned by the warehouse service is still not really the point of truth for the real quantity on hand. Whatever the quantity on hand is for a product in a database isn’t the truth. The real truth is what’s physically in the warehouse. Products get damaged or stolen and aren’t immediately reflected in the system. This is why physical stock counts exist which end up as inventory adjustments in our warehouse service.

If we’re using RPC, for the Sales Service to calculate ATP it would need to make synchronous RPC to:

  • Purchasing Service to get what purchase orders have not yet been received.
  • Warehouse Service to get the quantity on hand.
  • Invoicing Service to determine what other orders have been placed but not yet shipped.

However, if we want our Sales Service to be autonomous it needs to manage ATP itself. It can do so by subscribing to the events of the other services.

Sales can manage it’s own ATP for a product subscribing to the various events. When a purchase order is placed it will increase the ATP. When inventory is adjusted it will increase or decrease the ATP. And finally when an order is invoiced it will decrease it’s ATP.

Blog Series

More on all of these topics will be covered in greater length in other posts. If you have any questions or comments, please reach out to me in the comments section or on Twitter.

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Is CQRS Complicated?

There are many misconceptions about CQRS. It’s often referenced alongside other patterns that can make it seem difficult and complicated. Is CQRS complicated? No. CQRS is simple. Really simple.

What is CQRS?

First, let’s tackle at the very core what CQRS actually is.

CQRS stands for Command Query Responsibility Segregation and was coined by Greg Young. CQRS is related to CQS (Command Query Separation) principle by Bertrand Myer which states:

Every method should either be a command that performs an action, or a query that returns data to the caller, but not both.

In other words, a command is a method that mutates state and query is a method that returns state. A method generally doesn’t do both, but there are exceptions to this rule.

CQRS takes CQS a step further by separating commands and queries into different objects.

To use an exampling in C#, here is a shipment class has two methods. It applies CQS, in that each method either performs an action or returns data.

CQRS Applied

If we take the above class and were to apply CQRS, we simply just need to turn this into two objects. One object would be used for mutating state (ShipmentCommand) and the other object for returning state (ShipmentQuery).

That’s it. You’ve just applied CQRS. Wasn’t that totally unexciting?

Misconceptions

I suspect the reason for the misconceptions about being complex and difficult stems from people seeing a diagram like this:

Is CQRS Complicated?

If you search google images for CQRS, you are bound to find almost every diagram that looks like the one above or some variation of it.

Is the diagram applying CQRS? Yes.
Is the diagram only applying CQRS? No.

When you hear talks or read about CQRS you are often also hearing about a bunch of other patterns or technology. Mainly those that in attempted to be represented in the diagram above.

You do not need:

  • Message Broker or Bus
  • Messaging
  • Domain Model
  • Domain Events
  • Event Sourcing
  • Eventual Consistency
  • Separate Models for Reads and Writes
  • Domain Driven Design

Enabler

I often say that CQRS is an enabler. It enables or facilitates using other patterns that often fit well together. This is why you often see CQRS and Event Sourcing applied together.

CQRS is not Event Sourcing nor does it require you to use Event Sourcing. CQRS simply fits well and enables you to apply Event Sourcing.

Fat Controller CQRS Diet

I’ve blogged a bit about how to implement CQRS without any of the other fluff. You can check out my Fat Controller CQRS Diet blog series as well as a related talk:

More

I plan on breaking down some of the misconceptions and other aspects that are often lumped in with CQRS in coming posts.

If you have any questions or comments, please let me know on twitter as I will focus my posts on those questions and comments.

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Orleans Smart Cache Pattern

Orleans Smart Cache PatternI discovered the Orleans Smart Cache Pattern by listening to a talk by John Azariah and Sergey Bykov.  The idea is that you can use Orleans as a distributed cache in front of (permanent) storage.  This is really ideal if you have a read heavy system, which most are.  You could optionally also choose to buffer your writes when you make state changes.  Ultimately you will reduce load on your storage by accessing data/state from memory.

Blog Post Series:

Video Tutorial

 

State Holder Grain

The idea is we are going to create a Grain that will be used for holding/containing our state.  There are just two methods, setting and getting our state as defined in IStateHolderGrain<T>

Implementation

For this example, I’m creating a POCO CustomerState to hold some customer data. Then create a ICustomerGrain that just extends IStateHolderGrain where T is our POCO CustomerState. Our concrete class CustomerGrain that implements that new ICustomerGrain. Lastly I created a CustomerStateService which just contains some static methods that create and retrieve our POCO.

Usage

As per my previous post, I’m using ASP.NET Core with Botwin Middleware for a route endpoint.  From here I can use the CustomerStateService to create and fetch out our data.

Abstraction

One of the benefits is abstraction as we can have a POCO for our state that can be persisted to permanent storage.  There’s no dependency of Orleans in our POCO or Botwin Module. Also we have an immediate consistent cache.  If we were to expose methods to modify the state, our grain would persist those to permanent storage when it decides and we are always returning the most up to date state.

More!

If you want to try the demo, all the source is available on my PracticalOrleans GitHub Repo. Do you have any questions or comments? Are you using Orleans?  I’d love to hear about it in the comments or on Twitter.

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.