Keyboard shortcuts

Press ← or β†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Traits as Extension Points

A trait in a skeleton is a hole that someone else will fill: the agent now, or another team later. It needs the same care as the types around it.

/// A sink for decoded signal values. Implementations must be cheap to
/// call. Batching and I/O belong behind the trait, not in front of it.
pub trait SignalSink {
    /// Called once per decoded frame, in arrival order.
    fn accept(&mut self, signals: &DecodedSignals) -> Result<(), SinkError>;
}

Properties of a well-designed extension point:

  • It has as few methods as possible. Each method is a burden on every implementor, and an agent will happily generate many methods if the trait invites it.
  • Its doc comments state the contract: ordering, threading, and performance expectations. Implementors, including agents, rely on them.
  • It’s sealed unless external implementations are intended. The sealed trait pattern lets outside code name the trait but not implement it, which keeps your options open.

A useful review question for any trait: does it need to exist? A trait with one implementation and no test double can often be replaced by the concrete type, or by a function.