2.9 KiB
2.9 KiB
name: control-flow-clarity description: Branching and state-modeling clarity in C/C++. Use when writing or refactoring logic that branches on discrete values: if/else-if ladders, status flags, mode or state ints, or anything that should be an enum plus an exhaustive switch. Covers enum class over magic ints, exhaustive switch over nested if, early-return guard clauses, table dispatch, and when each is the right call.
Control-Flow Clarity
The goal: a reviewer verifies correctness by reading, not by tracing. Branching that mirrors the problem's shape is self-evident; branching that encodes it in ad-hoc ints and nesting forces the reader to reconstruct intent.
Core moves
- Model a closed set of states/modes as an
enum class, not ints or bools. A variable kept honest by a comment ("0 = hidden, 1 = showing, 2 = confirm") is a latent bug. Make it an enum and the comment becomes the type. - Dispatch on an enum with an exhaustive
switch, nodefault. This codebase relies on it: omittingdefaultlets the compiler flag the unhandled case when someone adds an enum value. Adefault:that swallows the unknown case throws that safety away. Adddefaultonly when "every other value does nothing" is a deliberate, documented decision. - Replace nested
if/else-ifladders that branch on one discriminant with aswitch. If each branch only maps input to a value, prefer a lookup table (static constexprarray) over both. - Prefer early-return guard clauses over nested success bodies. Handle the error/empty/skip cases first and return; keep the main path at the left margin.
When NOT to switch
- Branches test unrelated conditions, not one discriminant: a guarded
ifsequence is honest; a switch would be forced. - Two outcomes on a genuine boolean: keep the
if. - The discriminant is an open or unbounded set (arbitrary ints, strings): table or map, not a switch.
Enum hygiene
enum classby default for type safety. Plainenumonly when values must implicitly convert (e.g. a value that doubles as a UI dropdown index), and then give it a trailing_COUNTsentinel for safe bounds/iteration, matching the existing settings enums.- Name the discriminant after what it selects, not its storage:
Orientation orientation, notuint8_t mode. - No magic numeric codes for states. If you write a comment mapping numbers to meanings, you owe an enum.
Self-review
- No int/bool standing in for a closed set of modes; it is an
enum class. - Enum dispatch is an exhaustive
switchwith no catch-alldefault(or thedefaultis a documented deliberate choice). - No nested if/else-if ladder on a single discriminant that should be a switch or a table.
- Error/skip cases are early-return guards; the happy path is not buried.
- No magic numbers where a named enum or
constexprwould state the intent.