About Me

My photo
Rohit is an investor, startup advisor and an Application Modernization Scale Specialist working at Google.

Friday, September 22, 2017

HOW NOT TO DDD

Recently at the exploreDDD conference I gave a lightening talk on How Not To DDD.
Here are the 7 ways you should NOT do Domain Driven Design(DDD).

1. Dysfunctional DDD

Doing DDD has no effect if you do not affect organizational change that aligns with the bounded contexts.

2. Honeymoon DDD

The activities of DDD are only effective when they are done in a group to enable cross-discipline collaboration. Event storming for 7 days by two people locked in a room is a honeymoon not event storming

3. Cargo-Cult DDD

Using DDD terms but not really understanding the "Why" of practicing DDD. I usually steer clear  of folks who do this unless they are about to do real harm to the project.

4. DDD-Lite

Relying on the warm wooly blanket of tooling and IDEs to enforce all your DDD constructs. Generating package names and a proper project structure does not a DDD make. Practice DDD in the actual model and not on the surface.

5. Everybody in the Pool DDD 

When the going gets tough instead of refining the model abandon ship and start merging bounded contexts or have transactions span boundaries.

6. DDD Heaven

You have entered this state when your Process Mangers act like God objects and start orchestrating across domains and bounded contexts. 

7. Event Source/CQRS Everything DDD

Yes it is true that the ceremonies of DDD like event storming naturally lead you to messaging and event driven architectures. This does not mean that you must automatically resort to event sourcing /CQRS to implement your design. Saving state in a database and exposing APIs for event driven state transfer is perfectly fine. 





Thursday, September 21, 2017

How To Deal With XA Global Transactions in the Cloud

For decades developers have relied on global distributed XA transactions with a two phase commit protocol to coordinate  state updates across different resource types. Application vendors fueled this drug addiction by building increasingly powerful transaction managers and introducing extensions like last participant support. The XA protocol and the strong consistency provided by transactions does not model real life where eventual consistency abounds. 

In a distributed system built on the microservices architectural style deployed on the cloud the implicit guarantees provided by the default rollback of the XA protocol no longer work. In distributed systems the uncertainty of the state has to be explicitly dealt by the application.  This inconsistency in a distributed application is dealt with by a Saga or a Process Manager. Note that saga's and process manager's are NOT antithetical to DDD. 

Data consistency in a microservices system cannot be implemented by distributed transactions. Use the SAGA pattern to string together a series of local transactions with compensation events. Using Saga's or process managers correctly will not violate your context boundaries. In fact using a higher level state machine will allow you to focus more on the domain concerns rather than bike shedding over the implementation(re-sequencing, de-duplication) of an event driven architecture.

In today’s distributed world, consider global transaction managers an architecture smell. See Kevin Hoffman's article on this topic:  Distributed Transactions in a Cloud-Native, Microservice World.

Pat Helland in his updated paper Life Beyond Distributed Transactions states
In a system that cannot count on distributed transactions, the management of uncertainty must be implemented in the business logic. The uncertainty of the outcome is held in the business semantics rather than in the record lock. This is simply workflow. Nothing magic, just that we can’t use distributed transaction so we need to use workflow.
Another excellent source of insight on this topic is from Josh Long and Kenny Bastani in their excellent book Cloud Native Java. From See JTA and XA Transaction Management in Appendix A Using Spring Boot with Java EE in CloudNativeJava book.

Distributed transactions gate the ability of one service to process transactions at an independent cadence. Distributed transactions imply that state is being maintained across multiple services when they should ideally be in a single microservice. Ideally, services should share state not at the database level but at the API level, in which case this whole discussion is moot: REST APIs don’t support the X/Open protocol, anyway! There are other patterns for state synchronization that promote horizontal scalability and temporal decoupling, centered around messaging. You’ll find more on messaging in our discussion of messaging and integration.
From https://www.safaribooksonline.com/library/view/Cloud+Native+Java/9781449374631/part03ch02.html#messaging

With event carried state transfer or event sourcing  We can use the saga pattern and design compensating transactions for every service with which we integrate and any possible failure conditions, but we might be able to get away with something simpler if we use a message broker. Message brokers are conceptually very simple: as messages are delivered to the broker, they’re stored and delivered to connected consumers. If there are no connected consumers, the broker will store the messages and redeliver them upon connection of a consumer.
Message brokers have their own, resource-local notion of a transaction. A producer may deliver a message and then, if necessary, withdraw it, effectively rolling the message back. A consumer may accept delivery of a message, attempt to do something with it, and then acknowledge the delivery—or, if something should go wrong, return the message to the broker, effectively rolling back the delivery. Eventually both sides will agree upon the state. This is different than a distributed transaction in that the message broker introduces the variable of time, or temporal decoupling. In doing so, it simplifies the integration between services. This property makes it easier to reason about state in a distributed system. You can ensure that two otherwise non-transactional resources will eventually agree upon state. In this way, a message broker bridges the two otherwise non transactional resources.
If you wan to do Distributed Transactions In Spring, With And Without XA take a look at this article from David Syer and the code samples that go along with it on how to do non XA distrubuted transactions with Spring 

Best Efforts 1PC Pattern
The Best Efforts 1PC pattern is fairly general but can fail in some circumstances that the developer must be aware of. This is a non-XA pattern that involves a synchronized single-phase commit of a number of resources. Because the 2PC is not used, it can never be as safe as an XA transaction, but is often good enough if the participants are aware of the compromises. Many high-volume, high-throughput transaction-processing systems are set up this way to improve performance.

So in summary
  • Prefer Resource Local best effort single single resource Transactions over global transactions
  • Prefer Spring’s @Transactional variant over EJB’s @javax.ejb.TransactionAttribute or JTA’s @javax.transaction.Transactional
Moving away from distributed transactions requires an adjustment in mindset to make use of new paradigms. Move away from JTA to an architecture and implementation style where you model the domain uncertainty and make the best effort to model and handle it in the business logic instead of delegating this core responsibility to the underlying platform. 



Resources:
  1. Daniel Frey has created A Demo App to illustrate the use of the JPATransactionManager to handle Database and JMS “rollbacks”. distributed-tx