Business logic should be in deterministic functions
Lets unpack this... the idea of deterministic functions is borrowed from pure functional programming, so business logic must be separated from state and mutable logic such as retrieving data. This will make business logic easier to read and test.
Consider this function
func CustomerDiscount(id string) float64 {
c := LoadCustomerFromId(id)
// vip discount
if c.name == "Kavi" {
return 0.1
}
// pensioner discount
if c.age > 60 {
return 0.2
}
return 0.0
}
This is not deterministic and testable as LoadCustomerFromId makes CustomerDiscount stateful and unpredictable.
This is better:
// load the customer in the main control loop which calls the
// business logic function with the customer as a parameter
func CustomerDiscount(c *Customer) float64 {
// vip discount
if c.name == "Kavi" {
return 0.1
}
// pensioner discount
if c.age > 60 {
return 0.2
}
return 0.0
}
so you can deterministically test this business logic with tests like this:
func TestVipDiscount(t *testing.T) {
c := Customer{
id: "1",
name: "Kavi",
age: 30,
product: "Laptop",
}
d := CustomerDiscount(&c)
if !almostEqual(d, 0.1) {
t.Errorf("Kavi's VIP discount is not 10%%, got %.2f", d*100)
}
}