Reviews code using SOLID principles (SRP, OCP, LSP, ISP, DIP), DRY, KISS, YAGNI, and best practices for quality standards.
npx claudepluginhub sequenzia/agent-alchemy --plugin agent-alchemy-dev-toolsThis skill uses the workspace's default tool permissions.
This skill provides code quality principles and best practices for reviewing and improving implementations.
Provides language-agnostic SOLID principles, design patterns, DRY, KISS guidelines for code reviews, architecture analysis, refactoring, and design decisions.
Applies KISS, YAGNI, and SOLID principles with Python and Rust examples to simplify code, reduce complexity, and prevent over-engineering during refactoring and reviews.
Applies SOLID principles, TDD, and clean code practices for writing code, refactoring, architecture planning, code review, and debugging.
Share bugs, ideas, or general feedback.
This skill provides code quality principles and best practices for reviewing and improving implementations.
A class/function should have one reason to change.
Bad:
class UserService {
createUser(data) { /* creates user */ }
sendEmail(user) { /* sends email */ }
generateReport(users) { /* generates report */ }
}
Good:
class UserService {
createUser(data) { /* creates user */ }
}
class EmailService {
sendEmail(user) { /* sends email */ }
}
class ReportService {
generateReport(users) { /* generates report */ }
}
Open for extension, closed for modification.
Bad: Adding new payment types requires modifying existing code
function processPayment(type, amount) {
if (type === 'credit') { /* ... */ }
else if (type === 'debit') { /* ... */ }
// Must modify to add new types
}
Good: New payment types can be added without modification
interface PaymentProcessor {
process(amount: number): Promise<void>;
}
class CreditProcessor implements PaymentProcessor { /* ... */ }
class DebitProcessor implements PaymentProcessor { /* ... */ }
Subtypes must be substitutable for their base types.
Bad:
class Bird {
fly() { /* ... */ }
}
class Penguin extends Bird {
fly() { throw new Error("Can't fly!"); } // Violates LSP
}
Good:
class Bird { /* ... */ }
class FlyingBird extends Bird {
fly() { /* ... */ }
}
class Penguin extends Bird { /* no fly method */ }
Clients shouldn't depend on interfaces they don't use.
Bad:
interface Worker {
work(): void;
eat(): void;
sleep(): void;
}
Good:
interface Workable { work(): void; }
interface Eatable { eat(): void; }
interface Sleepable { sleep(): void; }
Depend on abstractions, not concretions.
Bad:
class UserService {
private db = new PostgresDatabase();
}
Good:
class UserService {
constructor(private db: Database) {}
}
Every piece of knowledge should have a single representation.
Apply when:
Don't over-apply:
Prefer simple solutions over clever ones.
Simple code:
Don't add functionality until it's needed.
Avoid:
// Bad
const d = new Date();
const arr = users.filter(u => u.a > 18);
// Good
const currentDate = new Date();
const adultUsers = users.filter(user => user.age > 18);
// Bad: side effect hidden in getter
getUser() {
this.lastAccess = Date.now(); // Side effect!
return this.user;
}
// Good: explicit about what it does
getUser() {
return this.user;
}
recordAccess() {
this.lastAccess = Date.now();
}
// Be specific about errors
class ValidationError extends Error {}
class NotFoundError extends Error {}
class AuthorizationError extends Error {}
// Handle at appropriate level
try {
await processOrder(order);
} catch (error) {
if (error instanceof ValidationError) {
return res.status(400).json({ error: error.message });
}
if (error instanceof NotFoundError) {
return res.status(404).json({ error: error.message });
}
throw error; // Re-throw unexpected errors
}
/\
/ \ E2E Tests (few)
/────\
/ \ Integration Tests (some)
/────────\
/ \ Unit Tests (many)
/────────────\
describe('calculateTotal', () => {
it('sums item prices', () => {
const items = [{ price: 10 }, { price: 20 }];
expect(calculateTotal(items)).toBe(30);
});
it('applies discount', () => {
const items = [{ price: 100 }];
expect(calculateTotal(items, { discount: 0.1 })).toBe(90);
});
it('handles empty cart', () => {
expect(calculateTotal([])).toBe(0);
});
});
// Bad: tests implementation details
it('calls _internalMethod', () => {
const spy = jest.spyOn(service, '_internalMethod');
service.doThing();
expect(spy).toHaveBeenCalled();
});
// Good: tests behavior
it('sends welcome email on registration', async () => {
await service.registerUser({ email: 'test@test.com' });
expect(emailSent).toContainEqual({
to: 'test@test.com',
template: 'welcome'
});
});
| Smell | Description | Solution |
|---|---|---|
| Long Method | Function > 20-30 lines | Extract methods |
| Large Class | Class with too many responsibilities | Split into focused classes |
| Long Parameter List | > 3-4 parameters | Use parameter object |
| Duplicate Code | Same code in multiple places | Extract function |
| Dead Code | Unused code | Delete it |
| Magic Numbers | Unexplained numeric literals | Use named constants |
| Nested Conditionals | Deep if/else nesting | Early returns, extract methods |
| Feature Envy | Method uses another class's data heavily | Move method to that class |
When a code block can be grouped and named
When the function body is as clear as the name
When an expression is complex
When the name doesn't communicate intent
When you have repeated switch/if statements on type
When several parameters travel together