
Library or Binary Splitting a Rust Crate for Testability
Put logic in a library crate and keep main.rs thin, so tests can call functions, integration tests see the public API and other binaries can reuse the code.
How to carve a growing Rust codebase into crates and modules that a team can still reason about.

Put logic in a library crate and keep main.rs thin, so tests can call functions, integration tests see the public API and other binaries can reuse the code.

A workspace groups crates under one Cargo.lock and target directory. See when to split, the root manifest, virtual versus root package workspaces, running commands per member and what to avoid.

Depend on a trait that you own, not on a concrete client. Learn generics versus Arc dyn for wiring, when a trait is not worth it and how to keep it small.

Each layer of an application should speak its own error type. Convert at the boundary with From, keep causes for logs and map to HTTP codes only at the edge.

Clean architecture's dependency rule fits Rust: inner layers define traits and outer layers implement them. Here is how many layers you need, with a layout and a verdict.

Use types to encode domain rules: value objects with validating constructors, enums for states, aggregates that guard invariants and domain errors. Skip the parts that need a framework.

Put the business rules in the middle, describe what they need as traits (ports) and plug in databases and HTTP as adapters. A complete small example with a test double.

How to structure a Rust codebase as it grows: modules, a lib and bin split, workspaces, layers and the boundaries that keep compile times and coupling in check.
We send one email when a new post is published. No spam.