Ehren Murdick
@rubyprogrammer
github.com/ehrenmurdick
Pyramid of errors
doc1 := entities.NewDocument("document 1")
_, err := printDocument(doc1)
if err != nil {
printError(err)
} else {
_, err = saveDocument(doc1)
if err != nil {
printError(err)
}
}
Container!
type OptionalDocument interface {
Try(func(Document) (Document, error)) OptionalDocument
HandleErr(func(error) error) OptionalDocument
}
func printDocument(d Document) (Document, error)
Using OptionalDocument
doc2 := entities.NewDocument("document 2")
opt2 := optionals.WrapDocument(doc2)
opt2.
Try(printDocument).
Try(saveDocument).
HandleErr(printError)
Contain Anything
type OptionalAny interface {
Try(f func(interface{}) (interface{}, error)) OptionalAny
HandleErr(f func(error) error) OptionalAny
}
func printAny(i interface{}) (interface{}, error)
Using OptionalAny
doc3 := entities.NewDocument("document 3")
opt3 := optionals.WrapAny(doc3, nil)
opt3.
Try(printAny).
Try(saveAny).
HandleErr(printError)
An example in Swift
struct Stack<Item> {
var items = [Item]()
func pop() -> Item
}
…is basically just generating…
struct StackInteger {
var items = [Integer]()
func pop() -> Integer
}
struct StackString {
var items = [String]()
func pop() -> String
}
We can generate too! (at build time)
//go:generate ./optional Document
type Optional<%= Item %> interface {
Try(func(<%= Item %>) (<%= Item %>, error)) Optional<%= Item %>
HandleErr(func(error) error) Optional<%= Item %>
}
Using Optional<%= Item %>
doc3 := entities.NewDocument("document 2")
opt3 := optionals.WrapDocument(doc2)
opt3.
Try(printDocument).
Try(saveDocument).
HandleErr(printError)