Skill: cc-data-organization
STOP - Priority 1: Never Skip
| Item |
Why Critical |
| No magic numbers in business logic |
Source of silent bugs |
| Currency uses integer cents, never float |
Financial bugs are lawsuits |
| No float == comparisons |
Non-deterministic failures |
| Variables initialized before use |
Undefined behavior |
| Boolean naming is unambiguous |
Logic inversion bugs |
Skipping Priority 1 items is NEVER acceptable. They represent latent defects that will manifest later.
Modes
CHECKER
Purpose: Execute data organization checklists against code
Triggers:
- "review my variable declarations"
- "check for magic numbers"
- "review data type usage"
- "check my variable names"
Non-Triggers:
- "what type should I use for X" -> APPLIER
- "how should I name this variable" -> APPLIER
- "fix these magic numbers" -> TRANSFORMER
Checklist: See checklists.md
Metrics: See hard-data.md for Span/Live Time measures (goal: minimize both)
Output Format:
| Item |
Status |
Evidence |
Location |
| Severity: |
|
|
|
- VIOLATION: Fails checklist item
- WARNING: Partial compliance
- PASS: Meets requirement
APPLIER
Purpose: Guide data type selection, variable naming, and structure design
Triggers:
- "what data type should I use for..."
- "how should I name this variable"
- "best practice for enums/constants"
- "how should I organize this data"
Non-Triggers:
- "review my types" -> CHECKER
- "fix this" -> TRANSFORMER
- "audit my code" -> CHECKER
Produces: Type recommendations, naming conventions, enum patterns, constant definitions, structure designs
Constraints:
- [p.308] Eliminate semantic literals - Replace business values (
86400, 12, 0.07) with named constants. Loop bounds 0, 1 and array indices are typically fine.
- [p.295] For currency: integer cents or BCD, never float
- [p.306] Enums (language-dependent):
- C/C++: Reserve 0 for invalid, define First/Last bounds
- TypeScript string enums: No zero-reservation needed (no uninitialized risk)
- Rust/Kotlin: Leverage exhaustive matching instead of bounds checks
- [p.259] Minimize scope: Declare variables in innermost block where all usages occur. Balance with testability—sometimes slightly wider scope enables testing.
- [p.263] Names describe the entity clearly: Reader should understand purpose without searching for definition. Examples:
d (bad) → data (vague) → userData (better) → validatedUserSubmission (good for complex entity)
- [p.279] Problem Orientation: names refer to problem domain (employeeData, printerReady), not computing (inputRec, bitFlag)
- [p.263] Name length heuristic: 2-4 words, long enough to describe purpose, short enough to scan. Research shows 10-16 chars minimizes debugging effort [Gorla et al. 1990], but this is guidance, not a hard rule.
TRANSFORMER
Purpose: Fix data organization violations
Triggers:
- CHECKER findings with VIOLATION status
- "replace magic numbers with constants"
- "fix float comparison"
- "refactor these globals"
Non-Triggers:
- Large refactorings beyond data organization -> cc-refactoring-guidance
- Control flow restructuring -> cc-control-flow-quality
Input -> Output:
- Magic
86400 -> SECONDS_PER_DAY = 86400
if (a == b) floats -> if (Math.abs(a-b) < EPSILON)
true, false, true params -> enum values
- Unstructured variables -> grouped structure
- Direct global access -> access routines
Preserves: Behavior, unrelated code
Verification: Re-run CHECKER; VIOLATION count = 0
Rationalization Counters
| Excuse |
Reality |
| "Everyone knows what 12 means" |
Named constants aid maintenance [Glass 1991] |
| "Floats are close enough for ==" |
0.1 added 10 times rarely equals 1.0 |
| "Magic numbers are faster to type" |
Debugging hard-coded literals takes far longer |
| "I don't need custom types" |
One typedef change vs hundreds of declarations |
| "Short names are faster to type" |
Code read far more than written; favor read-time convenience |
| "Global variables are more convenient" |
Convenience writing trades against difficulty reading, debugging, modifying |
Sunk Cost Counters
For resisting changes to "working" code:
| Excuse |
Reality |
| "It works, why change it?" |
Violations are latent defects; "works" means "hasn't failed yet" |
| "I already invested time in this" |
Time invested in bad code is lost regardless; fix now or pay more later |
| "Refactoring will break things" |
Violations already broken; you just haven't discovered how yet |
| "Currency has always used floats here" |
Every penny calculation is a potential lawsuit |
| "We've had no bugs from these magic numbers" |
You've had bugs—you attributed them to other causes |
| "The code passed review before" |
Past reviews missed issues; evidence now shows violations |
Success-Bias Warning
Past success does NOT predict future safety.
Violations that "worked for years" fail when:
- Edge cases finally occur (currency rounding in new scenarios)
- Scale changes (global variable contention under load)
- Maintenance happens (magic numbers misunderstood by new developers)
- Requirements shift (hard-coded values need changing)
Every checklist item applies regardless of past success. "Worked until it didn't" examples fill bug databases.
Modern Data Types Coverage
Beyond Code Complete's C-era focus:
Concurrent Access
When data may be accessed from multiple threads/async contexts:
- Identify shared state - Mark variables accessed across thread boundaries
- Access routines are mandatory - Never expose shared data directly
- Consider immutability - Immutable data eliminates race conditions by design
- Document thread safety - Comment whether type/routine is thread-safe
- Violations: Data races, torn reads, lost updates
Nullable/Optional Types
Modern languages use Option<T>, Maybe, T? instead of null pointers:
- Prefer non-nullable by default - Make nullability explicit and intentional
- Handle all cases - Exhaustive matching on Option/Maybe types
- Avoid null as "not found" - Use Option types or result types instead
- Document null semantics - When null is valid, document what it means
- C-style pointer guidance still applies to unsafe code
Temporal Data
Dates and times are a common bug source:
- Store timestamps in UTC - Convert to local only for display
- Use timezone-aware types - Never use naive datetime for user-facing data
- Be explicit about precision - Seconds, milliseconds, nanoseconds?
- Name with time unit -
timeoutMs, durationSeconds, not just timeout
- Avoid magic time values -
86400 → SECONDS_PER_DAY
Security-Sensitive Data
Secrets, tokens, API keys require special handling:
- Clear from memory after use - Don't leave secrets in variables longer than needed
- Never log sensitive data - Redact in all log statements
- Use dedicated types -
SecureString, SensitiveData wrappers
- Limit scope aggressively - Shortest possible lifetime
Chain
| After |
Next |
| Data organization verified |
cc-control-flow-quality (CHECKER) |
1---2name: cc-data-organization3description: Audit and fix data organization: variable declarations, data types, magic numbers, naming conventions, and global data. Three modes: CHECKER (92-item checklist -> status table), APPLIER (type selection and naming guidance), TRANSFORMER (fix violations). Cover modern types: concurrent/shared state, nullable/optional, temporal/timezone, security-sensitive. Use when reviewing code for data organization issues, choosing data types, or fixing magic numbers. Triggers on: review variables, data types, magic numbers, naming, global data, check types, fix floats, constants.4---5
6# Skill: cc-data-organization
7
8## STOP - Priority 1: Never Skip
9
10| Item | Why Critical |
11|------|--------------|
12| No magic numbers in business logic | Source of silent bugs |
13| Currency uses integer cents, never float | Financial bugs are lawsuits |
14| No float == comparisons | Non-deterministic failures |
15| Variables initialized before use | Undefined behavior |
16| Boolean naming is unambiguous | Logic inversion bugs |
17
18**Skipping Priority 1 items is NEVER acceptable.** They represent latent defects that will manifest later.
19
20---
21
22## Modes
23
24### CHECKER
25Purpose: Execute data organization checklists against code
26Triggers:
27 - "review my variable declarations"
28 - "check for magic numbers"
29 - "review data type usage"
30 - "check my variable names"
31Non-Triggers:
32 - "what type should I use for X" -> APPLIER
33 - "how should I name this variable" -> APPLIER
34 - "fix these magic numbers" -> TRANSFORMER
35Checklist: **See [checklists.md](./checklists.md)**
36Metrics: **See [hard-data.md](./hard-data.md)** for Span/Live Time measures (goal: minimize both)
37Output Format:
38 | Item | Status | Evidence | Location |
39 |------|--------|----------|----------|
40Severity:
41 - VIOLATION: Fails checklist item
42 - WARNING: Partial compliance
43 - PASS: Meets requirement
44
45### APPLIER
46Purpose: Guide data type selection, variable naming, and structure design
47Triggers:
48 - "what data type should I use for..."
49 - "how should I name this variable"
50 - "best practice for enums/constants"
51 - "how should I organize this data"
52Non-Triggers:
53 - "review my types" -> CHECKER
54 - "fix this" -> TRANSFORMER
55 - "audit my code" -> CHECKER
56Produces: Type recommendations, naming conventions, enum patterns, constant definitions, structure designs
57Constraints:
58 - [p.308] **Eliminate semantic literals** - Replace business values (`86400`, `12`, `0.07`) with named constants. Loop bounds `0`, `1` and array indices are typically fine.
59 - [p.295] For currency: integer cents or BCD, never float
60 - [p.306] **Enums (language-dependent):**
61 - C/C++: Reserve 0 for invalid, define First/Last bounds
62 - TypeScript string enums: No zero-reservation needed (no uninitialized risk)
63 - Rust/Kotlin: Leverage exhaustive matching instead of bounds checks
64 - [p.259] **Minimize scope**: Declare variables in innermost block where all usages occur. Balance with testability—sometimes slightly wider scope enables testing.
65 - [p.263] **Names describe the entity clearly**: Reader should understand purpose without searching for definition. Examples: `d` (bad) → `data` (vague) → `userData` (better) → `validatedUserSubmission` (good for complex entity)
66 - [p.279] Problem Orientation: names refer to problem domain (employeeData, printerReady), not computing (inputRec, bitFlag)
67 - [p.263] **Name length heuristic**: 2-4 words, long enough to describe purpose, short enough to scan. Research shows 10-16 chars minimizes debugging effort [Gorla et al. 1990], but this is guidance, not a hard rule.
68
69### TRANSFORMER
70Purpose: Fix data organization violations
71Triggers:
72 - CHECKER findings with VIOLATION status
73 - "replace magic numbers with constants"
74 - "fix float comparison"
75 - "refactor these globals"
76Non-Triggers:
77 - Large refactorings beyond data organization -> cc-refactoring-guidance
78 - Control flow restructuring -> cc-control-flow-quality
79Input -> Output:
80 - Magic `86400` -> `SECONDS_PER_DAY = 86400`
81 - `if (a == b)` floats -> `if (Math.abs(a-b) < EPSILON)`
82 - `true, false, true` params -> enum values
83 - Unstructured variables -> grouped structure
84 - Direct global access -> access routines
85Preserves: Behavior, unrelated code
86Verification: Re-run CHECKER; VIOLATION count = 0
87
88## Rationalization Counters
89| Excuse | Reality |
90|--------|---------|
91| "Everyone knows what 12 means" | Named constants aid maintenance [Glass 1991] |
92| "Floats are close enough for ==" | 0.1 added 10 times rarely equals 1.0 |
93| "Magic numbers are faster to type" | Debugging hard-coded literals takes far longer |
94| "I don't need custom types" | One typedef change vs hundreds of declarations |
95| "Short names are faster to type" | Code read far more than written; favor read-time convenience |
96| "Global variables are more convenient" | Convenience writing trades against difficulty reading, debugging, modifying |
97
98### Sunk Cost Counters
99**For resisting changes to "working" code:**
100
101| Excuse | Reality |
102|--------|---------|
103| "It works, why change it?" | Violations are latent defects; "works" means "hasn't failed yet" |
104| "I already invested time in this" | Time invested in bad code is lost regardless; fix now or pay more later |
105| "Refactoring will break things" | Violations already broken; you just haven't discovered how yet |
106| "Currency has always used floats here" | Every penny calculation is a potential lawsuit |
107| "We've had no bugs from these magic numbers" | You've had bugs—you attributed them to other causes |
108| "The code passed review before" | Past reviews missed issues; evidence now shows violations |
109
110### Success-Bias Warning
111**Past success does NOT predict future safety.**
112
113Violations that "worked for years" fail when:
114- Edge cases finally occur (currency rounding in new scenarios)
115- Scale changes (global variable contention under load)
116- Maintenance happens (magic numbers misunderstood by new developers)
117- Requirements shift (hard-coded values need changing)
118
119**Every checklist item applies regardless of past success.** "Worked until it didn't" examples fill bug databases.
120
121## Modern Data Types Coverage
122
123*Beyond Code Complete's C-era focus:*
124
125### Concurrent Access
126When data may be accessed from multiple threads/async contexts:
127- **Identify shared state** - Mark variables accessed across thread boundaries
128- **Access routines are mandatory** - Never expose shared data directly
129- **Consider immutability** - Immutable data eliminates race conditions by design
130- **Document thread safety** - Comment whether type/routine is thread-safe
131- Violations: Data races, torn reads, lost updates
132
133### Nullable/Optional Types
134Modern languages use `Option<T>`, `Maybe`, `T?` instead of null pointers:
135- **Prefer non-nullable by default** - Make nullability explicit and intentional
136- **Handle all cases** - Exhaustive matching on Option/Maybe types
137- **Avoid null as "not found"** - Use Option types or result types instead
138- **Document null semantics** - When null is valid, document what it means
139- C-style pointer guidance still applies to unsafe code
140
141### Temporal Data
142Dates and times are a common bug source:
143- **Store timestamps in UTC** - Convert to local only for display
144- **Use timezone-aware types** - Never use naive datetime for user-facing data
145- **Be explicit about precision** - Seconds, milliseconds, nanoseconds?
146- **Name with time unit** - `timeoutMs`, `durationSeconds`, not just `timeout`
147- **Avoid magic time values** - `86400` → `SECONDS_PER_DAY`
148
149### Security-Sensitive Data
150Secrets, tokens, API keys require special handling:
151- **Clear from memory after use** - Don't leave secrets in variables longer than needed
152- **Never log sensitive data** - Redact in all log statements
153- **Use dedicated types** - `SecureString`, `SensitiveData` wrappers
154- **Limit scope aggressively** - Shortest possible lifetime
155
156
157---
158
159## Chain
160
161| After | Next |
162|-------|------|
163| Data organization verified | cc-control-flow-quality (CHECKER) |
164