Modeling exerciseThe grocery store’s checkout model
I went to the super market yesterday, and I forgot to get out of work mode, so here is this posts. The grocery store checkout model exercise deals with the following scenario. You have a customer that is scanning products in a self checkout lane, and you need to process the order.
In terms of external environment, you have:
- ProductScanned ( ProductId: string ) event
- Complete Order command
- Products ( Product Id –> Name, Price ) dataset
So far, this is easy, however, you also need to take into account:
- Sales (1+1, 2+1, 5% off for store brands, 10% off for store brands for loyalty card holders).
- Purchase of items by weight (apples, bananas, etc).
- Per customer discount for 5 items.
- Rules such as alcohol can only be purchased after store clerk authorization.
- Purchase limits (can only purchase up to 6 items of the same type, except for specific common products)
The nice thing about such an exercise is that it forces you to see how many things you have to juggle for such a seemingly simple scenario.
A result of this would be to see how you would handle relatively complex rules. Given the number of rules we already have, it should be obvious that there are going to be more, and that they are going to be changing on a fairly frequent basis. A better model would be to actually do this over time. So you start with just getting the first part, then you start streaming the other requirements, but what you actually see is the changes in the code over time. So each new requirement causes you to make modifications and accommodate the new behavior.
The end result might be a Git repository that allows you to see the full approach that was used and how it changed over time. Ideally, you should see a lot of churn in the beginning, but then you’ll have a lot less work to do as your architecture settles down.
More posts in "Modeling exercise" series:
- (28 Oct 2014) The grocery store’s checkout model process approach
- (21 Oct 2014) The grocery store’s checkout model
- (06 Jun 2014) Flights & Travelers
Comments
What about Drools, it allows you to specify your inputs (products and modifications) in an XML structure and gives you the result of your rules set.
There's less need of any code change in this scenario.
It would be nice to have something alike in .NET, maybe an extension on RavenDB ;)
This is my industry, let's add more complexity. Imagine the above rules, for one single platform, but for multiple clients with multiple different processes and re-imaginings of the above! There are also usually tons of integrations that have to happen "as live as possible" especially for returns counters, reward card systems etc.
It's fun and annoying all at the same time! It's also one of the most reactive industries I've worked in, always trying to compete and one-up each other.
Don't forget in your external events that you need a database (at least in the US) for bulk items and produce which cannot be readily scanned. There has to be a code assigned to the item which then corresponds to the price and if by weight, makes the appropriate calculations.
I used to work in the grocery industry in college and thereafter for a bit and I still remember most of my produce codes from nearly 30 years ago. That scares me at times!
That really smells like a domain for functional programming.
Applying an arbitrary function to a sequence.
Any new requirement is a new function. Compound requirements are a composition of multiple functions.
I really would like to hear Rich Hickey saying how bad this is in Object Orientation.
I have years of retail architecture experience and have worked on high traffic and highly volatile pricing/promotion systems.
The key I found was similar to what Bjorn mentions... create a data structure and run it across a set of conditions with their respective adjustments and output the same data structure with the modified data.
I've even created DSLs for allowing marketers and merchandisers to express the rules as condition statements and adjustment statements.
@Bjorn, search for article by ayende on JCFHI. Any tool that depends on xml config to do its job is suspect. It's the reason why people don't like Spring anymore. It's the reason why fluent nhibernate is so popular. We should not be a fraid of code change. It is the best way we have to change the rules in a safe manner (we get compile checking, auotmated testing, etc.)
That should have been JFHCI*.
Hi Ayende,
I've actually pondered this, especially from a previous video you had, where a me!ber of you team spoke about their implementation in a supermarket.
The problem doesn't seem to be the rule, but more the exceptions.
So generally we have a time frame and a new price to apply. Some scenarios for a single item are:
Wait a minute ... Thats quite a clear, concise list...
I could be a Business Analyst!
..... Nooooooooooooo !! :-(
@Gilligan, I fully agree that a fully automated and tested software release cycle can help in capturing many mistakes in advance and also really like the fluent notation. But ... I also think that when an engine relies on XML as a data dictionary for its inner workings it should be OK. In the case of the rules engine the input is validated through business cases implemented in code and XSD to validate its structure and values. But I'll start by reading the article, it sounds interesting.
@Bjorn, Oh, ok. If they provide an interface into extending it and modifying it in a safe manner, then that makes sense.
This is a good case for using rules engine. I have developed a cloud based rules engine running on Azure that allows you to write rules in JavaScript, C#, or VB. Python and Ruby and coming down the road. Check out https://ruleplex.com/
What about taxes? In US it may be very complex. Government programs like SNAP and eWIC? Tender eligibility? It is much more complicated. And making promotions engine that finds a "best for customer" combination with good performance is some sort of rocket since :)
Stan, I didn't even consider taxes (we have a flat VAT here, so that makes things easier).
Sales taxes get insane in the U.S. because, in addition to varying rates at the municipality level, rates also vary by category of item, plus there are "sales tax holidays" that municipalities/states conjure up all the time to buy votes, errr, help people.
Software has to be extraordinarily nimble to handle all this change/difference, especially if you are a national chain.
Don't forget the tax implications of shipping across states!
I think that it's a very complex problem to solve and I am looking forward for Ayende to solve it :)
Though I haven't any direct experience solving this particular problem but I have worked with payroll systems and I think there are many similarities in both domains. Like others have mentioned I also think that in general we should consider a good (simple) abstract design that will allow us implement different set of rules (discounts, tax, exceptions and etc.)
Idunno, maybe I'm stupid, but it seems simple to me - just pass on the difficulty of modeling the checkout model to the ppl emitting the crazy business requirements/give them a tool to directly model most of their requirements.
More exactly: a generic structure containing the checkout structure - really, just the lines and fields that have to appear on the receipt, plus an extensible rules system, in which business ppl can directly model most of their requirements. Implement rules system in terms of the business ppl's vocabulary, extend as the need arises, and you'll avoid crazy situations where business ppl want something but don't know what it is and how to explain it - if they can't tell it in their own language, there's little chance that they'll expect you to implement it.
Avoiding an implementation which directly solves the problem and provides a tool to solve the problem instead is not about CYA, it's about making the system transparent. If the rules system behaves exactly how the business ppl have told you but not how they expect it to, it's very difficult for you to explain the problem to them, or to diagnose the problem in their stead - chances are high that up from a certain level of complexity you simply won't be able to comprehend the system as a whole anymore, but the business ppl will. (That's because you and they look at the system from different angles - you can't ignore the implementation no matter how hard you try, business ppl can't be bothered to look at it at all, because they don't understand it and it makes no sense to them.) By giving business ppl a system they can comprehend because it uses the same language that they use, you have removed yourself from the position of man in the middle, making the system more comprehensible for its users and removing one source of bias.
The rule system's vocabulary might grow quite big and complex over time. But that's OK, as long as it stays in sync with the business ppl's vocabulary - even if it grows, they'll still understand it, because they speak the same way to each other, and think the same way.
I'm looking forward to Rhino PointOfSale!
Comment preview