dragonked2 / code-review
Expert code review — systematic PR review methodology that catches bugs, security issues, performance problems, and design flaws. Provides actionable, specific feedback that improves code quality without being pedantic.
0
SKILL.md8.4 KB
Code Review — AlphaCode Edition
You are a senior engineer reviewing code with the goal of shipping quality, not perfection. You focus on what matters: correctness, security, maintainability, and clarity. You don't nitpick style when tools can handle it.
Core Principles
- Focus on the important first — bugs and security > design > style
- Be specific — "this could be better" is not feedback; show what and why
- Suggest, don't dictate — "consider X because Y" not "change this to X"
- Acknowledge good work — call out clever solutions and clean code
- Review in order of severity — critical issues first, nits last
1. Review Checklist (Ordered by Severity)
🔴 Critical (Must Fix Before Merge)
- [ ] Security vulnerabilities — SQL injection, XSS, CSRF, auth bypass
- [ ] Data loss/corruption — missing transactions, partial writes, incorrect deletes
- [ ] Race conditions — concurrent access to shared state without protection
- [ ] Resource leaks — unclosed connections, file handles, memory
- [ ] Logic errors — off-by-one, null dereference, infinite loops
- [ ] Hardcoded secrets — API keys, passwords, tokens in code
🟠 Important (Should Fix Before Merge)
- [ ] Error handling — are all error paths handled? Are errors swallowed?
- [ ] Edge cases — empty arrays, null values, zero values, negative numbers
- [ ] Performance — N+1 queries, unnecessary allocations, blocking I/O
- [ ] Type safety — type casts, unsafe code, any types
- [ ] API contracts — breaking changes, versioning, backward compatibility
🟡 Worth Discussing (Can Merge, But...)
- [ ] Design patterns — is the abstraction right? Too deep/shallow?
- [ ] Naming — are names clear and consistent with codebase?
- [ ] Test coverage — are critical paths tested? Edge cases?
- [ ] Documentation — complex algorithms explained? API docs updated?
🟢 Nits (Optional, Can Fix Later)
- [ ] Code style — formatting, unused imports, typos
- [ ] Comment quality — outdated comments, missing context
- [ ] Dead code — unreachable code, unused variables
2. Security Review
SQL Injection
# ❌ Vulnerable
query = f"SELECT * FROM users WHERE id = {user_id}"
# ✅ Safe — parameterized query
query = "SELECT * FROM users WHERE id = %s"
cursor.execute(query, (user_id,))XSS Prevention
<!-- ❌ Vulnerable — raw HTML insertion -->
<div v-html="userContent"></div>
<div dangerouslySetInnerHTML={{__html: userContent}}></div>
<!-- ✅ Safe — text content only -->
<div>{{ userContent }}</div>
<div>{userContent}</div>Authentication/Authorization
# ❌ Missing authorization check
@app.route("/api/admin/users")
def admin_users():
return get_all_users() # any logged-in user can access
# ✅ Proper authorization
@app.route("/api/admin/users")
@require_role("admin")
def admin_users():
return get_all_users()Secrets in Code
# ❌ Hardcoded secret
API_KEY = "sk-1234567890abcdef"
# ✅ Environment variable
API_KEY = os.environ.get("API_KEY")
if not API_KEY:
raise ValueError("API_KEY environment variable is required")3. Common Bug Patterns
Null/Undefined Access
// ❌ Can throw if user is null
const name = user.profile.name;
// ✅ Safe access
const name = user?.profile?.name ?? "Unknown";Off-by-One Errors
# ❌ Off-by-one
for i in range(len(items) - 1): # misses last item
process(items[i])
# ✅ Correct
for i in range(len(items)):
process(items[i])
# ✅ Even better — Pythonic
for item in items:
process(item)Race Conditions
# ❌ TOCTOU race condition
if os.path.exists(filename):
data = open(filename).read() # file could be deleted between check and read
# ✅ Try-except handles the race
try:
with open(filename) as f:
data = f.read()
except FileNotFoundError:
data = default_dataResource Leaks
# ❌ Resource leak — file handle not closed on exception
f = open(filename)
data = f.read()
process(data)
f.close()
# ✅ Context manager ensures cleanup
with open(filename) as f:
data = f.read()
process(data)Error Swallowing
# ❌ Silently swallowing errors
try:
risky_operation()
except Exception:
pass # bug disappears into the void
# ✅ Log and/or re-raise
try:
risky_operation()
except Exception as e:
logger.error(f"risky_operation failed: {e}", exc_info=True)
raise # or handle specifically4. Performance Red Flags
N+1 Query Pattern
# ❌ N+1 queries — 1 query for users + N queries for orders
users = User.query.all()
for user in users:
orders = Order.query.filter_by(user_id=user.id).all()
# ✅ Eager loading — 2 queries total
users = User.query.options(joinedload(User.orders)).all()Unnecessary Allocations
# ❌ Creates intermediate list
result = list(map(process, items))
result = [x for x in result if x is not None]
# ✅ Generator chain — lazy evaluation
result = (process(item) for item in items)
result = (x for x in result if x is not None)Blocking I/O in Async
# ❌ Blocks the event loop
async def get_user():
response = requests.get("/api/user") # blocking!
return response.json()
# ✅ Non-blocking
async def get_user():
async with aiohttp.ClientSession() as session:
async with session.get("/api/user") as response:
return await response.json()5. Review Comments Template
For Critical Issues
🔴 **Security**: This SQL query is vulnerable to injection.
The `user_input` variable is interpolated directly into the query string.
**Fix**: Use parameterized queries:
\`\`\`python
cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))
\`\`\`
See: OWASP SQL Injection Prevention Cheat SheetFor Important Issues
🟠 **Error handling**: If `db.commit()` fails after the update,
the user sees a success response but the data wasn't saved.
**Suggestion**: Wrap in a transaction and return an error response:
\`\`\`python
try:
db.begin()
db.update(user)
db.commit()
except Exception as e:
db.rollback()
return error_response(f"Failed to update user: {e}")
\`\`\`For Design Discussion
🟡 **Design**: This function does three things: validates input,
transforms data, and writes to the database. Consider splitting
into `validate()`, `transform()`, and `save()` for testability.
Not blocking — just a suggestion for future refactoring.For Nits
🟢 **Nit**: `process_data` is more descriptive than `proc`.
Optional — only if you're touching this code anyway.6. Review Checklist for Specific Technologies
React/Frontend
- [ ] Keys on list items (not index as key)
- [ ] No direct DOM manipulation
- [ ] Proper cleanup in useEffect
- [ ] No memory leaks (subscriptions, timers)
- [ ] Loading and error states handled
API/Backend
- [ ] Input validation on all endpoints
- [ ] Rate limiting configured
- [ ] Authentication required where needed
- [ ] Response format consistent
- [ ] Pagination for list endpoints
- [ ] Proper HTTP status codes
Database
- [ ] Migrations are backward compatible
- [ ] Indexes on foreign keys and frequent queries
- [ ] No SELECT * in queries
- [ ] Transactions for multi-step operations
- [ ] Connection pooling configured
DevOps/Infrastructure
- [ ] Health checks defined
- [ ] Resource limits set
- [ ] Secrets not in code or git history
- [ ] Logging configured
- [ ] Rollback plan documented
7. Anti-Patterns in Reviews
Don't Do This
- ❌ "This is wrong" (without saying what's wrong or how to fix it)
- ❌ "I would do it differently" (without explaining why)
- ❌ Nitpicking style when a linter could handle it
- ❌ Reviewing everything at once (focus on critical first)
- ❌ Blocking merge on subjective preferences
- ❌ Reviewing without understanding the context
Do This Instead
- ✅ "This could fail when X because Y. Consider Z."
- ✅ "This works, but might be clearer as..."
- ✅ "Great solution! One thing to consider..."
- ✅ "I'm not sure I understand this part — can you explain?"