Documentation
¶
Overview ¶
Package removebookcopy implements the "Remove Book Copy from Circulation" use case following Vertical Feature Slice architecture.
This package demonstrates proper separation of core domain logic from shell infrastructure concerns within a single cohesive feature slice:
Core (decide.go): Pure Decide() function with no side effects Shell (command_handler.go, command.go): Infrastructure orchestration and DTOs
This feature uses shared domain events from shared/core and infrastructure utilities from shared/shell for event conversion and storage operations.
The CommandHandler encapsulates the complete Query() -> Decide() -> Append() cycle, while the pure Decide() function contains only business rules and is easily testable.
Note: In a real application, the BuildCommand() function should validate input parameters if necessary. Important domain concepts like BookID might be better encapsulated in value objects rather than primitive types for stronger type safety, immutability, and domain modeling.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrExpectedExactlyOneEventGotMultiple = errors.New("got more than one event to append, expected exactly one")
Functions ¶
func Decide ¶
func Decide(domainEvents core.DomainEvents, command Command) (core.DomainEvent, core.ProducedNewEventToAppendBool)
Decide implements the business logic to determine whether a book copy should be removed from circulation. This is a pure function with no side effects - it takes the current domain events and a command and returns the events that should be appended based on the business rules.
Business rule: A book copy can only be removed if it currently exists in circulation. The existence is determined by analyzing the event history - the last relevant event determines the current state.
In a real application there should be a unit test for this business logic, unless coarse-grained feature tests are preferred. Complex business logic typically benefits from dedicated pure unit tests.
Types ¶
type Command ¶
type Command struct { BookID uuid.UUID OccurredAt core.OccurredAtTS }
Command represents the intent to remove a book copy from circulation. It encapsulates all the necessary information required to execute the remove book copy use case.
type CommandHandler ¶
type CommandHandler struct {
// contains filtered or unexported fields
}
CommandHandler orchestrates the complete command processing workflow. It handles infrastructure concerns like event store interactions, timing collection, and delegates business logic decisions to the pure core functions.
func NewCommandHandler ¶
func NewCommandHandler(eventStore EventStore) CommandHandler
NewCommandHandler creates a new CommandHandler with the provided EventStore dependency.
func (CommandHandler) Handle ¶
func (h CommandHandler) Handle(ctx context.Context, command Command, timingCollector TimingCollector) error
Handle executes the complete command processing workflow: Query -> Decide -> Append. It queries the current event history, delegates business logic to the core Decide function, and appends any resulting events while collecting detailed timing measurements.
type EventStore ¶
type EventStore interface { Query(ctx context.Context, filter eventstore.Filter) ( eventstore.StorableEvents, eventstore.MaxSequenceNumberUint, error, ) Append( ctx context.Context, filter eventstore.Filter, expectedMaxSequenceNumber eventstore.MaxSequenceNumberUint, event eventstore.StorableEvent, events ...eventstore.StorableEvent, ) error }
EventStore defines the interface needed by the CommandHandler for event store operations