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

Pattern 6: Generic Base Layer

Context

You want a reusable testing foundation that can support multiple domains without pulling in their dependencies.

Problem

If the base includes domain code, every consumer drags in unused dependencies, slowing builds and introducing coupling. Conversely, a minimal base risks missing essential primitives.

Solution

Keep the core crate focused on generic capabilities – fixtures, builders, assertions, macros, state tracking. Expose them through capability modules (core, testing, validation, observability, integration). Ensure modules depend only on the standard library and optional features. Domain-specific abstractions live in downstream crates that compose the base.

Forces

  • Reuse vs. specialization: core must be broadly useful without dictating domain models
  • Build time vs. flexibility: optional features load only when needed
  • Stability vs. growth: base APIs should be stable; extensions add behavior

Examples

#![allow(unused)]
fn main() {
// src/lib.rs
pub mod core;
pub mod testing;
pub mod validation;
pub mod observability;
pub mod integration;

pub use core::{fixture, builders, assertions};
}
  • Pattern 7: Extension Layer
  • Pattern 8: Composition Over Duplication
  • Pattern 10: Capability Grouping