@shaykec/bridge 0.4.24 → 0.4.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/journeys/ai-engineer.yaml +34 -0
- package/journeys/backend-developer.yaml +36 -0
- package/journeys/business-analyst.yaml +37 -0
- package/journeys/devops-engineer.yaml +37 -0
- package/journeys/engineering-manager.yaml +44 -0
- package/journeys/frontend-developer.yaml +41 -0
- package/journeys/fullstack-developer.yaml +49 -0
- package/journeys/mobile-developer.yaml +42 -0
- package/journeys/product-manager.yaml +35 -0
- package/journeys/qa-engineer.yaml +37 -0
- package/journeys/ux-designer.yaml +43 -0
- package/modules/README.md +52 -0
- package/modules/accessibility-fundamentals/content.md +126 -0
- package/modules/accessibility-fundamentals/exercises.md +88 -0
- package/modules/accessibility-fundamentals/module.yaml +43 -0
- package/modules/accessibility-fundamentals/quick-ref.md +71 -0
- package/modules/accessibility-fundamentals/quiz.md +100 -0
- package/modules/accessibility-fundamentals/resources.md +29 -0
- package/modules/accessibility-fundamentals/walkthrough.md +80 -0
- package/modules/adr-writing/content.md +121 -0
- package/modules/adr-writing/exercises.md +81 -0
- package/modules/adr-writing/module.yaml +41 -0
- package/modules/adr-writing/quick-ref.md +57 -0
- package/modules/adr-writing/quiz.md +73 -0
- package/modules/adr-writing/resources.md +29 -0
- package/modules/adr-writing/walkthrough.md +64 -0
- package/modules/ai-agents/content.md +120 -0
- package/modules/ai-agents/exercises.md +82 -0
- package/modules/ai-agents/module.yaml +42 -0
- package/modules/ai-agents/quick-ref.md +60 -0
- package/modules/ai-agents/quiz.md +103 -0
- package/modules/ai-agents/resources.md +30 -0
- package/modules/ai-agents/walkthrough.md +85 -0
- package/modules/ai-assisted-research/content.md +136 -0
- package/modules/ai-assisted-research/exercises.md +80 -0
- package/modules/ai-assisted-research/module.yaml +42 -0
- package/modules/ai-assisted-research/quick-ref.md +67 -0
- package/modules/ai-assisted-research/quiz.md +73 -0
- package/modules/ai-assisted-research/resources.md +33 -0
- package/modules/ai-assisted-research/walkthrough.md +85 -0
- package/modules/ai-pair-programming/content.md +105 -0
- package/modules/ai-pair-programming/exercises.md +98 -0
- package/modules/ai-pair-programming/module.yaml +39 -0
- package/modules/ai-pair-programming/quick-ref.md +58 -0
- package/modules/ai-pair-programming/quiz.md +73 -0
- package/modules/ai-pair-programming/resources.md +34 -0
- package/modules/ai-pair-programming/walkthrough.md +117 -0
- package/modules/ai-test-generation/content.md +125 -0
- package/modules/ai-test-generation/exercises.md +98 -0
- package/modules/ai-test-generation/module.yaml +39 -0
- package/modules/ai-test-generation/quick-ref.md +65 -0
- package/modules/ai-test-generation/quiz.md +74 -0
- package/modules/ai-test-generation/resources.md +41 -0
- package/modules/ai-test-generation/walkthrough.md +100 -0
- package/modules/api-design/content.md +189 -0
- package/modules/api-design/exercises.md +84 -0
- package/modules/api-design/game.yaml +113 -0
- package/modules/api-design/module.yaml +45 -0
- package/modules/api-design/quick-ref.md +73 -0
- package/modules/api-design/quiz.md +100 -0
- package/modules/api-design/resources.md +55 -0
- package/modules/api-design/walkthrough.md +88 -0
- package/modules/clean-code/content.md +136 -0
- package/modules/clean-code/exercises.md +137 -0
- package/modules/clean-code/game.yaml +172 -0
- package/modules/clean-code/module.yaml +44 -0
- package/modules/clean-code/quick-ref.md +44 -0
- package/modules/clean-code/quiz.md +105 -0
- package/modules/clean-code/resources.md +40 -0
- package/modules/clean-code/walkthrough.md +78 -0
- package/modules/clean-code/workshop.yaml +149 -0
- package/modules/code-review/content.md +130 -0
- package/modules/code-review/exercises.md +95 -0
- package/modules/code-review/game.yaml +83 -0
- package/modules/code-review/module.yaml +42 -0
- package/modules/code-review/quick-ref.md +77 -0
- package/modules/code-review/quiz.md +105 -0
- package/modules/code-review/resources.md +40 -0
- package/modules/code-review/walkthrough.md +106 -0
- package/modules/daily-workflow/content.md +81 -0
- package/modules/daily-workflow/exercises.md +50 -0
- package/modules/daily-workflow/module.yaml +33 -0
- package/modules/daily-workflow/quick-ref.md +37 -0
- package/modules/daily-workflow/quiz.md +65 -0
- package/modules/daily-workflow/resources.md +38 -0
- package/modules/daily-workflow/walkthrough.md +83 -0
- package/modules/debugging-systematically/content.md +139 -0
- package/modules/debugging-systematically/exercises.md +91 -0
- package/modules/debugging-systematically/module.yaml +46 -0
- package/modules/debugging-systematically/quick-ref.md +59 -0
- package/modules/debugging-systematically/quiz.md +105 -0
- package/modules/debugging-systematically/resources.md +42 -0
- package/modules/debugging-systematically/walkthrough.md +84 -0
- package/modules/debugging-systematically/workshop.yaml +127 -0
- package/modules/demo-test/content.md +68 -0
- package/modules/demo-test/exercises.md +28 -0
- package/modules/demo-test/game.yaml +171 -0
- package/modules/demo-test/module.yaml +41 -0
- package/modules/demo-test/quick-ref.md +54 -0
- package/modules/demo-test/quiz.md +74 -0
- package/modules/demo-test/resources.md +21 -0
- package/modules/demo-test/walkthrough.md +122 -0
- package/modules/demo-test/workshop.yaml +31 -0
- package/modules/design-critique/content.md +93 -0
- package/modules/design-critique/exercises.md +71 -0
- package/modules/design-critique/module.yaml +41 -0
- package/modules/design-critique/quick-ref.md +63 -0
- package/modules/design-critique/quiz.md +73 -0
- package/modules/design-critique/resources.md +27 -0
- package/modules/design-critique/walkthrough.md +68 -0
- package/modules/design-patterns/content.md +335 -0
- package/modules/design-patterns/exercises.md +82 -0
- package/modules/design-patterns/game.yaml +55 -0
- package/modules/design-patterns/module.yaml +45 -0
- package/modules/design-patterns/quick-ref.md +44 -0
- package/modules/design-patterns/quiz.md +101 -0
- package/modules/design-patterns/resources.md +40 -0
- package/modules/design-patterns/walkthrough.md +64 -0
- package/modules/exploratory-testing/content.md +133 -0
- package/modules/exploratory-testing/exercises.md +88 -0
- package/modules/exploratory-testing/module.yaml +41 -0
- package/modules/exploratory-testing/quick-ref.md +68 -0
- package/modules/exploratory-testing/quiz.md +75 -0
- package/modules/exploratory-testing/resources.md +39 -0
- package/modules/exploratory-testing/walkthrough.md +87 -0
- package/modules/git/content.md +128 -0
- package/modules/git/exercises.md +53 -0
- package/modules/git/game.yaml +190 -0
- package/modules/git/module.yaml +44 -0
- package/modules/git/quick-ref.md +67 -0
- package/modules/git/quiz.md +89 -0
- package/modules/git/resources.md +49 -0
- package/modules/git/walkthrough.md +92 -0
- package/modules/git/workshop.yaml +145 -0
- package/modules/hiring-interviews/content.md +130 -0
- package/modules/hiring-interviews/exercises.md +88 -0
- package/modules/hiring-interviews/module.yaml +41 -0
- package/modules/hiring-interviews/quick-ref.md +68 -0
- package/modules/hiring-interviews/quiz.md +73 -0
- package/modules/hiring-interviews/resources.md +36 -0
- package/modules/hiring-interviews/walkthrough.md +75 -0
- package/modules/hooks/content.md +97 -0
- package/modules/hooks/exercises.md +69 -0
- package/modules/hooks/module.yaml +39 -0
- package/modules/hooks/quick-ref.md +93 -0
- package/modules/hooks/quiz.md +81 -0
- package/modules/hooks/resources.md +34 -0
- package/modules/hooks/walkthrough.md +105 -0
- package/modules/hooks/workshop.yaml +64 -0
- package/modules/incident-response/content.md +124 -0
- package/modules/incident-response/exercises.md +82 -0
- package/modules/incident-response/game.yaml +132 -0
- package/modules/incident-response/module.yaml +45 -0
- package/modules/incident-response/quick-ref.md +53 -0
- package/modules/incident-response/quiz.md +103 -0
- package/modules/incident-response/resources.md +40 -0
- package/modules/incident-response/walkthrough.md +82 -0
- package/modules/llm-fundamentals/content.md +114 -0
- package/modules/llm-fundamentals/exercises.md +83 -0
- package/modules/llm-fundamentals/module.yaml +42 -0
- package/modules/llm-fundamentals/quick-ref.md +64 -0
- package/modules/llm-fundamentals/quiz.md +103 -0
- package/modules/llm-fundamentals/resources.md +30 -0
- package/modules/llm-fundamentals/walkthrough.md +91 -0
- package/modules/one-on-ones/content.md +133 -0
- package/modules/one-on-ones/exercises.md +81 -0
- package/modules/one-on-ones/module.yaml +44 -0
- package/modules/one-on-ones/quick-ref.md +67 -0
- package/modules/one-on-ones/quiz.md +73 -0
- package/modules/one-on-ones/resources.md +37 -0
- package/modules/one-on-ones/walkthrough.md +69 -0
- package/modules/package.json +9 -0
- package/modules/prioritization-frameworks/content.md +130 -0
- package/modules/prioritization-frameworks/exercises.md +93 -0
- package/modules/prioritization-frameworks/module.yaml +41 -0
- package/modules/prioritization-frameworks/quick-ref.md +77 -0
- package/modules/prioritization-frameworks/quiz.md +73 -0
- package/modules/prioritization-frameworks/resources.md +32 -0
- package/modules/prioritization-frameworks/walkthrough.md +69 -0
- package/modules/prompt-engineering/content.md +123 -0
- package/modules/prompt-engineering/exercises.md +82 -0
- package/modules/prompt-engineering/game.yaml +101 -0
- package/modules/prompt-engineering/module.yaml +45 -0
- package/modules/prompt-engineering/quick-ref.md +65 -0
- package/modules/prompt-engineering/quiz.md +105 -0
- package/modules/prompt-engineering/resources.md +36 -0
- package/modules/prompt-engineering/walkthrough.md +81 -0
- package/modules/rag-fundamentals/content.md +111 -0
- package/modules/rag-fundamentals/exercises.md +80 -0
- package/modules/rag-fundamentals/module.yaml +45 -0
- package/modules/rag-fundamentals/quick-ref.md +58 -0
- package/modules/rag-fundamentals/quiz.md +75 -0
- package/modules/rag-fundamentals/resources.md +34 -0
- package/modules/rag-fundamentals/walkthrough.md +75 -0
- package/modules/react-fundamentals/content.md +140 -0
- package/modules/react-fundamentals/exercises.md +81 -0
- package/modules/react-fundamentals/game.yaml +145 -0
- package/modules/react-fundamentals/module.yaml +45 -0
- package/modules/react-fundamentals/quick-ref.md +62 -0
- package/modules/react-fundamentals/quiz.md +106 -0
- package/modules/react-fundamentals/resources.md +42 -0
- package/modules/react-fundamentals/walkthrough.md +89 -0
- package/modules/react-fundamentals/workshop.yaml +112 -0
- package/modules/react-native-fundamentals/content.md +141 -0
- package/modules/react-native-fundamentals/exercises.md +79 -0
- package/modules/react-native-fundamentals/module.yaml +42 -0
- package/modules/react-native-fundamentals/quick-ref.md +60 -0
- package/modules/react-native-fundamentals/quiz.md +61 -0
- package/modules/react-native-fundamentals/resources.md +24 -0
- package/modules/react-native-fundamentals/walkthrough.md +84 -0
- package/modules/registry.yaml +1650 -0
- package/modules/risk-management/content.md +162 -0
- package/modules/risk-management/exercises.md +86 -0
- package/modules/risk-management/module.yaml +41 -0
- package/modules/risk-management/quick-ref.md +82 -0
- package/modules/risk-management/quiz.md +73 -0
- package/modules/risk-management/resources.md +40 -0
- package/modules/risk-management/walkthrough.md +67 -0
- package/modules/running-effective-standups/content.md +119 -0
- package/modules/running-effective-standups/exercises.md +79 -0
- package/modules/running-effective-standups/module.yaml +40 -0
- package/modules/running-effective-standups/quick-ref.md +61 -0
- package/modules/running-effective-standups/quiz.md +73 -0
- package/modules/running-effective-standups/resources.md +36 -0
- package/modules/running-effective-standups/walkthrough.md +76 -0
- package/modules/solid-principles/content.md +154 -0
- package/modules/solid-principles/exercises.md +107 -0
- package/modules/solid-principles/module.yaml +42 -0
- package/modules/solid-principles/quick-ref.md +50 -0
- package/modules/solid-principles/quiz.md +102 -0
- package/modules/solid-principles/resources.md +39 -0
- package/modules/solid-principles/walkthrough.md +84 -0
- package/modules/sprint-planning/content.md +142 -0
- package/modules/sprint-planning/exercises.md +79 -0
- package/modules/sprint-planning/game.yaml +84 -0
- package/modules/sprint-planning/module.yaml +44 -0
- package/modules/sprint-planning/quick-ref.md +76 -0
- package/modules/sprint-planning/quiz.md +102 -0
- package/modules/sprint-planning/resources.md +39 -0
- package/modules/sprint-planning/walkthrough.md +75 -0
- package/modules/sql-fundamentals/content.md +160 -0
- package/modules/sql-fundamentals/exercises.md +87 -0
- package/modules/sql-fundamentals/game.yaml +105 -0
- package/modules/sql-fundamentals/module.yaml +45 -0
- package/modules/sql-fundamentals/quick-ref.md +53 -0
- package/modules/sql-fundamentals/quiz.md +103 -0
- package/modules/sql-fundamentals/resources.md +42 -0
- package/modules/sql-fundamentals/walkthrough.md +92 -0
- package/modules/sql-fundamentals/workshop.yaml +109 -0
- package/modules/stakeholder-communication/content.md +186 -0
- package/modules/stakeholder-communication/exercises.md +87 -0
- package/modules/stakeholder-communication/module.yaml +38 -0
- package/modules/stakeholder-communication/quick-ref.md +89 -0
- package/modules/stakeholder-communication/quiz.md +73 -0
- package/modules/stakeholder-communication/resources.md +41 -0
- package/modules/stakeholder-communication/walkthrough.md +74 -0
- package/modules/system-design/content.md +149 -0
- package/modules/system-design/exercises.md +83 -0
- package/modules/system-design/game.yaml +95 -0
- package/modules/system-design/module.yaml +46 -0
- package/modules/system-design/quick-ref.md +59 -0
- package/modules/system-design/quiz.md +102 -0
- package/modules/system-design/resources.md +46 -0
- package/modules/system-design/walkthrough.md +90 -0
- package/modules/team-topologies/content.md +166 -0
- package/modules/team-topologies/exercises.md +85 -0
- package/modules/team-topologies/module.yaml +41 -0
- package/modules/team-topologies/quick-ref.md +61 -0
- package/modules/team-topologies/quiz.md +101 -0
- package/modules/team-topologies/resources.md +37 -0
- package/modules/team-topologies/walkthrough.md +76 -0
- package/modules/technical-debt/content.md +111 -0
- package/modules/technical-debt/exercises.md +92 -0
- package/modules/technical-debt/module.yaml +39 -0
- package/modules/technical-debt/quick-ref.md +60 -0
- package/modules/technical-debt/quiz.md +73 -0
- package/modules/technical-debt/resources.md +25 -0
- package/modules/technical-debt/walkthrough.md +94 -0
- package/modules/technical-mentoring/content.md +128 -0
- package/modules/technical-mentoring/exercises.md +84 -0
- package/modules/technical-mentoring/module.yaml +41 -0
- package/modules/technical-mentoring/quick-ref.md +74 -0
- package/modules/technical-mentoring/quiz.md +73 -0
- package/modules/technical-mentoring/resources.md +33 -0
- package/modules/technical-mentoring/walkthrough.md +65 -0
- package/modules/test-strategy/content.md +136 -0
- package/modules/test-strategy/exercises.md +84 -0
- package/modules/test-strategy/game.yaml +99 -0
- package/modules/test-strategy/module.yaml +45 -0
- package/modules/test-strategy/quick-ref.md +66 -0
- package/modules/test-strategy/quiz.md +99 -0
- package/modules/test-strategy/resources.md +60 -0
- package/modules/test-strategy/walkthrough.md +97 -0
- package/modules/test-strategy/workshop.yaml +96 -0
- package/modules/typescript-fundamentals/content.md +127 -0
- package/modules/typescript-fundamentals/exercises.md +79 -0
- package/modules/typescript-fundamentals/game.yaml +111 -0
- package/modules/typescript-fundamentals/module.yaml +45 -0
- package/modules/typescript-fundamentals/quick-ref.md +55 -0
- package/modules/typescript-fundamentals/quiz.md +104 -0
- package/modules/typescript-fundamentals/resources.md +42 -0
- package/modules/typescript-fundamentals/walkthrough.md +71 -0
- package/modules/typescript-fundamentals/workshop.yaml +146 -0
- package/modules/user-story-mapping/content.md +123 -0
- package/modules/user-story-mapping/exercises.md +87 -0
- package/modules/user-story-mapping/module.yaml +41 -0
- package/modules/user-story-mapping/quick-ref.md +64 -0
- package/modules/user-story-mapping/quiz.md +73 -0
- package/modules/user-story-mapping/resources.md +29 -0
- package/modules/user-story-mapping/walkthrough.md +86 -0
- package/modules/writing-prds/content.md +133 -0
- package/modules/writing-prds/exercises.md +93 -0
- package/modules/writing-prds/game.yaml +83 -0
- package/modules/writing-prds/module.yaml +44 -0
- package/modules/writing-prds/quick-ref.md +77 -0
- package/modules/writing-prds/quiz.md +103 -0
- package/modules/writing-prds/resources.md +30 -0
- package/modules/writing-prds/walkthrough.md +87 -0
- package/package.json +5 -3
- package/src/server.js +17 -7
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Clean Code Exercises
|
|
2
|
+
|
|
3
|
+
## Exercise 1: Name Refactor
|
|
4
|
+
|
|
5
|
+
**Task:** Refactor this function with better names and structure:
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
function proc(u, p) {
|
|
9
|
+
if (p.length < 8) return false;
|
|
10
|
+
const h = crypto.hash(p);
|
|
11
|
+
return u.pw === h;
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Validation:**
|
|
16
|
+
- [ ] All variables and the function have intent-revealing names
|
|
17
|
+
- [ ] A reader can understand the logic without guessing
|
|
18
|
+
- [ ] No abbreviations unless universally known (e.g., `id`)
|
|
19
|
+
|
|
20
|
+
**Hints:**
|
|
21
|
+
1. `proc` → what does it do? `validatePassword`, `checkCredentials`?
|
|
22
|
+
2. `u` → `user`; `p` → `password`; `h` → `hashedPassword`
|
|
23
|
+
3. Consider extracting the length check or the hash step
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Exercise 2: Extract Function
|
|
28
|
+
|
|
29
|
+
**Task:** This function does several things. Extract at least two smaller functions:
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
function processOrder(order) {
|
|
33
|
+
if (!order.items || order.items.length === 0) return { error: 'No items' };
|
|
34
|
+
if (!order.shippingAddress) return { error: 'No address' };
|
|
35
|
+
let total = 0;
|
|
36
|
+
for (const item of order.items) total += item.price * item.quantity;
|
|
37
|
+
const tax = total * 0.1;
|
|
38
|
+
const finalTotal = total + tax;
|
|
39
|
+
saveToDatabase({ ...order, total: finalTotal });
|
|
40
|
+
sendConfirmationEmail(order.customerEmail);
|
|
41
|
+
return { success: true, total: finalTotal };
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Validation:**
|
|
46
|
+
- [ ] At least 2 focused functions extracted
|
|
47
|
+
- [ ] Original function orchestrates, doesn't contain low-level logic
|
|
48
|
+
- [ ] Each extracted function has a clear name
|
|
49
|
+
|
|
50
|
+
**Hints:**
|
|
51
|
+
1. Extract validation into `validateOrder` or separate checks
|
|
52
|
+
2. Extract total calculation into `calculateOrderTotal`
|
|
53
|
+
3. Consider extracting `saveAndNotify` or keep save/email separate
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Exercise 3: Replace Magic Numbers
|
|
58
|
+
|
|
59
|
+
**Task:** Identify and replace magic numbers in this code:
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
function getPriceTier(customer) {
|
|
63
|
+
if (customer.orders < 5) return 'bronze';
|
|
64
|
+
if (customer.orders < 20) return 'silver';
|
|
65
|
+
return 'gold';
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Add constants for the thresholds. Consider: what if the thresholds change?
|
|
70
|
+
|
|
71
|
+
**Validation:**
|
|
72
|
+
- [ ] Thresholds (5, 20) are named constants
|
|
73
|
+
- [ ] Tier names could also be constants if used elsewhere
|
|
74
|
+
- [ ] Logic is unchanged, readability improved
|
|
75
|
+
|
|
76
|
+
**Hints:**
|
|
77
|
+
1. `const BRONZE_MIN_ORDERS = 0`, `SILVER_MIN_ORDERS = 5`, `GOLD_MIN_ORDERS = 20`
|
|
78
|
+
2. Or `const TIER_THRESHOLDS = [5, 20]` for easier config
|
|
79
|
+
3. Document the business rule if non-obvious
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Exercise 4: Reduce Nesting
|
|
84
|
+
|
|
85
|
+
**Task:** Refactor this to use early returns:
|
|
86
|
+
|
|
87
|
+
```javascript
|
|
88
|
+
function findUser(id) {
|
|
89
|
+
if (id) {
|
|
90
|
+
const user = db.query('users', id);
|
|
91
|
+
if (user) {
|
|
92
|
+
if (user.isActive) {
|
|
93
|
+
return user;
|
|
94
|
+
} else {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Validation:**
|
|
107
|
+
- [ ] No more than 2 levels of nesting
|
|
108
|
+
- [ ] Early returns handle invalid cases
|
|
109
|
+
- [ ] Happy path is clear at the end
|
|
110
|
+
|
|
111
|
+
**Hints:**
|
|
112
|
+
1. `if (!id) return null;` first
|
|
113
|
+
2. `if (!user) return null;` next
|
|
114
|
+
3. `if (!user.isActive) return null;` then return user
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Exercise 5: Self-Documenting Code
|
|
119
|
+
|
|
120
|
+
**Task:** Remove the comment and make the code speak for itself:
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
// Check if the user has reached the free tier limit
|
|
124
|
+
if (users.filter(u => u.plan === 'free').length >= 10) {
|
|
125
|
+
showUpgradePrompt();
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Validation:**
|
|
130
|
+
- [ ] Comment removed
|
|
131
|
+
- [ ] Intent clear from names and structure
|
|
132
|
+
- [ ] Consider extracting to a named boolean variable
|
|
133
|
+
|
|
134
|
+
**Hints:**
|
|
135
|
+
1. `const freeUserCount = users.filter(u => u.plan === 'free').length;`
|
|
136
|
+
2. `const FREE_TIER_LIMIT = 10;`
|
|
137
|
+
3. `const hasReachedFreeTierLimit = freeUserCount >= FREE_TIER_LIMIT;`
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
games:
|
|
2
|
+
- type: bug-hunt
|
|
3
|
+
title: "Code Smell Detective"
|
|
4
|
+
snippets:
|
|
5
|
+
- code: |
|
|
6
|
+
function process(d) {
|
|
7
|
+
if (d < 18) return "minor";
|
|
8
|
+
if (d < 65) return "adult";
|
|
9
|
+
return "senior";
|
|
10
|
+
}
|
|
11
|
+
const result = process(25);
|
|
12
|
+
bugLine: 2
|
|
13
|
+
explanation: "Magic number 18 — age thresholds should be named constants (e.g. MIN_ADULT_AGE) so intent is clear and changes are centralized."
|
|
14
|
+
hint: "What does the number 18 represent?"
|
|
15
|
+
- code: |
|
|
16
|
+
function doStuff(a, b, c, x, y) {
|
|
17
|
+
const t = a * x + b * y;
|
|
18
|
+
const r = c ? t * 1.1 : t;
|
|
19
|
+
return Math.round(r * 100) / 100;
|
|
20
|
+
}
|
|
21
|
+
bugLine: 2
|
|
22
|
+
explanation: "God function — does too much: computes a formula, applies a flag-based adjustment, and formats. Split into focused functions with descriptive names."
|
|
23
|
+
hint: "How many responsibilities does this function have?"
|
|
24
|
+
- code: |
|
|
25
|
+
const d = new Date();
|
|
26
|
+
const x = users.filter(u => u.active).length;
|
|
27
|
+
const discount = price > 100 ? 0.1 : 0.05;
|
|
28
|
+
bugLine: 1
|
|
29
|
+
explanation: "Unclear variable names — 'd', 'x' tell nothing. Use descriptive names: currentDate, activeUserCount, discountRate."
|
|
30
|
+
hint: "What does 'd' or 'x' convey to a reader?"
|
|
31
|
+
- code: |
|
|
32
|
+
function sendEmail(user, body, notify = true) {
|
|
33
|
+
if (notify) {
|
|
34
|
+
log("Sent to " + user.email);
|
|
35
|
+
}
|
|
36
|
+
return mailer.send(user.email, body);
|
|
37
|
+
}
|
|
38
|
+
bugLine: 2
|
|
39
|
+
explanation: "Boolean parameter — 'notify' obscures intent. Prefer separate methods (sendEmail vs sendEmailQuietly) or an options object."
|
|
40
|
+
hint: "What does notify=true mean at the call site?"
|
|
41
|
+
- code: |
|
|
42
|
+
function calcTotal(items) {
|
|
43
|
+
let t = 0;
|
|
44
|
+
for (let i = 0; i < items.length; i++) {
|
|
45
|
+
if (items[i].onSale) {
|
|
46
|
+
t += items[i].price * 0.8;
|
|
47
|
+
} else {
|
|
48
|
+
t += items[i].price;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return t;
|
|
52
|
+
}
|
|
53
|
+
bugLine: 5
|
|
54
|
+
explanation: "Magic number 0.8 — discount factor should be a named constant (e.g. SALE_DISCOUNT = 0.8) for clarity and easy maintenance."
|
|
55
|
+
hint: "What does 0.8 mean in this context?"
|
|
56
|
+
- code: |
|
|
57
|
+
function validateOrder(order) {
|
|
58
|
+
if (order.items) {
|
|
59
|
+
if (order.items.length > 0) {
|
|
60
|
+
if (order.shipping) {
|
|
61
|
+
if (order.shipping.address) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
bugLine: 3
|
|
70
|
+
explanation: "Deeply nested conditionals — hard to follow. Use guard clauses or early returns to flatten and improve readability."
|
|
71
|
+
hint: "How many levels of nesting?"
|
|
72
|
+
- code: |
|
|
73
|
+
function fetchUser(id) {
|
|
74
|
+
const user = db.query("SELECT * FROM users WHERE id = ?", id);
|
|
75
|
+
return user;
|
|
76
|
+
console.log("Fetched user:", id);
|
|
77
|
+
}
|
|
78
|
+
bugLine: 4
|
|
79
|
+
explanation: "Dead code — the console.log is unreachable after the return statement. Remove it or move before the return."
|
|
80
|
+
hint: "Can this line ever execute?"
|
|
81
|
+
- code: |
|
|
82
|
+
const data = await fetch("/api/config");
|
|
83
|
+
const cfg = JSON.parse(data);
|
|
84
|
+
const t = cfg.timeout || 5000;
|
|
85
|
+
return t;
|
|
86
|
+
bugLine: 3
|
|
87
|
+
explanation: "Magic number 5000 — default timeout should be a named constant (e.g. DEFAULT_TIMEOUT_MS) so milliseconds intent is clear."
|
|
88
|
+
hint: "What unit is 5000? Is that obvious?"
|
|
89
|
+
|
|
90
|
+
- type: speed-round
|
|
91
|
+
title: "Clean Code Quick Fire"
|
|
92
|
+
rounds:
|
|
93
|
+
- question: "Which variable name is better for a user's email address?"
|
|
94
|
+
options:
|
|
95
|
+
- "e"
|
|
96
|
+
- "em"
|
|
97
|
+
- "userEmail"
|
|
98
|
+
- "ue"
|
|
99
|
+
answer: 2
|
|
100
|
+
timeLimit: 14
|
|
101
|
+
- question: "What code smell does a function with 8 parameters and 50 lines typically have?"
|
|
102
|
+
options:
|
|
103
|
+
- "Magic numbers"
|
|
104
|
+
- "Dead code"
|
|
105
|
+
- "God function / too many responsibilities"
|
|
106
|
+
- "Unclear naming"
|
|
107
|
+
answer: 2
|
|
108
|
+
timeLimit: 15
|
|
109
|
+
- question: "A literal number 86400000 appears in code. What should you do?"
|
|
110
|
+
options:
|
|
111
|
+
- "Leave it as is — it's self-explanatory"
|
|
112
|
+
- "Replace with a named constant (e.g. MS_PER_DAY)"
|
|
113
|
+
- "Add a comment explaining it"
|
|
114
|
+
- "Move it to a config file only"
|
|
115
|
+
answer: 1
|
|
116
|
+
timeLimit: 16
|
|
117
|
+
- question: "Which is the better practice for a boolean parameter like sendNotification?"
|
|
118
|
+
options:
|
|
119
|
+
- "Keep the boolean — it's clear"
|
|
120
|
+
- "Split into two functions (e.g. send vs sendQuietly)"
|
|
121
|
+
- "Use 0 or 1 instead"
|
|
122
|
+
- "Add more boolean parameters for related options"
|
|
123
|
+
answer: 1
|
|
124
|
+
timeLimit: 15
|
|
125
|
+
- question: "You find code that runs after a return statement. What is it?"
|
|
126
|
+
options:
|
|
127
|
+
- "A feature for logging"
|
|
128
|
+
- "Dead code"
|
|
129
|
+
- "A fallback path"
|
|
130
|
+
- "Defensive programming"
|
|
131
|
+
answer: 1
|
|
132
|
+
timeLimit: 12
|
|
133
|
+
- question: "What should you refactor first when improving readability?"
|
|
134
|
+
options:
|
|
135
|
+
- "Add more comments"
|
|
136
|
+
- "Rename unclear variables and extract magic numbers"
|
|
137
|
+
- "Increase indentation for clarity"
|
|
138
|
+
- "Split the file into more files"
|
|
139
|
+
answer: 1
|
|
140
|
+
timeLimit: 16
|
|
141
|
+
- question: "A function has 4 levels of nested if statements. What's the main issue?"
|
|
142
|
+
options:
|
|
143
|
+
- "Too many parameters"
|
|
144
|
+
- "Deep nesting reduces readability — use guard clauses"
|
|
145
|
+
- "Missing type annotations"
|
|
146
|
+
- "Wrong programming language"
|
|
147
|
+
answer: 1
|
|
148
|
+
timeLimit: 15
|
|
149
|
+
- question: "Which name better describes a function that formats a price for display?"
|
|
150
|
+
options:
|
|
151
|
+
- "doIt"
|
|
152
|
+
- "format"
|
|
153
|
+
- "formatPriceForDisplay"
|
|
154
|
+
- "fn"
|
|
155
|
+
answer: 2
|
|
156
|
+
timeLimit: 14
|
|
157
|
+
- question: "Code has numbers 30, 60, 90 scattered throughout. What smell is this?"
|
|
158
|
+
options:
|
|
159
|
+
- "Dead code"
|
|
160
|
+
- "Magic numbers — extract to named constants"
|
|
161
|
+
- "Bad naming"
|
|
162
|
+
- "Long function"
|
|
163
|
+
answer: 1
|
|
164
|
+
timeLimit: 14
|
|
165
|
+
- question: "A 200-line function validates input, transforms data, calls 5 APIs, and formats output. What's wrong?"
|
|
166
|
+
options:
|
|
167
|
+
- "Nothing — monoliths are fine"
|
|
168
|
+
- "God function — does too many things; should be split"
|
|
169
|
+
- "Needs more comments"
|
|
170
|
+
- "Should use a different framework"
|
|
171
|
+
answer: 1
|
|
172
|
+
timeLimit: 16
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
slug: clean-code
|
|
2
|
+
title: "Clean Code — Naming, Functions, and Readability That Scales"
|
|
3
|
+
version: 1.0.0
|
|
4
|
+
description: "Write code that humans can read — naming, function design, and refactoring habits."
|
|
5
|
+
category: fundamentals
|
|
6
|
+
tags: [clean-code, readability, refactoring, naming, functions]
|
|
7
|
+
difficulty: beginner
|
|
8
|
+
|
|
9
|
+
xp:
|
|
10
|
+
read: 10
|
|
11
|
+
walkthrough: 30
|
|
12
|
+
exercise: 20
|
|
13
|
+
quiz: 15
|
|
14
|
+
quiz-perfect-bonus: 10
|
|
15
|
+
game: 20
|
|
16
|
+
game-perfect-bonus: 10
|
|
17
|
+
|
|
18
|
+
time:
|
|
19
|
+
quick: 5
|
|
20
|
+
read: 15
|
|
21
|
+
guided: 40
|
|
22
|
+
|
|
23
|
+
prerequisites: []
|
|
24
|
+
related: [solid-principles, code-review]
|
|
25
|
+
|
|
26
|
+
triggers:
|
|
27
|
+
- "How do I write clean code?"
|
|
28
|
+
- "What makes code readable?"
|
|
29
|
+
- "How should I name variables and functions?"
|
|
30
|
+
- "When should I refactor?"
|
|
31
|
+
|
|
32
|
+
visuals:
|
|
33
|
+
diagrams: [diagram-flow]
|
|
34
|
+
quiz-types: [quiz-fill-blank, quiz-timed-choice]
|
|
35
|
+
game-types: [bug-hunt, speed-round]
|
|
36
|
+
playground: javascript
|
|
37
|
+
|
|
38
|
+
sources:
|
|
39
|
+
- url: "https://martinfowler.com/books/refactoring.html"
|
|
40
|
+
label: "Refactoring by Martin Fowler"
|
|
41
|
+
type: docs
|
|
42
|
+
- url: "https://www.oreilly.com/library/view/clean-code-a/9780136083238/"
|
|
43
|
+
label: "Clean Code by Robert Martin"
|
|
44
|
+
type: docs
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Clean Code Quick Reference
|
|
2
|
+
|
|
3
|
+
## Naming
|
|
4
|
+
|
|
5
|
+
| Principle | Example |
|
|
6
|
+
|-----------|---------|
|
|
7
|
+
| Reveal intent | `secondsPerDay` not `d` |
|
|
8
|
+
| Avoid disinformation | `accounts` not `accountList` if not a List |
|
|
9
|
+
| Use pronounceable names | `generationTimestamp` not `genymdhms` |
|
|
10
|
+
| Use searchable names | `MAX_ITEMS` not `7` |
|
|
11
|
+
|
|
12
|
+
## Functions
|
|
13
|
+
|
|
14
|
+
| Guideline | Target |
|
|
15
|
+
|-----------|--------|
|
|
16
|
+
| Do one thing | One level of abstraction |
|
|
17
|
+
| Small | Fits on one screen |
|
|
18
|
+
| Few args | 0–2 ideal; 3+ use object |
|
|
19
|
+
| No side effects | Don't surprise callers |
|
|
20
|
+
|
|
21
|
+
## Refactoring Quick Wins
|
|
22
|
+
|
|
23
|
+
| Smell | Fix |
|
|
24
|
+
|-------|-----|
|
|
25
|
+
| Magic number | Named constant |
|
|
26
|
+
| Long function | Extract functions |
|
|
27
|
+
| Deep nesting | Early returns |
|
|
28
|
+
| Unclear name | Rename |
|
|
29
|
+
| Comment explaining what | Refactor code |
|
|
30
|
+
|
|
31
|
+
## Comments
|
|
32
|
+
|
|
33
|
+
| Good | Bad |
|
|
34
|
+
|------|-----|
|
|
35
|
+
| Why (business rule, workaround) | What (code already shows this) |
|
|
36
|
+
| Legal, compliance | Obvious logic |
|
|
37
|
+
| Non-obvious algorithm | Outdated info |
|
|
38
|
+
|
|
39
|
+
## DRY vs YAGNI
|
|
40
|
+
|
|
41
|
+
| DRY | YAGNI |
|
|
42
|
+
|-----|-------|
|
|
43
|
+
| Don't duplicate logic | Don't add speculative code |
|
|
44
|
+
| Extract on 3rd repetition | Build for today's needs |
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Clean Code Quiz
|
|
2
|
+
|
|
3
|
+
## Question 1
|
|
4
|
+
|
|
5
|
+
What is the primary benefit of intent-revealing names?
|
|
6
|
+
|
|
7
|
+
A) Shorter code
|
|
8
|
+
B) Less need for comments; code explains itself
|
|
9
|
+
C) Faster execution
|
|
10
|
+
D) Fewer bugs from the compiler
|
|
11
|
+
|
|
12
|
+
<!-- ANSWER: B -->
|
|
13
|
+
<!-- EXPLANATION: Good names make code self-documenting. A reader can understand what the code does without comments. This reduces cognitive load and maintenance cost. -->
|
|
14
|
+
|
|
15
|
+
## Question 2
|
|
16
|
+
|
|
17
|
+
When should you extract a block of code into a separate function?
|
|
18
|
+
|
|
19
|
+
A) Whenever a block is longer than 5 lines
|
|
20
|
+
B) When it represents a distinct abstraction or single logical task
|
|
21
|
+
C) Never — more functions mean more complexity
|
|
22
|
+
D) Only when you reuse it in two places
|
|
23
|
+
|
|
24
|
+
<!-- ANSWER: B -->
|
|
25
|
+
<!-- EXPLANATION: Extract when the block does one thing that can be named. Length alone isn't the criterion — a 20-line function that does one thing may be fine. Reuse is a bonus, not the only reason. -->
|
|
26
|
+
|
|
27
|
+
## Question 3
|
|
28
|
+
|
|
29
|
+
What does DRY stand for?
|
|
30
|
+
|
|
31
|
+
A) Don't Repeat Yourself
|
|
32
|
+
B) Do Recursive Yields
|
|
33
|
+
C) Dynamic Run Yields
|
|
34
|
+
D) Data Replication Yearly
|
|
35
|
+
|
|
36
|
+
<!-- ANSWER: A -->
|
|
37
|
+
<!-- EXPLANATION: DRY = Don't Repeat Yourself. The principle says every piece of knowledge should have a single representation. Duplication breeds inconsistency when one copy is updated and another isn't. -->
|
|
38
|
+
|
|
39
|
+
## Question 4
|
|
40
|
+
|
|
41
|
+
When is a comment preferable to self-documenting code?
|
|
42
|
+
|
|
43
|
+
A) Never — comments are always bad
|
|
44
|
+
B) When explaining *why* something is done, especially non-obvious business rules
|
|
45
|
+
C) When the code is complex
|
|
46
|
+
D) When the function is long
|
|
47
|
+
|
|
48
|
+
<!-- ANSWER: B -->
|
|
49
|
+
<!-- EXPLANATION: Good comments explain *why* — business rules, workarounds, legal requirements. Bad comments explain *what* — that's the code's job. If code can be clear, prefer refactoring over comments. -->
|
|
50
|
+
|
|
51
|
+
## Question 5
|
|
52
|
+
|
|
53
|
+
What is a "guard clause"?
|
|
54
|
+
|
|
55
|
+
A) A security check
|
|
56
|
+
B) An early return that handles invalid/edge cases before the main logic
|
|
57
|
+
C) A type check in TypeScript
|
|
58
|
+
D) A unit test
|
|
59
|
+
|
|
60
|
+
<!-- ANSWER: B -->
|
|
61
|
+
<!-- EXPLANATION: Guard clauses are early returns (e.g., if (!valid) return;) that handle edge cases first. They reduce nesting and make the happy path more prominent. -->
|
|
62
|
+
|
|
63
|
+
## Question 6
|
|
64
|
+
|
|
65
|
+
Which is a code smell indicating a function may do too much?
|
|
66
|
+
|
|
67
|
+
A) The function has 2 parameters
|
|
68
|
+
B) You need "and" to describe what it does
|
|
69
|
+
C) The function returns a value
|
|
70
|
+
D) The function uses a loop
|
|
71
|
+
|
|
72
|
+
<!-- ANSWER: B -->
|
|
73
|
+
<!-- EXPLANATION: If you can't describe the function without "and" (e.g., "validates and saves and sends email"), it likely has multiple responsibilities and should be split. -->
|
|
74
|
+
|
|
75
|
+
## Question 7
|
|
76
|
+
|
|
77
|
+
<!-- VISUAL: fill-blank -->
|
|
78
|
+
|
|
79
|
+
Complete the refactored function with a guard clause:
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
function processOrder(order) {
|
|
83
|
+
if (___0___) return null;
|
|
84
|
+
return calculateTotal(order.items);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
<!-- ANSWER: !order -->
|
|
89
|
+
<!-- EXPLANATION: A guard clause checks for invalid input early and returns. !order handles null or undefined; it's the inverse of a validity check. -->
|
|
90
|
+
|
|
91
|
+
## Question 8
|
|
92
|
+
|
|
93
|
+
<!-- VISUAL: fill-blank -->
|
|
94
|
+
|
|
95
|
+
Complete the intent-revealing name for a function that validates and formats a user's email:
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
function ___0___(email) {
|
|
99
|
+
if (!email || !email.includes('@')) return null;
|
|
100
|
+
return email.trim().toLowerCase();
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
<!-- ANSWER: validateAndFormatEmail -->
|
|
105
|
+
<!-- EXPLANATION: The function both validates (returns null if invalid) and formats (trim, lowercase). The name should reveal both intents. Alternatives like normalizeEmail are valid if they convey the same. -->
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Clean Code — Resources
|
|
2
|
+
|
|
3
|
+
## Videos
|
|
4
|
+
|
|
5
|
+
- [Clean Code — Uncle Bob](https://www.youtube.com/watch?v=7EmboKQH8Ul) — Key principles in lecture form.
|
|
6
|
+
- [Refactoring Code](https://www.youtube.com/watch?v=DC-pQPq0acs) — Web Dev Simplified. Practical refactoring examples.
|
|
7
|
+
- [Clean Code Tutorial](https://www.youtube.com/watch?v=UjhX2sVf0eg) — Fireship. Quick overview.
|
|
8
|
+
|
|
9
|
+
## Articles and Readings
|
|
10
|
+
|
|
11
|
+
- [Refactoring.com](https://refactoring.com/) — Martin Fowler. Catalog of refactorings.
|
|
12
|
+
- [Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html) — Conventions many teams follow.
|
|
13
|
+
- [Clean Code JavaScript](https://github.com/ryanmcdermott/clean-code-javascript) — GitHub repo. JS-specific clean code guidelines.
|
|
14
|
+
|
|
15
|
+
## Books
|
|
16
|
+
|
|
17
|
+
- **Clean Code** by Robert C. Martin — Foundational text on readable, maintainable code.
|
|
18
|
+
- **Refactoring** by Martin Fowler — Step-by-step refactoring patterns and smells.
|
|
19
|
+
|
|
20
|
+
## Tools
|
|
21
|
+
|
|
22
|
+
- [SonarQube](https://www.sonarsource.com/products/sonarqube/) — Static analysis for code quality.
|
|
23
|
+
- [ESLint](https://eslint.org/) — Linting with rules for consistency and common mistakes.
|
|
24
|
+
|
|
25
|
+
## Podcasts
|
|
26
|
+
|
|
27
|
+
- [Changelog — Clean Code Episodes](https://changelog.com/topic/code-quality) — Discussions on readability, maintainability, and team conventions.
|
|
28
|
+
- [Software Engineering Radio — Ep 463: Code Smells](https://www.se-radio.net/) — Technical analysis of when code needs refactoring.
|
|
29
|
+
- [Syntax.fm — Code Quality](https://syntax.fm/) — Wes Bos & Scott Tolinski on JS/web code practices.
|
|
30
|
+
|
|
31
|
+
## Interactive and Visual
|
|
32
|
+
|
|
33
|
+
- [Refactoring Guru — Code Smells](https://refactoring.guru/refactoring/smells) — Visual catalog of code smells with before/after refactoring examples.
|
|
34
|
+
- [JS Linter Playground](https://eslint.org/play/) — Try ESLint rules in the browser, see violations in real time.
|
|
35
|
+
- [Sourcery](https://sourcery.ai/) — AI-powered refactoring suggestions shown inline.
|
|
36
|
+
|
|
37
|
+
## Courses
|
|
38
|
+
|
|
39
|
+
- [Clean Code (Udemy — Robert Martin)](https://www.udemy.com/course/writing-clean-code/) — Video course from the author of Clean Code.
|
|
40
|
+
- [freeCodeCamp — JavaScript Best Practices](https://www.freecodecamp.org/news/tag/clean-code/) — Free articles and tutorials on writing clean JavaScript.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Clean Code Walkthrough — Learn by Doing
|
|
2
|
+
|
|
3
|
+
## Before We Begin
|
|
4
|
+
|
|
5
|
+
Clean code isn't about perfection—it's about code that others (and future-you) can read, change, and debug without unnecessary friction.
|
|
6
|
+
|
|
7
|
+
**Diagnostic question:** Recall a time you struggled to understand someone else's code (or your own from months ago). What made it hard? Was it names, structure, length, or something else?
|
|
8
|
+
|
|
9
|
+
**Checkpoint:** You can name at least one concrete frustration and guess what a "clean" version might have looked like.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Step 1: Improving Names
|
|
14
|
+
|
|
15
|
+
<!-- hint:code language="javascript" highlight="1,3" -->
|
|
16
|
+
<!-- hint:card type="concept" title="Intent-revealing names" -->
|
|
17
|
+
|
|
18
|
+
**Task:** Find a function or variable in your codebase (or use a sample) with an unclear name. Rename it to reveal intent. Before and after: what did the new name communicate that the old one didn't?
|
|
19
|
+
|
|
20
|
+
**Question:** How do you decide when a name is "good enough"? What would make you choose a longer vs shorter name?
|
|
21
|
+
|
|
22
|
+
**Checkpoint:** The user can articulate the difference between vague and intent-revealing names.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Step 2: Extracting a Function
|
|
27
|
+
|
|
28
|
+
**Task:** Take a block of code that does multiple things (e.g., validates input, transforms it, and saves it). Extract one logical piece into a separate function. Ensure the extracted function has a clear, single purpose.
|
|
29
|
+
|
|
30
|
+
**Question:** How did you decide where to make the cut? What would have been a bad extraction?
|
|
31
|
+
|
|
32
|
+
**Checkpoint:** The user has a smaller, focused function and can explain the extraction boundary.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Step 3: Reducing Parameters
|
|
37
|
+
|
|
38
|
+
**Task:** Find or write a function with 4+ parameters. Refactor it to accept a single object parameter. Update the call site.
|
|
39
|
+
|
|
40
|
+
**Question:** When would you keep separate parameters instead of an object? (Hint: think about 1–2 parameters with distinct roles.)
|
|
41
|
+
|
|
42
|
+
**Checkpoint:** The user understands when object parameters improve readability.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Step 4: Eliminating Magic Numbers
|
|
47
|
+
|
|
48
|
+
<!-- hint:card type="warning" title="Common mistake: over-naming obvious literals" -->
|
|
49
|
+
|
|
50
|
+
**Task:** Find numeric or string literals in code that represent business concepts (status codes, limits, timeouts). Replace them with named constants. Ensure the meaning is now obvious.
|
|
51
|
+
|
|
52
|
+
**Question:** Is every literal a "magic number"? When is `0` or `1` acceptable without a constant?
|
|
53
|
+
|
|
54
|
+
**Checkpoint:** The user has replaced at least 2–3 magic values with named constants.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Step 5: Simplifying Nesting
|
|
59
|
+
|
|
60
|
+
<!-- hint:buttons type="single" prompt="When nesting is deep, which approach do you prefer?" options="Early returns,Extract functions,Both depending on context" -->
|
|
61
|
+
|
|
62
|
+
**Task:** Take code with 3+ levels of nesting (if/else inside loops, etc.). Refactor using early returns or extracted functions to reduce nesting. Compare readability.
|
|
63
|
+
|
|
64
|
+
**Question:** What's the "guard clause" pattern? How does returning early simplify the rest of the function?
|
|
65
|
+
|
|
66
|
+
**Checkpoint:** The user can use early returns and reduced nesting effectively.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Step 6: Comments vs Code
|
|
71
|
+
|
|
72
|
+
**Task:** Find a comment that explains *what* the code does. Delete the comment and refactor the code so it's self-explanatory. If the comment explained *why*, keep it and ensure it's accurate.
|
|
73
|
+
|
|
74
|
+
**Question:** When is a comment the right choice instead of refactoring?
|
|
75
|
+
|
|
76
|
+
**Checkpoint:** The user distinguishes good vs bad comments and prefers self-documenting code when possible.
|
|
77
|
+
|
|
78
|
+
<!-- hint:celebrate -->
|