Mục lục

Lesson 1.3: Definition of Done cho Standards

Học cách định nghĩa 'hoàn thành' cho mỗi standard để đảm bảo quality mà không over-engineer

Standards
Quality
Documentation

Thời lượng: 20 phút
Level: Beginner
Yêu cầu: Hoàn thành Lesson 1.2

Mục tiêu bài học

Sau bài học này, bạn sẽ:

  • Biết 5 thành phần của một standard hoàn chỉnh
  • Có checklist Definition of Done cho các loại changes
  • Hiểu tại sao "no examples = fail"

Nội dung chính

1. Tại sao cần Definition of Done?

Vấn đề: Ai đó viết một "standard" nhưng:

  • Chỉ có text, không có examples
  • Không có automation
  • Không ai biết khi nào là "đủ"

Kết quả: Standard được interpret khác nhau → Thất bại

Code:
"Tất cả APIs nên return consistent errors"
   → "Nên" nghĩa là gì? "Consistent" như thế nào?

"Tất cả APIs PHẢI return error theo schema này:
   {code: string, message: string}
   Enforced by: lint rule #E001
   Examples: Xem error-examples.md"

2. Năm thành phần của Standard hoàn chỉnh

#ComponentMô tảVí dụ
1SpecificationRules rõ ràng, unambiguous"Errors MUST have code field"
2ExamplesReal code showing correct usage3-5 examples per standard
3Lint RulesAutomated checksESLint rule, OpenAPI validator
4TestsProve standard worksUnit tests, contract tests
5Migration GuideHow to transitionStep-by-step migration doc

3. Chi tiết từng thành phần

3.1. Specification - Viết rules rõ ràng

Vague:

markdown:
Errors should be descriptive and helpful.

Specific:

markdown:
## Error Response Specification

### MUST (Required)
- Error responses MUST include `code` field (string, SCREAMING_SNAKE_CASE)
- Error responses MUST include `message` field (string, user-readable)
- Error codes MUST be registered in error-catalog.md

### SHOULD (Recommended)
- Errors SHOULD include `details` object for field-level errors
- Errors SHOULD include `traceId` for debugging

### MAY (Optional)
- Errors MAY include `documentation` URL

Dùng RFC 2119 keywords:

KeywordMeaning
MUSTBắt buộc, không exception
SHOULDRecommended, exception với justification
MAYOptional, purely a choice

3.2. Examples - Code thực tế

"Không có examples = Developers interpret khác nhau = Standard fail"

Mỗi standard cần ít nhất 3 examples:

typescript:
// Example 1: Validation Error (400)
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input data",
    "details": {
      "email": "Must be a valid email address",
      "password": "Must be at least 8 characters"
    }
  }
}

// Example 2: Not Found Error (404)
{
  "success": false,
  "error": {
    "code": "USER_NOT_FOUND",
    "message": "The requested user does not exist"
  }
}

// Example 3: Internal Error (500)
{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "An unexpected error occurred",
    "traceId": "abc-123-def-456"
  }
}

3.3. Lint Rules - Automated enforcement

typescript:
// eslint-plugin-backend-ds/rules/error-format.js

module.exports = {
  meta: {
    type: "problem",
    docs: {
      description: "Enforce standard error format"
    }
  },
  create(context) {
    return {
      // Check all throw statements
      ThrowStatement(node) {
        // Validate error has required fields
        if (!hasRequiredFields(node)) {
          context.report({
            node,
            message: "Error must have 'code' and 'message' fields"
          });
        }
      }
    };
  }
};

Ví dụ OpenAPI Spectral rule:

yaml:
# .spectral.yaml
rules:
  error-response-schema:
    description: All 4xx/5xx responses must use standard error schema
    given: "$.paths.*.*.responses[?(@property >= 400)]"
    then:
      field: content.application/json.schema.$ref
      function: pattern
      functionOptions:
        match: "#/components/schemas/ErrorResponse"

3.4. Tests - Prove it works

typescript:
// tests/error-format.test.ts

describe('Error Response Format', () => {
  it('should return correct format for validation error', async () => {
    const response = await request(app)
      .post('/users')
      .send({ email: 'invalid' });
    
    expect(response.status).toBe(400);
    expect(response.body).toMatchObject({
      success: false,
      error: {
        code: expect.stringMatching(/^[A-Z_]+$/),
        message: expect.any(String)
      }
    });
  });

  it('should include traceId for 5xx errors', async () => {
    // Force internal error
    const response = await request(app)
      .get('/trigger-error');
    
    expect(response.status).toBe(500);
    expect(response.body.error).toHaveProperty('traceId');
  });
});

3.5. Migration Guide - Smooth transition

markdown:
# Migration Guide: Error Format v1 → v2

## Overview
- **Breaking change:** Yes
- **Estimated effort:** 2-4 hours per service
- **Deadline:** 2026-02-15

## Step-by-step

### Step 1: Update error-handler middleware (15 min)
Replace your current error handler with the new one:

```typescript
// OLD
catch(err) {
  res.status(500).json({ message: err.message });
}

// NEW
import { formatError } from '@company/error-handler';
catch(err) {
  res.status(getStatusCode(err)).json(formatError(err));
}

Step 2: Update error codes (30 min - 1 hour)

Map your current error strings to standard codes:

OldNew
"not found"RESOURCE_NOT_FOUND
"invalid"VALIDATION_ERROR
"unauthorized"UNAUTHORIZED

Step 3: Update tests (1-2 hours)

[...]

Rollback plan

If issues occur, revert to old middleware by [...]

Code:
---

## Nguyên tắc then chốt

> *"No examples = Developers interpret differently = Standard fails"*

Áp dụng:
1. **Mỗi rule cần ≥3 examples**
2. **Examples phải là real code**, không phải pseudo-code
3. **Include edge cases**, không chỉ happy path

```markdown
"Xem API spec để biết format"
Actual JSON response right in the doc

Thực hành

Bài tập 1: Viết Definition of Done Checklist

Mục tiêu: Tạo checklist cho các loại changes

Yêu cầu: Tạo 3 checklists cho:

  1. API Changes
  2. Database Changes
  3. Event/Message Changes

Template:

markdown:
# Definition of Done Checklists

## API Changes
- [ ] OpenAPI spec updated
- [ ] At least 3 request/response examples
- [ ] Breaking change analysis documented
- [ ] Migration guide (if breaking)
- [ ] Contract tests added
- [ ] Lint rules pass
- [ ] Reviewed by 2 team members

## Database Changes
- [ ] Migration script (up + down)
- [ ] Rollback plan documented
- [ ] Index analysis for new queries
- [ ] Data backfill strategy (if needed)
- [ ] Tested with production-like data volume
- [ ] DBA review (if > 1M rows affected)

## Event/Message Changes
- [ ] Schema version bumped
- [ ] Backward compatibility verified
- [ ] Consumer impact analyzed
- [ ] Deprecation timeline (if breaking)
- [ ] Example messages documented
- [ ] Dead letter queue handling defined
Xem gợi ý mở rộng

Thêm cho API Changes:

  • Performance test nếu endpoint critical
  • Rate limiting documented
  • Caching strategy defined

Thêm cho Database:

  • Estimated migration time
  • Maintenance window required?
  • Read replica impact

Bài tập 2: Audit một standard hiện có

Chọn một standard trong codebase của bạn và check:

ComponentCó?Quality (1-5)Action needed
Specification
Examples (≥3)
Lint rules
Tests
Migration Guide

Tình huống thực tế

Scenario 1: Standard không được follow

Bối cảnh: Bạn đã viết error format standard 3 tháng trước. Hôm nay review code và thấy 40% services vẫn return errors theo format cũ.

Câu hỏi:

  1. Root cause có thể là gì?
  2. Bạn sẽ fix như thế nào?
  3. Làm sao prevent tương lai?
Xem phân tích

Câu 1 - Root causes:

  • Không có lint rule → Không ai check
  • Không có examples → Devs không biết đúng/sai
  • Không có migration guide → Old code không update
  • Không communicate → Team không biết có standard

Câu 2 - Fix:

  1. Add lint rule ngay → CI fail nếu wrong format
  2. Add examples → Clear documentation
  3. Office hours session → Train team
  4. Migration sprint → Dedicated time to update old code

Câu 3 - Prevent:

  • Every standard MUST have lint rule trước khi publish
  • Every standard MUST be announced trong team meeting
  • Quarterly audit → Check compliance

Scenario 2: "Quá nhiều bureaucracy"

Bối cảnh: Developer phàn nàn: "Để add một field vào API response, tôi phải update OpenAPI spec, thêm examples, viết migration guide, add tests... Quá nhiều overhead!"

Câu hỏi:

  1. Concern này valid không?
  2. Bạn sẽ respond như thế nào?
  3. Có cách nào reduce overhead?
Xem phân tích

Câu 1 - Valid concern: Partially valid. Nếu MỌI change đều cần full checklist → Too slow.

Câu 2 - Response: "Tôi hiểu concern. Checklist designed cho BREAKING changes. Minor additions không cần full checklist."

Câu 3 - Reduce overhead:

Change TypeRequired Items
Breaking changeFull checklist
New optional fieldOpenAPI + 1 example
Bug fixTests only
DocumentationNone

"Thêm một optional field? Chỉ cần OpenAPI update + 1 example. 10 phút."


Câu hỏi phỏng vấn

Junior Level

Q1: Standard hoàn chỉnh cần có những gì?

Xem đáp án

Đáp án: 5 thành phần:

  1. Specification (clear rules)
  2. Examples (≥3)
  3. Lint rules (automation)
  4. Tests (proof it works)
  5. Migration guide (path forward)

Q2: Tại sao examples quan trọng?

Xem đáp án

Đáp án:

  • Không có examples → Mỗi người interpret khác
  • Examples = Single source of truth
  • Real code > Pseudo-code

Mid Level

Q1: Bạn phát hiện 50% team không follow error standard. Next steps?

Xem đáp án

Good answer:

  1. Root cause analysis: Tại sao không follow?
    • Không biết? → Communication issue
    • Không enforce? → Add lint rule
    • Quá khó? → Simplify standard
  2. Short-term fix: Add CI check, block non-compliant code
  3. Migration plan: Sprint để fix old code
  4. Long-term: Review process cho new standards

Senior Level

Q1: Design một governance system đảm bảo standards được follow trong org 100+ engineers.

Xem đáp án

Framework:

  1. Publishing process:

    • RFC cho new standards
    • 2-week review period
    • Automation REQUIRED trước publish
  2. Enforcement layers:

    • Layer 1: IDE plugins (instant feedback)
    • Layer 2: Pre-commit hooks (local)
    • Layer 3: CI checks (PR block)
    • Layer 4: Production monitoring (alerts)
  3. Compliance metrics:

    • Dashboard: % compliance per team
    • Weekly reports to Tech Lead
    • Quarterly review với Engineering Manager
  4. Exception process:

    • Documented in ADR
    • Time-boxed (6 months max)
    • Owner assigned
  5. Feedback loop:

    • Monthly survey: "Is standard helpful?"
    • Office hours: Q&A
    • Retrospective: What's not working?

Tóm tắt

Những điều cần nhớ

ConceptGiải thích
5 ComponentsSpec, Examples, Lint, Tests, Migration
RFC 2119MUST, SHOULD, MAY - clear expectations
Examples ruleNo examples = Standard fails
Proportional overheadBreaking change → Full checklist; Minor → Light

Key Takeaways

  1. Specification alone is not enough: Cần examples, automation, tests
  2. Automation > Documentation: Lint rules enforce, docs just suggest
  3. Migration guides are essential: Old code needs path forward

Checklist hoàn thành

  • Hiểu 5 components của standard hoàn chỉnh
  • Tạo được Definition of Done checklist
  • Biết dùng RFC 2119 keywords
  • Có thể audit existing standards

Tài liệu tham khảo


Module tiếp theo

🎉 Chúc mừng! Bạn đã hoàn thành Module 1: Initialization & Scope.

Bạn đã học:

  • Backend Design System là gì
  • Cách scope MVP trong 2 tuần
  • Definition of Done cho standards

Module tiếp theo: Module 2: API Contracts - Học cách thiết kế API contracts nhất quán, bao gồm response envelopes, error handling, và HTTP semantics.

Bắt đầu Module 2 →

Quảng cáo
mdhorizontal