Skip to content

Flatten parallel if-let chains; codify the rule in CLAUDE.md#113

Merged
saltyskip merged 2 commits intomainfrom
if-let-chain-cleanup
May 1, 2026
Merged

Flatten parallel if-let chains; codify the rule in CLAUDE.md#113
saltyskip merged 2 commits intomainfrom
if-let-chain-cleanup

Conversation

@saltyskip
Copy link
Copy Markdown
Owner

Summary

Removes the most egregious "if-let chain doing parallel work" cases in the codebase and adds a Style Guidelines bullet to CLAUDE.md so the pattern gets flagged in review.

The rule (added to CLAUDE.md Style Guidelines):

Three or more if let statements in a row applying parallel logic is a smell — there's almost always a flatter form: a struct literal (when each branch sets one field of the same struct), .map() / .and_then() (when transforming Option<A>Option<B>), filter_map (when conditionally building a Vec), or match (when conditions overlap). if let is for one conditional unwrap with a side effect, not a substitute for declarative construction.

Audit hits fixed:

Location Before After
create_link 9 if-lets unwrap then re-wrap through builder methods struct literal
update_link 6 conditional update.insert(...) calls (3 nested with bson encoding) filter_map + Document::extend + small to_doc_value helper
apply_subscription_update 7 conditional set_doc.insert(...) calls 3 fallible kept (need ?) + 4 infallible collapsed into one filter_map
JSON-LD entry_points 3 if-lets pushing json!({...}) per platform filter_map over [(opt, platform_tag)]
Landing-page dests Vec 5 if-lets pushing ("label", url) tuples filter_map

Side effect: since create_link was the last caller of the chained-builder methods on CreateLinkInput, the entire impl CreateLinkInput block (10 builder methods + new) is now unreferenced and gets deleted. Per CLAUDE.md "fix root cause, don't #[allow(dead_code)]."

Left alone deliberately: validate_link_urls, validate_agent_context, validate_social_preview each have if-let chains, but every branch calls a distinct validator with a distinct error label and uses ?. The flatter form (array-of-tuples + try_for_each) reads worse there. The rule says "almost always" not "always."

Test plan

  • cargo fmt -- --check, cargo clippy --all-targets -- -D warnings, cargo test (86 lib + 145 integration) all green
  • No behavior change — the refactor preserves the silent-error semantics in update_link's bson encoding (matching the pre-refactor behavior)

Note on stacking with #112

This branches off main, not bulk-links-create. The bulk PR (#112) also uses a struct-literal CreateLinkInput — neither PR re-introduces the builder methods, so they're orthogonal regardless of merge order.

🤖 Generated with Claude Code

Five spots had 3+ if-lets each doing parallel "if Some, do one thing"
work — typically a builder/insert/push chain that's just a struct
literal or filter_map under the syntactic noise:

- create_link (services/links/service.rs): 9 if-lets unwrap-then-builder
  → struct literal. Drops the entire builder impl on CreateLinkInput
  since the methods become unreferenced.
- update_link (services/links/service.rs): 6 conditional Document inserts
  → string and serializable-struct branches collapsed via filter_map +
  Document::extend, with a small `to_doc_value` helper for the bson
  encoding.
- apply_subscription_update (services/auth/tenants/repo.rs): 4 infallible
  inserts collapsed via filter_map; the 3 fallible bson encodings stay
  separate so `?` lifts the error inline.
- JSON-LD entry_points (api/links/routes.rs): 3 if-lets pushing
  EntryPoint json! objects → filter_map over a [(opt, platform)] array.
- Landing-page dests Vec (api/links/routes.rs): 5 if-lets pushing
  ("label", url) tuples → filter_map.

Adds a Style Guidelines bullet to CLAUDE.md so future code review
flags this shape: "Three or more if let statements in a row applying
parallel logic is a smell — there's almost always a flatter form."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 1, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
rift Ready Ready Preview, Comment May 1, 2026 1:36pm

Request Review

…n create_link

Walks back the builder deletion. The builder pattern is the right fit
for a struct with many optional fields — the original design just took
T in every setter, which forced every caller into an if-let chain to
unwrap an Option<T> source. Setters now take Option<T> directly so
create_link can fluent-chain straight from the request struct without
unwrapping.

Updates CLAUDE.md to add fluent builders to the list of valid fixes
for the if-let-chain smell, with a design note that taking T (instead
of Option<T>) reintroduces the smell at every call site.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@saltyskip saltyskip merged commit 70ff33d into main May 1, 2026
5 checks passed
@saltyskip saltyskip deleted the if-let-chain-cleanup branch May 1, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant