CONTEXT.md: domain model with entities (WidgetConfig, DataSource, LayoutPreset), value objects (Layout, LayoutNode, KeyMapping, WidgetState, Sizing), architecture decisions (CQRS, static dispatch, postcard), client domain model, and design constraints.
1.1 KiB
1.1 KiB
0002 — Static dispatch over trait objects
Status: accepted Date: 2026-06-18
Context
Hexagonal architecture uses port traits extensively. Rust offers two ways to consume them: trait objects (Box<dyn Port>, dynamic dispatch) or generics (T: Port, static dispatch / monomorphization).
Decision
Use generics for all port traits. No Box<dyn> anywhere. Composition roots (bootstrap on server, firmware crate on client) are the only places that know concrete types. Generic parameters propagate through application and presentation layers.
Alternatives considered
Trait objects — simpler type signatures, less generic noise. But adds vtable indirection, heap allocation per trait object, and prevents compiler optimizations. On ESP32 with limited RAM, every allocation matters.
Consequences
- Zero-cost abstractions — port calls are monomorphized, inlined where possible.
- More verbose type signatures — structs and functions carry generic parameters.
- Compile times may increase due to monomorphization.
- Consistent approach across server and client codebases.