How to make a state machine dependant on a higher level one? - state-machine

It's easier to be explained with an example:
Let's say I have a warehouse. My models are Order and Item.
The Order business logic is described in an FSM with states like: PendingPayment, Paid, PickingUp, PickedUp, etc.
An Item also has an FSM with states like: BackOrdered, InStock, Collected, Packed, etc.
The problem is this:
The Item has transitions that depend on the state of the entire Order. For example, transitions to BackOrdered and InStock depend on the Order being in the Paid state. Collected and Packed may be relevant only when Order state is PickingUp.
Hierarchical State Machine doesn't really fit here, since the Item state is "spread" between different Order states.
Any good ideas how to approach this problem?

Related

State Machine Diagram VS Flowchart

What are the differences and similarities between the state machine diagram and flowchart?
So far I found that the state diagram shows us the actual change in the state, not the process or commands like in the flowchart.
In a state diagram, the nodes are states and the arrows correspond to something that happens that triggers a change of state.
In a flow chart, the nodes are actions or decisions, and the arrows correspond to the flow of control, i.e. what happens next. Flow chart are not UML. The closest UML diagram is an activity diagram that allows you to meodell more precisely everything you can model with a flow-chart and more (since the arrows can also represent an object flow).
Both can be complementary: an action/decision in a flow-chart could trigger events that cause changes of state. But it's not necessarily one for one: an action may cause several state changes without any evidence in the flow-chart that these may happen.
Short and simplified example:
Imagine an Order object. It may have the state received, delivey in preparation, delivery complete, invoiced. Each of these state tells what can happen next with the order. That'll be a topic for astate diagram.
Imagine a flowchart. These are different actions happening in sequence: Get an order from customer, Pick items of the orders from the inventory, Send items to the customer, Are all items sent?, if yes, Prepare and send invoice, if no, Find missing items and then go back to Pick items ... and continue from there.
As you see: both can tell the same story, but from a different angle with different details.
As you mentioned, a State Machine Diagram focus on display from which state to which state the execution goes based on the input.
Although a State Machine can be handled as a specialized form of a flow chart / activity chart.

Multiple aggregates handle with one table?

we are modeling an order system and we have the Order concept. The Order has a life cycle from it is created to it is delivered and between them the order can be in other states. Some states have particular business logic, and sometimes share other business logic such as when an order can be expire in a concrete date if it has not finished on time.
Well, the team is doubting if
Use the state pattern (one aggregate, one repository), or
Use one aggregate/repository for handle each state of the order.
Within of the second approach, we are considering to use the same table for each repository, to have a table order to persist/load each aggregate. It is well seen from DDD perspective?
What do you think about?
In general, DDD is all about not polluting the domain with infrastructure concerns; whether different aggregates are stored in the same table is an infrastructure concern. As long as the repository/repositories are able to meet their obligations, go for it.
That said, having an Order have a lot of variation in terms of what operations are legal and what information is available from state to state might be a sign that the states might make sense being apportioned to different bounded contexts (e.g. a context where items are added to an order (e.g. a cart context), a checkout/payment context, an assembly for delivery context, and a being delivered context).

Stream aggregate relationship in an event sourced system

So I'm trying to figure out the structure behind general use cases of a CQRS+ES architecture and one of the problems I'm having is how aggregates are represented in the event store. If we divide the events into streams, what exactly would a stream represent? In the context of a hypothetical inventory management system that tracks a collection of items, each with an ID, product code, and location, I'm having trouble visualizing the layout of the system.
From what I could gather on the internet, it could be described succinctly "one stream per aggregate." So I would have an Inventory aggregate, a single stream with ItemAdded, ItemPulled, ItemRestocked, etc. events each with serialized data containing the Item ID, quantity changed, location, etc. The aggregate root would contain a collection of InventoryItem objects (each with their respective quantity, product codes, location, etc.) That seems like it would allow for easily enforcing domain rules, but I see one major flaw to this; when applying those events to the aggregate root, you would have to first rebuild that collection of InventoryItem. Even with snapshotting, that seems be very inefficient with a large number of items.
Another method would be to have one stream per InventoryItem tracking all events pertaining to only item. Each stream is named with the ID of that item. That seems like the simpler route, but now how would you enforce domain rules like ensuring product codes are unique or you're not putting multiple items into the same location? It seems like you would now have to bring in a Read model, but isn't the whole point to keep commands and query's seperate? It just feels wrong.
So my question is 'which is correct?' Partially both? Neither? Like most things, the more I learn, the more I learn that I don't know...
In a typical event store, each event stream is an isolated transaction boundary. Any time you change the model you lock the stream, append new events, and release the lock. (In designs that use optimistic concurrency, the boundaries are the same, but the "locking" mechanism is slightly different).
You will almost certainly want to ensure that any aggregate is enclosed within a single stream -- sharing an aggregate between two streams is analogous to sharing an aggregate across two databases.
A single stream can be dedicated to a single aggregate, to a collection of aggregates, or even to the entire model. Aggregates that are part of the same stream can be changed in the same transaction -- huzzah! -- at the cost of some contention and a bit of extra work to do when loading an aggregate from the stream.
The most commonly discussed design assigns each logical stream to a single aggregate.
That seems like it would allow for easily enforcing domain rules, but I see one major flaw to this; when applying those events to the aggregate root, you would have to first rebuild that collection of InventoryItem. Even with snapshotting, that seems be very inefficient with a large number of items.
There are a couple of possibilities; in some models, especially those with a strong temporal component, it makes sense to model some "entities" as a time series of aggregates. For example, in a scheduling system, rather than Bobs Calendar you might instead have Bobs March Calendar, Bobs April Calendar and so on. Chopping the life cycle into smaller installments can keep the event count in check.
Another possibility is snapshots, with an additional trick to it: each snapshot is annotated with metadata that describes where in the stream the snapshot was made, and you simply read the stream forward from that point.
This, of course, depends on having an implementation of an event stream that supports random access, or an implementation of stream that allows you to read last in first out.
Keep in mind that both of these are really performance optimizations, and the first rule of optimization is... don't.
So I'm trying to figure out the structure behind general use cases of a CQRS+ES architecture and one of the problems I'm having is how aggregates are represented in the event store
The event store in a DDD project is designed around event-sourced Aggregates:
it provides the efficient loading of all events previously emitted by an Aggregate root instance (having a given, specified ID)
those events must be retrieved in the order they where emitted
it must not permit appending events at the same time for the same Aggregate root instance
all events emitted as result of a single command must be all appended atomically; this means that they should all succeed or all fail
The 4th point could be implemented using transactions but this is not a necessity. In fact, for scalability reasons, if you can then you should choose a persistence that provides you atomicity without the use of transactions. For example, you could store the events in a MongoDB document, as MongoDB guaranties document-level atomicity.
The 3rd point can be implemented using optimistic locking, using a version column with an unique index per (version x AggregateType x AggregateId).
At the same time, there is a DDD rule regarding the Aggregates: don't mutate more than one Aggregate per transaction. This rule helps you A LOT to design a scalable system. Break it if you don't need one.
So, the solution to all these requirements is something that is called an Event-stream, that contains all the previous emitted events by an Aggregate instance.
So I would have an Inventory aggregate
The DDD has higher precedence than the Event-store. So, if you have some business rules that force you to decide that you must have a (big) Inventory aggregate, then yes, it would load ALL the previous events generated by itself. Then the InventoryItem would be a nested entity that cannot emit events by itself.
That seems like it would allow for easily enforcing domain rules, but I see one major flaw to this; when applying those events to the aggregate root, you would have to first rebuild that collection of InventoryItem. Even with snapshotting, that seems be very inefficient with a large number of items.
Yes, indeed. The simplest thing would be for us to all have a single Aggregate, with a single instance. Then the consistency would be the strongest possible. But this is not efficient so you need to better think about the real business requirements.
Another method would be to have one stream per InventoryItem tracking all events pertaining to only item. Each stream is named with the ID of that item. That seems like the simpler route, but now how would you enforce domain rules like ensuring product codes are unique or you're not putting multiple items into the same location?
There is another possibility. You should model the assigning of product codes as a Business Process. For this you could use a Saga/Process manager that would orchestrate the entire process. This Saga could use a collection with an unique index added to the product code column in order to ensure that only one product uses a given product code.
You could design the Saga to permit the allocation of an already-taken code to a product and to compensate later or to reject the invalid allocation in the first place.
It seems like you would now have to bring in a Read model, but isn't the whole point to keep commands and query's seperate? It just feels wrong.
The Saga uses indeed a private state maintained from the domain events in an eventual consistent state, just like a Read-model but this does not feel wrong for me. It may use whatever it needs in order to bring (eventually) the system as a hole to a consistent state. It complements the Aggregates, whose purpose is to not allow the building-blocks of the system to get into an invalid state.

Statecharts: Limit the number of time a state gets executed

How can I graphically represent within Statechart Diagrams that a state never gets executed more than a certain amount of times? So that it doesn't end in an infinite loop. Something like
assert enterPIN(int p) <= 3
and then branch to another state, if condition violated. Should I include it somehow in the guard? Or in the state activities?
EDIT:
(CheckPIN)--[invalid]-->(counter| + inc.)--[counter>3]-->(retainCard)
^ |
|-----[counter<=3]-----|
Something in this direction?
Legend: (StateName | (+-)activity), Transition: -->, [Guard]
I think your question is way too far down in the weeds. While you can model to infinitesimal detail, you should aim to create a much more durable model that will not require as much change over time.
H. S. Lahman makes an excellent case for using Moore state machines in his book, Model-Based Development: Applications. Moore state machines are where actions happen on entry to states, as opposed to where actions happen on transitions between states. His most compelling reason for using Moore state machines is that transitions do not degenerate into a sequence of function calls, they are instead announcements of things that have completed.
Here is an example of how to avoid all the detail and create a more durable model:
You'll notice that how things happen is completely encapsulated. For example, challenging the user might involve a PIN number, retina scan, or subdermal chip. The maximum failures allowed for each of those authentication modes might be completely different. That policy can be represented elsewhere.
To give a graphical answer:
This is how I would model it.
The counter object is usually not needed, since it's a simple counter and it's rather obvious that the rest/increment would refer to a common counter. Also there is no real <<flow>> to that counter. A not stereotyped dependency would also suffice.

Can an object take part in two state machines at the same time?

I am writing an object oriented program whose business process calls for a "ticket" object. The "ticket" object acts in two ways. It is stock to be sold and it is stock we ourselves are either holding on a sale-or-return basis or have committed to buying.
For this reason a ticket in the sales process can have a state of being "available" or "sold" (there are other states but these are the important ones). A ticket also as a state with regards to its SOR status it is either "sor" or "purchased".
In theory it is possible for an "sor" ticket to be either "available" or "sold", it is also possible for a purchased ticket to be "available" or "sold". The two sets of states have almost nothing to do with one another directly. It is presumed a "sold" ticket will eventually become "purchased" and for an "available" ticket to never make it. That's about it.
So would I be right to design the object with two separate and independent states? Or should it only ever have one state which incorporates all of the above? What is best practice?
ADDITIONAL: So here's a headwrecker, whilst I'm waiting in the wings for some help on this one I've gone back to my analysis and there's another bizarre layer to this. "Tickets" have subobjects called "Prices" this accounts for having a ticket that could be sold to an adult at one price, a child at another and a pensioner at yet a third.
When a ticket is in the "SOR" state that is noted at the ticket level, but when it enters the "Purchased" state that is logged against the Price because a ticket can have multiple possible prices but when it is paid for it is only paid for at one level (this is to do with things like venue capacities).
Similarly when the ticket is "available" it has multiple possible prices but it is "sold" against the "Price" because that's when a customer has made a decision to purchase, for example, one adult, two child tickets. The tickets for a given event could be entirely bought up by adults, or mostly sold to children, and obviously usually somewhere in between but the information related to the states happen in two different objects. Does this make a difference?
If the states themselves are truly independant then it seems to me that writing
ticket:
availability: available or sold
sor: sor or purchased
is much cleaner than what you'd get with a single state, which I guess would have to look like
ticket:
available_&_sor
available_&_purchased
sold_&_sor
sold_&_purchased
In the first case, you're treating the object as if it has a discrete availability state, as well as a discrete sor state, which sounds like it models your real world example clearly. In the second you have one artificial state that encodes these two values.
The difference between the two becomes magnified if you have more types of each discrete state, and suddenly you start having lots of combinations.
If the behavior on the two axes is independent (and particularly if there are conceivable subtypes or variant objects with overlapping behavior) it might make sense for Tickets to hold onto two state objects and to build its behavior out of the behavior of the separate state objects.

Resources