So for the first of the CodeKata exercises I am going to attempt. I am going to start at the beginning. I will start with Kata 01, Supermarket Pricing. This is a no code sort of kata. This one focuses on how to build an object to handle supermarket pricing. Because of the nature of this kata, there will be no code. I have put a 20 minute time limit on myself for figure out how I would consider tackling such a problem.
So what’s the solution to Kata 01, Supermarket Pricing?
Hold your horse bucko. There are no solutions. Remember from the previous post? We need to handle this in steps so we don’t get bogged down in the details. First thing to do is to frame the problems. These are the known problems.
Pain points to solve
- There must a good to sell
- There must be a fixed price on good
- X for a certain price condition
- $/unit Sold
- $/unit sub units Sold
- buy x, get x must manageable and flexible
- Sort out fractional money
- sort out rounding
- do we need audit trail
- having an audit trail
- cost and prices are they the same class
- valuation of the stock
Audience that will use it
- Stock Manager
- Check Out
- Order Entry
- etc
Let’s Start Kata 01, Supermarket Pricing
Now there are several ways to do this but I am trying to create an optimal solution. We know who needs to find the software useful for there to be a success. We also see some of the explicitly pointed out issues. I do have an issue with the way the exercise is setup. Without having a subject matter expert to guide some of those decisions and design choices this as it stands would probably fail. You as the developer are generally unqualified to make decisions like what is being asked. The costing, auditing, valuation and heck even the treatment of fractional money is way out of your wheel house. With that being said and what I know about business let’s look at each issue in Kata 01, Supermarket Pricing exercise.
There must a good to sell
This is simple. We can fix this by making a good or product object. There are characteristics of the product, like name, weight, dimensions and SKU that go into the object.
There must be a fixed price on good
So we need a price. We could stick that in the product object. We could also make an argument that sticking in the product object would be bad. Take for instance the can of beans in the example at .65 cents. Change that to .75 cents. Is that a different product? It is not. It is a different sales cycle. So taking this into account let’s create the product sale object that will handle a specific sales cycle of the product.
X for a Certain Price Condition
After all this we have two objects. A two for one sales does not change the nature of the product. Let’s look at how to apply the discount. We can’t just dump this thing into the Product Sale and call it good. That would take life miserable for the staff if a one day Memorial Day sales required readjusting the pricing on the May sales cycle. Since that is the case, let’s create a Discount object. This one will require a touch of cleverness to work. The construction of the object will depend on conditions not being present to govern its behavior. Take a look.
Explanation of My Madness
The start and end dates will control the time aspect of the discount. Without them, things just continue in perpetuity. This could be useful in a cost plus model of business. You want to make the price the cost plus something and keep it there forever.
The min and max quantity when absent means that there is no cap before something kicks in or when something falls out of discount. T
he discount amount will let you knock $5 off of a specific product and the percentage will allow someone to knock 5% off the product. Having it in two separate columns should make it easier for the GUI builder and the user as there is no calculations going on trying to determine 5% of something.
Finally leaving the product off means it is store wide. Add the product and BAM it and only it are clean.
As a result of trying to encapsulate the discounting complexity, this will be a tough object to build. Because of this, we use of the rule of if null then not applicable.
$/unit Sold
With this constraint, we need to add units to our product. There is a couple of different ways this could be handled. For example, bananas can be sold by the finger, the hand, pound or unit. I have seen it all those ways over the course of my life. So I think it belongs in the product sale object and we will need a type that contains the various units.
$/unit sub units Sold
This one is already solved by the price per unit. Each sales product can be sold as needed. Switch to finger or by the bundled unit of bananas. Each is handled for the specific product.
buy x, get x must manageable and flexible
I think we have this one humped. Let’s take a buy 2 get 1 free. Hold on, I don’t want to lose anyone. You set the min and max quantity to 3 and make the discount percentage .333. If they buy 2 then the discount does not kick in. If they buy 4 then only the 3 have the discount applied the remainder, 1 is a normal price. I could see a problem with how many time a discount can repeat.
For instance what about 6 cans. Under this model it would not work. As a result, I am going to ad to discount a repeating number. If left blank than it assumes repeatability. So in this instance 6 would become 3 units of product sale then the rule would apply until the entire items in cart are processed. Put in a 0 then it will only do it for the first set since it cannot repeat.
Sort out fractional money
This one is simple. I am not going to impede the money calculation by doing anything to them. I will let the software from accounting, or inventory or checking to sort it out as they need it sorted. Inventory is not going to be concerned about the mills for a product but accounting and checking may. It is better to leave that decision to them.
Sort out rounding
As with the above criteria, I think it is important to leave that to the implementing system. At this level of system, we can only do harm by adjusting any of the number.
Do we need audit trail
Honestly, that this level of the system, I don’t think so. W don’t yet have the purchasing and only part of the sales objects. Because of what they do and the requirements of know inventory and sales things. This system should have the components in place to have a audit trail but I think that implementing it here formally is the wrong level. Accounting will have a very different audit trail than inventory. Each have different rules they must follow. Better to leave that detail to their system’s implementation of these objects. Speaking of that fact, lets fill out the system a bit.
Cost and prices are they the same class
This one is simple. No they are not in the same class. The cost is the price to acquire something. It is not connected to the cost of selling something. You are always free to lose money. They should not be in the same class because they are not related. You could have multiple inventory shipments each with a different cost on the shelves. They all carry the same price but cost differently.
Valuation of the stock
This is straight-up an accounting question. We are not in that game period. The accounts can figure out that question. We only want to provide the data. Our system does this. The system the accountant setup using these objects will answer this question.
Wrapping it up Kata 01, Supermarket Pricing
In this system we have thought about how his effects the accounts, checkers and inventory people. I feel like I asked questions, does this work for their goals or does implementing it damage that objective? If it was damage then no push that closer to user on the implementation. These objects are general purpose.
I don’t feel bad about my results. This was a 20 minute exercise. For this reason, I have no doubt there are flaws in my logic and implementation. Despite this fact, I successfully broke a product away from its sale or acquisition process. Because discount is not acquisition specific but is product based, it can still attach to discount. Product Sale is attach to the Product Inventory because you can’t do grocery store retail with product and they product was purchased. I could see some issue tying a specific item to a specific sale. All in all, I am happy with this exercise.