- How to make go enforce your invariants
- See abstraction doc
- For comparison, see the rust version of this doc
-
Goal: Make illegal states in the domain model unrepresentable (compiler enforced)
-
Languages with strong modeling tools represent invariants with types
- Compiler is responsible for enforcing invariants
-
Languages with weak modeling tools represent invariants with methods/logic
- Runtime is responsible for enforcing invariants
-
Go has relatively weak modeling tools
- (but still stronger than c, javascript, python, all dynamic languages, ...)
- Compare to rust
- Compare to kotlin
- Use nilable type
sql
package also provides nilable types
var favoriteBook *Book = nil
At-most-one (aka "Maybe")
- Use nilable type
type Employee struct {
FavoriteBook *Book // at most one
}
- Use a slice
type Employee struct {
PreviousEmployers []Employer // zero or more
}
- TODO
TODO
Exactly-one of bounded set (Sum Algebraic data type)
- TODO
TODO
- TODO
TODO
var age uint8 = 30 // compiler enforced non-negative
Group of related fields (Product Algebraic data type)
- Use a
struct
- TODO
TODO
- Use a field on a
struct
TODO
- Implement an interface
- REMINDER: almost any type can implement an interface (numbers, strings, structs, ...)
- Use Upper/lower case
- Separate code into different packages
- See abstraction doc
- TODO
- TODO
- TODO: embedding
- TODO: pattern matching
- TODO: preconditions (logic)