code-reviewer
SKILL.md
Code Reviewer
Expert guidance for thorough, constructive code reviews that improve code quality and team practices.
When to Use This Skill
- Reviewing pull requests
- Establishing code review standards
- Identifying code quality issues
- Security vulnerability assessment
- Performance review
- Suggesting refactoring improvements
- Enforcing coding standards
- Mentoring through code review
Code Review Checklist
Functionality
- Does the code do what it's supposed to do?
- Are edge cases handled?
- Are error cases handled appropriately?
- Does it integrate correctly with existing code?
- Are there any off-by-one errors or boundary issues?
Code Quality
- Is the code easy to understand?
- Are variable/function names descriptive?
- Is there unnecessary complexity?
- Is there duplicated code?
- Are functions/methods appropriately sized?
Security
- Is user input validated and sanitized?
- Are there SQL injection vulnerabilities?
- Are there XSS vulnerabilities?
- Are secrets/credentials hardcoded?
- Is authentication/authorization implemented correctly?
Performance
- Are there obvious performance issues?
- Are database queries efficient?
- Is caching used appropriately?
- Are there unnecessary loops or iterations?
- Is memory usage reasonable?
Testing
- Are there sufficient tests?
- Do tests cover edge cases?
- Are tests readable and maintainable?
- Do tests actually verify behavior?
Documentation
- Is complex logic documented?
- Are public APIs documented?
- Is the README updated if needed?
- Are breaking changes documented?
SOLID Principles Review
Single Responsibility Principle (SRP)
❌ Violation:
class UserService {
async createUser(data: UserData) { /* creates user */ }
async sendWelcomeEmail(user: User) { /* sends email */ }
async generateReport(userId: string) { /* generates report */ }
async uploadAvatar(userId: string, file: File) { /* uploads file */ }
}
✅ Better:
class UserService {
async createUser(data: UserData) { /* creates user */ }
async findUser(id: string) { /* finds user */ }
}
class EmailService {
async sendWelcomeEmail(user: User) { /* sends email */ }
}
class ReportService {
async generateUserReport(userId: string) { /* generates report */ }
}
class AvatarService {
async uploadAvatar(userId: string, file: File) { /* uploads file */ }
}
Open/Closed Principle (OCP)
❌ Violation:
class PaymentProcessor {
process(payment: Payment) {
if (payment.type === 'credit_card') {
// process credit card
} else if (payment.type === 'paypal') {
// process paypal
} else if (payment.type === 'bitcoin') {
// process bitcoin - added later, modifying class
}
}
}
✅ Better:
interface PaymentMethod {
process(payment: Payment): Promise<Result>;
}
class CreditCardPayment implements PaymentMethod {
async process(payment: Payment) { /* credit card logic */ }
}
class PayPalPayment implements PaymentMethod {
async process(payment: Payment) { /* paypal logic */ }
}
// New payment methods don't require modifying existing code
class BitcoinPayment implements PaymentMethod {
async process(payment: Payment) { /* bitcoin logic */ }
}
Liskov Substitution Principle (LSP)
❌ Violation:
class Rectangle {
constructor(protected width: number, protected height: number) {}
setWidth(w: number) { this.width = w; }
setHeight(h: number) { this.height = h; }
getArea() { return this.width * this.height; }
}
class Square extends Rectangle {
setWidth(w: number) {
this.width = w;
this.height = w; // Unexpected side effect!
}
setHeight(h: number) {
this.width = h;
this.height = h;
}
}
// Breaks when substituted
function resize(rect: Rectangle) {
rect.setWidth(5);
rect.setHeight(10);
console.log(rect.getArea()); // Expected 50, Square gives 100
}
✅ Better:
interface Shape {
getArea(): number;
}
class Rectangle implements Shape {
constructor(private width: number, private height: number) {}
getArea() { return this.width * this.height; }
}
class Square implements Shape {
constructor(private side: number) {}
getArea() { return this.side * this.side; }
}
Interface Segregation Principle (ISP)
❌ Violation:
interface Worker {
work(): void;
eat(): void;
sleep(): void;
}
class Robot implements Worker {
work() { /* working */ }
eat() { throw new Error('Robots do not eat'); } // Forced to implement
sleep() { throw new Error('Robots do not sleep'); }
}
✅ Better:
interface Workable {
work(): void;
}
interface Eatable {
eat(): void;
}
interface Sleepable {
sleep(): void;
}
class Human implements Workable, Eatable, Sleepable {
work() { /* working */ }
eat() { /* eating */ }
sleep() { /* sleeping */ }
}
class Robot implements Workable {
work() { /* working */ }
}
Dependency Inversion Principle (DIP)
❌ Violation:
class MySQLDatabase {
query(sql: string) { /* MySQL specific */ }
}
class UserRepository {
private database = new MySQLDatabase(); // Direct dependency
findById(id: string) {
return this.database.query(`SELECT * FROM users WHERE id = '${id}'`);
}
}
✅ Better:
interface Database {
query<T>(sql: string, params?: any[]): Promise<T>;
}
class UserRepository {
constructor(private database: Database) {} // Injected dependency
findById(id: string) {
return this.database.query('SELECT * FROM users WHERE id = ?', [id]);
}
}
// Can use any database implementation
const repo = new UserRepository(new MySQLDatabase());
const testRepo = new UserRepository(new InMemoryDatabase());
Clean Code Principles
Naming Conventions
// Variables: descriptive, pronounceable
// ❌ Bad
const d = new Date();
const u = getUser();
const arr = items.filter(x => x > 0);
// ✅ Good
const currentDate = new Date();
const currentUser = getUser();
const positiveNumbers = items.filter(num => num > 0);
// Functions: verb + noun, describe action
// ❌ Bad
function data() { }
function process() { }
function handleIt() { }
// ✅ Good
function fetchUserProfile() { }
function calculateTotalPrice() { }
function handleFormSubmission() { }
// Booleans: is/has/can/should prefix
// ❌ Bad
const active = true;
const admin = false;
// ✅ Good
const isActive = true;
const isAdmin = false;
const hasPermission = true;
const canEdit = false;
Function Guidelines
// Keep functions small (ideally < 20 lines)
// Single level of abstraction
// ❌ Bad: Multiple abstraction levels
async function processOrder(order: Order) {
// Validation (low level)
if (!order.items.length) throw new Error('Empty order');
if (!order.userId) throw new Error('No user');
// Calculate total (medium level)
let total = 0;
for (const item of order.items) {
total += item.price * item.quantity;
}
// Apply discount (medium level)
if (order.coupon) {
total *= (1 - order.coupon.discount);
}
// Save to database (low level)
await db.orders.insert({ ...order, total });
// Send email (low level)
await emailService.send(order.userId, 'order_confirmation', { order });
}
// ✅ Good: Single level of abstraction
async function processOrder(order: Order) {
validateOrder(order);
const total = calculateOrderTotal(order);
await saveOrder(order, total);
await sendOrderConfirmation(order);
}
Avoid Magic Numbers/Strings
// ❌ Bad
if (user.role === 'admin') { }
if (retries > 3) { }
const timeout = 5000;
// ✅ Good
const ROLES = {
ADMIN: 'admin',
USER: 'user',
} as const;
const MAX_RETRIES = 3;
const DEFAULT_TIMEOUT_MS = 5000;
if (user.role === ROLES.ADMIN) { }
if (retries > MAX_RETRIES) { }
const timeout = DEFAULT_TIMEOUT_MS;
Error Handling
// ❌ Bad: Swallowing errors
try {
await riskyOperation();
} catch (e) {
// silently ignore
}
// ❌ Bad: Generic error handling
try {
await riskyOperation();
} catch (e) {
console.log('Error');
}
// ✅ Good: Specific error handling
try {
await riskyOperation();
} catch (error) {
if (error instanceof ValidationError) {
logger.warn('Validation failed', { error: error.message });
throw new BadRequestError(error.message);
}
if (error instanceof NotFoundError) {
return null; // Expected case
}
logger.error('Unexpected error in riskyOperation', { error });
throw error; // Re-throw unknown errors
}
Security Review Checklist
Input Validation
// ❌ Dangerous: No validation
app.post('/users', (req, res) => {
db.query(`INSERT INTO users (name) VALUES ('${req.body.name}')`);
});
// ✅ Safe: Validated and parameterized
app.post('/users', (req, res) => {
const schema = z.object({
name: z.string().min(1).max(100).regex(/^[a-zA-Z\s]+$/),
});
const result = schema.safeParse(req.body);
if (!result.success) {
return res.status(422).json({ error: result.error });
}
db.query('INSERT INTO users (name) VALUES ($1)', [result.data.name]);
});
Authentication/Authorization
// ❌ Missing authorization check
app.delete('/users/:id', async (req, res) => {
await userService.delete(req.params.id);
res.status(204).send();
});
// ✅ With authorization
app.delete('/users/:id',
requireAuth,
requirePermission('users:delete'),
async (req, res) => {
// Additional check: can only delete own account unless admin
if (req.user.id !== req.params.id && !req.user.isAdmin) {
return res.status(403).json({ error: 'Cannot delete other users' });
}
await userService.delete(req.params.id);
res.status(204).send();
}
);
Secrets Management
// ❌ Hardcoded secrets
const API_KEY = 'sk_live_abc123xyz';
const DB_PASSWORD = 'supersecret';
// ✅ Environment variables
const API_KEY = process.env.API_KEY;
const DB_PASSWORD = process.env.DB_PASSWORD;
if (!API_KEY || !DB_PASSWORD) {
throw new Error('Missing required environment variables');
}
Performance Review
Database Queries
// ❌ N+1 Problem
const users = await db.users.findAll();
for (const user of users) {
user.orders = await db.orders.findByUserId(user.id); // N queries!
}
// ✅ Eager loading
const users = await db.users.findAll({
include: [{ model: Order }],
});
// ❌ Missing index
SELECT * FROM orders WHERE status = 'pending' ORDER BY created_at;
// ✅ Add index for frequent queries
CREATE INDEX idx_orders_status_created ON orders(status, created_at);
Unnecessary Work
// ❌ Recalculating in loop
items.forEach(item => {
const tax = calculateTax(item.price); // Same calculation
const discount = getDiscount(); // Same for all items
process(item, tax, discount);
});
// ✅ Calculate once
const discount = getDiscount();
items.forEach(item => {
const tax = calculateTax(item.price);
process(item, tax, discount);
});
Review Comment Guidelines
Comment Types
🔴 Blocker: Must be fixed before merge
🟡 Suggestion: Should consider, but not required
🟢 Nitpick: Minor style/preference issue
💬 Question: Seeking clarification
📚 FYI: Educational information
Writing Good Comments
❌ Bad comments:
"This is wrong"
"Fix this"
"???"
✅ Good comments:
"This could throw if `user` is null. Consider adding a null check:
`if (!user) return null;`"
"Nice use of the factory pattern here! One suggestion: we could
make this more flexible by accepting an options object."
"Question: Is there a reason we're not using the existing
`formatDate` utility here? It handles timezone conversion."
Constructive Feedback
| Instead of... | Say... |
|---|---|
| "This is wrong" | "This might cause X when Y happens" |
| "Don't do this" | "Consider X instead because..." |
| "Why did you...?" | "I'm curious about the reasoning for..." |
| "Obviously..." | (Just explain without condescension) |
Code Review Process
Before Review
- Read the PR description: Understand the context
- Check linked issues: Know the requirements
- Build and test locally: Verify it works
- Review tests first: Understand expected behavior
During Review
- Start with high-level feedback: Architecture, approach
- Then dive into details: Implementation specifics
- Check for completeness: Tests, docs, migrations
- Look for patterns: Systemic issues vs. one-offs
After Review
- Summarize feedback: Overall assessment
- Prioritize issues: What must be fixed vs. nice-to-have
- Offer to pair: If changes are complex
- Re-review promptly: Don't block progress
Output Artifacts
When this skill is activated, I can help create:
- Code Review: Detailed review with categorized feedback
- Review Checklist: Custom checklist for specific codebases
- Refactoring Suggestions: Specific improvements with examples
- Security Audit: Security-focused review findings
- Performance Analysis: Performance issue identification
- Code Standards Document: Team coding guidelines
- Review Guidelines: Team code review process
Weekly Installs
2
Repository
navedanan/backg…-removerFirst Seen
11 days ago
Security Audits
Installed on
opencode2
gemini-cli2
claude-code2
github-copilot2
windsurf2
codex2