Koazee — The shopping cart
In this guide we will learn how to make use of Koazee to implement a very usual scenario: A shopping cart
The shopping cart
The input will be a list of items. For each item will find the next info:
- Name
- Units
- Price per unit
- Expiration date
type Item struct {
Name string
Units int
PricePerUnit float32
ExpirationDate time.Time
}
and the software requisites are:
- Print the list of items ordered by name. For each item we will print the following information: name, units and the total price
- Items on expired date must be removed from cart
- If there’s 3 or more units of the same product in the cart, a 20% discount must be saved for this product.
- We need to print the total price.
After having a look at the requirements we can easily understand that we need to do is:
- Filter: We only need to leave in the cart those items whose expiration date has not expired yet.
- Sort: We need to print the items ordered by name
- Map: For any item we need to add a new attribute, the total price of the items
- ForEach: For each item in the cart we need to print the required info
- Reduce: We need to calculate the total price for our shopping cart.
It looks like Functional programming!!!
Since Koazee does a Lazy evaluation of the operations we can define a variable shoppingStream and then we will be able to reuse it for any shopping cart.
var shoppingStream = koazee.Stream().
Filter(func(item *cart.Item) bool {
return item.ExpirationDate.After(time.Now())
}).
Sort(func(itemLeft, itemRight *cart.Item) int {
return strings.Compare(itemLeft.Name, itemRight.Name)
}).
Map(func(item *cart.Item) *ItemTotal {
total := float32(item.Units) * item.PricePerUnit
if item.Units >= 3 {
total *= discount
}
return &ItemTotal{item, total}
}).
ForEach(func(item *ItemTotal) {
fmt.Printf(" - %s, %d units, %.2f€\n", item.Name, item.Units, item.total)
})
We define a new struct to add the total price for item
type ItemTotal struct {
*cart.Item
total float32
}
Finally, we only need to define a function that will make use of variable shoppingStream and will calculate the price for the cart.
func process(items []*cart.Item) {
myStream := shoppingStream.With(items).Do()
output := myStream.Reduce(
func(acc float32, item *ItemTotal) float32 {
return acc + item.total
})
if output.Err() != nil {
log.Fatal(output.Err().Error())
}
fmt.Printf(" Total price %.2f€\n", output.Float32())
}
Goals:
- We write clean code.
- Functional oriented code is easier to test.
- Lazy evaluation, we don’t need to perform any operation until It’s required.
- No Loops, no switch-cases and no if-else statements
- Koazee provides several operations, and much more are coming. Have a look at Koazee Wiki
Code
Full code can be found on Koazee repository To run the full test:
git clone https://github.com/wesovilabs/koazee.git
cd koazee/samples/shopping
go run main.go
You will find a couple of array of items that can be used to test our example easily.