Learn-skills.dev m15-anti-pattern

Use when reviewing code for anti-patterns. Keywords: anti-pattern, common mistake, pitfall, code smell, bad practice, code review, is this an anti-pattern, better way to do this, common mistake to avoid, why is this bad, idiomatic way, beginner mistake, fighting borrow checker, clone everywhere, unwrap in production, should I refactor, 反模式, 常见错误, 代码异味, 最佳实践, 地道写法

install
source · Clone the upstream repo
git clone https://github.com/NeverSight/learn-skills.dev
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/NeverSight/learn-skills.dev "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/skills-md/actionbook/rust-skills/m15-anti-pattern" ~/.claude/skills/neversight-learn-skills-dev-m15-anti-pattern && rm -rf "$T"
manifest: data/skills-md/actionbook/rust-skills/m15-anti-pattern/SKILL.md
source content

Anti-Patterns

Layer 2: Design Choices

Core Question

Is this pattern hiding a design problem?

When reviewing code:

  • Is this solving the symptom or the cause?
  • Is there a more idiomatic approach?
  • Does this fight or flow with Rust?

Anti-Pattern → Better Pattern

Anti-PatternWhy BadBetter
.clone()
everywhere
Hides ownership issuesProper references or ownership
.unwrap()
in production
Runtime panics
?
,
expect
, or handling
Rc
when single owner
Unnecessary overheadSimple ownership
unsafe
for convenience
UB riskFind safe pattern
OOP via
Deref
Misleading APIComposition, traits
Giant match armsUnmaintainableExtract to methods
String
everywhere
Allocation waste
&str
,
Cow<str>
Ignoring
#[must_use]
Lost errorsHandle or
let _ =

Thinking Prompt

When seeing suspicious code:

  1. Is this symptom or cause?

    • Clone to avoid borrow? → Ownership design issue
    • Unwrap "because it won't fail"? → Unhandled case
  2. What would idiomatic code look like?

    • References instead of clones
    • Iterators instead of index loops
    • Pattern matching instead of flags
  3. Does this fight Rust?

    • Fighting borrow checker → restructure
    • Excessive unsafe → find safe pattern

Trace Up ↑

To design understanding:

"Why does my code have so many clones?"
    ↑ Ask: Is the ownership model correct?
    ↑ Check: m09-domain (data flow design)
    ↑ Check: m01-ownership (reference patterns)
Anti-PatternTrace ToQuestion
Clone everywherem01-ownershipWho should own this data?
Unwrap everywherem06-error-handlingWhat's the error strategy?
Rc everywherem09-domainIs ownership clear?
Fighting lifetimesm09-domainShould data structure change?

Trace Down ↓

To implementation (Layer 1):

"Replace clone with proper ownership"
    ↓ m01-ownership: Reference patterns
    ↓ m02-resource: Smart pointer if needed

"Replace unwrap with proper handling"
    ↓ m06-error-handling: ? operator
    ↓ m06-error-handling: expect with message

Top 5 Beginner Mistakes

RankMistakeFix
1Clone to escape borrow checkerUse references
2Unwrap in productionPropagate with
?
3String for everythingUse
&str
4Index loopsUse iterators
5Fighting lifetimesRestructure to own data

Code Smell → Refactoring

SmellIndicatesRefactoring
Many
.clone()
Ownership unclearClarify data flow
Many
.unwrap()
Error handling missingAdd proper handling
Many
pub
fields
Encapsulation brokenPrivate + accessors
Deep nestingComplex logicExtract methods
Long functionsMultiple responsibilitiesSplit
Giant enumsMissing abstractionTrait + types

Common Error Patterns

ErrorAnti-Pattern CauseFix
E0382 use after moveCloning vs ownershipProper references
Panic in productionUnwrap everywhere?, matching
Slow performanceString for all text&str, Cow
Borrow checker fightsWrong structureRestructure
Memory bloatRc/Arc everywhereSimple ownership

Deprecated → Better

DeprecatedBetter
Index-based loops
.iter()
,
.enumerate()
collect::<Vec<_>>()
then iterate
Chain iterators
Manual unsafe cell
Cell
,
RefCell
mem::transmute
for casts
as
or
TryFrom
Custom linked list
Vec
,
VecDeque
lazy_static!
std::sync::OnceLock

Quick Review Checklist

  • No
    .clone()
    without justification
  • No
    .unwrap()
    in library code
  • No
    pub
    fields with invariants
  • No index loops when iterator works
  • No
    String
    where
    &str
    suffices
  • No ignored
    #[must_use]
    warnings
  • No
    unsafe
    without SAFETY comment
  • No giant functions (>50 lines)

Related Skills

WhenSee
Ownership patternsm01-ownership
Error handlingm06-error-handling
Mental modelsm14-mental-model
Performancem10-performance