Docs / ArchitectureKit / Fundamentals / Making Decisions
Making Decisions
A decider connects a state with the decision made on it. Create a Decider, hand over the state, and provide a Decide function that receives the command and the current state, and returns the events to write:
var acquireBook = architecturekit.Decider[AcquireBook, Book]{
State: bookState,
Decide: func(ctx context.Context, cmd AcquireBook, book Book) ([]architecturekit.Event, error) {
if book.IsAcquired {
return nil, architecturekit.NewDomainError("book %s has already been acquired", cmd.BookID)
}
return []architecturekit.Event{
BookAcquired{
Title: cmd.Title,
Author: cmd.Author,
ISBN: cmd.ISBN,
},
}, nil
},
}
To reject a command, return an error created with the NewDomainError function. It takes a format string and arguments, like fmt.Errorf, and returns a *DomainError, whose message is exactly the formatted text, and which belongs to the category ErrDomain (see Handling Errors).
A decider may check several rules:
var borrowBook = architecturekit.Decider[BorrowBook, Book]{
State: bookState,
Decide: func(ctx context.Context, cmd BorrowBook, book Book) ([]architecturekit.Event, error) {
if !book.IsAcquired {
return nil, architecturekit.NewDomainError("book %s does not exist", cmd.BookID)
}
if book.IsBorrowed {
return nil, architecturekit.NewDomainError("book %s is already borrowed", cmd.BookID)
}
return []architecturekit.Event{
BookBorrowed{
BorrowedBy: cmd.ReaderID,
BorrowedUntil: cmd.BorrowedUntil,
},
}, nil
},
}
If there is nothing to do, return neither events nor an error:
var returnBook = architecturekit.Decider[ReturnBook, Book]{
State: bookState,
Decide: func(ctx context.Context, cmd ReturnBook, book Book) ([]architecturekit.Event, error) {
if !book.IsBorrowed {
return nil, nil
}
return []architecturekit.Event{
BookReturned{},
}, nil
},
}