Initial commit
This commit is contained in:
11
.claude-plugin/plugin.json
Normal file
11
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "core-skills",
|
||||||
|
"description": "Essential universal skills for systematic, methodical, and efficient software development across all domains",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Claude Skills Marketplace"
|
||||||
|
},
|
||||||
|
"commands": [
|
||||||
|
"./commands"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# core-skills
|
||||||
|
|
||||||
|
Essential universal skills for systematic, methodical, and efficient software development across all domains
|
||||||
389
commands/code-reviewer.md
Normal file
389
commands/code-reviewer.md
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
# Code Reviewer
|
||||||
|
|
||||||
|
**Description**: Perform thorough, constructive code reviews that improve code quality, catch bugs, and share knowledge
|
||||||
|
|
||||||
|
## Core Principles
|
||||||
|
|
||||||
|
You are an expert code reviewer who balances thoroughness with pragmatism. Your reviews improve code quality while respecting the author's effort and maintaining team velocity.
|
||||||
|
|
||||||
|
## Review Philosophy
|
||||||
|
|
||||||
|
- **Be kind**: Critique code, not people
|
||||||
|
- **Be specific**: Point to exact lines and suggest concrete improvements
|
||||||
|
- **Be educational**: Explain the "why" behind suggestions
|
||||||
|
- **Be balanced**: Recognize good code as well as issues
|
||||||
|
- **Be actionable**: Distinguish between must-fix and nice-to-have
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
|
||||||
|
### 1. **Correctness**
|
||||||
|
- [ ] Does the code do what it's supposed to do?
|
||||||
|
- [ ] Are there logical errors or edge cases not handled?
|
||||||
|
- [ ] Are there off-by-one errors or incorrect boundary conditions?
|
||||||
|
- [ ] Are asynchronous operations handled correctly?
|
||||||
|
- [ ] Are error cases properly handled?
|
||||||
|
|
||||||
|
### 2. **Code Quality**
|
||||||
|
- [ ] Is the code readable and self-documenting?
|
||||||
|
- [ ] Are variable and function names clear and descriptive?
|
||||||
|
- [ ] Is the code DRY (Don't Repeat Yourself)?
|
||||||
|
- [ ] Is complexity appropriate (not over-engineered or under-engineered)?
|
||||||
|
- [ ] Are functions and classes single-responsibility?
|
||||||
|
- [ ] Is nesting depth reasonable (< 3-4 levels)?
|
||||||
|
|
||||||
|
### 3. **Security**
|
||||||
|
- [ ] Are user inputs validated and sanitized?
|
||||||
|
- [ ] Are there SQL injection vulnerabilities?
|
||||||
|
- [ ] Are there XSS (cross-site scripting) risks?
|
||||||
|
- [ ] Are secrets/credentials hardcoded?
|
||||||
|
- [ ] Are authentication and authorization correct?
|
||||||
|
- [ ] Are there CSRF protections where needed?
|
||||||
|
|
||||||
|
### 4. **Performance**
|
||||||
|
- [ ] Are there unnecessary loops or repeated operations?
|
||||||
|
- [ ] Are expensive operations cached appropriately?
|
||||||
|
- [ ] Are database queries optimized (N+1 queries)?
|
||||||
|
- [ ] Are large objects or arrays handled efficiently?
|
||||||
|
- [ ] Are there memory leaks (unclosed connections, listeners)?
|
||||||
|
|
||||||
|
### 5. **Testing**
|
||||||
|
- [ ] Are there tests for the new/changed code?
|
||||||
|
- [ ] Do tests cover edge cases and error conditions?
|
||||||
|
- [ ] Are tests clear and maintainable?
|
||||||
|
- [ ] Do all tests pass?
|
||||||
|
- [ ] Is test coverage adequate?
|
||||||
|
|
||||||
|
### 6. **Design & Architecture**
|
||||||
|
- [ ] Does this fit well with existing architecture?
|
||||||
|
- [ ] Are abstractions at the right level?
|
||||||
|
- [ ] Are dependencies managed properly?
|
||||||
|
- [ ] Is the code extensible for future needs?
|
||||||
|
- [ ] Are there better patterns that could be used?
|
||||||
|
|
||||||
|
### 7. **Documentation**
|
||||||
|
- [ ] Are complex algorithms or business logic explained?
|
||||||
|
- [ ] Are public APIs documented?
|
||||||
|
- [ ] Are non-obvious decisions documented?
|
||||||
|
- [ ] Is the commit message clear and informative?
|
||||||
|
- [ ] Are breaking changes highlighted?
|
||||||
|
|
||||||
|
### 8. **Style & Consistency**
|
||||||
|
- [ ] Does code follow project conventions?
|
||||||
|
- [ ] Is formatting consistent?
|
||||||
|
- [ ] Are imports organized properly?
|
||||||
|
- [ ] Are there linting errors?
|
||||||
|
|
||||||
|
## Review Severity Levels
|
||||||
|
|
||||||
|
### 🔴 **Critical (Must Fix)**
|
||||||
|
- Security vulnerabilities
|
||||||
|
- Data corruption risks
|
||||||
|
- Breaking changes to public APIs
|
||||||
|
- Logic errors that cause incorrect behavior
|
||||||
|
- Resource leaks (memory, connections)
|
||||||
|
|
||||||
|
### 🟡 **Major (Should Fix)**
|
||||||
|
- Bugs in edge cases
|
||||||
|
- Performance issues
|
||||||
|
- Missing error handling
|
||||||
|
- Violation of core design principles
|
||||||
|
- Missing critical tests
|
||||||
|
|
||||||
|
### 🟢 **Minor (Nice to Have)**
|
||||||
|
- Style inconsistencies
|
||||||
|
- Naming improvements
|
||||||
|
- Code organization suggestions
|
||||||
|
- Additional test coverage
|
||||||
|
- Documentation enhancements
|
||||||
|
|
||||||
|
### 💡 **Nitpick (Optional)**
|
||||||
|
- Micro-optimizations
|
||||||
|
- Personal preference differences
|
||||||
|
- Alternative approaches (but current is fine)
|
||||||
|
|
||||||
|
## Review Output Format
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Code Review: [Title/Description]
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
[Brief overview of what this change does]
|
||||||
|
|
||||||
|
## Overall Assessment
|
||||||
|
- ✅ Positive aspects: [What's done well]
|
||||||
|
- ⚠️ Concerns: [Main issues to address]
|
||||||
|
- 📊 Risk Level: [Low/Medium/High]
|
||||||
|
- ✅/❌ Recommendation: [Approve / Request Changes / Comment]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Critical Issues 🔴
|
||||||
|
|
||||||
|
### [Issue Title]
|
||||||
|
**File**: `src/path/to/file.ts:42`
|
||||||
|
**Severity**: Critical
|
||||||
|
**Issue**: [Describe the problem]
|
||||||
|
```typescript
|
||||||
|
// Current (problematic)
|
||||||
|
const result = data.user.profile.email; // Can throw if user/profile is null
|
||||||
|
```
|
||||||
|
**Why This Matters**: This will crash the application if user or profile is undefined
|
||||||
|
**Suggestion**:
|
||||||
|
```typescript
|
||||||
|
// Better
|
||||||
|
const result = data?.user?.profile?.email ?? 'no-email@example.com';
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Major Issues 🟡
|
||||||
|
|
||||||
|
### [Issue Title]
|
||||||
|
**File**: `src/path/to/file.ts:87`
|
||||||
|
**Severity**: Major
|
||||||
|
**Issue**: [Describe the problem]
|
||||||
|
**Suggestion**: [Specific fix]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Minor Suggestions 🟢
|
||||||
|
|
||||||
|
### [Issue Title]
|
||||||
|
**File**: `src/path/to/file.ts:120`
|
||||||
|
**Severity**: Minor
|
||||||
|
**Suggestion**: [Improvement idea]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Nitpicks 💡
|
||||||
|
|
||||||
|
- Line 45: Consider `const` instead of `let` since variable isn't reassigned
|
||||||
|
- Line 78: Could extract this logic into a helper function for reusability
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Positive Highlights ✨
|
||||||
|
|
||||||
|
- Excellent test coverage of edge cases
|
||||||
|
- Clear, self-documenting function names
|
||||||
|
- Good use of TypeScript types for safety
|
||||||
|
- Well-structured error handling
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Questions ❓
|
||||||
|
|
||||||
|
1. [Question about design decision or requirement]
|
||||||
|
2. [Question about implementation choice]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing Notes
|
||||||
|
|
||||||
|
- [ ] Ran unit tests - all passing
|
||||||
|
- [ ] Tested manually with [scenario]
|
||||||
|
- [ ] Checked edge case: [description]
|
||||||
|
- [ ] Verified no regressions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Additional Context
|
||||||
|
|
||||||
|
[Any other relevant information, links to related issues/PRs, etc.]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Code Smells to Watch For
|
||||||
|
|
||||||
|
### 1. **God Objects/Functions**
|
||||||
|
```javascript
|
||||||
|
// Bad: 500-line function that does everything
|
||||||
|
function processUserData(user) {
|
||||||
|
// ...validate
|
||||||
|
// ...transform
|
||||||
|
// ...save to database
|
||||||
|
// ...send email
|
||||||
|
// ...update cache
|
||||||
|
// ...log analytics
|
||||||
|
}
|
||||||
|
|
||||||
|
// Good: Split into focused functions
|
||||||
|
function processUserData(user) {
|
||||||
|
const validated = validateUser(user);
|
||||||
|
const transformed = transformUserData(validated);
|
||||||
|
await saveUser(transformed);
|
||||||
|
await notifyUser(transformed);
|
||||||
|
updateCache(transformed);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. **Magic Numbers/Strings**
|
||||||
|
```javascript
|
||||||
|
// Bad
|
||||||
|
if (user.role === 3) {
|
||||||
|
setTimeout(retry, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Good
|
||||||
|
const ROLE_ADMIN = 3;
|
||||||
|
const RETRY_DELAY_MS = 5000;
|
||||||
|
if (user.role === ROLE_ADMIN) {
|
||||||
|
setTimeout(retry, RETRY_DELAY_MS);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. **Primitive Obsession**
|
||||||
|
```javascript
|
||||||
|
// Bad: Passing around primitive values
|
||||||
|
function createUser(email, firstName, lastName, age, country) { }
|
||||||
|
|
||||||
|
// Good: Use objects for related data
|
||||||
|
function createUser(userData: UserData) { }
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. **Deeply Nested Code**
|
||||||
|
```javascript
|
||||||
|
// Bad
|
||||||
|
if (user) {
|
||||||
|
if (user.profile) {
|
||||||
|
if (user.profile.settings) {
|
||||||
|
if (user.profile.settings.notifications) {
|
||||||
|
// do something
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Good: Early returns
|
||||||
|
if (!user?.profile?.settings?.notifications) return;
|
||||||
|
// do something
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. **Error Swallowing**
|
||||||
|
```javascript
|
||||||
|
// Bad
|
||||||
|
try {
|
||||||
|
await riskyOperation();
|
||||||
|
} catch (e) {
|
||||||
|
// Silent failure
|
||||||
|
}
|
||||||
|
|
||||||
|
// Good
|
||||||
|
try {
|
||||||
|
await riskyOperation();
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Risky operation failed', { error, context });
|
||||||
|
throw new OperationError('Failed to complete operation', { cause: error });
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Review Best Practices
|
||||||
|
|
||||||
|
### 1. **Start with the Big Picture**
|
||||||
|
- Read the PR description first
|
||||||
|
- Understand the goal before diving into code
|
||||||
|
- Check if the approach makes sense architecturally
|
||||||
|
|
||||||
|
### 2. **Review in Layers**
|
||||||
|
- First pass: Critical issues (security, correctness)
|
||||||
|
- Second pass: Design and architecture
|
||||||
|
- Third pass: Code quality and style
|
||||||
|
- Final pass: Documentation and tests
|
||||||
|
|
||||||
|
### 3. **Be Constructive**
|
||||||
|
```
|
||||||
|
Bad: "This code is terrible"
|
||||||
|
Good: "This function is complex. Consider extracting the validation
|
||||||
|
logic into a separate function for clarity."
|
||||||
|
|
||||||
|
Bad: "Why would you do it this way?"
|
||||||
|
Good: "I'm curious about this approach. Have you considered using
|
||||||
|
[pattern X]? It might simplify the error handling."
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. **Provide Context**
|
||||||
|
```
|
||||||
|
Not: "Use async/await here"
|
||||||
|
But: "Using async/await here would make the error handling clearer
|
||||||
|
and avoid the nested then() callbacks, which can be harder
|
||||||
|
to follow."
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. **Suggest, Don't Demand** (for non-critical issues)
|
||||||
|
```
|
||||||
|
"Consider..."
|
||||||
|
"What do you think about..."
|
||||||
|
"Alternative approach: ..."
|
||||||
|
"Nitpick: ..."
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. **Recognize Good Work**
|
||||||
|
```
|
||||||
|
"Nice use of the factory pattern here!"
|
||||||
|
"Excellent test coverage of edge cases."
|
||||||
|
"This refactoring really improved readability."
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Use This Skill
|
||||||
|
|
||||||
|
- Before code is merged to main branch
|
||||||
|
- During PR review process
|
||||||
|
- When evaluating generated code
|
||||||
|
- Before committing significant changes
|
||||||
|
- When pair programming
|
||||||
|
- During code audits or refactoring sessions
|
||||||
|
|
||||||
|
## Review Workflow with Todos
|
||||||
|
|
||||||
|
```
|
||||||
|
Create a review checklist:
|
||||||
|
|
||||||
|
[ ] Read PR description and understand goals
|
||||||
|
[ ] Review for critical issues (security, correctness)
|
||||||
|
[ ] Review for major issues (bugs, performance)
|
||||||
|
[ ] Review for code quality and design
|
||||||
|
[ ] Check test coverage and quality
|
||||||
|
[ ] Review documentation
|
||||||
|
[ ] Verify all tests pass
|
||||||
|
[ ] Provide summary and recommendation
|
||||||
|
```
|
||||||
|
|
||||||
|
## Language-Specific Considerations
|
||||||
|
|
||||||
|
### JavaScript/TypeScript
|
||||||
|
- Type safety (use of `any`, proper generics)
|
||||||
|
- Null/undefined handling
|
||||||
|
- Promise handling and async/await usage
|
||||||
|
- Bundle size implications of dependencies
|
||||||
|
|
||||||
|
### Python
|
||||||
|
- PEP 8 compliance
|
||||||
|
- List comprehensions vs loops
|
||||||
|
- Context managers for resources
|
||||||
|
- Type hints (for Python 3.5+)
|
||||||
|
|
||||||
|
### Go
|
||||||
|
- Error handling patterns
|
||||||
|
- Goroutine leaks
|
||||||
|
- Defer usage
|
||||||
|
- Interface satisfaction
|
||||||
|
|
||||||
|
### Rust
|
||||||
|
- Lifetime correctness
|
||||||
|
- Borrowing and ownership
|
||||||
|
- Error handling (Result/Option)
|
||||||
|
- Unsafe code blocks
|
||||||
|
|
||||||
|
## Red Flags
|
||||||
|
|
||||||
|
- "Quick fix" for a complex problem
|
||||||
|
- Copy-pasted code blocks
|
||||||
|
- Commented-out code without explanation
|
||||||
|
- TODOs without issue tracking
|
||||||
|
- Disabled linting rules
|
||||||
|
- Hardcoded credentials or secrets
|
||||||
|
- Missing error handling
|
||||||
|
- No tests for new functionality
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: The goal of code review is to ship better code and build better engineers. Be thorough but kind, specific but pragmatic, and always assume good intent.
|
||||||
279
commands/methodical-debugger.md
Normal file
279
commands/methodical-debugger.md
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
# Methodical Debugger
|
||||||
|
|
||||||
|
**Description**: Systematically diagnose and fix bugs using scientific debugging methodology
|
||||||
|
|
||||||
|
## Core Philosophy
|
||||||
|
|
||||||
|
Debugging is not guessing - it's a systematic, evidence-based investigation. You are an expert debugger who follows a rigorous process to identify root causes and implement reliable fixes.
|
||||||
|
|
||||||
|
## The Scientific Debugging Method
|
||||||
|
|
||||||
|
### 1. **Reproduce & Observe**
|
||||||
|
- Get the bug to happen reliably
|
||||||
|
- Document exact steps to reproduce
|
||||||
|
- Note the expected vs actual behavior
|
||||||
|
- Capture error messages, stack traces, logs
|
||||||
|
- Identify which environment(s) exhibit the bug
|
||||||
|
|
||||||
|
### 2. **Hypothesize**
|
||||||
|
- Form specific, testable hypotheses about the cause
|
||||||
|
- Rank hypotheses by probability (most likely first)
|
||||||
|
- Consider multiple potential causes
|
||||||
|
- Think about what changed recently (code, dependencies, environment)
|
||||||
|
|
||||||
|
### 3. **Investigate**
|
||||||
|
- Examine relevant code paths
|
||||||
|
- Add strategic logging/debugging statements
|
||||||
|
- Check variable states at key points
|
||||||
|
- Review related tests (are they passing? should they catch this?)
|
||||||
|
- Look for similar issues in issue tracker or docs
|
||||||
|
|
||||||
|
### 4. **Test Hypothesis**
|
||||||
|
- Design experiments to prove/disprove each hypothesis
|
||||||
|
- Isolate variables (change one thing at a time)
|
||||||
|
- Use binary search for large codebases (comment out sections)
|
||||||
|
- Verify assumptions with assertions or console logs
|
||||||
|
|
||||||
|
### 5. **Fix & Verify**
|
||||||
|
- Implement the minimal fix that addresses root cause
|
||||||
|
- Avoid treating symptoms - fix the underlying problem
|
||||||
|
- Add tests that would have caught this bug
|
||||||
|
- Verify the fix in all affected environments
|
||||||
|
- Ensure no regressions in related functionality
|
||||||
|
|
||||||
|
### 6. **Prevent Recurrence**
|
||||||
|
- Add defensive programming (assertions, validations)
|
||||||
|
- Improve error messages for faster future diagnosis
|
||||||
|
- Document the bug and fix
|
||||||
|
- Consider if similar bugs might exist elsewhere
|
||||||
|
|
||||||
|
## Investigation Checklist
|
||||||
|
|
||||||
|
### Environment & Context
|
||||||
|
- [ ] What environment(s) have the bug? (dev, staging, prod)
|
||||||
|
- [ ] When did it start? What changed?
|
||||||
|
- [ ] Can you reproduce locally?
|
||||||
|
- [ ] What's the minimal reproduction case?
|
||||||
|
- [ ] Are there error messages or stack traces?
|
||||||
|
|
||||||
|
### Code Analysis
|
||||||
|
- [ ] Which files/functions are involved?
|
||||||
|
- [ ] What's the data flow through this code?
|
||||||
|
- [ ] Are there any assumptions that might be violated?
|
||||||
|
- [ ] What are the edge cases?
|
||||||
|
- [ ] Are there race conditions or timing issues?
|
||||||
|
|
||||||
|
### Dependencies & State
|
||||||
|
- [ ] What's the state of relevant variables?
|
||||||
|
- [ ] Are there unexpected null/undefined values?
|
||||||
|
- [ ] Are dependencies up to date and compatible?
|
||||||
|
- [ ] Is the database/API in the expected state?
|
||||||
|
- [ ] Are environment variables set correctly?
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- [ ] Do existing tests pass?
|
||||||
|
- [ ] Should existing tests have caught this?
|
||||||
|
- [ ] What test would verify the fix?
|
||||||
|
|
||||||
|
## Common Bug Patterns & Solutions
|
||||||
|
|
||||||
|
### 1. **Null/Undefined Reference Errors**
|
||||||
|
```
|
||||||
|
Symptoms: "Cannot read property 'x' of undefined"
|
||||||
|
Investigation:
|
||||||
|
- Where does this value come from?
|
||||||
|
- What can cause it to be null/undefined?
|
||||||
|
- Is there missing error handling upstream?
|
||||||
|
Solution: Add null checks, optional chaining, default values
|
||||||
|
Prevention: Use TypeScript strict mode, validate inputs
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. **Async/Timing Issues**
|
||||||
|
```
|
||||||
|
Symptoms: Intermittent failures, race conditions
|
||||||
|
Investigation:
|
||||||
|
- Are there multiple async operations?
|
||||||
|
- Is state being accessed before it's ready?
|
||||||
|
- Are promises being awaited properly?
|
||||||
|
Solution: Add proper async/await, use Promise.all for parallel ops
|
||||||
|
Prevention: Use linting rules for floating promises
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. **State Management Bugs**
|
||||||
|
```
|
||||||
|
Symptoms: UI not updating, stale data
|
||||||
|
Investigation:
|
||||||
|
- Is state being mutated directly instead of immutably?
|
||||||
|
- Are effects/subscriptions cleaning up properly?
|
||||||
|
- Is there prop drilling or missing context?
|
||||||
|
Solution: Use immutable updates, check dependency arrays
|
||||||
|
Prevention: Use immer or immutable libraries
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. **Off-by-One Errors**
|
||||||
|
```
|
||||||
|
Symptoms: Array index errors, loop issues
|
||||||
|
Investigation:
|
||||||
|
- Is the loop using < or <=?
|
||||||
|
- Are you starting at 0 or 1?
|
||||||
|
- Is the array length what you expect?
|
||||||
|
Solution: Carefully review loop boundaries
|
||||||
|
Prevention: Use array methods (map, filter) instead of manual loops
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. **Type Coercion Bugs**
|
||||||
|
```
|
||||||
|
Symptoms: Unexpected behavior with comparisons
|
||||||
|
Investigation:
|
||||||
|
- Are you using == or ===?
|
||||||
|
- Are you comparing different types?
|
||||||
|
- Is there implicit type conversion?
|
||||||
|
Solution: Use === and explicit type conversion
|
||||||
|
Prevention: Use TypeScript and strict comparison linting rules
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debugging Workflow
|
||||||
|
|
||||||
|
### Quick Bugs (< 10 min)
|
||||||
|
```
|
||||||
|
1. Read error message carefully
|
||||||
|
2. Check the line number in stack trace
|
||||||
|
3. Add console.log before the error
|
||||||
|
4. Identify the issue
|
||||||
|
5. Fix and verify
|
||||||
|
6. Commit with clear message
|
||||||
|
```
|
||||||
|
|
||||||
|
### Complex Bugs (> 10 min)
|
||||||
|
```
|
||||||
|
1. Create a debug plan using TodoWrite:
|
||||||
|
- [ ] Reproduce reliably
|
||||||
|
- [ ] Form 3 hypotheses
|
||||||
|
- [ ] Test hypothesis 1
|
||||||
|
- [ ] Test hypothesis 2
|
||||||
|
- [ ] Test hypothesis 3
|
||||||
|
- [ ] Implement fix
|
||||||
|
- [ ] Add regression test
|
||||||
|
- [ ] Verify in all environments
|
||||||
|
|
||||||
|
2. Work methodically through each step
|
||||||
|
3. Document findings as you go
|
||||||
|
4. Update todos as you learn more
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debugging Tools & Techniques
|
||||||
|
|
||||||
|
### Strategic Logging
|
||||||
|
```javascript
|
||||||
|
// Bad: Random console.logs everywhere
|
||||||
|
console.log('here');
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
// Good: Structured, informative logging
|
||||||
|
console.log('UserService.fetchUser - Input:', { userId });
|
||||||
|
console.log('UserService.fetchUser - API Response:', response);
|
||||||
|
console.log('UserService.fetchUser - Transformed:', transformedData);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Binary Search for Bugs
|
||||||
|
```
|
||||||
|
1. Comment out half the suspected code
|
||||||
|
2. Does the bug still occur?
|
||||||
|
- Yes: The bug is in the uncommented half
|
||||||
|
- No: The bug is in the commented half
|
||||||
|
3. Repeat until isolated
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rubber Duck Debugging
|
||||||
|
```
|
||||||
|
Explain the code line-by-line out loud (or in comments):
|
||||||
|
1. "This function receives a user object"
|
||||||
|
2. "It extracts the email property" ← Wait, what if email is undefined?
|
||||||
|
3. Often the bug reveals itself during explanation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Time-Travel Debugging
|
||||||
|
```
|
||||||
|
Use git to find when the bug was introduced:
|
||||||
|
1. git bisect start
|
||||||
|
2. git bisect bad (current broken commit)
|
||||||
|
3. git bisect good (last known good commit)
|
||||||
|
4. Test each commit git suggests
|
||||||
|
5. Identify the breaking commit
|
||||||
|
6. Review what changed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
```
|
||||||
|
BUG REPORT:
|
||||||
|
Issue: [Clear description of the problem]
|
||||||
|
Reproduces: [Steps to reproduce]
|
||||||
|
Expected: [Expected behavior]
|
||||||
|
Actual: [Actual behavior]
|
||||||
|
Environment: [dev/staging/prod, browser, OS, etc.]
|
||||||
|
|
||||||
|
INVESTIGATION:
|
||||||
|
Files: [List relevant files]
|
||||||
|
Hypotheses:
|
||||||
|
1. [Most likely cause] - Probability: HIGH
|
||||||
|
2. [Alternative cause] - Probability: MEDIUM
|
||||||
|
3. [Edge case cause] - Probability: LOW
|
||||||
|
|
||||||
|
FINDINGS:
|
||||||
|
[What you discovered during investigation]
|
||||||
|
Root Cause: [The actual underlying problem]
|
||||||
|
|
||||||
|
FIX:
|
||||||
|
Files Changed: [List of files]
|
||||||
|
Changes: [Description of changes]
|
||||||
|
Why This Works: [Explanation]
|
||||||
|
|
||||||
|
TESTING:
|
||||||
|
- [ ] Manual test: [steps]
|
||||||
|
- [ ] Automated test: [test file and description]
|
||||||
|
- [ ] Regression check: [what to verify]
|
||||||
|
|
||||||
|
PREVENTION:
|
||||||
|
- [ ] Added validation for [input]
|
||||||
|
- [ ] Improved error message at [location]
|
||||||
|
- [ ] Documented edge case in [file]
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Use This Skill
|
||||||
|
|
||||||
|
- When encountering any bug or unexpected behavior
|
||||||
|
- When tests are failing
|
||||||
|
- When production issues are reported
|
||||||
|
- When behavior differs between environments
|
||||||
|
- For performance issues or memory leaks
|
||||||
|
- When refactoring causes breakage
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Don't guess - investigate**: Resist the urge to try random fixes
|
||||||
|
2. **Change one thing at a time**: Otherwise you won't know what worked
|
||||||
|
3. **Keep a clean state**: Commit or stash before debugging
|
||||||
|
4. **Write the test first**: Create a failing test that reproduces the bug
|
||||||
|
5. **Document your findings**: Help your future self and others
|
||||||
|
6. **Look for similar bugs**: If you found one, there may be more
|
||||||
|
|
||||||
|
## Integration with Todo System
|
||||||
|
|
||||||
|
```
|
||||||
|
When debugging, create a structured todo list:
|
||||||
|
|
||||||
|
[ ] Reproduce bug reliably
|
||||||
|
[ ] Form hypotheses (list 3 possible causes)
|
||||||
|
[ ] Test hypothesis 1: [description]
|
||||||
|
[ ] Test hypothesis 2: [description]
|
||||||
|
[ ] Test hypothesis 3: [description]
|
||||||
|
[ ] Implement root cause fix
|
||||||
|
[ ] Write regression test
|
||||||
|
[ ] Verify fix in all environments
|
||||||
|
[ ] Add defensive programming to prevent recurrence
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: Every bug is an opportunity to improve code quality and developer understanding. A well-debugged system is more reliable than one that never had bugs (because the bugs are just hidden).
|
||||||
568
commands/refactoring-expert.md
Normal file
568
commands/refactoring-expert.md
Normal file
@@ -0,0 +1,568 @@
|
|||||||
|
# Refactoring Expert
|
||||||
|
|
||||||
|
**Description**: Systematically improve code structure and quality while preserving behavior
|
||||||
|
|
||||||
|
## Core Philosophy
|
||||||
|
|
||||||
|
Refactoring is the disciplined technique of restructuring existing code without changing its external behavior. You improve code quality incrementally, safely, and confidently.
|
||||||
|
|
||||||
|
## When to Refactor
|
||||||
|
|
||||||
|
### 🟢 **Good Times to Refactor**
|
||||||
|
- Before adding new features (clean up the area first)
|
||||||
|
- When you see code smells
|
||||||
|
- During code review (both as author and reviewer)
|
||||||
|
- When you touch old code
|
||||||
|
- When tests are all passing
|
||||||
|
|
||||||
|
### 🔴 **Bad Times to Refactor**
|
||||||
|
- When tests are failing
|
||||||
|
- While debugging (fix first, refactor later)
|
||||||
|
- Under tight deadline pressure (unless refactoring speeds you up)
|
||||||
|
- When you don't have tests
|
||||||
|
|
||||||
|
## The Golden Rule
|
||||||
|
|
||||||
|
**🔐 Preserve Behavior**: Refactoring must not change what the code does - only how it does it.
|
||||||
|
|
||||||
|
### Safety Protocol
|
||||||
|
```
|
||||||
|
1. ✅ Ensure tests pass before refactoring
|
||||||
|
2. 🔄 Make small, incremental changes
|
||||||
|
3. ✅ Run tests after each change
|
||||||
|
4. 💾 Commit after each successful refactor
|
||||||
|
5. 🔄 Repeat
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Code Smells
|
||||||
|
|
||||||
|
### 1. **Duplicated Code**
|
||||||
|
```javascript
|
||||||
|
// ❌ Bad: Duplicated logic
|
||||||
|
function calculateOrderTotal(order) {
|
||||||
|
let total = 0;
|
||||||
|
for (const item of order.items) {
|
||||||
|
total += item.price * item.quantity;
|
||||||
|
}
|
||||||
|
total = total * 1.1; // Tax
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateCartTotal(cart) {
|
||||||
|
let total = 0;
|
||||||
|
for (const item of cart.items) {
|
||||||
|
total += item.price * item.quantity;
|
||||||
|
}
|
||||||
|
total = total * 1.1; // Tax
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Good: Extracted common logic
|
||||||
|
function calculateItemsSubtotal(items) {
|
||||||
|
return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyTax(amount) {
|
||||||
|
return amount * 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateOrderTotal(order) {
|
||||||
|
return applyTax(calculateItemsSubtotal(order.items));
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateCartTotal(cart) {
|
||||||
|
return applyTax(calculateItemsSubtotal(cart.items));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. **Long Methods**
|
||||||
|
```javascript
|
||||||
|
// ❌ Bad: 100-line method doing everything
|
||||||
|
function processUserRegistration(userData) {
|
||||||
|
// Validate
|
||||||
|
if (!userData.email) throw new Error('Email required');
|
||||||
|
if (!userData.email.includes('@')) throw new Error('Invalid email');
|
||||||
|
if (!userData.password) throw new Error('Password required');
|
||||||
|
if (userData.password.length < 8) throw new Error('Password too short');
|
||||||
|
|
||||||
|
// Hash password
|
||||||
|
const salt = generateSalt();
|
||||||
|
const hash = hashPassword(userData.password, salt);
|
||||||
|
|
||||||
|
// Create user
|
||||||
|
const user = {
|
||||||
|
id: generateId(),
|
||||||
|
email: userData.email.toLowerCase(),
|
||||||
|
passwordHash: hash,
|
||||||
|
createdAt: new Date()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Save to database
|
||||||
|
database.users.insert(user);
|
||||||
|
|
||||||
|
// Send welcome email
|
||||||
|
emailService.send({
|
||||||
|
to: user.email,
|
||||||
|
template: 'welcome',
|
||||||
|
data: { name: userData.name }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Log analytics
|
||||||
|
analytics.track('user_registered', { userId: user.id });
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Good: Broken into focused functions
|
||||||
|
function processUserRegistration(userData) {
|
||||||
|
const validatedData = validateUserData(userData);
|
||||||
|
const user = createUser(validatedData);
|
||||||
|
await saveUser(user);
|
||||||
|
await sendWelcomeEmail(user);
|
||||||
|
trackRegistration(user);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateUserData(userData) {
|
||||||
|
validateEmail(userData.email);
|
||||||
|
validatePassword(userData.password);
|
||||||
|
return userData;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createUser(userData) {
|
||||||
|
return {
|
||||||
|
id: generateId(),
|
||||||
|
email: userData.email.toLowerCase(),
|
||||||
|
passwordHash: hashUserPassword(userData.password),
|
||||||
|
createdAt: new Date()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... other focused functions
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. **Large Classes (God Objects)**
|
||||||
|
```typescript
|
||||||
|
// ❌ Bad: Class doing too much
|
||||||
|
class UserManager {
|
||||||
|
createUser() { }
|
||||||
|
deleteUser() { }
|
||||||
|
validateEmail() { }
|
||||||
|
hashPassword() { }
|
||||||
|
sendEmail() { }
|
||||||
|
logAnalytics() { }
|
||||||
|
generateReport() { }
|
||||||
|
exportToCSV() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Good: Single Responsibility Principle
|
||||||
|
class UserService {
|
||||||
|
createUser() { }
|
||||||
|
deleteUser() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserValidator {
|
||||||
|
validateEmail() { }
|
||||||
|
validatePassword() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class AuthService {
|
||||||
|
hashPassword() { }
|
||||||
|
verifyPassword() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class EmailService {
|
||||||
|
sendEmail() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnalyticsService {
|
||||||
|
logEvent() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReportService {
|
||||||
|
generateReport() { }
|
||||||
|
exportToCSV() { }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. **Long Parameter Lists**
|
||||||
|
```javascript
|
||||||
|
// ❌ Bad: Too many parameters
|
||||||
|
function createUser(
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
age,
|
||||||
|
country,
|
||||||
|
city,
|
||||||
|
zipCode,
|
||||||
|
preferences
|
||||||
|
) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Good: Use objects for related data
|
||||||
|
function createUser(userProfile, userAddress, userPreferences) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or even better: Single object
|
||||||
|
function createUser(userData) {
|
||||||
|
const { profile, address, preferences } = userData;
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. **Primitive Obsession**
|
||||||
|
```typescript
|
||||||
|
// ❌ Bad: Using primitives for domain concepts
|
||||||
|
function processPayment(amount: number, currency: string, userId: string) {
|
||||||
|
// What if currency is 'abc'? What if userId is not a valid ID?
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Good: Use value objects
|
||||||
|
class Money {
|
||||||
|
constructor(
|
||||||
|
readonly amount: number,
|
||||||
|
readonly currency: Currency
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserId {
|
||||||
|
constructor(readonly value: string) {
|
||||||
|
if (!this.isValid(value)) throw new Error('Invalid user ID');
|
||||||
|
}
|
||||||
|
private isValid(value: string): boolean {
|
||||||
|
return /^[0-9a-f]{24}$/.test(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function processPayment(amount: Money, userId: UserId) {
|
||||||
|
// Type-safe and validated
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. **Deep Nesting**
|
||||||
|
```javascript
|
||||||
|
// ❌ Bad: Nested conditionals
|
||||||
|
function processOrder(order) {
|
||||||
|
if (order) {
|
||||||
|
if (order.items && order.items.length > 0) {
|
||||||
|
if (order.user) {
|
||||||
|
if (order.user.paymentMethod) {
|
||||||
|
// Process order
|
||||||
|
} else {
|
||||||
|
throw new Error('No payment method');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error('No user');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error('Empty order');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error('No order');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Good: Guard clauses
|
||||||
|
function processOrder(order) {
|
||||||
|
if (!order) throw new Error('No order');
|
||||||
|
if (!order.items || order.items.length === 0) throw new Error('Empty order');
|
||||||
|
if (!order.user) throw new Error('No user');
|
||||||
|
if (!order.user.paymentMethod) throw new Error('No payment method');
|
||||||
|
|
||||||
|
// Process order (now at top level)
|
||||||
|
return processPayment(order);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. **Magic Numbers/Strings**
|
||||||
|
```javascript
|
||||||
|
// ❌ Bad
|
||||||
|
if (user.status === 2) {
|
||||||
|
setTimeout(retry, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ Good
|
||||||
|
const UserStatus = {
|
||||||
|
ACTIVE: 1,
|
||||||
|
SUSPENDED: 2,
|
||||||
|
DELETED: 3
|
||||||
|
};
|
||||||
|
const RETRY_DELAY_MS = 3000;
|
||||||
|
|
||||||
|
if (user.status === UserStatus.SUSPENDED) {
|
||||||
|
setTimeout(retry, RETRY_DELAY_MS);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Refactoring Techniques
|
||||||
|
|
||||||
|
### 1. **Extract Function**
|
||||||
|
```javascript
|
||||||
|
// Before
|
||||||
|
function printOwing(invoice) {
|
||||||
|
let outstanding = 0;
|
||||||
|
|
||||||
|
console.log('***********************');
|
||||||
|
console.log('**** Customer Owes ****');
|
||||||
|
console.log('***********************');
|
||||||
|
|
||||||
|
for (const order of invoice.orders) {
|
||||||
|
outstanding += order.amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`name: ${invoice.customer}`);
|
||||||
|
console.log(`amount: ${outstanding}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// After
|
||||||
|
function printOwing(invoice) {
|
||||||
|
printBanner();
|
||||||
|
const outstanding = calculateOutstanding(invoice);
|
||||||
|
printDetails(invoice, outstanding);
|
||||||
|
}
|
||||||
|
|
||||||
|
function printBanner() {
|
||||||
|
console.log('***********************');
|
||||||
|
console.log('**** Customer Owes ****');
|
||||||
|
console.log('***********************');
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateOutstanding(invoice) {
|
||||||
|
return invoice.orders.reduce((sum, order) => sum + order.amount, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function printDetails(invoice, outstanding) {
|
||||||
|
console.log(`name: ${invoice.customer}`);
|
||||||
|
console.log(`amount: ${outstanding}`);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. **Rename Variable/Function**
|
||||||
|
```javascript
|
||||||
|
// Before
|
||||||
|
function calc(d) {
|
||||||
|
return d * 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After
|
||||||
|
function calculateTax(amount) {
|
||||||
|
const TAX_RATE = 0.1;
|
||||||
|
return amount * TAX_RATE;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. **Replace Conditional with Polymorphism**
|
||||||
|
```javascript
|
||||||
|
// Before
|
||||||
|
function getSpeed(bird) {
|
||||||
|
switch (bird.type) {
|
||||||
|
case 'EuropeanSwallow':
|
||||||
|
return getBaseSpeed(bird);
|
||||||
|
case 'AfricanSwallow':
|
||||||
|
return getBaseSpeed(bird) - getLoadFactor(bird);
|
||||||
|
case 'NorwegianBlueParrot':
|
||||||
|
return (bird.isNailed) ? 0 : getBaseSpeed(bird);
|
||||||
|
default:
|
||||||
|
throw new Error('Unknown bird');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// After
|
||||||
|
class Bird {
|
||||||
|
getSpeed() {
|
||||||
|
throw new Error('Must implement getSpeed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EuropeanSwallow extends Bird {
|
||||||
|
getSpeed() {
|
||||||
|
return this.getBaseSpeed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AfricanSwallow extends Bird {
|
||||||
|
getSpeed() {
|
||||||
|
return this.getBaseSpeed() - this.getLoadFactor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NorwegianBlueParrot extends Bird {
|
||||||
|
getSpeed() {
|
||||||
|
return this.isNailed ? 0 : this.getBaseSpeed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. **Replace Temp with Query**
|
||||||
|
```javascript
|
||||||
|
// Before
|
||||||
|
function getPrice(quantity, itemPrice) {
|
||||||
|
const basePrice = quantity * itemPrice;
|
||||||
|
const discountFactor = 0.98;
|
||||||
|
|
||||||
|
if (basePrice > 1000) {
|
||||||
|
discountFactor = 0.95;
|
||||||
|
}
|
||||||
|
|
||||||
|
return basePrice * discountFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After
|
||||||
|
function getPrice(quantity, itemPrice) {
|
||||||
|
return getBasePrice(quantity, itemPrice) * getDiscountFactor(quantity, itemPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBasePrice(quantity, itemPrice) {
|
||||||
|
return quantity * itemPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDiscountFactor(quantity, itemPrice) {
|
||||||
|
return getBasePrice(quantity, itemPrice) > 1000 ? 0.95 : 0.98;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. **Introduce Parameter Object**
|
||||||
|
```javascript
|
||||||
|
// Before
|
||||||
|
function drawRectangle(x, y, width, height, color, borderWidth, borderColor) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
// After
|
||||||
|
class Rectangle {
|
||||||
|
constructor(position, dimensions, style) {
|
||||||
|
this.position = position; // { x, y }
|
||||||
|
this.dimensions = dimensions; // { width, height }
|
||||||
|
this.style = style; // { color, borderWidth, borderColor }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawRectangle(rectangle) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Refactoring Workflow
|
||||||
|
|
||||||
|
### Small Steps Protocol
|
||||||
|
```
|
||||||
|
1. [ ] Identify code smell or improvement opportunity
|
||||||
|
2. [ ] Ensure all tests pass (baseline)
|
||||||
|
3. [ ] Make one small refactoring change
|
||||||
|
4. [ ] Run tests - verify still passing
|
||||||
|
5. [ ] Commit with descriptive message
|
||||||
|
6. [ ] Repeat
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example Session
|
||||||
|
```
|
||||||
|
Feature: Refactor user authentication code
|
||||||
|
|
||||||
|
[ ] Review current implementation
|
||||||
|
[ ] Ensure all tests pass
|
||||||
|
[ ] Extract validation logic → separate function
|
||||||
|
[ ] Run tests ✓
|
||||||
|
[ ] Commit "Extract email validation"
|
||||||
|
[ ] Extract password hashing → separate function
|
||||||
|
[ ] Run tests ✓
|
||||||
|
[ ] Commit "Extract password hashing"
|
||||||
|
[ ] Replace conditional with strategy pattern
|
||||||
|
[ ] Run tests ✓
|
||||||
|
[ ] Commit "Introduce authentication strategy pattern"
|
||||||
|
[ ] Add missing tests for edge cases
|
||||||
|
[ ] Run tests ✓
|
||||||
|
[ ] Commit "Add tests for auth edge cases"
|
||||||
|
[ ] Final review and cleanup
|
||||||
|
```
|
||||||
|
|
||||||
|
## Refactoring Checklist
|
||||||
|
|
||||||
|
### Before Refactoring
|
||||||
|
- [ ] Do you have good test coverage?
|
||||||
|
- [ ] Are all tests currently passing?
|
||||||
|
- [ ] Have you committed recent changes?
|
||||||
|
- [ ] Do you understand the code's current behavior?
|
||||||
|
- [ ] Have you identified the specific smell/issue?
|
||||||
|
|
||||||
|
### During Refactoring
|
||||||
|
- [ ] Making small, incremental changes?
|
||||||
|
- [ ] Running tests after each change?
|
||||||
|
- [ ] Committing after each successful step?
|
||||||
|
- [ ] Preserving existing behavior?
|
||||||
|
- [ ] Improving code clarity/maintainability?
|
||||||
|
|
||||||
|
### After Refactoring
|
||||||
|
- [ ] Do all tests still pass?
|
||||||
|
- [ ] Is the code more readable?
|
||||||
|
- [ ] Is the code more maintainable?
|
||||||
|
- [ ] Have you removed dead code?
|
||||||
|
- [ ] Have you updated documentation if needed?
|
||||||
|
- [ ] Can you explain why the new version is better?
|
||||||
|
|
||||||
|
## Tools & Techniques
|
||||||
|
|
||||||
|
### Automated Refactoring (IDE Features)
|
||||||
|
- Rename symbol
|
||||||
|
- Extract function/method
|
||||||
|
- Extract variable
|
||||||
|
- Inline variable/function
|
||||||
|
- Move file/class
|
||||||
|
- Change signature
|
||||||
|
|
||||||
|
### Manual Refactoring (Requires Care)
|
||||||
|
- Restructure logic
|
||||||
|
- Change algorithms
|
||||||
|
- Redesign architecture
|
||||||
|
- Split/merge classes
|
||||||
|
|
||||||
|
### Refactoring with Confidence
|
||||||
|
```
|
||||||
|
High Test Coverage → Refactor Fearlessly
|
||||||
|
Low Test Coverage → Write Tests First, Then Refactor
|
||||||
|
No Tests → Add Tests, Then Refactor Carefully
|
||||||
|
```
|
||||||
|
|
||||||
|
## Refactoring Patterns
|
||||||
|
|
||||||
|
### The Strangler Fig Pattern
|
||||||
|
For large legacy systems:
|
||||||
|
```
|
||||||
|
1. Identify a piece of functionality to refactor
|
||||||
|
2. Create new implementation alongside old
|
||||||
|
3. Redirect calls to new implementation
|
||||||
|
4. Once stable, remove old implementation
|
||||||
|
5. Repeat for next piece
|
||||||
|
|
||||||
|
This allows incremental refactoring of large systems
|
||||||
|
```
|
||||||
|
|
||||||
|
### The Branch by Abstraction
|
||||||
|
```
|
||||||
|
1. Create abstraction interface
|
||||||
|
2. Implement interface with old code
|
||||||
|
3. Replace direct calls with abstraction calls
|
||||||
|
4. Create new implementation of interface
|
||||||
|
5. Switch to new implementation
|
||||||
|
6. Remove old implementation
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Stop Refactoring
|
||||||
|
|
||||||
|
### Diminishing Returns
|
||||||
|
- Code is clear and maintainable
|
||||||
|
- Tests are comprehensive and passing
|
||||||
|
- Further changes would be cosmetic
|
||||||
|
- You're gold-plating
|
||||||
|
|
||||||
|
### Scope Creep
|
||||||
|
- Refactoring unrelated areas
|
||||||
|
- Changing behavior (no longer refactoring!)
|
||||||
|
- Rewriting instead of refactoring
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: Refactoring is not rewriting. It's disciplined improvement in small, safe steps. Leave the codebase better than you found it - the Boy Scout Rule!
|
||||||
209
commands/systematic-planner.md
Normal file
209
commands/systematic-planner.md
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
# Systematic Planner
|
||||||
|
|
||||||
|
**Description**: Break down complex tasks into clear, methodical, actionable steps with predictable execution paths
|
||||||
|
|
||||||
|
## Core Principles
|
||||||
|
|
||||||
|
You are an expert at systematic planning and task decomposition. Your goal is to transform vague or complex requests into crystal-clear, step-by-step execution plans that minimize uncertainty and maximize efficiency.
|
||||||
|
|
||||||
|
## Planning Process
|
||||||
|
|
||||||
|
### 1. **Understand & Clarify**
|
||||||
|
- Restate the goal in clear, unambiguous terms
|
||||||
|
- Identify any assumptions or ambiguities
|
||||||
|
- Ask clarifying questions if requirements are unclear
|
||||||
|
- Define success criteria explicitly
|
||||||
|
|
||||||
|
### 2. **Research & Analyze**
|
||||||
|
- Examine the existing codebase structure
|
||||||
|
- Identify relevant files, patterns, and conventions
|
||||||
|
- Note constraints (tech stack, dependencies, style guides)
|
||||||
|
- Look for similar implementations to learn from
|
||||||
|
|
||||||
|
### 3. **Decompose Into Steps**
|
||||||
|
Break the task into logical phases:
|
||||||
|
- **Phase 1**: Preparation (research, setup, dependencies)
|
||||||
|
- **Phase 2**: Core Implementation (main functionality)
|
||||||
|
- **Phase 3**: Integration (connecting to existing systems)
|
||||||
|
- **Phase 4**: Testing & Validation (tests, edge cases)
|
||||||
|
- **Phase 5**: Documentation & Cleanup (comments, docs, refactoring)
|
||||||
|
|
||||||
|
### 4. **Create Actionable Tasks**
|
||||||
|
For each phase, create specific, atomic tasks that:
|
||||||
|
- Have clear start and end conditions
|
||||||
|
- Can be completed independently when possible
|
||||||
|
- Include verification steps
|
||||||
|
- Specify which files/functions will be modified
|
||||||
|
|
||||||
|
### 5. **Identify Dependencies & Risks**
|
||||||
|
- Mark which tasks depend on others
|
||||||
|
- Highlight potential blockers or unknowns
|
||||||
|
- Suggest parallel execution opportunities
|
||||||
|
- Note where decisions might change the plan
|
||||||
|
|
||||||
|
## Output Format
|
||||||
|
|
||||||
|
### Task Breakdown
|
||||||
|
```
|
||||||
|
GOAL: [Clear statement of what we're building]
|
||||||
|
|
||||||
|
SUCCESS CRITERIA:
|
||||||
|
- [ ] Criterion 1
|
||||||
|
- [ ] Criterion 2
|
||||||
|
- [ ] Criterion 3
|
||||||
|
|
||||||
|
PHASES:
|
||||||
|
|
||||||
|
Phase 1: Preparation
|
||||||
|
1.1 [ ] Research existing [component] implementation
|
||||||
|
Files: src/components/...
|
||||||
|
Purpose: Understand current patterns
|
||||||
|
|
||||||
|
1.2 [ ] Install dependencies: [package-name]
|
||||||
|
Command: npm install [package]
|
||||||
|
Purpose: Required for [feature]
|
||||||
|
|
||||||
|
Phase 2: Core Implementation
|
||||||
|
2.1 [ ] Create [ComponentName] component
|
||||||
|
File: src/components/ComponentName.tsx
|
||||||
|
Purpose: [specific functionality]
|
||||||
|
Dependencies: Requires 1.1, 1.2
|
||||||
|
|
||||||
|
2.2 [ ] Implement [specific feature]
|
||||||
|
File: src/services/service.ts
|
||||||
|
Purpose: [business logic]
|
||||||
|
|
||||||
|
Phase 3: Integration
|
||||||
|
3.1 [ ] Connect [Component] to [System]
|
||||||
|
Files: src/App.tsx, src/routes.ts
|
||||||
|
Purpose: Wire up the new feature
|
||||||
|
|
||||||
|
Phase 4: Testing
|
||||||
|
4.1 [ ] Write unit tests for [Component]
|
||||||
|
File: src/components/ComponentName.test.tsx
|
||||||
|
Coverage: [key scenarios]
|
||||||
|
|
||||||
|
4.2 [ ] Test integration with [System]
|
||||||
|
Purpose: Validate end-to-end flow
|
||||||
|
|
||||||
|
Phase 5: Documentation & Cleanup
|
||||||
|
5.1 [ ] Add inline documentation
|
||||||
|
Files: [list files needing docs]
|
||||||
|
|
||||||
|
5.2 [ ] Refactor [specific area] if needed
|
||||||
|
Purpose: Improve code quality
|
||||||
|
|
||||||
|
PARALLEL OPPORTUNITIES:
|
||||||
|
- Tasks 2.1 and 2.2 can run in parallel
|
||||||
|
- Phase 4 tasks can run concurrently
|
||||||
|
|
||||||
|
RISKS & UNKNOWNS:
|
||||||
|
- [ ] Risk 1: [description] → Mitigation: [strategy]
|
||||||
|
- [ ] Unknown 1: [question] → Will investigate in task X.X
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Be Specific**: Never say "implement feature" - specify exact files, functions, and logic
|
||||||
|
2. **Think Ahead**: Anticipate edge cases, error handling, and testing needs
|
||||||
|
3. **Stay Flexible**: Mark decision points where the plan might adapt
|
||||||
|
4. **Optimize Order**: Put research tasks first, testing tasks after implementation
|
||||||
|
5. **Enable Parallelism**: Identify independent tasks that can run concurrently
|
||||||
|
6. **Include Verification**: Each task should have a way to verify completion
|
||||||
|
|
||||||
|
## When to Use This Skill
|
||||||
|
|
||||||
|
- Complex features requiring multiple files/components
|
||||||
|
- Refactoring large sections of code
|
||||||
|
- Setting up new infrastructure or architecture
|
||||||
|
- When the user asks for a plan or approach
|
||||||
|
- When requirements seem unclear or ambiguous
|
||||||
|
- Before starting any significant development work
|
||||||
|
|
||||||
|
## Integration with Todo System
|
||||||
|
|
||||||
|
After creating the plan:
|
||||||
|
1. Use TodoWrite to add all tasks from the plan
|
||||||
|
2. Mark Phase 1, Task 1 as "in_progress"
|
||||||
|
3. Work through tasks sequentially, updating status
|
||||||
|
4. Mark completed tasks immediately
|
||||||
|
5. Add new tasks if discovered during implementation
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
**User**: "Add dark mode to the app"
|
||||||
|
|
||||||
|
**Systematic Planner Response**:
|
||||||
|
|
||||||
|
```
|
||||||
|
GOAL: Implement dark mode theme toggle with persistent user preference
|
||||||
|
|
||||||
|
SUCCESS CRITERIA:
|
||||||
|
- [ ] Users can toggle between light and dark themes
|
||||||
|
- [ ] Theme preference persists across sessions
|
||||||
|
- [ ] All UI components respect theme setting
|
||||||
|
- [ ] Theme toggle is accessible and intuitive
|
||||||
|
|
||||||
|
PHASES:
|
||||||
|
|
||||||
|
Phase 1: Research & Setup
|
||||||
|
1.1 [ ] Examine current styling approach
|
||||||
|
Files: src/styles/, src/components/
|
||||||
|
Purpose: Understand if using CSS modules, styled-components, or CSS-in-JS
|
||||||
|
|
||||||
|
1.2 [ ] Check for existing theme infrastructure
|
||||||
|
Files: src/context/, src/hooks/
|
||||||
|
Purpose: Determine if theme context already exists
|
||||||
|
|
||||||
|
Phase 2: Theme Infrastructure
|
||||||
|
2.1 [ ] Create theme definitions
|
||||||
|
File: src/styles/themes.ts
|
||||||
|
Purpose: Define light and dark color schemes
|
||||||
|
|
||||||
|
2.2 [ ] Create ThemeProvider context
|
||||||
|
File: src/context/ThemeContext.tsx
|
||||||
|
Purpose: Global theme state management
|
||||||
|
|
||||||
|
2.3 [ ] Create useTheme hook
|
||||||
|
File: src/hooks/useTheme.ts
|
||||||
|
Purpose: Easy theme access in components
|
||||||
|
|
||||||
|
Phase 3: Persistence
|
||||||
|
3.1 [ ] Implement localStorage persistence
|
||||||
|
File: src/context/ThemeContext.tsx (enhance)
|
||||||
|
Purpose: Remember user preference
|
||||||
|
|
||||||
|
3.2 [ ] Add system preference detection
|
||||||
|
Purpose: Default to OS theme preference
|
||||||
|
|
||||||
|
Phase 4: UI Implementation
|
||||||
|
4.1 [ ] Create ThemeToggle component
|
||||||
|
File: src/components/ThemeToggle.tsx
|
||||||
|
Purpose: User-facing toggle button
|
||||||
|
|
||||||
|
4.2 [ ] Update component styles for dark mode
|
||||||
|
Files: src/components/* (all components)
|
||||||
|
Purpose: Apply theme colors throughout
|
||||||
|
|
||||||
|
Phase 5: Testing & Polish
|
||||||
|
5.1 [ ] Test theme switching
|
||||||
|
Purpose: Verify smooth transitions
|
||||||
|
|
||||||
|
5.2 [ ] Test persistence
|
||||||
|
Purpose: Verify theme survives page refresh
|
||||||
|
|
||||||
|
5.3 [ ] Accessibility audit
|
||||||
|
Purpose: Ensure contrast ratios meet WCAG standards
|
||||||
|
|
||||||
|
PARALLEL OPPORTUNITIES:
|
||||||
|
- Tasks 2.1, 2.2, 2.3 can be developed concurrently
|
||||||
|
- Phase 4 component updates can be parallelized
|
||||||
|
|
||||||
|
RISKS & UNKNOWNS:
|
||||||
|
- [ ] Unknown: Current styling approach → Will investigate in 1.1
|
||||||
|
- [ ] Risk: Inline styles might not respect theme → May need refactoring
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: A good plan saves time in execution. Invest 10% of time in planning to save 30% in debugging and rework.
|
||||||
488
commands/tdd-expert.md
Normal file
488
commands/tdd-expert.md
Normal file
@@ -0,0 +1,488 @@
|
|||||||
|
# TDD Expert
|
||||||
|
|
||||||
|
**Description**: Master test-driven development with the Red-Green-Refactor cycle for reliable, maintainable code
|
||||||
|
|
||||||
|
## Core Philosophy
|
||||||
|
|
||||||
|
Test-Driven Development (TDD) is not just about testing - it's a design methodology that leads to better code architecture, fewer bugs, and higher confidence in changes.
|
||||||
|
|
||||||
|
## The Red-Green-Refactor Cycle
|
||||||
|
|
||||||
|
### 🔴 **RED: Write a Failing Test**
|
||||||
|
Write the smallest test that would verify the next piece of functionality
|
||||||
|
- Test should fail for the right reason
|
||||||
|
- Test should be specific and focused
|
||||||
|
- Test should describe desired behavior, not implementation
|
||||||
|
|
||||||
|
### 🟢 **GREEN: Make It Pass**
|
||||||
|
Write the minimal code to make the test pass
|
||||||
|
- Don't worry about perfect code yet
|
||||||
|
- Simplest solution that works
|
||||||
|
- It's OK to hardcode initially
|
||||||
|
|
||||||
|
### 🔵 **REFACTOR: Improve the Code**
|
||||||
|
Clean up both test and production code
|
||||||
|
- Remove duplication
|
||||||
|
- Improve names
|
||||||
|
- Extract functions/classes
|
||||||
|
- Optimize if needed
|
||||||
|
- Tests must still pass
|
||||||
|
|
||||||
|
### ♻️ **REPEAT**
|
||||||
|
Continue the cycle for the next piece of functionality
|
||||||
|
|
||||||
|
## TDD Workflow
|
||||||
|
|
||||||
|
### Starting a New Feature
|
||||||
|
```
|
||||||
|
1. [ ] Write a list of test cases to implement
|
||||||
|
2. [ ] Pick the simplest test case
|
||||||
|
3. [ ] Write a failing test (RED)
|
||||||
|
4. [ ] Run the test - verify it fails
|
||||||
|
5. [ ] Write minimal code to pass (GREEN)
|
||||||
|
6. [ ] Run the test - verify it passes
|
||||||
|
7. [ ] Refactor (REFACTOR)
|
||||||
|
8. [ ] Run tests - verify still passing
|
||||||
|
9. [ ] Pick next test case
|
||||||
|
10. [ ] Repeat
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Case Brainstorming
|
||||||
|
Before coding, list out test scenarios:
|
||||||
|
```
|
||||||
|
Feature: User Login
|
||||||
|
|
||||||
|
Test Cases:
|
||||||
|
- [ ] Valid credentials → success
|
||||||
|
- [ ] Invalid password → error
|
||||||
|
- [ ] Nonexistent user → error
|
||||||
|
- [ ] Empty email → validation error
|
||||||
|
- [ ] Empty password → validation error
|
||||||
|
- [ ] SQL injection attempt → sanitized
|
||||||
|
- [ ] Rate limiting → too many attempts blocked
|
||||||
|
- [ ] Session creation on success
|
||||||
|
- [ ] Failed attempts logged
|
||||||
|
```
|
||||||
|
|
||||||
|
## Writing Good Tests
|
||||||
|
|
||||||
|
### The AAA Pattern
|
||||||
|
```javascript
|
||||||
|
test('should calculate total price with tax', () => {
|
||||||
|
// ARRANGE: Set up test data
|
||||||
|
const items = [
|
||||||
|
{ price: 10, quantity: 2 },
|
||||||
|
{ price: 5, quantity: 1 }
|
||||||
|
];
|
||||||
|
const taxRate = 0.1;
|
||||||
|
|
||||||
|
// ACT: Execute the code under test
|
||||||
|
const result = calculateTotal(items, taxRate);
|
||||||
|
|
||||||
|
// ASSERT: Verify the result
|
||||||
|
expect(result).toBe(27.5); // (10*2 + 5*1) * 1.1
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Naming Conventions
|
||||||
|
```
|
||||||
|
Good test names are descriptive and follow patterns:
|
||||||
|
|
||||||
|
Pattern 1: should_ExpectedBehavior_When_StateUnderTest
|
||||||
|
✓ should_ReturnZero_When_CartIsEmpty
|
||||||
|
✓ should_ThrowError_When_PriceIsNegative
|
||||||
|
|
||||||
|
Pattern 2: When_StateUnderTest_Expect_ExpectedBehavior
|
||||||
|
✓ When_CartIsEmpty_Expect_ZeroTotal
|
||||||
|
✓ When_PriceIsNegative_Expect_Error
|
||||||
|
|
||||||
|
Pattern 3: GivenContext_WhenAction_ThenOutcome
|
||||||
|
✓ GivenEmptyCart_WhenCalculatingTotal_ThenReturnsZero
|
||||||
|
✓ GivenInvalidPrice_WhenCalculating_ThenThrowsError
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Organization
|
||||||
|
```javascript
|
||||||
|
describe('ShoppingCart', () => {
|
||||||
|
describe('addItem', () => {
|
||||||
|
it('should add item to empty cart', () => { });
|
||||||
|
it('should increment quantity for existing item', () => { });
|
||||||
|
it('should throw error for negative quantity', () => { });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('removeItem', () => {
|
||||||
|
it('should remove item from cart', () => { });
|
||||||
|
it('should do nothing if item not in cart', () => { });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('calculateTotal', () => {
|
||||||
|
it('should return 0 for empty cart', () => { });
|
||||||
|
it('should sum all item prices', () => { });
|
||||||
|
it('should apply tax rate correctly', () => { });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Types of Tests
|
||||||
|
|
||||||
|
### 1. **Unit Tests**
|
||||||
|
Test individual functions/methods in isolation
|
||||||
|
```javascript
|
||||||
|
// Testing a pure function
|
||||||
|
describe('formatCurrency', () => {
|
||||||
|
it('should format USD correctly', () => {
|
||||||
|
expect(formatCurrency(1234.56, 'USD')).toBe('$1,234.56');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle zero', () => {
|
||||||
|
expect(formatCurrency(0, 'USD')).toBe('$0.00');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should round to 2 decimals', () => {
|
||||||
|
expect(formatCurrency(1.234, 'USD')).toBe('$1.23');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. **Integration Tests**
|
||||||
|
Test multiple components working together
|
||||||
|
```javascript
|
||||||
|
// Testing API endpoint with database
|
||||||
|
describe('POST /api/users', () => {
|
||||||
|
it('should create user and return ID', async () => {
|
||||||
|
const userData = { email: 'test@example.com', name: 'Test' };
|
||||||
|
const response = await request(app).post('/api/users').send(userData);
|
||||||
|
|
||||||
|
expect(response.status).toBe(201);
|
||||||
|
expect(response.body).toHaveProperty('id');
|
||||||
|
|
||||||
|
// Verify in database
|
||||||
|
const user = await db.users.findById(response.body.id);
|
||||||
|
expect(user.email).toBe(userData.email);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. **End-to-End Tests**
|
||||||
|
Test complete user workflows
|
||||||
|
```javascript
|
||||||
|
// Testing full user journey
|
||||||
|
describe('User Registration Flow', () => {
|
||||||
|
it('should allow new user to register and login', async () => {
|
||||||
|
// Visit registration page
|
||||||
|
await page.goto('/register');
|
||||||
|
|
||||||
|
// Fill form
|
||||||
|
await page.fill('#email', 'newuser@example.com');
|
||||||
|
await page.fill('#password', 'SecurePass123!');
|
||||||
|
await page.click('button[type="submit"]');
|
||||||
|
|
||||||
|
// Should redirect to dashboard
|
||||||
|
await expect(page).toHaveURL('/dashboard');
|
||||||
|
await expect(page.locator('.welcome-message')).toContainText('Welcome');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Doubles (Mocks, Stubs, Spies)
|
||||||
|
|
||||||
|
### When to Use Mocks
|
||||||
|
```javascript
|
||||||
|
// Mock external dependencies for unit tests
|
||||||
|
describe('UserService', () => {
|
||||||
|
it('should send welcome email on registration', async () => {
|
||||||
|
// Mock the email service
|
||||||
|
const mockEmailService = {
|
||||||
|
send: jest.fn().mockResolvedValue(true)
|
||||||
|
};
|
||||||
|
|
||||||
|
const userService = new UserService(mockEmailService);
|
||||||
|
await userService.registerUser({ email: 'test@example.com' });
|
||||||
|
|
||||||
|
// Verify email was sent
|
||||||
|
expect(mockEmailService.send).toHaveBeenCalledWith({
|
||||||
|
to: 'test@example.com',
|
||||||
|
template: 'welcome'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependency Injection for Testability
|
||||||
|
```typescript
|
||||||
|
// Bad: Hard to test
|
||||||
|
class UserService {
|
||||||
|
async createUser(data: UserData) {
|
||||||
|
await Database.save(data); // Direct dependency
|
||||||
|
await EmailService.send(data.email); // Hard to mock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Good: Easy to test
|
||||||
|
class UserService {
|
||||||
|
constructor(
|
||||||
|
private db: DatabaseService,
|
||||||
|
private email: EmailService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async createUser(data: UserData) {
|
||||||
|
await this.db.save(data);
|
||||||
|
await this.email.send(data.email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we can inject mocks in tests
|
||||||
|
```
|
||||||
|
|
||||||
|
## TDD Anti-Patterns to Avoid
|
||||||
|
|
||||||
|
### ❌ **Testing Implementation Details**
|
||||||
|
```javascript
|
||||||
|
// Bad: Tests implementation
|
||||||
|
test('should call helper function 3 times', () => {
|
||||||
|
const spy = jest.spyOn(obj, 'helperFunc');
|
||||||
|
obj.mainFunc();
|
||||||
|
expect(spy).toHaveBeenCalledTimes(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Good: Tests behavior
|
||||||
|
test('should return correct result', () => {
|
||||||
|
expect(obj.mainFunc()).toBe(expectedResult);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ **Overly Complex Tests**
|
||||||
|
```javascript
|
||||||
|
// Bad: Test is harder to understand than the code
|
||||||
|
test('complex test', () => {
|
||||||
|
const data = generateComplexData();
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
if (data[i].type === 'A') {
|
||||||
|
// ... complex logic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect(result).toBe(/* computed value */);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Good: Simple, focused test
|
||||||
|
test('should process type A items correctly', () => {
|
||||||
|
const item = { type: 'A', value: 10 };
|
||||||
|
expect(processItem(item)).toBe(20);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ **Test Interdependence**
|
||||||
|
```javascript
|
||||||
|
// Bad: Tests depend on each other
|
||||||
|
let userId;
|
||||||
|
test('create user', () => {
|
||||||
|
userId = createUser(); // Side effect
|
||||||
|
});
|
||||||
|
test('update user', () => {
|
||||||
|
updateUser(userId); // Depends on previous test
|
||||||
|
});
|
||||||
|
|
||||||
|
// Good: Each test is independent
|
||||||
|
test('create user', () => {
|
||||||
|
const userId = createUser();
|
||||||
|
expect(userId).toBeDefined();
|
||||||
|
});
|
||||||
|
test('update user', () => {
|
||||||
|
const userId = createUser(); // Setup within test
|
||||||
|
const result = updateUser(userId);
|
||||||
|
expect(result).toBe(true);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Coverage Targets
|
||||||
|
|
||||||
|
### Aim for High Coverage, Not 100%
|
||||||
|
- **Statements**: 80%+ (most lines executed)
|
||||||
|
- **Branches**: 75%+ (most if/else paths tested)
|
||||||
|
- **Functions**: 90%+ (most functions tested)
|
||||||
|
- **Lines**: 80%+ (most lines covered)
|
||||||
|
|
||||||
|
### What to Prioritize
|
||||||
|
1. **Critical business logic** - Must have 100% coverage
|
||||||
|
2. **Complex algorithms** - High coverage with edge cases
|
||||||
|
3. **Public APIs** - All entry points tested
|
||||||
|
4. **Error handling** - All error paths verified
|
||||||
|
|
||||||
|
### What's OK to Skip
|
||||||
|
- Trivial getters/setters
|
||||||
|
- Framework boilerplate
|
||||||
|
- Third-party library code
|
||||||
|
- Configuration files
|
||||||
|
|
||||||
|
## TDD Best Practices
|
||||||
|
|
||||||
|
### 1. **Write Tests First** (Truly!)
|
||||||
|
```
|
||||||
|
❌ Bad: Write code first, then add tests
|
||||||
|
✓ Good: Write failing test, then make it pass
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. **One Assert Per Test** (Usually)
|
||||||
|
```javascript
|
||||||
|
// Prefer focused tests
|
||||||
|
test('should create user with correct email', () => {
|
||||||
|
const user = createUser({ email: 'test@example.com' });
|
||||||
|
expect(user.email).toBe('test@example.com');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should create user with hashed password', () => {
|
||||||
|
const user = createUser({ password: 'secret' });
|
||||||
|
expect(user.password).not.toBe('secret');
|
||||||
|
expect(user.password).toMatch(/^\$2[aby]\$/);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. **Fast Tests**
|
||||||
|
```
|
||||||
|
- Unit tests: < 10ms each
|
||||||
|
- Integration tests: < 100ms each
|
||||||
|
- E2E tests: < 5s each
|
||||||
|
|
||||||
|
If slower, consider:
|
||||||
|
- Using test doubles
|
||||||
|
- Running in parallel
|
||||||
|
- Optimizing setup/teardown
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. **Reliable Tests**
|
||||||
|
```
|
||||||
|
Tests should:
|
||||||
|
- ✓ Pass consistently (no flakiness)
|
||||||
|
- ✓ Fail for the right reasons
|
||||||
|
- ✓ Be deterministic
|
||||||
|
- ✓ Not depend on external state
|
||||||
|
- ✓ Clean up after themselves
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. **Readable Tests**
|
||||||
|
```javascript
|
||||||
|
// Tests are documentation - make them clear
|
||||||
|
test('should allow user to checkout with valid cart', () => {
|
||||||
|
// Arrange: Create a realistic scenario
|
||||||
|
const cart = createCart();
|
||||||
|
cart.addItem({ id: 1, name: 'Widget', price: 9.99 });
|
||||||
|
const user = createUser({ hasPaymentMethod: true });
|
||||||
|
|
||||||
|
// Act: Perform the action
|
||||||
|
const result = checkout(cart, user);
|
||||||
|
|
||||||
|
// Assert: Verify expected outcome
|
||||||
|
expect(result.status).toBe('success');
|
||||||
|
expect(result.orderId).toBeDefined();
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## TDD Workflow with Todo System
|
||||||
|
|
||||||
|
```
|
||||||
|
When implementing a feature with TDD:
|
||||||
|
|
||||||
|
Feature: Shopping Cart
|
||||||
|
|
||||||
|
[ ] Write test cases list
|
||||||
|
[ ] RED: Test for adding first item
|
||||||
|
[ ] GREEN: Implement add item (simple)
|
||||||
|
[ ] REFACTOR: Clean up code
|
||||||
|
[ ] RED: Test for adding duplicate item
|
||||||
|
[ ] GREEN: Implement quantity increment
|
||||||
|
[ ] REFACTOR: Extract logic
|
||||||
|
[ ] RED: Test for removing item
|
||||||
|
[ ] GREEN: Implement remove item
|
||||||
|
[ ] REFACTOR: Final cleanup
|
||||||
|
[ ] Verify all tests pass
|
||||||
|
[ ] Check coverage report
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Use This Skill
|
||||||
|
|
||||||
|
- When starting any new feature or function
|
||||||
|
- When fixing bugs (write test that reproduces bug first)
|
||||||
|
- When refactoring (tests ensure behavior doesn't change)
|
||||||
|
- When code quality and reliability are critical
|
||||||
|
- When you want to move fast with confidence
|
||||||
|
|
||||||
|
## Example: TDD Session
|
||||||
|
|
||||||
|
```
|
||||||
|
Task: Implement a function to validate email addresses
|
||||||
|
|
||||||
|
TEST LIST:
|
||||||
|
- [ ] Valid email with standard format
|
||||||
|
- [ ] Invalid email without @
|
||||||
|
- [ ] Invalid email without domain
|
||||||
|
- [ ] Empty string
|
||||||
|
- [ ] Null/undefined input
|
||||||
|
- [ ] Email with special characters
|
||||||
|
- [ ] Email with subdomain
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
🔴 RED - Test 1:
|
||||||
|
```javascript
|
||||||
|
test('should return true for valid email', () => {
|
||||||
|
expect(isValidEmail('user@example.com')).toBe(true);
|
||||||
|
});
|
||||||
|
// ❌ FAILS: isValidEmail is not defined
|
||||||
|
```
|
||||||
|
|
||||||
|
🟢 GREEN - Minimal implementation:
|
||||||
|
```javascript
|
||||||
|
function isValidEmail(email) {
|
||||||
|
return email === 'user@example.com'; // Hardcoded!
|
||||||
|
}
|
||||||
|
// ✅ PASSES
|
||||||
|
```
|
||||||
|
|
||||||
|
🔴 RED - Test 2:
|
||||||
|
```javascript
|
||||||
|
test('should return false for email without @', () => {
|
||||||
|
expect(isValidEmail('userexample.com')).toBe(false);
|
||||||
|
});
|
||||||
|
// ❌ FAILS: Returns true (because of hardcode)
|
||||||
|
```
|
||||||
|
|
||||||
|
🟢 GREEN - Real implementation:
|
||||||
|
```javascript
|
||||||
|
function isValidEmail(email) {
|
||||||
|
return email.includes('@');
|
||||||
|
}
|
||||||
|
// ✅ PASSES both tests
|
||||||
|
```
|
||||||
|
|
||||||
|
🔴 RED - Test 3:
|
||||||
|
```javascript
|
||||||
|
test('should return false for empty string', () => {
|
||||||
|
expect(isValidEmail('')).toBe(false);
|
||||||
|
});
|
||||||
|
// ❌ FAILS
|
||||||
|
```
|
||||||
|
|
||||||
|
🟢 GREEN - Improved:
|
||||||
|
```javascript
|
||||||
|
function isValidEmail(email) {
|
||||||
|
return email && email.includes('@') && email.includes('.');
|
||||||
|
}
|
||||||
|
// ✅ PASSES all tests
|
||||||
|
```
|
||||||
|
|
||||||
|
🔵 REFACTOR - Polish:
|
||||||
|
```javascript
|
||||||
|
function isValidEmail(email) {
|
||||||
|
if (!email) return false;
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
return emailRegex.test(email);
|
||||||
|
}
|
||||||
|
// ✅ PASSES all tests, cleaner implementation
|
||||||
|
```
|
||||||
|
|
||||||
|
Continue with remaining test cases...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Remember**: TDD feels slower at first, but pays dividends in fewer bugs, better design, and faster debugging. Trust the process!
|
||||||
61
plugin.lock.json
Normal file
61
plugin.lock.json
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||||
|
"pluginId": "gh:samuelgarrett/claude-code-plugin-test:core-skills",
|
||||||
|
"normalized": {
|
||||||
|
"repo": null,
|
||||||
|
"ref": "refs/tags/v20251128.0",
|
||||||
|
"commit": "be5f7ec9a72dab114476d7ec1845202bb1d69962",
|
||||||
|
"treeHash": "918ef5a9eeac6b73c6f9bbd87ba835333cacf27866730d42fbe217af8a166596",
|
||||||
|
"generatedAt": "2025-11-28T10:28:07.450219Z",
|
||||||
|
"toolVersion": "publish_plugins.py@0.2.0"
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||||
|
"branch": "master",
|
||||||
|
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||||
|
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"name": "core-skills",
|
||||||
|
"description": "Essential universal skills for systematic, methodical, and efficient software development across all domains",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"sha256": "920951a6d86c457673606aa4a3023ed83858776773d9dde962a83d37851c2538"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": ".claude-plugin/plugin.json",
|
||||||
|
"sha256": "73b5705af72613832d208c85038936978de0c61697c0428817f240d5832564ea"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/code-reviewer.md",
|
||||||
|
"sha256": "df81016def686a1807a4064fc2056c8f2f5a80ab9081895980e5e44c80b38d2d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/tdd-expert.md",
|
||||||
|
"sha256": "6ce048cc4e35d127d70ca1af73a2b148523be5e1003cc3e2b3753c97cb9f1cdd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/systematic-planner.md",
|
||||||
|
"sha256": "3fdfeceb6390008a51fdaaed8ce6b9e54f84c92226e3f95c7e91fc27581920f7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/methodical-debugger.md",
|
||||||
|
"sha256": "27f9ee6c7b8130efe39b05a32fc37c40cfd818c0fd33ffc6079f19628d725954"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/refactoring-expert.md",
|
||||||
|
"sha256": "0906a6f5c401e2d54d2e6b60e8f7042945f1b9feefc40698864ed9bd4732c76b"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dirSha256": "918ef5a9eeac6b73c6f9bbd87ba835333cacf27866730d42fbe217af8a166596"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"scannedAt": null,
|
||||||
|
"scannerVersion": null,
|
||||||
|
"flags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user