What would the actor be in a use case where stock is reordered automatically when it hits a certain point - uml

Say there is 5 bags of potatoes, when it hits two bags, an order is sent to the supplier automatically. Who/What is the actor?

Clearly you have an actor to watch the queue like this:
Even if the Potato Watcher is something implemented inside the SUC, it would be an actor on its own. You may drag it inside the SUC boundary. In a final implementation it might be a system task to poll a queue or a subscriber to the queue. But from the added value viewpoint it's just a simple actor to watch a queue and do something with it.

Since "an order is sent... automatically" the system is the actor. Assuming you are automating using software system.
However in real life it all goes wrong and businesses are far away from sending orders automatically.
Badgerbadger, you need to be carefull about statement "sent an order".
It is easy to overlook actual business process and previous subfunction-level answers are giving a nudge.
More realistic scenario is that the system is the actor who just initiates the check of stocks, maybe orchestrates. And then there is a complicated process of getting approval, finding budget, checking if goods are really required to be ordered and so on. In theory all of those can be automated, but usually in practice there is a work for human actor as well. Of course you may be lucky and avoid all of this.
Example of pessimistic scenario to consider:
It was eight bags, but now hits three. John just bought five bags from us, hooray!
System automatically places an order and pays for 10 more bags.
In ten minutes someone ordered one more.
System automatically places an order again and pays for 10 more bags.
We don't have enough money on account so we are facing overdraft.
At the same time regular inspection found that one bag is rotten.
System: 10 more bags please!
Our colleague just told us that we've missed 20% discount from supplier on simultaneous orders of 25+ bags which can be obtained only by calling a company manager.
John cancels his order in an hour after placing it.
Now we have 36 bags and a hole in our budget.
And our marketing manager just told us that the green bags system ordered are actually now selling with a discount, we are getting rid of them in favour of new line of blue bags.

You have to possibilities here:
Each time the stock is used the system checks if the condition to order is met and if yes then order it. As ordering will probably involve another actor (e.g. supplier's system), you might need to model it as a separate UC and use extend relationship. In this case you will not have any additional actor initiating the order, only the actor initiating stock usage.
The system checks on a regular basis what stocks reached the automated order level and make a single mass order. In this case you'll have to model Scheduler as an actor (in reality it's another system running on the server so it's fine to call it an actor). Some people prefer modelling such actor as "time" but it's discouraged.

Related

Modeling one-to-many relations using Domain Driven Design

This question is more of a general question about how to model simple one-to-many relations using collections: should a change in a list item be reflected in the version of the aggregate containing it?
The domain is about meeting scheduling (like in Outlook).
I have a Meeting entity, which can have multiple Participants.
A participant can accept/decline meeting requests.
Rescheduling a meeting nullifies all of the participants confirmations.
I thought of two ways to model this.
Option 1
The Meeting aggregate will contain a list of Participants where each Participant has a ParticipantId and a Status (accepted/denied).
The problem here is that every Accept or Deny command, for a specific participant, increments the Meeting's version, which means two participants will enter a race condition if trying to Accept the meeting request based on the same original version.
Although this could be solved by re-reading the Meeting's document and retrying the Accept command, it's quite annoying considering how often this could happen.
Another approach is to ignore the meeting's version when executing the Accept command, but this introduces a new problem: what happens if, after sending the meeting requests, the meeting has been rescheduled? In this case we can't afford to ignore the Meeting's version, because this time the version DOES represent a real version that should be considered.
BTW, is it at all a good practice to ignore the version in some of the commands and not in others?
Option 2
Extract a Participation aggregate out of Meeting.
Participation will have MeetingId, ParticipantId, and Status.
It will also have its own version.
This way, when participant X Accepts the meeting request, only the relevant Participation will be modified, and the rest will be left intact.
And, when rescheduling the meeting, a "Meeting Rescheduled" event will be published and an event handler will respond to it by resetting all of the Participations' statuses to "NotAccepted" regardless of their current version.
On the one hand this sounds logical in the sense that a meeting's version shouldn't be incremented just because someone accepted/denied its request.
On the other hand, modeling Participation as a standalone aggregate doesn't sound quite right to me, because it is has no meaning outside of the context of the meeting.
Anyway, would love to get feedback on this and see the various approaches to this problem.
Although this could be solved by re-reading the Meeting's document and retrying the Accept command, it's quite annoying considering how often this could happen.
This looks like a modeling error. You should keep in mind that the meeting aggregate is not the book of record for the participants availability - the real world is. So the message shouldn't be AcceptInvitation, but instead InvitationAccepted. There shouldn't be a conflict about this, because the domain model doesn't get to veto events outside of its authority boundary.
You might, depending on your implementation, end up with a concurrent modification exception in your plumbing, but that's something that you should be handling automatically (ie: expected version any, or a retry).
Another approach is to ignore the meeting's version when executing the Accept command, but this introduces a new problem: what happens if, after sending the meeting requests, the meeting has been rescheduled?
The solution here is to model more carefully. Yes, sometimes you will get a message that accepts or declines an invitation that has expired.
Put another way: race conditions don't exist.
A microsecond difference in timing shouldn’t make a difference to core business behaviors.
What happens to Alice, who replied instantly to the invitation, when the meeting is rescheduled? Why wouldn't the same thing happen to Bob, when his reply arrives just after the meeting is rescheduled?
Participation as a standalone aggregate doesn't sound quite right to me, because it is has no meaning outside of the context of the meeting.
I find that heuristic isn't particularly effective. It's much more important to understand whether entities can change state independently, or if their changes need to be coordinated.
Actually, the Meeting aggregate is used to track the participants availability. That's what it purpose is. Unless I didn't fully understand you...
It's a bit subtle, and I didn't spell it out very well.
Suppose the model says that I'm available, but an emergency in the real world calls me away. What happens? Am I blocked from going to the hospital because the model says I have to go to a meeting? Can somebody cancel my emergency by changing the invitation I've submitted?
Furthermore, if I'm away on an emergency, are you available for a meeting that is scheduled for the same time as the meeting you and I were going to have?
In this space, the real world is the authority for whether or not somebody is available. The model is just looking at a cached copy of a message describing whether or not somebody was available in the past.
The cached information being used by the model is not guaranteed to be complete. See Greg Young on warehouse systems and exception reports.
which makes me think that perhaps the Meeting aggregate should have two version fields: one will be a strong version which, when incremented, represents a breaking change, and another soft version for non-breaking changes. Does this make any sense?
Not really. Version is not, as far as I know, a term taken from the ubiquitous language of scheduling meetings. It's meta data, if it exists at all, and the business rules in your model should not depend upon meta data.
I agree, but a Meeting ID (or any ID for that matter) is also not part of the ubiquitous language, yet I might pass it back and forth between my domain world and external worlds.

How to resolve Order and Warehouse bounded contexts dependency?

I am working on DDD project and I am currently focused on two bouned contexts, Orders and Warehouse.
What confuses me is the following situation:
Order keep track of all the placed orders, and warehouse keeps track about all the available inventory. If user places one order for certain product item, that would mean one less item of that product in a warehouse. I am oversimplifying this process, so please bear with me.
Since two domain models are placed inside of a different BC, i am currently relying on eventual consistency ie. after one item has been sold, it would eventually be removed from the warehouse.
That situation unfortunately leads to the problem scenario where another user could simultaneously make another order of the same item, and it would appear as available until eventual consistency kicks is. That is something it is unacceptable by the domain expert.
So IMO I am stuck with two options
merge order and warehouse (at least the part regarding product
inventory, units available in warehouse) into one BC
have Order BC (or microservice if you wish) to be dependent of Warehouse BC (microservice) in order to pull a live product units
available
Which option does actually follows DDD patern? Is there another way out?
You could use a reservation system with a timeout.
Using a messaging analogy: With a broker-style queuing mechanism (such as RabbitMQ) you get a message from the queue and you have control over it until you either acknowledge that it can be removed from the queue or you release it back to the queue.
You could do the same thing in your ordering process. You reserve any items on your order. SO when you add them they have a status of, say, reserving and upon sending some message to reserve the items. If the response comes back you can decide how to proceed. Perhaps you could add any items that cannot be reserved onto a back order or try again later.
There are going to be different ways to approach this. Depending on your business case it may be acceptable to only check availability when someone really accepts the order.
If you domain expert reckons it is totally unacceptable that having this resolved at the end of the process then you could move it to the start. The issue is of course that user A could reserve and never buy thereby losing user B as a customer; whereas only applying the real "taking" of the item at the end of the process is closer to ensuring a purchase. But that is a business decision.
This issue is a really great example of where reality actually is eventually consistent. Is it really the best thing to decline an order if there is no inventory currently in the warehouse - even if there was a replenishment due in the next 20 minutes?
What if the item was actually on the shelf, but the operator hadn't yet keyed it into the system?
Sometimes designers and domain experts assume that people want 100% consistency, when really, users might be willing to accept a delay in confirmation of their order, if it increased the chance that their order would be accepted rather than rejected.
In the case above, why make it the user's job to retry their order N minutes later? In an eventually consistent system, you can accommodate such timing flexibility by including a timeout to retry the attempt to fulfill the order for a period of time before confirming to the client that it really wasn't possible.
There are technical solutions that will give you 100% consistency, but I think really this is not a technical challenge but a cultural/mindset one, changing people's minds about what is possible & acceptable to achieve an what is actually a better outcome.
IMO you can build a PlaceOrderSaga which will ask for inventory availability before placing the order.

Keeping consistency between aggregates

I am wondering how to solve transactional consistency problems between aggregates. My first impression is that whenever you need transactional consistency between aggregates, you wrongly designed your aggregates. However, I would still like to ask this question to make sure I am not missing anything.
Imagine you sell cow milk. You have multiple cows, each producing a certain amount of liters milk a day. You need to have a service that is able to get the amount of milk in stock. Besides that you should also be able to order milk. Based on this information you can create three aggregates, Cow, Stock and Order. Whenever a certain amount of milk is ordered, one of the business rules is to check if that amount is in stock and if not, let the user know right away. How can this be achieved when two users do a concurrent request and order a total amount of 150 liters milk, while only a 130 liters are available? My first idea is that you can achieve this by optimistic/pessimistic locking, but in that case one aggregate depends on the other. Is there a certain way to solve this particular issue, or is this just bad aggregate design?
My first impression is that whenever you need transactional consistency between aggregates, you wrongly designed your aggregates.
That's exactly right; the way that you discover aggregate boundaries is first by identifying values that need to by kept consistent, and then choose boundaries that have the property that any two values that need to be consistent with each other are within the same boundary.
Note: we don't always get this right; perhaps the requirements were wrong, perhaps our model wasn't adequate, perhaps the business changed. Part of the challenge is to make sure that it is always easy to replace the current model with a better one.
Based on this information you can create three aggregates, Cow, Stock and Order.
Note: Cow is a lousy aggregate -- assuming we are talking about real out in the world eating grass cows. It's an entity, yes, but it is outside the influence of the model. If the model says that the cow is empty, and the cow says that it is full of milk, the cow is right.
Similarly, if the cows are real, then most of your stock is real as well. If the model says there are seven full canisters of milk, and the farmer counts six, then six is the right answer.
Aggregates are information resources.
Whenever a certain amount of milk is ordered, one of the business rules is to check if that amount is in stock and if not, let the user know right away. How can this be achieved when two users do a concurrent request and order a total amount of 150 liters milk, while only a 130 liters are available?
An important thing to realize about "right away"; you are here, the user (buyer?) is there. There's a certain amount of latency in the communication, which means that the information you are sending to the buyer is already stale when it arrives. (Technically, it's already stale at the point when you send it.)
Second fulfilling the orders requires understanding both orders and available stock. So you might model this as a single aggregate that does everything, or you might model it as order aggregates that communicate asynchronously with some fulfillment aggregate; for instance, it might be that what Stock really does is match up notifications of available milk with pending orders.
In your concurrent processing example, this would look like two commands to reserve 130 liters of milk running concurrently against a stock aggregate with 150 liters of milk available. Using optimistic concurrency both commands would discover that there is enough milk to satify the order, and would try to update the book of record. That update, however, is serialized -- think transaction, or compare and swap -- so one of the commands succeeds, and the other gets a concurrent modification exception instead. This second command therefore tries again, reloading the stock in its new state. This time through, it discovers that the available stock is insufficient, and acts accordingly (moving the order into the waiting list, advising the buyer of the expected fulfillment date, etc).
Note that you would also get concurrent modification exceptions when a command to reserve milk is run in parallel to an announcement that more milk is available.
My first impression is that whenever you need transactional consistency between aggregates, you wrongly designed your aggregates.
I'll go the other direction here and say: not necessarily. You are always going to require consistency between aggregates at some point in time. The only question is when. You may find that you run into some politics in some situations. I have had to implement 100%, immediate consistency, between a whole bunch of aggregates simply because I was instructed to do so by those holding the purse strings. In the ideal world we'd be free to choose. But in my real world you can bet we're going to lose. Anyway, lyrics aside, it certainly is possible to get away from immediate consistency.
Altering more than one aggregate in a transaction isn't the end of the world but if you can avoid you certainly should. It does come with some slight overhead as can be expected.
In your example you can check the stock levels but, as noted, concurrent reads lead to misleading information. However, you could place an order and before you even kick off your process you could "reserve" the quantity using what will become your process manager's Id and your overall "correlation id". if you cannot reserve the stock you could abandon the order. However, you'd have to reserve multiple items for certain orders with more than one item.
There are quite a number of approaches to this (airline reservation can also be used as an example). You may want to take the order anyway and see what you can do. Order may have different turnaround times and more milk, or other items, may become available in the meantime. You could notify the client that their order could not be filled and has been cancelled or inform them to click a link to adjust the order or perhaps accept an alternative.
Just some thoughts :)

Identifying class diagram classes from a use case specification?

I'm currently trying to learn the construction of class diagrams for an upcoming exam, although I'm having difficulties knowing how to identify classes based on a use case specification (or any similar description of a system).
I understand people here can be reluctant to help with education based questions, I just wanted to clarify that I'm not asking for the work to be done for me, I just need to be pointed in the right direction.
I'm going over a past revision paper which contains a use case specification for the process of 'purchasing an ice cream' at a vending machine. The first question is to identify 9 typical classes from this specification.
I understand a class is like an object and usually identified by a noun, although my confusion is how I am able to extract 9 classes as I can only seem to find 6, that is if they're even correct:
Customer, Student, Staff, Touch Screen, Change Dispenser, and Member Card.
Here is the use case specification, apologies for the length:
Ben & Jerry’s company has just installed a new vending machine at a
University; it has a variety of ice creams available, in the format of
tubs or mini-tubs of different flavours. Products are subsidised for
students and staff but not for the rest of users; such that a customer
can insert a member card in a card reader and the subsidised prize for
the selected ice cream is displayed. You have designed a use case
model of the system, and identified a single use case (“purchase an
ice cream”) where the main actors are the customers.
ID: VM1
Name: Purchase a tub
Main Actors:
Subsidised customer (staff and students) 2 Non-subsidised customer
Pre-conditions:
Machine is on and works perfectly fine
There is stock of drinks and coins
There is sufficient stock of coins in the machine for providing change
There is sufficient stock of products
Main Flow:
Machine displays a welcome message
Student/staff inserts member card
System validates member card
Customer selects the tub by pressing the touch screen
Machine displays the subsidised price for the selected ice cream
REPEAT until sufficient coins entered: 6.1 Customer enters coin 6.2 Touch screen displays the amount entered so far
System dispenses the tub
IF too many coins are entered change is delivered
Price is added to the weekly total amount
Machine resets
Post Condition: Ice cream purchased
Alternative flow 1:
IF customer does not have sufficient coins 6.1 Customer presses the return button 6.2 System returns the entered coins
Alternative flow 2:
IF validation is unsuccessful 3.1 Message informing user 3.2 Non-subsidised price is show 3.3 Use case continues main flow 4
If anybody can help I'd really appreciate it. Thanks
You have mostly identified a number of actors, few classes itself. To start your design, ask yourself what the system under consideration (SUC) is. Obviously a vending machine. Now look at the UC how this SUC acts. There are a couple of hints:
control resources (temperature, ice cream, tubs, etc.),
control collection of money,
control dispension of ice cream.
For these you can create controller classes which look to the outside and act accordingly (read temp -> turn on cooling; count money -> start vending; etc.)
The vending process with customer interaction is probably even more complex (show offers, make selection, pricing, etc.)
As you already guessed, this is no tutorial point. However, those are the basic steps to start the design. You can go on and create sequence diagrams to verify collaboration between the single classes (lots of exceptions like: temp controller starting to yell when temp does go up too much).

Real inventory vs Finance inventory

I'm pretty new to Maximo and I have a question about how things should be handled. We have a project of integrating our ERP with Maximo using MIF interfaces. I'd like to know how you performed this in your company as I'm sure we're not the only one facing this challenges.
Let's go pretty simple about the Inventory. Receiving will be performed in our ERP and sent to Maximo. "Consumption" and inventory movements will be performed in Maximo and interfaced back to our ERP. so far so good, standard process.
However, there's a difference in the real inventory vs the inventory from a Financial perspective. As an example, we have let's say 3 cutters (same part number, different serial number). We have 2 in the internal storage and 1 in the machine where its being used. Once it is in the machine, it's known as "consumed" by finance. So from a finance point of view, there's only 2 in stock. From the tooling guy however, there's 3! The one in the machine can be taken out and replaced by one of the two others.
How are things like that handled in maximo? Any help, advices would be appreciated.
Regards
M.
It depends on how you plan to track on the individual level (track cutters by individual asset tags or serial numbers) or on the group level (3 cutters with the same item number)
If the cutter is treated as inventory and not as an asset, once it is issued then it is considered used. You can opt to use "Condition Code" and give each item a value from 0 to 100. Think of this value as depreciation. If a cutter is swapped out, then the new cutter (100%) is issued, and the replaced cutter is disposed of or returned to the shelf with a diminished value (e.g. 25%).

Resources