Data Modeling Patterns
State Transitions
A transition function makes the rules for moving between model states easy to test.
transition function
Keep state changes in one helper so each branch explains when the model can advance.
State Transitions
state_transitions.go
Replay: real traced execution (multi-file project)
package main
import "fmt"
const (
OrderNew = iota
OrderPaid
OrderShipped
)
func nextState(current int, paid bool) int {
if current == OrderNew && paid {
return OrderPaid
}
if current == OrderPaid {
return OrderShipped
}
return current
}
func main() {
var paid = true
current := OrderNew
next := nextState(current, paid)
done := next == OrderShipped
fmt.Println("paid=", paid)
fmt.Println("current=", current)
fmt.Println("next=", next)
fmt.Println("done=", done)
}
package main
import "fmt"
const (
OrderNew = iota
OrderPaid
OrderShipped
)
func nextState(current int, paid bool) int {
if current == OrderNew && paid {
return OrderPaid
}
if current == OrderPaid {
return OrderShipped
}
return current
}
func main() {
var paid = false
current := OrderNew
next := nextState(current, paid)
done := next == OrderShipped
fmt.Println("paid=", paid)
fmt.Println("current=", current)
fmt.Println("next=", next)
fmt.Println("done=", done)
}
paid ← true, current ← 0
21func main() {22 var paid→ true = true //@paid=false23 current→ 0 := OrderNew024 next := nextState(current0, paidtrue)25 done := next == OrderShippedfunc nextState(current int, paid bool) int
11func nextState(current0 int, paidtrue bool) int {12 if current == OrderNew && paid {if current == OrderNew && paid
11func nextState(current int, paid bool) int {12 if current0 == OrderNew0 && paidtrue {13 return OrderPaid114 }next ← 1, done ← false
23 current := OrderNew24 next→ 1 := nextState(current0, paidtrue)25 done→ false := next1 == OrderShipped22627 fmt.Println("paid=", paidtrue)28 fmt.Println("current=", current0)29 fmt.Println("next=", next1)30 fmt.Println("done=", donefalse)31}outputpaid= true current= 0 next= 1 done= false
paid ← false, current ← 0
21func main() {22 var paid→ false = false23 current→ 0 := OrderNew024 next := nextState(current0, paidfalse)25 done := next == OrderShippedfunc nextState(current int, paid bool) int
11func nextState(current0 int, paidfalse bool) int {12 if current == OrderNew && paid {13 return OrderPaid14 }15 if current == OrderPaid {16 return OrderShipped17 }18 return current019}next ← 0, done ← false
23 current := OrderNew24 next→ 0 := nextState(current0, paidfalse)25 done→ false := next0 == OrderShipped22627 fmt.Println("paid=", paidfalse)28 fmt.Println("current=", current0)29 fmt.Println("next=", next0)30 fmt.Println("done=", donefalse)31}outputpaid= false current= 0 next= 0 done= false