Examples & Patterns
No Silent Fallbacks
Fallbacks that silently handle errors can mask real problems. Prefer explicit error handling.
---
id: no-silent-fallbacks
version: 1.0.0
patterns:
- "**/*.ts"
- "**/*.tsx"
context_files: []
---
# No Silent Fallbacks
Fallbacks that silently handle errors or missing data can mask real problems.
## Guidelines
1. **Avoid silent fallbacks in error handling**
- Don't catch errors and silently continue
- Don't use default values that hide missing data
2. **Prefer explicit error handling**
- Log errors so we know they occurred
- Throw errors or return error states
- Fail fast rather than continuing with invalid data
## Examples
```typescript
// ❌ Bad - Silent fallback hides API failure
const fetchData = async () => {
try {
const response = await fetch('/api/data')
return (await response.json()).items || [] // Hides failure
} catch (error) {
return [] // Hides error
}
}
// ✅ Good - Explicit error handling
const fetchData = async () => {
const response = await fetch('/api/data')
if (!response.ok) {
throw new Error(`API failed: ${response.status}`)
}
const data = await response.json()
if (!data.items) {
throw new Error('Invalid response structure')
}
return data.items
}
```React Component Over-Abstraction
Avoid "prop soup" and premature abstraction. Components overloaded with props become unmaintainable. Sometimes duplication is better than over-abstraction.
---
id: react-component-over-abstraction
version: 1.0.0
patterns:
- "**/*.tsx"
- "**/components/**/*.ts"
- "**/components/**/*.tsx"
context_files: []
---
# React Component Over-Abstraction
Over-emphasizing "reusability" often leads to "prop soup": components overloaded with props to handle every possible variation. This creates abstractions that become difficult to maintain and modify.
## Guidelines
1. **Avoid "prop soup"**
- Components with 10+ props are a code smell
- Components with 20+ props exceed reasonable complexity
- Prefer composition over configuration
- Sometimes duplication is better than entanglement
2. **Avoid premature abstraction**
- Don't abstract until you've seen 3-4 real use cases
- Abstraction without proven reuse is speculation
- Every abstraction adds cognitive overhead
3. **Keep components simple and context-aware**
- Components should be easy to understand
- Prefer self-contained components over generic ones
- It's acceptable to have similar components that are 80% the same
4. **Know when reuse stops being efficient**
- If modifying a component risks breaking unrelated features, it's over-abstracted
- If a component has many conditional branches, split it
- Reuse should serve clarity, not the other way around
## Examples
```typescript
// ❌ Bad - "Prop soup" - too many props, hard to understand and maintain
<Button
variant="primary"
size="large"
icon="arrow"
iconPosition="left"
loading={false}
disabled={false}
onClick={handleClick}
onHover={handleHover}
onFocus={handleFocus}
ariaLabel="..."
dataTestId="..."
className="..."
style={...}
theme="dark"
rounded={true}
shadow={true}
fullWidth={false}
tooltip="..."
badge={...}
/>
// ❌ Bad - Over-abstracted mega-component with conditional branches
function UniversalForm({ type, ...props }) {
if (type === 'login') {
// login logic
} else if (type === 'register') {
// register logic
} else if (type === 'password-reset') {
// reset logic
}
// ... 20 more conditionals
}
// ✅ Good - Focused, composable, easy to understand
<Button variant="primary" onClick={handleClick}>
<Icon name="arrow" />
Submit
</Button>
// ✅ Good - Simple, self-contained components (even if similar)
function LoginForm() {
// Simple, focused login form
}
function RegisterForm() {
// Simple, focused register form
// Similar to LoginForm but independent
}
```SQL Query Complexity
Complex SQL queries are hard to maintain and optimize. Break them into simpler queries.
---
id: sql-query-complexity
version: 1.0.0
patterns:
- "**/*.sql"
- "**/queries/**"
context_files:
- "schema.sql"
---
# SQL Query Complexity
Keep SQL queries simple and maintainable.
## Guidelines
1. **Limit table joins**
- Maximum 5 tables per query
- Maximum join depth of 2
2. **Break complex queries apart**
- Split into multiple simpler queries
- Use application logic to combine results
- Consider separate endpoints for complex data needs
3. **Prefer readability over cleverness**
- Simple queries are easier to optimize
- Easier to debug and maintain
## Examples
```sql
-- ❌ Bad - Too many tables, complex joins
SELECT u.*, p.*, o.*, i.*, r.*, c.*
FROM users u
JOIN profiles p ON u.id = p.user_id
JOIN orders o ON u.id = o.user_id
JOIN items i ON o.id = i.order_id
JOIN reviews r ON i.id = r.item_id
JOIN categories c ON i.category_id = c.id
WHERE u.status = 'active';
-- ✅ Good - Simpler, focused query
SELECT u.*, p.*
FROM users u
JOIN profiles p ON u.id = p.user_id
WHERE u.status = 'active';
```Writing Your Own
Good threadlines are:
- Specific: Focus on one concern
- Actionable: Clear guidelines developers can follow
- Well-documented: Include examples and reasoning
- Pattern-matched: Use glob patterns to target relevant files