agentic-qe 1.9.4 → 2.1.0
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/.claude/agents/qe-api-contract-validator.md +95 -1336
- package/.claude/agents/qe-chaos-engineer.md +152 -1211
- package/.claude/agents/qe-code-complexity.md +144 -707
- package/.claude/agents/qe-coverage-analyzer.md +147 -743
- package/.claude/agents/qe-deployment-readiness.md +143 -1496
- package/.claude/agents/qe-flaky-test-hunter.md +132 -1529
- package/.claude/agents/qe-fleet-commander.md +12 -12
- package/.claude/agents/qe-performance-tester.md +150 -886
- package/.claude/agents/qe-production-intelligence.md +155 -1396
- package/.claude/agents/qe-quality-analyzer.md +6 -6
- package/.claude/agents/qe-quality-gate.md +151 -648
- package/.claude/agents/qe-regression-risk-analyzer.md +132 -1150
- package/.claude/agents/qe-requirements-validator.md +149 -932
- package/.claude/agents/qe-security-scanner.md +157 -797
- package/.claude/agents/qe-test-data-architect.md +96 -1365
- package/.claude/agents/qe-test-executor.md +8 -8
- package/.claude/agents/qe-test-generator.md +145 -1540
- package/.claude/agents/qe-visual-tester.md +153 -1257
- package/.claude/agents/qx-partner.md +248 -0
- package/.claude/agents/subagents/qe-code-reviewer.md +40 -136
- package/.claude/agents/subagents/qe-coverage-gap-analyzer.md +40 -480
- package/.claude/agents/subagents/qe-data-generator.md +41 -125
- package/.claude/agents/subagents/qe-flaky-investigator.md +55 -411
- package/.claude/agents/subagents/qe-integration-tester.md +53 -141
- package/.claude/agents/subagents/qe-performance-validator.md +54 -130
- package/.claude/agents/subagents/qe-security-auditor.md +56 -114
- package/.claude/agents/subagents/qe-test-data-architect-sub.md +57 -548
- package/.claude/agents/subagents/qe-test-implementer.md +58 -551
- package/.claude/agents/subagents/qe-test-refactorer.md +65 -722
- package/.claude/agents/subagents/qe-test-writer.md +63 -726
- package/.claude/skills/accessibility-testing/SKILL.md +144 -692
- package/.claude/skills/agentic-quality-engineering/SKILL.md +176 -529
- package/.claude/skills/api-testing-patterns/SKILL.md +180 -560
- package/.claude/skills/brutal-honesty-review/SKILL.md +113 -603
- package/.claude/skills/bug-reporting-excellence/SKILL.md +116 -517
- package/.claude/skills/chaos-engineering-resilience/SKILL.md +127 -72
- package/.claude/skills/cicd-pipeline-qe-orchestrator/SKILL.md +209 -404
- package/.claude/skills/code-review-quality/SKILL.md +158 -608
- package/.claude/skills/compatibility-testing/SKILL.md +148 -38
- package/.claude/skills/compliance-testing/SKILL.md +132 -63
- package/.claude/skills/consultancy-practices/SKILL.md +114 -446
- package/.claude/skills/context-driven-testing/SKILL.md +117 -381
- package/.claude/skills/contract-testing/SKILL.md +176 -141
- package/.claude/skills/database-testing/SKILL.md +137 -130
- package/.claude/skills/exploratory-testing-advanced/SKILL.md +160 -629
- package/.claude/skills/holistic-testing-pact/SKILL.md +140 -188
- package/.claude/skills/localization-testing/SKILL.md +145 -33
- package/.claude/skills/mobile-testing/SKILL.md +132 -448
- package/.claude/skills/mutation-testing/SKILL.md +147 -41
- package/.claude/skills/performance-testing/SKILL.md +200 -546
- package/.claude/skills/quality-metrics/SKILL.md +164 -519
- package/.claude/skills/refactoring-patterns/SKILL.md +132 -699
- package/.claude/skills/regression-testing/SKILL.md +120 -926
- package/.claude/skills/risk-based-testing/SKILL.md +157 -660
- package/.claude/skills/security-testing/SKILL.md +199 -538
- package/.claude/skills/sherlock-review/SKILL.md +163 -699
- package/.claude/skills/shift-left-testing/SKILL.md +161 -465
- package/.claude/skills/shift-right-testing/SKILL.md +161 -519
- package/.claude/skills/six-thinking-hats/SKILL.md +175 -1110
- package/.claude/skills/skills-manifest.json +683 -0
- package/.claude/skills/tdd-london-chicago/SKILL.md +131 -448
- package/.claude/skills/technical-writing/SKILL.md +103 -154
- package/.claude/skills/test-automation-strategy/SKILL.md +166 -772
- package/.claude/skills/test-data-management/SKILL.md +126 -910
- package/.claude/skills/test-design-techniques/SKILL.md +179 -89
- package/.claude/skills/test-environment-management/SKILL.md +136 -91
- package/.claude/skills/test-reporting-analytics/SKILL.md +169 -92
- package/.claude/skills/testability-scoring/README.md +71 -0
- package/.claude/skills/testability-scoring/SKILL.md +245 -0
- package/.claude/skills/testability-scoring/resources/templates/config.template.js +84 -0
- package/.claude/skills/testability-scoring/resources/templates/testability-scoring.spec.template.js +532 -0
- package/.claude/skills/testability-scoring/scripts/generate-html-report.js +1007 -0
- package/.claude/skills/testability-scoring/scripts/run-assessment.sh +70 -0
- package/.claude/skills/visual-testing-advanced/SKILL.md +155 -78
- package/.claude/skills/xp-practices/SKILL.md +151 -587
- package/CHANGELOG.md +110 -0
- package/README.md +55 -21
- package/dist/agents/QXPartnerAgent.d.ts +146 -0
- package/dist/agents/QXPartnerAgent.d.ts.map +1 -0
- package/dist/agents/QXPartnerAgent.js +1831 -0
- package/dist/agents/QXPartnerAgent.js.map +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +82 -2
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/lifecycle/AgentLifecycleManager.d.ts.map +1 -1
- package/dist/agents/lifecycle/AgentLifecycleManager.js +34 -31
- package/dist/agents/lifecycle/AgentLifecycleManager.js.map +1 -1
- package/dist/cli/commands/debug/agent.d.ts.map +1 -1
- package/dist/cli/commands/debug/agent.js +19 -6
- package/dist/cli/commands/debug/agent.js.map +1 -1
- package/dist/cli/commands/debug/health-check.js +20 -7
- package/dist/cli/commands/debug/health-check.js.map +1 -1
- package/dist/cli/commands/init-claude-md-template.d.ts +1 -0
- package/dist/cli/commands/init-claude-md-template.d.ts.map +1 -1
- package/dist/cli/commands/init-claude-md-template.js +18 -3
- package/dist/cli/commands/init-claude-md-template.js.map +1 -1
- package/dist/cli/commands/workflow/cancel.d.ts.map +1 -1
- package/dist/cli/commands/workflow/cancel.js +4 -3
- package/dist/cli/commands/workflow/cancel.js.map +1 -1
- package/dist/cli/commands/workflow/list.d.ts.map +1 -1
- package/dist/cli/commands/workflow/list.js +4 -3
- package/dist/cli/commands/workflow/list.js.map +1 -1
- package/dist/cli/commands/workflow/pause.d.ts.map +1 -1
- package/dist/cli/commands/workflow/pause.js +4 -3
- package/dist/cli/commands/workflow/pause.js.map +1 -1
- package/dist/cli/init/claude-config.d.ts.map +1 -1
- package/dist/cli/init/claude-config.js +3 -8
- package/dist/cli/init/claude-config.js.map +1 -1
- package/dist/cli/init/claude-md.d.ts.map +1 -1
- package/dist/cli/init/claude-md.js +44 -2
- package/dist/cli/init/claude-md.js.map +1 -1
- package/dist/cli/init/database-init.js +1 -1
- package/dist/cli/init/index.d.ts.map +1 -1
- package/dist/cli/init/index.js +13 -6
- package/dist/cli/init/index.js.map +1 -1
- package/dist/cli/init/skills.d.ts.map +1 -1
- package/dist/cli/init/skills.js +2 -1
- package/dist/cli/init/skills.js.map +1 -1
- package/dist/core/SwarmCoordinator.d.ts +180 -0
- package/dist/core/SwarmCoordinator.d.ts.map +1 -0
- package/dist/core/SwarmCoordinator.js +473 -0
- package/dist/core/SwarmCoordinator.js.map +1 -0
- package/dist/core/memory/AgentDBIntegration.d.ts +24 -6
- package/dist/core/memory/AgentDBIntegration.d.ts.map +1 -1
- package/dist/core/memory/AgentDBIntegration.js +66 -10
- package/dist/core/memory/AgentDBIntegration.js.map +1 -1
- package/dist/core/memory/UnifiedMemoryCoordinator.d.ts +341 -0
- package/dist/core/memory/UnifiedMemoryCoordinator.d.ts.map +1 -0
- package/dist/core/memory/UnifiedMemoryCoordinator.js +986 -0
- package/dist/core/memory/UnifiedMemoryCoordinator.js.map +1 -0
- package/dist/core/memory/index.d.ts +5 -0
- package/dist/core/memory/index.d.ts.map +1 -1
- package/dist/core/memory/index.js +23 -1
- package/dist/core/memory/index.js.map +1 -1
- package/dist/core/metrics/MetricsAggregator.d.ts +228 -0
- package/dist/core/metrics/MetricsAggregator.d.ts.map +1 -0
- package/dist/core/metrics/MetricsAggregator.js +482 -0
- package/dist/core/metrics/MetricsAggregator.js.map +1 -0
- package/dist/core/metrics/index.d.ts +5 -0
- package/dist/core/metrics/index.d.ts.map +1 -0
- package/dist/core/metrics/index.js +11 -0
- package/dist/core/metrics/index.js.map +1 -0
- package/dist/core/optimization/SwarmOptimizer.d.ts +190 -0
- package/dist/core/optimization/SwarmOptimizer.d.ts.map +1 -0
- package/dist/core/optimization/SwarmOptimizer.js +648 -0
- package/dist/core/optimization/SwarmOptimizer.js.map +1 -0
- package/dist/core/optimization/index.d.ts +9 -0
- package/dist/core/optimization/index.d.ts.map +1 -0
- package/dist/core/optimization/index.js +25 -0
- package/dist/core/optimization/index.js.map +1 -0
- package/dist/core/optimization/types.d.ts +53 -0
- package/dist/core/optimization/types.d.ts.map +1 -0
- package/dist/core/optimization/types.js +6 -0
- package/dist/core/optimization/types.js.map +1 -0
- package/dist/core/orchestration/AdaptiveScheduler.d.ts +190 -0
- package/dist/core/orchestration/AdaptiveScheduler.d.ts.map +1 -0
- package/dist/core/orchestration/AdaptiveScheduler.js +460 -0
- package/dist/core/orchestration/AdaptiveScheduler.js.map +1 -0
- package/dist/core/orchestration/PriorityQueue.d.ts +54 -0
- package/dist/core/orchestration/PriorityQueue.d.ts.map +1 -0
- package/dist/core/orchestration/PriorityQueue.js +122 -0
- package/dist/core/orchestration/PriorityQueue.js.map +1 -0
- package/dist/core/orchestration/WorkflowOrchestrator.d.ts +189 -0
- package/dist/core/orchestration/WorkflowOrchestrator.d.ts.map +1 -0
- package/dist/core/orchestration/WorkflowOrchestrator.js +845 -0
- package/dist/core/orchestration/WorkflowOrchestrator.js.map +1 -0
- package/dist/core/orchestration/index.d.ts +7 -0
- package/dist/core/orchestration/index.d.ts.map +1 -0
- package/dist/core/orchestration/index.js +11 -0
- package/dist/core/orchestration/index.js.map +1 -0
- package/dist/core/orchestration/types.d.ts +96 -0
- package/dist/core/orchestration/types.d.ts.map +1 -0
- package/dist/core/orchestration/types.js +6 -0
- package/dist/core/orchestration/types.js.map +1 -0
- package/dist/core/recovery/CircuitBreaker.d.ts +176 -0
- package/dist/core/recovery/CircuitBreaker.d.ts.map +1 -0
- package/dist/core/recovery/CircuitBreaker.js +382 -0
- package/dist/core/recovery/CircuitBreaker.js.map +1 -0
- package/dist/core/recovery/RecoveryOrchestrator.d.ts +186 -0
- package/dist/core/recovery/RecoveryOrchestrator.d.ts.map +1 -0
- package/dist/core/recovery/RecoveryOrchestrator.js +476 -0
- package/dist/core/recovery/RecoveryOrchestrator.js.map +1 -0
- package/dist/core/recovery/RetryStrategy.d.ts +127 -0
- package/dist/core/recovery/RetryStrategy.d.ts.map +1 -0
- package/dist/core/recovery/RetryStrategy.js +314 -0
- package/dist/core/recovery/RetryStrategy.js.map +1 -0
- package/dist/core/recovery/index.d.ts +8 -0
- package/dist/core/recovery/index.d.ts.map +1 -0
- package/dist/core/recovery/index.js +27 -0
- package/dist/core/recovery/index.js.map +1 -0
- package/dist/core/skills/DependencyResolver.d.ts +99 -0
- package/dist/core/skills/DependencyResolver.d.ts.map +1 -0
- package/dist/core/skills/DependencyResolver.js +260 -0
- package/dist/core/skills/DependencyResolver.js.map +1 -0
- package/dist/core/skills/DynamicSkillLoader.d.ts +96 -0
- package/dist/core/skills/DynamicSkillLoader.d.ts.map +1 -0
- package/dist/core/skills/DynamicSkillLoader.js +353 -0
- package/dist/core/skills/DynamicSkillLoader.js.map +1 -0
- package/dist/core/skills/ManifestGenerator.d.ts +114 -0
- package/dist/core/skills/ManifestGenerator.d.ts.map +1 -0
- package/dist/core/skills/ManifestGenerator.js +449 -0
- package/dist/core/skills/ManifestGenerator.js.map +1 -0
- package/dist/core/skills/index.d.ts +9 -0
- package/dist/core/skills/index.d.ts.map +1 -0
- package/dist/core/skills/index.js +24 -0
- package/dist/core/skills/index.js.map +1 -0
- package/dist/core/skills/types.d.ts +118 -0
- package/dist/core/skills/types.d.ts.map +1 -0
- package/dist/core/skills/types.js +7 -0
- package/dist/core/skills/types.js.map +1 -0
- package/dist/core/transport/QUICTransport.d.ts +320 -0
- package/dist/core/transport/QUICTransport.d.ts.map +1 -0
- package/dist/core/transport/QUICTransport.js +711 -0
- package/dist/core/transport/QUICTransport.js.map +1 -0
- package/dist/core/transport/index.d.ts +40 -0
- package/dist/core/transport/index.d.ts.map +1 -0
- package/dist/core/transport/index.js +46 -0
- package/dist/core/transport/index.js.map +1 -0
- package/dist/core/transport/quic-loader.d.ts +123 -0
- package/dist/core/transport/quic-loader.d.ts.map +1 -0
- package/dist/core/transport/quic-loader.js +293 -0
- package/dist/core/transport/quic-loader.js.map +1 -0
- package/dist/core/transport/quic.d.ts +154 -0
- package/dist/core/transport/quic.d.ts.map +1 -0
- package/dist/core/transport/quic.js +214 -0
- package/dist/core/transport/quic.js.map +1 -0
- package/dist/mcp/server.d.ts +9 -9
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +1 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/services/AgentRegistry.d.ts.map +1 -1
- package/dist/mcp/services/AgentRegistry.js +4 -1
- package/dist/mcp/services/AgentRegistry.js.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/qx.d.ts +429 -0
- package/dist/types/qx.d.ts.map +1 -0
- package/dist/types/qx.js +71 -0
- package/dist/types/qx.js.map +1 -0
- package/dist/visualization/api/RestEndpoints.js +2 -2
- package/dist/visualization/api/RestEndpoints.js.map +1 -1
- package/dist/visualization/api/WebSocketServer.d.ts +44 -0
- package/dist/visualization/api/WebSocketServer.d.ts.map +1 -1
- package/dist/visualization/api/WebSocketServer.js +144 -23
- package/dist/visualization/api/WebSocketServer.js.map +1 -1
- package/dist/visualization/core/DataTransformer.d.ts +10 -0
- package/dist/visualization/core/DataTransformer.d.ts.map +1 -1
- package/dist/visualization/core/DataTransformer.js +60 -5
- package/dist/visualization/core/DataTransformer.js.map +1 -1
- package/dist/visualization/emit-event.d.ts +75 -0
- package/dist/visualization/emit-event.d.ts.map +1 -0
- package/dist/visualization/emit-event.js +213 -0
- package/dist/visualization/emit-event.js.map +1 -0
- package/dist/visualization/index.d.ts +1 -0
- package/dist/visualization/index.d.ts.map +1 -1
- package/dist/visualization/index.js +7 -1
- package/dist/visualization/index.js.map +1 -1
- package/docs/reference/skills.md +63 -1
- package/package.json +16 -58
|
@@ -1,770 +1,203 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: refactoring-patterns
|
|
3
|
-
description: Apply safe refactoring patterns to improve code structure without changing behavior. Use when cleaning up code, reducing technical debt, or improving maintainability.
|
|
3
|
+
description: "Apply safe refactoring patterns to improve code structure without changing behavior. Use when cleaning up code, reducing technical debt, or improving maintainability."
|
|
4
|
+
category: development-practices
|
|
5
|
+
priority: medium
|
|
6
|
+
tokenEstimate: 1000
|
|
7
|
+
agents: [qe-code-reviewer, qe-quality-analyzer, qe-test-refactorer]
|
|
8
|
+
implementation_status: optimized
|
|
9
|
+
optimization_version: 1.0
|
|
10
|
+
last_optimized: 2025-12-03
|
|
11
|
+
dependencies: []
|
|
12
|
+
quick_reference_card: true
|
|
13
|
+
tags: [refactoring, code-quality, technical-debt, maintainability, clean-code]
|
|
4
14
|
---
|
|
5
15
|
|
|
6
16
|
# Refactoring Patterns
|
|
7
17
|
|
|
8
|
-
|
|
18
|
+
<default_to_action>
|
|
19
|
+
When refactoring:
|
|
20
|
+
1. ENSURE tests pass (never refactor without tests)
|
|
21
|
+
2. MAKE small change (one refactoring at a time)
|
|
22
|
+
3. RUN tests (must stay green)
|
|
23
|
+
4. COMMIT (save progress)
|
|
24
|
+
5. REPEAT
|
|
9
25
|
|
|
10
|
-
Refactoring
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
26
|
+
**Safe Refactoring Cycle:**
|
|
27
|
+
```bash
|
|
28
|
+
npm test # Green ✅
|
|
29
|
+
# Make ONE small change
|
|
30
|
+
npm test # Still green ✅
|
|
31
|
+
git commit -m "refactor: extract calculateTotal"
|
|
32
|
+
# Repeat
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Code Smells → Refactoring:**
|
|
36
|
+
| Smell | Refactoring |
|
|
37
|
+
|-------|-------------|
|
|
38
|
+
| Long method (>20 lines) | Extract Method |
|
|
39
|
+
| Large class | Extract Class |
|
|
40
|
+
| Long parameter list (>3) | Introduce Parameter Object |
|
|
41
|
+
| Duplicated code | Extract Method/Class |
|
|
42
|
+
| Complex conditional | Decompose Conditional |
|
|
43
|
+
| Magic numbers | Named Constants |
|
|
44
|
+
| Nested loops | Replace Loop with Pipeline |
|
|
45
|
+
|
|
46
|
+
**NEVER REFACTOR:**
|
|
47
|
+
- Without tests (write tests first)
|
|
48
|
+
- When deadline is tomorrow
|
|
49
|
+
- Code you don't understand
|
|
50
|
+
- Code that works and won't be touched
|
|
51
|
+
</default_to_action>
|
|
52
|
+
|
|
53
|
+
## Quick Reference Card
|
|
54
|
+
|
|
55
|
+
### Common Refactorings
|
|
56
|
+
|
|
57
|
+
| Pattern | Before | After |
|
|
58
|
+
|---------|--------|-------|
|
|
59
|
+
| **Extract Method** | 50-line function | 5 small functions |
|
|
60
|
+
| **Extract Class** | Class doing 5 things | 5 single-purpose classes |
|
|
61
|
+
| **Parameter Object** | `fn(a,b,c,d,e,f)` | `fn(options)` |
|
|
62
|
+
| **Replace Conditional** | `if (type === 'a') {...}` | Polymorphism |
|
|
63
|
+
| **Pipeline** | Nested loops | `.filter().map().reduce()` |
|
|
64
|
+
|
|
65
|
+
### The Rule of Three
|
|
66
|
+
|
|
67
|
+
1. First time → Just do it
|
|
68
|
+
2. Second time → Wince and duplicate
|
|
69
|
+
3. Third time → **Refactor**
|
|
41
70
|
|
|
42
|
-
|
|
71
|
+
---
|
|
43
72
|
|
|
44
|
-
|
|
73
|
+
## Key Patterns
|
|
45
74
|
|
|
46
|
-
|
|
75
|
+
### Extract Method
|
|
47
76
|
```javascript
|
|
77
|
+
// Before: Long method
|
|
48
78
|
function processOrder(order) {
|
|
49
|
-
//
|
|
50
|
-
if (!order.items || order.items.length === 0) {
|
|
51
|
-
throw new Error('Order has no items');
|
|
52
|
-
}
|
|
53
|
-
if (!order.customer || !order.customer.email) {
|
|
54
|
-
throw new Error('Invalid customer');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Calculate total
|
|
58
|
-
let subtotal = 0;
|
|
59
|
-
for (let item of order.items) {
|
|
60
|
-
subtotal += item.price * item.quantity;
|
|
61
|
-
}
|
|
62
|
-
let tax = subtotal * 0.10;
|
|
63
|
-
let total = subtotal + tax;
|
|
64
|
-
|
|
65
|
-
// Save order
|
|
66
|
-
const savedOrder = db.orders.create({
|
|
67
|
-
...order,
|
|
68
|
-
subtotal,
|
|
69
|
-
tax,
|
|
70
|
-
total,
|
|
71
|
-
status: 'pending'
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// Send email
|
|
75
|
-
emailService.send({
|
|
76
|
-
to: order.customer.email,
|
|
77
|
-
subject: 'Order Confirmation',
|
|
78
|
-
body: `Your order #${savedOrder.id} has been received.`
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
return savedOrder;
|
|
79
|
+
// 50 lines of validation, calculation, saving, emailing...
|
|
82
80
|
}
|
|
83
|
-
```
|
|
84
81
|
|
|
85
|
-
|
|
86
|
-
```javascript
|
|
82
|
+
// After: Clear responsibilities
|
|
87
83
|
function processOrder(order) {
|
|
88
84
|
validateOrder(order);
|
|
89
85
|
const pricing = calculatePricing(order);
|
|
90
|
-
const
|
|
91
|
-
sendConfirmationEmail(
|
|
92
|
-
return
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function validateOrder(order) {
|
|
96
|
-
if (!order.items || order.items.length === 0) {
|
|
97
|
-
throw new Error('Order has no items');
|
|
98
|
-
}
|
|
99
|
-
if (!order.customer || !order.customer.email) {
|
|
100
|
-
throw new Error('Invalid customer');
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function calculatePricing(order) {
|
|
105
|
-
const subtotal = order.items.reduce((sum, item) =>
|
|
106
|
-
sum + item.price * item.quantity, 0
|
|
107
|
-
);
|
|
108
|
-
const tax = subtotal * 0.10;
|
|
109
|
-
const total = subtotal + tax;
|
|
110
|
-
return { subtotal, tax, total };
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function saveOrder(order, pricing) {
|
|
114
|
-
return db.orders.create({
|
|
115
|
-
...order,
|
|
116
|
-
...pricing,
|
|
117
|
-
status: 'pending'
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function sendConfirmationEmail(email, orderId) {
|
|
122
|
-
emailService.send({
|
|
123
|
-
to: email,
|
|
124
|
-
subject: 'Order Confirmation',
|
|
125
|
-
body: `Your order #${orderId} has been received.`
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
**Benefits:**
|
|
131
|
-
- Each function has single responsibility
|
|
132
|
-
- Easy to test each part independently
|
|
133
|
-
- Clear what the code does at a glance
|
|
134
|
-
|
|
135
|
-
## Extract Class
|
|
136
|
-
|
|
137
|
-
**Problem:** Class doing too much
|
|
138
|
-
|
|
139
|
-
**Before:**
|
|
140
|
-
```javascript
|
|
141
|
-
class Order {
|
|
142
|
-
constructor(items, customer) {
|
|
143
|
-
this.items = items;
|
|
144
|
-
this.customer = customer;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
calculateSubtotal() {
|
|
148
|
-
return this.items.reduce((sum, item) =>
|
|
149
|
-
sum + item.price * item.quantity, 0
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
calculateTax() {
|
|
154
|
-
return this.calculateSubtotal() * 0.10;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
calculateTotal() {
|
|
158
|
-
return this.calculateSubtotal() + this.calculateTax();
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
sendConfirmationEmail() {
|
|
162
|
-
emailService.send({
|
|
163
|
-
to: this.customer.email,
|
|
164
|
-
subject: 'Order Confirmation',
|
|
165
|
-
body: `Your order has been received. Total: $${this.calculateTotal()}`
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
sendShippingNotification() {
|
|
170
|
-
emailService.send({
|
|
171
|
-
to: this.customer.email,
|
|
172
|
-
subject: 'Order Shipped',
|
|
173
|
-
body: `Your order has been shipped.`
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
**After:**
|
|
180
|
-
```javascript
|
|
181
|
-
class Order {
|
|
182
|
-
constructor(items, customer) {
|
|
183
|
-
this.items = items;
|
|
184
|
-
this.customer = customer;
|
|
185
|
-
this.pricing = new OrderPricing(items);
|
|
186
|
-
this.notifications = new OrderNotifications(customer.email);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
getTotal() {
|
|
190
|
-
return this.pricing.calculateTotal();
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
sendConfirmation() {
|
|
194
|
-
this.notifications.sendConfirmation(this.getTotal());
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
sendShippingNotification() {
|
|
198
|
-
this.notifications.sendShipping();
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
class OrderPricing {
|
|
203
|
-
constructor(items) {
|
|
204
|
-
this.items = items;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
calculateSubtotal() {
|
|
208
|
-
return this.items.reduce((sum, item) =>
|
|
209
|
-
sum + item.price * item.quantity, 0
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
calculateTax() {
|
|
214
|
-
return this.calculateSubtotal() * 0.10;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
calculateTotal() {
|
|
218
|
-
return this.calculateSubtotal() + this.calculateTax();
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
class OrderNotifications {
|
|
223
|
-
constructor(email) {
|
|
224
|
-
this.email = email;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
sendConfirmation(total) {
|
|
228
|
-
emailService.send({
|
|
229
|
-
to: this.email,
|
|
230
|
-
subject: 'Order Confirmation',
|
|
231
|
-
body: `Your order has been received. Total: $${total}`
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
sendShipping() {
|
|
236
|
-
emailService.send({
|
|
237
|
-
to: this.email,
|
|
238
|
-
subject: 'Order Shipped',
|
|
239
|
-
body: `Your order has been shipped.`
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
## Replace Conditional with Polymorphism
|
|
246
|
-
|
|
247
|
-
**Problem:** Complex conditionals based on type
|
|
248
|
-
|
|
249
|
-
**Before:**
|
|
250
|
-
```javascript
|
|
251
|
-
class PaymentProcessor {
|
|
252
|
-
processPayment(payment) {
|
|
253
|
-
if (payment.type === 'credit_card') {
|
|
254
|
-
return this.chargeCreditCard(
|
|
255
|
-
payment.cardNumber,
|
|
256
|
-
payment.amount
|
|
257
|
-
);
|
|
258
|
-
} else if (payment.type === 'paypal') {
|
|
259
|
-
return this.chargePayPal(
|
|
260
|
-
payment.paypalAccount,
|
|
261
|
-
payment.amount
|
|
262
|
-
);
|
|
263
|
-
} else if (payment.type === 'crypto') {
|
|
264
|
-
return this.chargeCrypto(
|
|
265
|
-
payment.walletAddress,
|
|
266
|
-
payment.amount
|
|
267
|
-
);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
**After:**
|
|
274
|
-
```javascript
|
|
275
|
-
class PaymentProcessor {
|
|
276
|
-
processPayment(paymentMethod) {
|
|
277
|
-
return paymentMethod.charge();
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
class CreditCardPayment {
|
|
282
|
-
constructor(cardNumber, amount) {
|
|
283
|
-
this.cardNumber = cardNumber;
|
|
284
|
-
this.amount = amount;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
charge() {
|
|
288
|
-
return gateway.chargeCreditCard(this.cardNumber, this.amount);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
class PayPalPayment {
|
|
293
|
-
constructor(account, amount) {
|
|
294
|
-
this.account = account;
|
|
295
|
-
this.amount = amount;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
charge() {
|
|
299
|
-
return gateway.chargePayPal(this.account, this.amount);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
class CryptoPayment {
|
|
304
|
-
constructor(walletAddress, amount) {
|
|
305
|
-
this.walletAddress = walletAddress;
|
|
306
|
-
this.amount = amount;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
charge() {
|
|
310
|
-
return gateway.chargeCrypto(this.walletAddress, this.amount);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
## Introduce Parameter Object
|
|
316
|
-
|
|
317
|
-
**Problem:** Functions with many parameters
|
|
318
|
-
|
|
319
|
-
**Before:**
|
|
320
|
-
```javascript
|
|
321
|
-
function createUser(
|
|
322
|
-
firstName,
|
|
323
|
-
lastName,
|
|
324
|
-
email,
|
|
325
|
-
phoneNumber,
|
|
326
|
-
address,
|
|
327
|
-
city,
|
|
328
|
-
state,
|
|
329
|
-
zipCode,
|
|
330
|
-
country
|
|
331
|
-
) {
|
|
332
|
-
// ...
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
createUser(
|
|
336
|
-
'John',
|
|
337
|
-
'Doe',
|
|
338
|
-
'john@example.com',
|
|
339
|
-
'555-1234',
|
|
340
|
-
'123 Main St',
|
|
341
|
-
'Springfield',
|
|
342
|
-
'IL',
|
|
343
|
-
'62701',
|
|
344
|
-
'USA'
|
|
345
|
-
);
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
**After:**
|
|
349
|
-
```javascript
|
|
350
|
-
class UserProfile {
|
|
351
|
-
constructor(firstName, lastName, contactInfo, address) {
|
|
352
|
-
this.firstName = firstName;
|
|
353
|
-
this.lastName = lastName;
|
|
354
|
-
this.contactInfo = contactInfo;
|
|
355
|
-
this.address = address;
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
class ContactInfo {
|
|
360
|
-
constructor(email, phoneNumber) {
|
|
361
|
-
this.email = email;
|
|
362
|
-
this.phoneNumber = phoneNumber;
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
class Address {
|
|
367
|
-
constructor(street, city, state, zipCode, country) {
|
|
368
|
-
this.street = street;
|
|
369
|
-
this.city = city;
|
|
370
|
-
this.state = state;
|
|
371
|
-
this.zipCode = zipCode;
|
|
372
|
-
this.country = country;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
function createUser(profile) {
|
|
377
|
-
// ...
|
|
86
|
+
const saved = saveOrder(order, pricing);
|
|
87
|
+
sendConfirmationEmail(saved);
|
|
88
|
+
return saved;
|
|
378
89
|
}
|
|
379
|
-
|
|
380
|
-
createUser(new UserProfile(
|
|
381
|
-
'John',
|
|
382
|
-
'Doe',
|
|
383
|
-
new ContactInfo('john@example.com', '555-1234'),
|
|
384
|
-
new Address('123 Main St', 'Springfield', 'IL', '62701', 'USA')
|
|
385
|
-
));
|
|
386
90
|
```
|
|
387
91
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
**Before:**
|
|
92
|
+
### Replace Loop with Pipeline
|
|
391
93
|
```javascript
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
} else if (customerType === 3) {
|
|
398
|
-
return price * 0.30;
|
|
94
|
+
// Before
|
|
95
|
+
let results = [];
|
|
96
|
+
for (let item of items) {
|
|
97
|
+
if (item.inStock) {
|
|
98
|
+
results.push(item.name.toUpperCase());
|
|
399
99
|
}
|
|
400
|
-
return 0;
|
|
401
100
|
}
|
|
402
|
-
```
|
|
403
101
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
PREMIUM: 2,
|
|
409
|
-
VIP: 3
|
|
410
|
-
};
|
|
411
|
-
|
|
412
|
-
const DiscountRate = {
|
|
413
|
-
[CustomerType.STANDARD]: 0.10,
|
|
414
|
-
[CustomerType.PREMIUM]: 0.20,
|
|
415
|
-
[CustomerType.VIP]: 0.30
|
|
416
|
-
};
|
|
417
|
-
|
|
418
|
-
function calculateDiscount(price, customerType) {
|
|
419
|
-
const rate = DiscountRate[customerType] || 0;
|
|
420
|
-
return price * rate;
|
|
421
|
-
}
|
|
102
|
+
// After
|
|
103
|
+
const results = items
|
|
104
|
+
.filter(item => item.inStock)
|
|
105
|
+
.map(item => item.name.toUpperCase());
|
|
422
106
|
```
|
|
423
107
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
**Problem:** Complex conditional logic
|
|
427
|
-
|
|
428
|
-
**Before:**
|
|
108
|
+
### Decompose Conditional
|
|
429
109
|
```javascript
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
order.shippingMethod === 'express' &&
|
|
434
|
-
order.items.every(item => item.inStock)
|
|
435
|
-
) {
|
|
436
|
-
return 'ELIGIBLE_FOR_FREE_SHIPPING';
|
|
437
|
-
}
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
**After:**
|
|
441
|
-
```javascript
|
|
442
|
-
function isEligibleForFreeShipping(order) {
|
|
443
|
-
return (
|
|
444
|
-
isLargeOrder(order) &&
|
|
445
|
-
isPremiumCustomer(order) &&
|
|
446
|
-
isExpressShipping(order) &&
|
|
447
|
-
allItemsInStock(order)
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
function isLargeOrder(order) {
|
|
452
|
-
return order.total > 1000;
|
|
110
|
+
// Before
|
|
111
|
+
if (order.total > 1000 && customer.isPremium && allInStock(order)) {
|
|
112
|
+
return 'FREE_SHIPPING';
|
|
453
113
|
}
|
|
454
114
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
return order.shippingMethod === 'express';
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
function allItemsInStock(order) {
|
|
464
|
-
return order.items.every(item => item.inStock);
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
if (isEligibleForFreeShipping(order)) {
|
|
468
|
-
return 'ELIGIBLE_FOR_FREE_SHIPPING';
|
|
115
|
+
// After
|
|
116
|
+
function isEligibleForFreeShipping(order, customer) {
|
|
117
|
+
return isLargeOrder(order) &&
|
|
118
|
+
isPremiumCustomer(customer) &&
|
|
119
|
+
allInStock(order);
|
|
469
120
|
}
|
|
470
121
|
```
|
|
471
122
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
**Before:**
|
|
475
|
-
```javascript
|
|
476
|
-
function getTopExpensiveProducts(products) {
|
|
477
|
-
let inStock = [];
|
|
478
|
-
for (let product of products) {
|
|
479
|
-
if (product.inStock) {
|
|
480
|
-
inStock.push(product);
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
inStock.sort((a, b) => b.price - a.price);
|
|
485
|
-
|
|
486
|
-
let top5 = [];
|
|
487
|
-
for (let i = 0; i < 5 && i < inStock.length; i++) {
|
|
488
|
-
top5.push(inStock[i]);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
let names = [];
|
|
492
|
-
for (let product of top5) {
|
|
493
|
-
names.push(product.name);
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
return names;
|
|
497
|
-
}
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
**After:**
|
|
501
|
-
```javascript
|
|
502
|
-
function getTopExpensiveProducts(products) {
|
|
503
|
-
return products
|
|
504
|
-
.filter(p => p.inStock)
|
|
505
|
-
.sort((a, b) => b.price - a.price)
|
|
506
|
-
.slice(0, 5)
|
|
507
|
-
.map(p => p.name);
|
|
508
|
-
}
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
## Remove Duplication
|
|
512
|
-
|
|
513
|
-
**Before:**
|
|
514
|
-
```javascript
|
|
515
|
-
function processOnlineOrder(order) {
|
|
516
|
-
validateOrder(order);
|
|
517
|
-
const total = calculateTotal(order);
|
|
518
|
-
const savedOrder = saveOrder(order, total);
|
|
519
|
-
sendEmail(order.customer.email, savedOrder.id);
|
|
520
|
-
logActivity('Order processed', savedOrder.id);
|
|
521
|
-
return savedOrder;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
function processPhoneOrder(order) {
|
|
525
|
-
validateOrder(order);
|
|
526
|
-
const total = calculateTotal(order);
|
|
527
|
-
const savedOrder = saveOrder(order, total);
|
|
528
|
-
sendEmail(order.customer.email, savedOrder.id);
|
|
529
|
-
logActivity('Phone order processed', savedOrder.id);
|
|
530
|
-
return savedOrder;
|
|
531
|
-
}
|
|
532
|
-
```
|
|
533
|
-
|
|
534
|
-
**After:**
|
|
535
|
-
```javascript
|
|
536
|
-
function processOrder(order, source) {
|
|
537
|
-
validateOrder(order);
|
|
538
|
-
const total = calculateTotal(order);
|
|
539
|
-
const savedOrder = saveOrder(order, total);
|
|
540
|
-
sendEmail(order.customer.email, savedOrder.id);
|
|
541
|
-
logActivity(`${source} order processed`, savedOrder.id);
|
|
542
|
-
return savedOrder;
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
function processOnlineOrder(order) {
|
|
546
|
-
return processOrder(order, 'Online');
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
function processPhoneOrder(order) {
|
|
550
|
-
return processOrder(order, 'Phone');
|
|
551
|
-
}
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
## Refactoring Smells (When to Refactor)
|
|
555
|
-
|
|
556
|
-
### Long Method
|
|
557
|
-
**Smell:** Method has too many lines (>20-30)
|
|
558
|
-
**Refactor:** Extract Method
|
|
559
|
-
|
|
560
|
-
### Large Class
|
|
561
|
-
**Smell:** Class has too many responsibilities
|
|
562
|
-
**Refactor:** Extract Class
|
|
563
|
-
|
|
564
|
-
### Long Parameter List
|
|
565
|
-
**Smell:** Function has >3-4 parameters
|
|
566
|
-
**Refactor:** Introduce Parameter Object
|
|
567
|
-
|
|
568
|
-
### Duplicated Code
|
|
569
|
-
**Smell:** Same code in multiple places
|
|
570
|
-
**Refactor:** Extract Method/Class
|
|
571
|
-
|
|
572
|
-
### Dead Code
|
|
573
|
-
**Smell:** Unused code
|
|
574
|
-
**Refactor:** Delete it
|
|
575
|
-
|
|
576
|
-
### Comments Explaining What Code Does
|
|
577
|
-
**Smell:** Comment saying "This calculates discount"
|
|
578
|
-
**Refactor:** Extract method named `calculateDiscount()`
|
|
579
|
-
|
|
580
|
-
### Magic Numbers
|
|
581
|
-
**Smell:** Unexplained constants (42, 0.10, 1000)
|
|
582
|
-
**Refactor:** Named Constants
|
|
583
|
-
|
|
584
|
-
### Nested Conditionals
|
|
585
|
-
**Smell:** If inside if inside if
|
|
586
|
-
**Refactor:** Extract methods, early returns, guard clauses
|
|
587
|
-
|
|
588
|
-
## Safe Refactoring Workflow
|
|
589
|
-
|
|
590
|
-
### Step 1: Ensure Tests Pass
|
|
591
|
-
```bash
|
|
592
|
-
npm test
|
|
593
|
-
# All tests green ✅
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
### Step 2: Make Small Change
|
|
597
|
-
```javascript
|
|
598
|
-
// Extract one small method
|
|
599
|
-
function calculateSubtotal(items) {
|
|
600
|
-
return items.reduce((sum, item) =>
|
|
601
|
-
sum + item.price * item.quantity, 0
|
|
602
|
-
);
|
|
603
|
-
}
|
|
604
|
-
```
|
|
605
|
-
|
|
606
|
-
### Step 3: Run Tests Again
|
|
607
|
-
```bash
|
|
608
|
-
npm test
|
|
609
|
-
# Still green ✅
|
|
610
|
-
```
|
|
611
|
-
|
|
612
|
-
### Step 4: Commit
|
|
613
|
-
```bash
|
|
614
|
-
git add .
|
|
615
|
-
git commit -m "refactor: extract calculateSubtotal method"
|
|
616
|
-
```
|
|
617
|
-
|
|
618
|
-
### Step 5: Repeat
|
|
619
|
-
Next small refactoring...
|
|
620
|
-
|
|
621
|
-
## IDE Refactoring Tools
|
|
622
|
-
|
|
623
|
-
### Automated Refactorings (Safe)
|
|
624
|
-
- **Rename** - Change variable/function/class name everywhere
|
|
625
|
-
- **Extract Method** - Pull code into new function
|
|
626
|
-
- **Extract Variable** - Give expression a name
|
|
627
|
-
- **Inline** - Remove unnecessary abstraction
|
|
628
|
-
- **Move** - Relocate code to better place
|
|
629
|
-
|
|
630
|
-
### Use These!
|
|
631
|
-
Modern IDEs (VS Code, IntelliJ, WebStorm) do these safely with guaranteed correctness.
|
|
123
|
+
---
|
|
632
124
|
|
|
633
125
|
## Refactoring Anti-Patterns
|
|
634
126
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
127
|
+
| ❌ Anti-Pattern | Problem | ✅ Better |
|
|
128
|
+
|-----------------|---------|-----------|
|
|
129
|
+
| Without tests | No safety net | Write tests first |
|
|
130
|
+
| Big bang | Rewrite everything | Small incremental steps |
|
|
131
|
+
| For perfection | Endless tweaking | Good enough, move on |
|
|
132
|
+
| Premature abstraction | Pattern not clear yet | Wait for Rule of Three |
|
|
133
|
+
| During feature work | Mixed changes | Separate commits |
|
|
638
134
|
|
|
639
|
-
|
|
640
|
-
**Problem:** Rewrite everything at once
|
|
641
|
-
**Solution:** Incremental refactoring, small steps
|
|
642
|
-
|
|
643
|
-
### ❌ Refactoring for Perfection
|
|
644
|
-
**Problem:** Endless tweaking
|
|
645
|
-
**Solution:** Good enough is good enough. Move on.
|
|
646
|
-
|
|
647
|
-
### ❌ Premature Abstraction
|
|
648
|
-
**Problem:** Creating abstractions before patterns clear
|
|
649
|
-
**Solution:** Wait for duplication, then extract
|
|
650
|
-
|
|
651
|
-
### ❌ Refactoring During Feature Work
|
|
652
|
-
**Problem:** Mixing refactoring with new features
|
|
653
|
-
**Solution:** Separate commits: refactor first, then feature
|
|
654
|
-
|
|
655
|
-
## Boy Scout Rule
|
|
656
|
-
|
|
657
|
-
**"Leave the code better than you found it."**
|
|
658
|
-
|
|
659
|
-
Every time you touch code:
|
|
660
|
-
1. Make it slightly better
|
|
661
|
-
2. Don't need to make it perfect
|
|
662
|
-
3. Small improvements accumulate
|
|
663
|
-
|
|
664
|
-
**Example:**
|
|
665
|
-
```javascript
|
|
666
|
-
// Found this
|
|
667
|
-
function calc(a,b,c){return a*b+c;}
|
|
668
|
-
|
|
669
|
-
// Left it as this
|
|
670
|
-
function calculateTotal(price, quantity, tax) {
|
|
671
|
-
return price * quantity + tax;
|
|
672
|
-
}
|
|
673
|
-
```
|
|
674
|
-
|
|
675
|
-
## Using with QE Agents
|
|
135
|
+
---
|
|
676
136
|
|
|
677
|
-
|
|
137
|
+
## Agent Integration
|
|
678
138
|
|
|
679
|
-
**qe-quality-analyzer** identifies refactoring opportunities:
|
|
680
139
|
```typescript
|
|
681
|
-
//
|
|
682
|
-
const
|
|
683
|
-
|
|
684
|
-
patterns: [
|
|
685
|
-
|
|
686
|
-
'large-class',
|
|
687
|
-
'duplicate-code',
|
|
688
|
-
'feature-envy',
|
|
689
|
-
'data-clumps'
|
|
690
|
-
]
|
|
691
|
-
});
|
|
140
|
+
// Detect code smells
|
|
141
|
+
const smells = await Task("Detect Code Smells", {
|
|
142
|
+
source: 'src/services/',
|
|
143
|
+
patterns: ['long-method', 'large-class', 'duplicate-code']
|
|
144
|
+
}, "qe-quality-analyzer");
|
|
692
145
|
|
|
693
|
-
//
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
});
|
|
146
|
+
// Safe refactoring with test verification
|
|
147
|
+
await Task("Verify Refactoring", {
|
|
148
|
+
beforeCommit: 'abc123',
|
|
149
|
+
afterCommit: 'def456',
|
|
150
|
+
expectSameBehavior: true
|
|
151
|
+
}, "qe-test-executor");
|
|
699
152
|
```
|
|
700
153
|
|
|
701
|
-
|
|
154
|
+
---
|
|
702
155
|
|
|
703
|
-
|
|
704
|
-
// Agent validates refactoring didn't break behavior
|
|
705
|
-
const before = await git.getCurrentCommit();
|
|
706
|
-
await human.performRefactoring();
|
|
707
|
-
const after = await git.getCurrentCommit();
|
|
708
|
-
|
|
709
|
-
const validation = await qe-test-executor.verifyRefactoring({
|
|
710
|
-
beforeCommit: before,
|
|
711
|
-
afterCommit: after,
|
|
712
|
-
expectSameBehavior: true,
|
|
713
|
-
runFullSuite: true
|
|
714
|
-
});
|
|
156
|
+
## Agent Coordination Hints
|
|
715
157
|
|
|
716
|
-
|
|
158
|
+
### Memory Namespace
|
|
159
|
+
```
|
|
160
|
+
aqe/refactoring/
|
|
161
|
+
├── smells/* - Detected code smells
|
|
162
|
+
├── suggestions/* - Refactoring recommendations
|
|
163
|
+
├── verifications/* - Behavior preservation checks
|
|
164
|
+
└── history/* - Refactoring log
|
|
717
165
|
```
|
|
718
166
|
|
|
719
|
-
### Fleet Coordination
|
|
720
|
-
|
|
167
|
+
### Fleet Coordination
|
|
721
168
|
```typescript
|
|
722
|
-
// Multiple agents coordinate on large refactoring
|
|
723
169
|
const refactoringFleet = await FleetManager.coordinate({
|
|
724
170
|
strategy: 'refactoring',
|
|
725
171
|
agents: [
|
|
726
|
-
'qe-quality-analyzer',
|
|
727
|
-
'qe-test-generator',
|
|
728
|
-
'qe-test-executor',
|
|
729
|
-
'qe-
|
|
172
|
+
'qe-quality-analyzer', // Identify targets
|
|
173
|
+
'qe-test-generator', // Add safety tests
|
|
174
|
+
'qe-test-executor', // Verify behavior
|
|
175
|
+
'qe-test-refactorer' // TDD refactor phase
|
|
730
176
|
],
|
|
731
177
|
topology: 'sequential'
|
|
732
178
|
});
|
|
733
|
-
|
|
734
|
-
await refactoringFleet.execute({
|
|
735
|
-
target: 'src/services/OrderService.ts',
|
|
736
|
-
refactoringType: 'extract-class'
|
|
737
|
-
});
|
|
738
179
|
```
|
|
739
180
|
|
|
740
181
|
---
|
|
741
182
|
|
|
742
183
|
## Related Skills
|
|
743
|
-
|
|
744
|
-
**Core Quality:**
|
|
745
|
-
- [agentic-quality-engineering](../agentic-quality-engineering/) - Agent-driven refactoring workflows
|
|
746
|
-
|
|
747
|
-
**Development:**
|
|
748
|
-
- [tdd-london-chicago](../tdd-london-chicago/) - Test coverage during refactoring
|
|
184
|
+
- [tdd-london-chicago](../tdd-london-chicago/) - TDD refactor phase
|
|
749
185
|
- [code-review-quality](../code-review-quality/) - Review refactored code
|
|
750
|
-
- [xp-practices](../xp-practices/) - Collective
|
|
751
|
-
|
|
752
|
-
**Testing:**
|
|
753
|
-
- [test-automation-strategy](../test-automation-strategy/) - Maintain test suite during refactoring
|
|
186
|
+
- [xp-practices](../xp-practices/) - Collective ownership
|
|
754
187
|
|
|
755
188
|
---
|
|
756
189
|
|
|
757
190
|
## Remember
|
|
758
191
|
|
|
759
|
-
Refactoring is
|
|
192
|
+
**Refactoring is NOT:**
|
|
760
193
|
- Adding features
|
|
761
194
|
- Fixing bugs
|
|
762
|
-
-
|
|
195
|
+
- Performance optimization
|
|
763
196
|
- Rewriting from scratch
|
|
764
197
|
|
|
765
|
-
Refactoring
|
|
766
|
-
- Improving
|
|
767
|
-
- Making code
|
|
198
|
+
**Refactoring IS:**
|
|
199
|
+
- Improving structure
|
|
200
|
+
- Making code clearer
|
|
768
201
|
- Reducing complexity
|
|
769
202
|
- Removing duplication
|
|
770
203
|
- **Without changing behavior**
|