Vlad
Vlad

Reputation: 842

How to deal with external stateful webservices in DDD?

Scenario #1

Scenario #2

Scenario #3

Scenario #4 (problems start...)

Scenario #n [many many variants of #4] ...

So I cannot make my mind around a clear criteria on how to use webservices in DDD when they make changes in their state.

Ideally, I would do the changes in my storage, and then having some kind of integration layer that replicates those changes in external databases or services, with events for example. However, most of times there is a read-after-write consistency requirement, where if you refresh after a operation returns, the right data is shown on screen (eg: the payment receipt that comes from the same webservice where the payment was done).

Another example: A screen allows to save the data about a book, however the book specifications is saved in a database, and the descriptions (in several languages) are saved in an external service. The operation has to be consistent, if a user click "Save" and refresh, the screen needs to show all together, cannot just show the specifications with old translations or not translations at all because they are being replicated to another database.

Which is a solid criteria to decide?

Upvotes: 4

Views: 530

Answers (2)

Constantin Galbenu
Constantin Galbenu

Reputation: 17683

The rule that I always apply is that an Aggregate should be pure, without any dependencies to services that make IO calls (i.e. disk or network). It should give the same result every time it executes a command in a given state. Injecting a service or passing it as argument in a method call breaks this rule. The abstract idea is that an Aggregate should never make a decision based on data it doesn't own.

However, each complex system contains more than Aggregates. It contains also Sagas/Process managers (just Saga from now on) that model business processes. All one needs in order to design a perfect Saga is a clear business process and idempotent Endpoints.

A Saga starts and then listens to changes in the domain, usually by subscribing to Domain events. It reacts to them by sending commands to the corresponding Endpoint. Please note that I use the term Endpoint to refer to any receiver that process commands in an idempotent way. Aggregates, being pure, are such Endpoints. But a Saga Endpoint can be also an external system, like a Payment Gateway. Such a Gateway should not initiate a new Payment with an existing PaymentID (the opaque field that your system is sending).

Conclusion: from what I see, all your scenarios can be implemented as Sagas.

You can read more about Sagas here and here and here.

Upvotes: 1

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57297

The answer is to read Life Beyond Distributed Transactions.

The short form is that trying to reliably coordinate writes at different locations is expensive. In most cases it is better to admit in your design that you can't be in all places at once, and invest in your handling of the consequences of that fact.

Upvotes: 2

Related Questions