| name | code-review-guide |
| description | Comprehensive code review process, checklists, and best practices |
| version | 1.0.0 |
| category | development |
| tags | ["code-review","quality","collaboration","pr"] |
| author | ZGO Team |
| updated | "2026-01-24T00:00:00.000Z" |
Code Review Guide
📋 Purpose
This skill provides a comprehensive guide to performing effective code reviews in the ZGO project, ensuring code quality, knowledge sharing, and team collaboration.
🎯 When to Use
- As a Reviewer: When reviewing a Pull Request
- As an Author: Before submitting a Pull Request
- As a Team Lead: Setting up review standards
- Onboarding: Teaching new team members review practices
⚙️ Prerequisites
🔄 The 4-Phase Review Process
Phase 1: Pre-Review (Author Self-Check) ⏱️ 5 minutes
Before creating a PR, authors must:
make test
make lint
go fmt ./...
.agent/skills/coding-standards/scripts/verify-standards.sh <module>
.agent/skills/api-development/scripts/validate-api.sh <module>
git diff main...HEAD
Pre-Review Checklist:
Phase 2: First Pass (Structure & Design) ⏱️ 10-15 minutes
Focus: High-level design, architecture, approach
What to Check:
1. PR Description Quality
✅ Good PR Description:
## What
Implemented user authentication with JWT tokens
## Why
Users need secure login without storing passwords in session
## How
- Added JWT middleware
- Created auth service with token generation
- Added login/logout endpoints
- Migrated password hashing to bcrypt
## Testing
- Unit tests for auth service
- Integration tests for login flow
- Manual testing with Postman
## Screenshots
[Login flow screenshot]
## Checklist
- [x] Tests passing
- [x] Documentation updated
- [x] Breaking changes documented
2. Architecture & Design
func (h *Handler) Create(c *gin.Context) {
var req CreateRequest
if !handler.BindJSON(c, &req) {
return
}
user, err := h.service.Create(c.Request.Context(), &req)
response.Success(c, ToResponse(user))
}
func (h *Handler) Create(c *gin.Context) {
var po UserPO
c.BindJSON(&po)
h.db.Create(&po)
c.JSON(200, po)
}
Review Questions:
Comments to Leave:
🏗️ **Architecture**: This violates layer separation. Handlers should not
access repositories directly. Please route through the service layer.
💡 **Suggestion**: Consider using the Circuit Breaker pattern for this
external API call to prevent cascading failures.
⚠️ **Concern**: This approach will create N+1 query problem. Consider
using eager loading or batch fetching.
Phase 3: Deep Dive (Implementation) ⏱️ 20-30 minutes
Focus: Code quality, correctness, edge cases
1. Naming & Conventions
type UserPO struct { ... }
type CreateUserRequest struct { ... }
func GetByEmail(email string) { ... }
type User struct { ... }
type CreateUserDTO struct { ... }
func Get(param string) { ... }
Check:
2. Error Handling
user, err := s.repo.GetByID(ctx, id)
if err != nil {
if errors.Is(err, repository.ErrNotFound) {
return nil, ErrUserNotFound
}
return nil, fmt.Errorf("failed to get user %d: %w", id, err)
}
user, _ := s.repo.GetByID(ctx, id)
user, err := s.repo.GetByID(ctx, id)
if err != nil {
return nil, err
}
user, err := s.repo.GetByID(ctx, id)
if err != nil {
log.Println(err)
return nil, nil
}
Check:
3. Security
hash, err := crypto.HashPassword(req.Password)
if err != nil {
return nil, err
}
user.Password = hash
type User struct {
Password string `json:"-"`
}
user.Password = req.Password
log.Printf("User password: %s", password)
db.Where("username = '" + username + "'")
Check:
4. Performance
users, err := db.Preload("Profile").Find(&users)
users, _ := db.Find(&users)
for _, user := range users {
profile, _ := db.Where("user_id = ?", user.ID).First(&profile)
}
paginator, err := pagination.PaginateFromContext[*domain.User](c, db)
var users []User
db.Find(&users)
Check:
5. Testing
func TestService_Create_Success(t *testing.T) {
mockRepo := new(MockRepository)
service := NewService(mockRepo)
req := &CreateUserRequest{
Email: "test@example.com",
Username: "testuser",
}
mockRepo.On("Create", mock.Anything, mock.MatchedBy(func(user *domain.User) bool {
return user.Email == req.Email
})).Return(nil)
user, err := service.Create(context.Background(), req)
assert.NoError(t, err)
assert.NotNil(t, user)
assert.Equal(t, req.Email, user.Email)
mockRepo.AssertExpectations(t)
}
func TestCreate(t *testing.T) {
service.Create(context.Background(), &req)
}
Check:
Phase 4: Final Review (Polish) ⏱️ 5-10 minutes
Focus: Documentation, readability, maintainability
1. Code Comments
func HashPassword(password string) (string, error) {
if password == "" {
return "", errors.New("password cannot be empty")
}
hash, err := bcrypt.GenerateFromPassword([]byte(password), 10)
return string(hash), err
}
func HashPassword(password string) (string, error) {
hash, err := bcrypt.GenerateFromPassword([]byte(password), 10)
return string(hash), err
}
func GetUser(id uint) {
return db.First(id)
}
Check:
2. Swagger Documentation
func (h *Handler) Create(c *gin.Context) {
}
func (h *Handler) Create(c *gin.Context) {
}
3. Code Readability
func (s *service) IsEligibleForDiscount(user *domain.User, order *domain.Order) bool {
isPremiumMember := user.Tier == "premium"
isLargeOrder := order.Total > 100
isFirstOrder := user.OrderCount == 0
return isPremiumMember || isLargeOrder || isFirstOrder
}
func (s *service) IsEligibleForDiscount(u *domain.User, o *domain.Order) bool {
return u.Tier == "premium" || o.Total > 100 || u.OrderCount == 0
}
Check:
📝 Review Feedback Guidelines
✅ Good Feedback
1. Be Specific
❌ Bad: "This is wrong"
✅ Good: "The error is not being handled on line 45. This could cause a panic
if the database connection fails. Consider wrapping with an error check."
2. Be Constructive
❌ Bad: "This code is terrible"
✅ Good: "This approach works, but could be improved. Consider using the
repository pattern to separate data access concerns. See module-creation
skill for examples."
3. Ask Questions
✅ "Could you explain why you chose to use a goroutine here? I'm concerned
about potential race conditions."
✅ "Have you considered using the Circuit Breaker pattern for this external
API call? See coding-standards skill section 9.2."
4. Provide Context
✅ "According to our API standards (api-development skill), all list endpoints
must use pagination. Can you add pagination.PaginateFromContext() here?"
✅ "This violates our naming convention. Database entities should have 'PO'
suffix. See coding-standards Level 2 for details."
5. Praise Good Work
✅ "Great use of the Circuit Breaker pattern here! This will prevent cascading
failures if the payment gateway goes down."
✅ "Excellent test coverage! I appreciate the edge case tests."
✅ "This is a clean implementation of the repository pattern."
❌ Avoid
- Personal attacks or judgment
- Vague comments ("fix this", "bad code")
- Nitpicking without reasoning
- Blocking on style preferences
- Demanding changes without explanation
🎯 Priority Levels
🔴 MUST FIX (Blocking)
- Security vulnerabilities
- Breaking changes without migration
- Violations of architecture standards
- Failing tests
- Critical bugs
- Data loss risks
Example:
🔴 **MUST FIX**: SQL injection vulnerability on line 67. User input is
concatenated directly into query. Use parameterized queries instead:
db.Where("email = ?", email) // ✅ Safe
not: db.Where("email = '" + email + "'") // ❌ Vulnerable
🟡 SHOULD FIX (Important)
- Missing error handling
- Missing tests
- Performance issues
- Naming violations
- Missing documentation
- Code duplication
Example:
🟡 **Should Fix**: Error is ignored on line 34. This could hide failures.
Please add error handling:
if err != nil {
return fmt.Errorf("failed to create user: %w", err)
}
🟢 CONSIDER (Suggestions)
- Code style improvements
- Refactoring opportunities
- Alternative approaches
- Minor optimizations
- Nice-to-have features
Example:
🟢 **Consider**: This function could be simplified using the MultiError
pattern from coding-standards skill section 9.5. Not blocking, but would
improve error visibility in batch operations.
📋 Review Checklists
Quick Review Checklist (10 min)
For small changes (< 100 lines):
Full Review Checklist (30 min)
For significant changes:
Architecture (5 min):
Code Quality (10 min):
Testing (5 min):
Documentation (5 min):
API Standards (5 min):
Expert Review Checklist (60 min)
For critical or complex changes:
Deep Architecture Review:
Security Audit:
Performance Analysis:
🤝 PR Author Responsibilities
Before Creating PR
- Self-Review: Review your own changes first
- Run Checks: All tests and linters passing
- Write Description: Clear "what, why, how"
- Add Tests: Ensure coverage > 80%
- Update Docs: README, CHANGELOG, comments
During Review
- Respond Promptly: Within 24 hours
- Be Open: Accept feedback gracefully
- Ask Questions: If feedback unclear
- Make Changes: Address all blocking issues
- Explain Decisions: When disagreeing with feedback
After Approval
- Merge Promptly: Don't leave approved PRs open
- Monitor: Watch for issues after merge
- Follow Up: Fix any post-merge bugs quickly
👥 Reviewer Responsibilities
Before Review
- Understand Context: Read PR description and linked issues
- Check Out Code: Review running code, not just diff
- Run Tests: Verify tests pass locally
- Allocate Time: Block 30-60 min for thorough review
During Review
- Be Timely: Review within 24-48 hours
- Be Thorough: Check all checklist items
- Be Kind: Constructive, not destructive
- Be Clear: Specific, actionable feedback
- Be Consistent: Follow review standards
After Review
- Follow Up: Check if author has questions
- Re-Review: When changes are made
- Approve: When all issues addressed
- Unblock: Don't leave PRs waiting
🛠️ Tools & Automation
GitHub Review Tools
gh pr checkout <pr-number>
gh pr diff <pr-number>
gh pr review <pr-number> --comment -b "Review comments here"
gh pr review <pr-number> --approve
gh pr review <pr-number> --request-changes -b "Please fix X"
Automated Checks (CI/CD)
name: PR Checks
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
- run: make test
- run: make lint
- run: go test -coverprofile=coverage.out ./...
- run: go tool cover -func=coverage.out | grep total
Review Scripts
.agent/skills/coding-standards/scripts/verify-standards.sh <module>
.agent/skills/api-development/scripts/validate-api.sh <module>
.agent/skills/logging-standards/scripts/validate-logging.sh <module>
📚 Examples
🔗 Related Skills
✅ Quick Reference
Before creating PR:
make test && make lint
.agent/skills/coding-standards/scripts/verify-standards.sh <module>
git diff main...HEAD
When reviewing:
- Phase 1: Check PR description & architecture (10 min)
- Phase 2: Review implementation details (20 min)
- Phase 3: Check tests & documentation (10 min)
- Phase 4: Leave clear, constructive feedback (5 min)
Feedback levels:
- 🔴 MUST FIX: Security, breaking changes, critical bugs
- 🟡 SHOULD FIX: Missing tests, poor error handling
- 🟢 CONSIDER: Suggestions, improvements, style
Version: 1.0.0
Last Updated: 2026-01-24
Maintainer: ZGO Team