iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0
Build on AWS

AWS架構師的自我修養:30天雲端系統思維實戰指南系列 第 28

Day 13-3 | 跨團隊協作設計:技術文件、OpenAPI、共用契約 : API 文檔化與團隊協作標準建立 - 可文檔版控的視覺化商業邏輯具象(end):技術文件 與總結

  • 分享至 

  • xImage
  •  

3. 技術文件 (Technical Documentation)

抽象概念:系統的「使用說明書」和「設計藍圖」

技術文件 = 系統知識的外化表達
- 架構設計文件 → 房子的結構圖
- API 文件 → 各部件的接口說明
- 部署文件 → 組裝指南
- 開發指南 → 建造手冊
- 故障排除 → 維修說明書

技術文件是軟體開發中的「知識基礎設施」,它將隱性知識轉化為顯性知識,確保團隊的智慧資產不會因為人員流動而流失。想像一下,如果你接手一個沒有任何文件的專案,就像是拿到一個沒有說明書的複雜機器,你需要花費大量時間去逆向工程才能理解它的運作原理。

3.1 為什麼技術文件如此重要?

情境重現:沒有技術文件的困境

場景一:新人入職
新工程師:「這個系統要怎麼跑起來?」
資深工程師:「你要先裝 Docker,然後...等等,讓我想想還需要什麼...」
新工程師:「資料庫要怎麼設定?」
資深工程師:「這個...我記得當初是這樣做的,但可能有些步驟忘了...」

場景二:系統故障
值班工程師:「系統掛了!這個錯誤是什麼意思?」
(聯絡不到原開發者)
產品經理:「什麼時候能修好?客戶在等!」
值班工程師:「我需要先研究程式碼...可能要幾個小時...」

場景三:技術債務
主管:「這個功能為什麼當初要這樣設計?」
工程師:「呃...我不知道,原本的開發者已經離職了...」
主管:「那我們能不能改?會有什麼影響?」
工程師:「不敢動,怕會影響到其他功能...」

這些場景是否似曾相識?技術文件的缺失會導致:

  • 知識孤島:核心知識只存在少數人腦中
  • 重複投入:每次都要重新摸索和學習
  • 風險累積:沒人敢動「祖傳程式碼」
  • 效率低下:簡單問題變成複雜調查

3.2 技術文件的層次架構

技術文件應該是一個完整的知識體系,我們可以按照不同的受眾和用途來分層:

第一層:戰略層文件 (Strategic Level)

  • 受眾:技術主管、架構師、產品經理
  • 目的:理解系統的整體設計思路和商業脈絡

第二層:戰術層文件 (Tactical Level)

  • 受眾:開發團隊、DevOps 工程師
  • 目的:理解具體的技術實作和操作流程

第三層:操作層文件 (Operational Level)

  • 受眾:所有團隊成員、維運人員
  • 目的:解決日常開發和維運中的具體問題

3.3 戰略層文件:系統全貌的鳥瞰圖

1. 系統架構概覽 (System Architecture Overview)

# 電商平台技術架構文件

## 系統概述

### 商業背景

電商平台需要處理高並發的商品瀏覽、下單和支付流程,同時確保資料一致性和系統穩定性。

### 技術目標

- **高可用性**:99.9% 系統可用時間
- **高性能**:首頁載入時間 < 2 秒
- **高擴展性**:支援 10x 流量增長
- **高安全性**:符合 PCI DSS 支付安全標準

### 整體架構圖 (C4 Model)

#### Level 1: 系統上下文圖 (System Context)

```mermaid
C4Context
    title 電商平台系統上下文圖

    Person(customer, "顧客", "購買商品的用戶")
    Person(admin, "管理員", "管理商品和訂單的內部用戶")
    Person(vendor, "供應商", "提供商品的合作夥伴")

    System(ecommerce, "電商平台", "提供線上購物功能的核心系統")

    System_Ext(payment, "支付系統", "第三方支付服務 (Stripe, PayPal)")
    System_Ext(shipping, "物流系統", "第三方物流追蹤服務")
    System_Ext(notification, "通知系統", "郵件和簡訊服務 (SendGrid, Twilio)")
    System_Ext(analytics, "分析系統", "數據分析平台 (Google Analytics)")

    Rel(customer, ecommerce, "瀏覽商品、下單購買", "HTTPS")
    Rel(admin, ecommerce, "管理商品、處理訂單", "HTTPS")
    Rel(vendor, ecommerce, "上架商品、查看銷售數據", "HTTPS")

    Rel(ecommerce, payment, "處理支付", "API")
    Rel(ecommerce, shipping, "追蹤物流", "API")
    Rel(ecommerce, notification, "發送通知", "API")
    Rel(ecommerce, analytics, "記錄用戶行為", "JavaScript SDK")

    UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="2")
```

#### Level 2: 容器圖 (Container Diagram)

```mermaid
C4Container
    title 電商平台容器圖

    Person(customer, "顧客")
    Person(admin, "管理員")

    Container_Boundary(frontend, "前端應用") {
        Container(web, "Web 應用", "React.js", "提供購物網站界面")
        Container(mobile, "行動應用", "React Native", "提供行動購物體驗")
        Container(admin_panel, "管理後台", "Vue.js", "提供商品和訂單管理界面")
    }

    Container_Boundary(api_layer, "API 層") {
        Container(api_gateway, "API Gateway", "Kong", "統一的API入口,處理認證、限流、路由")
        Container(cdn, "CDN", "CloudFlare", "靜態資源分發和快取")
    }

    Container_Boundary(services, "微服務層") {
        Container(user_service, "用戶服務", "Node.js + Express", "處理用戶註冊、登入、個人資料")
        Container(product_service, "商品服務", "Python + FastAPI", "管理商品信息、庫存、分類")
        Container(order_service, "訂單服務", "Java + Spring Boot", "處理訂單流程、支付、物流")
        Container(notification_service, "通知服務", "Node.js", "發送郵件、簡訊、推播通知")
    }

    Container_Boundary(data_layer, "數據層") {
        ContainerDb(user_db, "用戶資料庫", "PostgreSQL", "存儲用戶信息和認證資料")
        ContainerDb(product_db, "商品資料庫", "PostgreSQL", "存儲商品和庫存信息")
        ContainerDb(order_db, "訂單資料庫", "PostgreSQL", "存儲訂單和支付信息")
        ContainerDb(cache, "快取層", "Redis", "快取熱門商品和會話信息")
        ContainerDb(search, "搜尋引擎", "Elasticsearch", "提供商品搜尋功能")
    }

    Container_Boundary(infrastructure, "基礎設施") {
        Container(message_queue, "訊息佇列", "Apache Kafka", "異步事件處理")
        Container(file_storage, "檔案存儲", "AWS S3", "存儲商品圖片和檔案")
        Container(monitoring, "監控系統", "Prometheus + Grafana", "系統監控和告警")
    }

    System_Ext(payment_sys, "支付系統", "Stripe")
    System_Ext(shipping_sys, "物流系統", "物流API")

    Rel(customer, web, "使用", "HTTPS")
    Rel(customer, mobile, "使用", "HTTPS")
    Rel(admin, admin_panel, "使用", "HTTPS")

    Rel(web, api_gateway, "API呼叫", "HTTPS/JSON")
    Rel(mobile, api_gateway, "API呼叫", "HTTPS/JSON")
    Rel(admin_panel, api_gateway, "API呼叫", "HTTPS/JSON")

    Rel(api_gateway, user_service, "路由請求", "HTTP/JSON")
    Rel(api_gateway, product_service, "路由請求", "HTTP/JSON")
    Rel(api_gateway, order_service, "路由請求", "HTTP/JSON")

    Rel(user_service, user_db, "讀寫", "SQL")
    Rel(product_service, product_db, "讀寫", "SQL")
    Rel(order_service, order_db, "讀寫", "SQL")

    Rel(product_service, cache, "快取", "Redis Protocol")
    Rel(product_service, search, "索引", "REST API")
    Rel(order_service, payment_sys, "支付", "HTTPS/API")
    Rel(order_service, shipping_sys, "物流", "HTTPS/API")

    Rel(user_service, message_queue, "發布事件", "Kafka Protocol")
    Rel(order_service, message_queue, "發布事件", "Kafka Protocol")
    Rel(notification_service, message_queue, "訂閱事件", "Kafka Protocol")

    UpdateLayoutConfig($c4ShapeInRow="2", $c4BoundaryInRow="1")
```

#### Level 3: 組件圖 (Component Diagram) - 以商品服務為例

```mermaid
C4Component
    title 商品服務組件圖

    Container(api_gateway, "API Gateway", "Kong")
    ContainerDb(product_db, "商品資料庫", "PostgreSQL")
    ContainerDb(cache, "Redis快取", "Redis")
    ContainerDb(search, "搜尋引擎", "Elasticsearch")
    Container(message_queue, "Kafka", "Apache Kafka")

    Container_Boundary(product_service, "商品服務") {
        Component(product_controller, "商品控制器", "FastAPI Router", "處理HTTP請求和回應")
        Component(product_service_layer, "商品業務邏輯", "Python Service", "實現商品相關業務規則")
        Component(inventory_service, "庫存管理", "Python Service", "管理商品庫存和預訂")
        Component(category_service, "分類管理", "Python Service", "管理商品分類結構")
        Component(search_service, "搜尋服務", "Python Service", "處理商品搜尋和篩選")

        Component(product_repository, "商品倉儲", "SQLAlchemy ORM", "數據存取層")
        Component(cache_manager, "快取管理器", "Redis Client", "快取策略和失效處理")
        Component(search_indexer, "搜尋索引器", "Elasticsearch Client", "維護搜尋索引")
        Component(event_publisher, "事件發布器", "Kafka Producer", "發布領域事件")

        Component(product_model, "商品模型", "Pydantic Model", "資料驗證和序列化")
        Component(inventory_model, "庫存模型", "Pydantic Model", "庫存資料結構")
    }

    Rel(api_gateway, product_controller, "HTTP請求", "JSON/HTTPS")

    Rel(product_controller, product_service_layer, "調用", "Python")
    Rel(product_controller, inventory_service, "調用", "Python")
    Rel(product_controller, category_service, "調用", "Python")
    Rel(product_controller, search_service, "調用", "Python")

    Rel(product_service_layer, product_repository, "數據操作", "SQLAlchemy")
    Rel(inventory_service, product_repository, "庫存查詢", "SQLAlchemy")
    Rel(search_service, search_indexer, "搜尋查詢", "Python")

    Rel(product_service_layer, cache_manager, "快取操作", "Redis")
    Rel(product_service_layer, event_publisher, "發布事件", "Kafka")

    Rel(product_repository, product_db, "SQL查詢", "PostgreSQL")
    Rel(cache_manager, cache, "快取讀寫", "Redis Protocol")
    Rel(search_indexer, search, "索引操作", "REST API")
    Rel(event_publisher, message_queue, "事件發布", "Kafka Protocol")

    Rel(product_service_layer, product_model, "使用", "Python")
    Rel(inventory_service, inventory_model, "使用", "Python")

    UpdateLayoutConfig($c4ShapeInRow="3", $c4BoundaryInRow="1")
```

#### Level 4: 程式碼圖 (Code Diagram) - 商品模型詳細設計

```mermaid
classDiagram
    class Product {
        +UUID id
        +String name
        +String description
        +Decimal price
        +Decimal original_price
        +String category_id
        +List~String~ images
        +Integer stock
        +Boolean is_active
        +DateTime created_at
        +DateTime updated_at
        +String created_by
        +calculate_discount_percentage() Decimal
        +is_in_stock() Boolean
        +update_stock(quantity: Integer) None
        +mark_as_sold_out() None
    }

    class Category {
        +UUID id
        +String name
        +String description
        +String parent_id
        +Integer sort_order
        +Boolean is_active
        +get_full_path() String
        +get_children() List~Category~
        +get_products() List~Product~
    }

    class Inventory {
        +UUID id
        +UUID product_id
        +Integer available_stock
        +Integer reserved_stock
        +Integer reorder_level
        +DateTime last_updated
        +reserve_stock(quantity: Integer) Boolean
        +release_reservation(quantity: Integer) None
        +adjust_stock(quantity: Integer, reason: String) None
        +is_below_reorder_level() Boolean
    }

    class ProductImage {
        +UUID id
        +UUID product_id
        +String url
        +String alt_text
        +Integer sort_order
        +Boolean is_primary
        +ImageType type
    }

    class ProductReview {
        +UUID id
        +UUID product_id
        +UUID user_id
        +Integer rating
        +String comment
        +List~String~ images
        +DateTime created_at
        +Boolean is_verified_purchase
        +Integer helpful_count
    }

    class SearchIndex {
        +UUID product_id
        +String search_text
        +Map~String,Any~ attributes
        +List~String~ tags
        +DateTime indexed_at
        +update_index() None
        +remove_from_index() None
    }



    class ProductService {
        -ProductRepository repository
        -CacheManager cache
        -EventPublisher events
        +create_product(data: CreateProductRequest) Product
        +get_product(id: UUID) Product
        +update_product(id: UUID, data: UpdateProductRequest) Product
        +delete_product(id: UUID) None
        +search_products(criteria: SearchCriteria) List~Product~
        +get_products_by_category(category_id: UUID) List~Product~
    }

    class InventoryService {
        -ProductRepository repository
        -EventPublisher events
        +reserve_stock(product_id: UUID, quantity: Integer) Boolean
        +release_stock(product_id: UUID, quantity: Integer) None
        +adjust_stock(product_id: UUID, quantity: Integer, reason: String) None
        +check_stock_availability(product_id: UUID, quantity: Integer) Boolean
        +get_low_stock_products() List~Product~
    }

    ProductService --> Product : manages
    ProductService --> ProductRepository : uses
    InventoryService --> Inventory : manages
    InventoryService --> Product : updates
```



#### 架構決策說明

**為什麼採用 C4 Model?**

1. **層次化視角**:從高層次的系統上下文到具體的程式碼實作,提供了完整的架構視角
2. **受眾導向**:不同層次的圖表適合不同的受眾(高管、架構師、開發者)
3. **標準化表示**:使用統一的符號和約定,提高了溝通效率
4. **可維護性**:結構化的表示方式便於文件維護和更新

**各層次的用途**:

- **Level 1 (Context)**:適合向業務人員和高管展示系統邊界
- **Level 2 (Container)**:適合架構師和技術主管了解技術選型
- **Level 3 (Component)**:適合開發團隊理解模組設計
- **Level 4 (Code)**:適合開發者了解具體實作細節

### 核心設計決策

#### 為什麼選擇微服務架構?

**問題**:原本的單體架構在流量增長後出現效能瓶頸
**解決方案**:採用微服務架構,按業務領域拆分服務
**優點**:

- 獨立部署:不同服務可以獨立發布
- 技術多樣性:可以為不同服務選擇最適合的技術棧
- 故障隔離:單一服務故障不會影響整個系統

**權衡考量**:

- 複雜度增加:需要處理分散式系統的複雜性
- 運維成本:需要更多的監控和部署流程
- 資料一致性:需要處理跨服務的事務管理

#### 為什麼選擇 Event-Driven 架構?

**問題**:服務間的同步調用造成級聯故障
**解決方案**:採用事件驅動架構,透過訊息佇列實現異步通訊
**實作**:使用 Apache Kafka 作為事件流平台

### 關鍵品質屬性

| 品質屬性 | 目標指標      | 實現策略                           |
| -------- | ------------- | ---------------------------------- |
| 可用性   | 99.9%         | 多區域部署、負載均衡、自動故障切換 |
| 效能     | < 2s 響應時間 | CDN、Redis 快取、資料庫優化        |
| 擴展性   | 支援 10x 流量 | 水平擴展、自動擴縮容               |
| 安全性   | PCI DSS 合規  | HTTPS、OAuth 2.0、資料加密         |

2. 技術選型決策記錄 (Architecture Decision Records, ADR)

# ADR-001: 採用 React.js 作為前端框架

## 狀態

已接受 (2024-01-15)

## 背景

我們需要選擇一個前端框架來建構電商平台的使用者介面。主要考慮的選項有 React.js、Vue.js 和 Angular。

## 決策

選擇 React.js 作為主要前端框架。

## 理由

### 優點

1. **豐富的生態系統**:有大量的第三方套件和工具
2. **團隊熟悉度**:現有團隊成員對 React 較為熟悉
3. **社群支援**:活躍的社群和豐富的學習資源
4. **企業級應用**:被眾多大型企業廣泛使用,證明其穩定性

### 權衡

1. **學習曲線**:新手可能需要時間適應 JSX 語法
2. **工具鏈複雜**:需要配置 webpack、babel 等工具
3. **版本更新**:React 更新較為頻繁,需要持續跟進

## 替代方案

- **Vue.js**:學習曲線較緩,但生態系統相對較小
- **Angular**:完整的框架,但對小型團隊來說可能過於複雜

## 影響

- 前端開發團隊需要統一使用 React.js
- 需要建立 React 相關的開發規範和最佳實務
- CI/CD 流程需要支援 React 專案的建置和部署

## 相關文件

- [React 開發規範](./frontend-coding-standards.md)
- [前端專案結構](./frontend-project-structure.md)

3.4 戰術層文件:實作細節的深度指南

1. 開發環境設定指南

# 開發環境設定指南

## 前置需求

### 系統需求

- **作業系統**:macOS 10.15+、Ubuntu 18.04+、Windows 10+
- **記憶體**:建議 16GB 以上
- **硬碟空間**:至少 20GB 可用空間

### 必要軟體

- Node.js 18.x (使用 nvm 管理版本)
- Docker Desktop 4.x
- Git 2.x
- IDE:推薦 VS Code 或 WebStorm

## 環境安裝步驟

### 1. 安裝 Node.js 和 npm

### 2. 安裝 Docker

### 3. 克隆專案並安裝依賴

### 4. 環境設定

### 5. 啟動本地服務

### 6. 驗證安裝

### 常見問題排解

### HTTP 狀態碼使用規範

互動式文件平台

1. GitBook

優點:美觀、易用、支援協作
設定範例

# .gitbook.yaml
root: ./docs
structure:
  readme: README.md
  summary: SUMMARY.md

2. Notion

優點:所見即所得、支援資料庫、團隊協作佳
使用技巧

  • 建立文件模板
  • 使用資料庫管理 API 清單
  • 設定自動化工作流程

3. Confluence

優點:企業級功能、與 Jira 整合佳
最佳實務

  • 建立清晰的空間結構
  • 使用標籤和標籤進行分類
  • 設定定期文件審查流程

**3. 文件維護策略**

```markdown
# 文件維護策略

## 文件生命週期管理

### 建立階段
- [ ] 確定文件目標受眾
- [ ] 選擇適當的文件類型和模板
- [ ] 撰寫初版內容
- [ ] 同儕審查

### 維護階段
- [ ] 定期審查和更新 (每季度)
- [ ] 根據程式碼變更同步更新
- [ ] 收集使用者回饋
- [ ] 效能指標追蹤

### 淘汰階段
- [ ] 識別過時文件
- [ ] 歸檔或刪除
- [ ] 重新導向到新文件

## 品質保證檢查清單

### 內容品質
- [ ] 資訊準確性
- [ ] 完整性檢查
- [ ] 範例程式碼可執行
- [ ] 連結有效性

### 可用性
- [ ] 導航清晰
- [ ] 搜尋功能可用
- [ ] 行動裝置相容
- [ ] 無障礙設計

### 維護性
- [ ] 版本控制
- [ ] 變更記錄
- [ ] 責任歸屬
- [ ] 更新頻率

這個主題的核心在於建立一個「共同語言」,讓不同背景的團隊成員能夠高效協作。每一份共用契約、每一個 OpenAPI 規格、每一篇技術文件,都是團隊智慧的結晶,也是未來協作的基石。當下一個新成員加入團隊時,當下一個功能需要開發時,當下一次系統重構來臨時,這些協作設計的投入將會產生複利效應。

這就是跨團隊協作設計的真正價值:不是讓我們做得更快,而是讓我們做得更對;不是讓個人更強,而是讓團隊更強。

最終,我們建立的不僅是技術規範,更是一種協作文化——一種以共識為基礎、以標準為橋樑、以文件為載體的高效協作文化。這種文化將成為團隊最寶貴的資產,支撐著我們在快速變化的技術環境中持續創造價值。


上一篇
Day 13-2 | 跨團隊協作設計:技術文件、OpenAPI、共用契約 : API 文檔化與團隊協作標準建立 - 可文檔版控的視覺化商業邏輯具象(2):系統交互介面(OpenAPI)
系列文
AWS架構師的自我修養:30天雲端系統思維實戰指南28
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言