rust-abstraction
Decide whether a long Rust file has seams worth extracting, and if there are, how to extract each.
Check the cheap fixes first
Before looking for abstractions, see if a mechanical fix handles it.
- Tests inline? Measure prod vs. test lines. If tests are >20% of the file and live in
#[cfg(test)] mod ...blocks, lift them tofoo/tests.rsper the project convention. That alone often resolves "this file is too long." - Hand-written
Clone/Debugthat couldderive? Replace and stop. - Dead code from a half-done refactor? Delete and stop.
Seam smells
Look for these if there are no cheap fixes. One strong signal is enough; three weak ones is not.
- Inline
struct/enumin a function body. The author already factored the concept but didn't lift the boundary. Promote it. - Repeated loop or match shape with varying bodies. N near-identical
for/matchwalks differing only in body or predicate → consolidate. - Read-only narrow access to a wide type. A method that touches one or two fields of a large struct and never the rest. That slice is the boundary.
- Load-bearing invariant living as a docstring. A rule that must be preserved (cache-safety, ordering, "don't recurse here") is one rename away from being lost — promote it to a type name.
When picking a shape
Your goal is to make the code easier to read and safer to edit. Try to encapsulate data and invariants.
- No empty wrappers. If
Foo::new(thing).do_x()just renamesThing::do_x(thing), reject it. The test: can you state in one sentence what the new type guarantees? If not, it's a wrapper.
Workflow
- Read the file end to end (not skim).
- Run it by the cheap-fixes list, then the seam smells list. Give honest judgment - weak signals are not seams.
- If you find one or more seams, report the name of the proposed abstraction and (briefly) how it improves the code.
- f you don't find a seam: report "no seams found" and move on.
Source: jackhall/koan — distributed by TomeVault.