dramaling-vocab-learning/docs/03_development/backend-api-development-pla...

21 KiB
Raw Blame History

DramaLing 後端 API 開發計劃

1. 概述

1.1 計劃目的

本開發計劃旨在基於現有的詞卡管理 API 規格,完善和優化後端 API 實現,確保 API 功能完整性、效能和穩定性。

1.2 依賴文檔

📋 參考文檔引用

本開發計劃基於以下文檔制定:

🔧 API 規格文檔 (主要參考)

🏗️ 技術架構文檔

📋 需求規格文檔

1.3 當前狀態評估

根據 詞卡管理 API 規格 分析,目前後端 API 狀態:

已完成的 API 端點

  • GET /api/flashcards - 取得詞卡列表 (含搜尋和收藏篩選)
  • GET /api/flashcards/{id} - 取得單一詞卡
  • POST /api/flashcards - 創建新詞卡 (含重複檢測)
  • PUT /api/flashcards/{id} - 更新詞卡
  • DELETE /api/flashcards/{id} - 刪除詞卡 (軟刪除)
  • POST /api/flashcards/{id}/favorite - 切換收藏狀態

🎯 需要改進的項目

  • 🔄 搜尋功能擴展 (目前不支援例句搜尋)
  • 🔄 進階篩選 API (CEFR 等級、詞性、掌握度)
  • 🔄 批量操作 API (未來功能)
  • 🔄 效能優化 (查詢索引、快取機制)
  • 🔄 API 文檔生成 (Swagger 增強)

2. 開發任務清單

2.1 搜尋功能增強 (優先級:🔴 高)

任務 1: 擴展搜尋範圍支援例句

影響檔案:

  • backend/DramaLing.Api/Controllers/FlashcardsController.cs - 修改 GetFlashcards 方法

當前實現:

// 目前搜尋邏輯 (第 53-59 行)
if (!string.IsNullOrEmpty(search))
{
    query = query.Where(f =>
        f.Word.Contains(search) ||
        f.Translation.Contains(search) ||
        (f.Definition != null && f.Definition.Contains(search)));
}

改進實現:

// 擴展搜尋範圍,新增例句搜尋
if (!string.IsNullOrEmpty(search))
{
    query = query.Where(f =>
        f.Word.Contains(search) ||
        f.Translation.Contains(search) ||
        (f.Definition != null && f.Definition.Contains(search)) ||
        (f.Example != null && f.Example.Contains(search)) ||
        (f.ExampleTranslation != null && f.ExampleTranslation.Contains(search)));
}

驗收標準:

  • 搜尋範圍包含例句 (Example) 和例句翻譯 (ExampleTranslation)
  • 搜尋效能無明顯下降
  • 搜尋結果準確性維持 100%

任務 2: 新增進階篩選查詢參數

影響檔案:

  • backend/DramaLing.Api/Controllers/FlashcardsController.cs - 修改 GetFlashcards 方法參數

新增查詢參數:

[HttpGet]
public async Task<ActionResult> GetFlashcards(
    [FromQuery] string? search = null,
    [FromQuery] bool favoritesOnly = false,
    [FromQuery] string? cefrLevel = null,        // 新增: A1, A2, B1, B2, C1, C2
    [FromQuery] string? partOfSpeech = null,     // 新增: noun, verb, adjective, etc.
    [FromQuery] string? masteryLevel = null      // 新增: high, medium, low
)

篩選邏輯實現:

// CEFR 等級篩選
if (!string.IsNullOrEmpty(cefrLevel))
{
    query = query.Where(f => f.DifficultyLevel == cefrLevel);
}

// 詞性篩選
if (!string.IsNullOrEmpty(partOfSpeech))
{
    query = query.Where(f => f.PartOfSpeech == partOfSpeech);
}

// 掌握度篩選
if (!string.IsNullOrEmpty(masteryLevel))
{
    switch (masteryLevel.ToLower())
    {
        case "high":
            query = query.Where(f => f.MasteryLevel >= 80);
            break;
        case "medium":
            query = query.Where(f => f.MasteryLevel >= 60 && f.MasteryLevel < 80);
            break;
        case "low":
            query = query.Where(f => f.MasteryLevel < 60);
            break;
    }
}

驗收標準:

  • 支援 CEFR 等級篩選 (A1-C2)
  • 支援詞性篩選 (noun, verb, adjective 等)
  • 支援掌握度篩選 (high, medium, low)
  • 多重篩選條件正確組合 (AND 邏輯)

2.2 效能優化 (優先級:🟡 中)

任務 3: 資料庫查詢優化

影響檔案:

  • backend/DramaLing.Api/Data/DramaLingDbContext.cs - 新增索引配置

索引優化:

// 在 OnModelCreating 方法中新增索引
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // 現有配置...

    // 搜尋優化索引
    modelBuilder.Entity<Flashcard>()
        .HasIndex(f => f.Word)
        .HasDatabaseName("IX_Flashcards_Word");

    modelBuilder.Entity<Flashcard>()
        .HasIndex(f => f.Translation)
        .HasDatabaseName("IX_Flashcards_Translation");

    // 複合查詢索引
    modelBuilder.Entity<Flashcard>()
        .HasIndex(f => new { f.UserId, f.IsArchived, f.IsFavorite })
        .HasDatabaseName("IX_Flashcards_UserId_IsArchived_IsFavorite");

    // CEFR 等級索引
    modelBuilder.Entity<Flashcard>()
        .HasIndex(f => f.DifficultyLevel)
        .HasDatabaseName("IX_Flashcards_DifficultyLevel");
}

查詢邏輯優化:

// 使用 AsNoTracking 提升查詢效能
var flashcards = await query
    .AsNoTracking()
    .OrderByDescending(f => f.CreatedAt)
    .ToListAsync();

驗收標準:

  • 新增適當的資料庫索引
  • 查詢時間 < 200ms (1000+ 詞卡)
  • 搜尋響應時間 < 100ms

任務 4: 快取機制實現

影響檔案:

  • backend/DramaLing.Api/Controllers/FlashcardsController.cs - 整合快取服務
  • backend/DramaLing.Api/Extensions/ServiceCollectionExtensions.cs - 已有快取配置

快取策略實現:

// 在 FlashcardsController 中使用快取
private readonly ICacheService _cacheService;

[HttpGet]
public async Task<ActionResult> GetFlashcards(...)
{
    var cacheKey = $"flashcards:user:{userId}:search:{search}:favorites:{favoritesOnly}";

    var cachedResult = await _cacheService.GetAsync<object>(cacheKey);
    if (cachedResult != null)
    {
        return Ok(cachedResult);
    }

    // 執行資料庫查詢...
    var result = new { Success = true, Data = ... };

    // 快取結果 (30分鐘)
    await _cacheService.SetAsync(cacheKey, result, TimeSpan.FromMinutes(30));

    return Ok(result);
}

驗收標準:

  • 詞卡列表查詢快取 30 分鐘
  • 快取命中率 > 70%
  • 快取失效機制正確 (CRUD 操作後清除)

2.3 API 增強功能 (優先級:🟡 中)

任務 5: 新增批量操作 API

影響檔案:

  • backend/DramaLing.Api/Controllers/FlashcardsController.cs - 新增批量操作端點

新增 API 端點:

[HttpPost("batch/favorite")]
public async Task<ActionResult> BatchToggleFavorite([FromBody] BatchFavoriteRequest request)
{
    try
    {
        var userId = GetUserId();
        var flashcards = await _context.Flashcards
            .Where(f => request.FlashcardIds.Contains(f.Id) && f.UserId == userId && !f.IsArchived)
            .ToListAsync();

        foreach (var flashcard in flashcards)
        {
            flashcard.IsFavorite = request.IsFavorite;
            flashcard.UpdatedAt = DateTime.UtcNow;
        }

        await _context.SaveChangesAsync();

        return Ok(new { Success = true, UpdatedCount = flashcards.Count });
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error in batch favorite operation");
        return StatusCode(500, new { Success = false, Error = "批量操作失敗" });
    }
}

[HttpDelete("batch")]
public async Task<ActionResult> BatchDelete([FromBody] BatchDeleteRequest request)
{
    // 批量軟刪除實現
}

新增 DTO 類別:

public class BatchFavoriteRequest
{
    public List<Guid> FlashcardIds { get; set; } = new();
    public bool IsFavorite { get; set; }
}

public class BatchDeleteRequest
{
    public List<Guid> FlashcardIds { get; set; } = new();
}

驗收標準:

  • 支援批量收藏/取消收藏
  • 支援批量刪除 (軟刪除)
  • 批量操作事務性 (全部成功或全部失敗)
  • 操作日誌記錄完整

任務 6: 統計資料 API

影響檔案:

  • backend/DramaLing.Api/Controllers/FlashcardsController.cs - 新增統計端點

新增統計 API:

[HttpGet("statistics")]
public async Task<ActionResult> GetStatistics()
{
    try
    {
        var userId = GetUserId();

        var stats = await _context.Flashcards
            .Where(f => f.UserId == userId && !f.IsArchived)
            .GroupBy(f => 1) // 單一群組用於統計
            .Select(g => new
            {
                TotalCount = g.Count(),
                FavoriteCount = g.Count(f => f.IsFavorite),
                MasteredCount = g.Count(f => f.MasteryLevel >= 80),
                LearningCount = g.Count(f => f.MasteryLevel >= 60 && f.MasteryLevel < 80),
                NewCount = g.Count(f => f.MasteryLevel < 60),
                CefrDistribution = g.GroupBy(f => f.DifficultyLevel)
                                  .ToDictionary(cg => cg.Key, cg => cg.Count())
            })
            .FirstOrDefaultAsync();

        return Ok(new { Success = true, Data = stats });
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error getting flashcard statistics");
        return StatusCode(500, new { Success = false, Error = "統計資料載入失敗" });
    }
}

驗收標準:

  • 提供詞卡總數、收藏數、掌握度分布統計
  • 提供 CEFR 等級分布統計
  • 統計資料準確性 100%
  • 響應時間 < 200ms

2.4 錯誤處理增強 (優先級:🟡 中)

任務 7: 標準化錯誤回應格式

影響檔案:

  • backend/DramaLing.Api/Models/DTOs/ - 新增錯誤回應 DTO
  • backend/DramaLing.Api/Controllers/FlashcardsController.cs - 統一錯誤處理

錯誤回應 DTO:

public class ApiErrorResponse
{
    public bool Success { get; set; } = false;
    public string Error { get; set; } = string.Empty;
    public string? Details { get; set; }
    public string? ErrorCode { get; set; }
    public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}

public class ApiSuccessResponse<T>
{
    public bool Success { get; set; } = true;
    public T? Data { get; set; }
    public string? Message { get; set; }
}

統一錯誤處理:

// 基礎控制器類別
public abstract class BaseApiController : ControllerBase
{
    protected ActionResult ApiError(string message, string? details = null, string? errorCode = null)
    {
        return BadRequest(new ApiErrorResponse
        {
            Error = message,
            Details = details,
            ErrorCode = errorCode
        });
    }

    protected ActionResult ApiSuccess<T>(T data, string? message = null)
    {
        return Ok(new ApiSuccessResponse<T>
        {
            Data = data,
            Message = message
        });
    }
}

驗收標準:

  • 所有 API 端點使用統一錯誤格式
  • 錯誤代碼標準化 (如 FLASHCARD_NOT_FOUND)
  • 錯誤訊息本地化 (中文)
  • 詳細錯誤信息僅在開發環境顯示

2.5 認證與授權準備 (優先級:🟢 低)

任務 8: 準備生產環境認證

影響檔案:

  • backend/DramaLing.Api/Controllers/FlashcardsController.cs - 準備認證代碼

實現內容:

// 保留現有測試模式,準備生產環境切換
private Guid GetUserId()
{
    // 開發環境:使用固定測試用戶
    if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Development")
    {
        return Guid.Parse("00000000-0000-0000-0000-000000000001");
    }

    // 生產環境:解析 JWT Token
    var userIdString = User.FindFirst(ClaimTypes.NameIdentifier)?.Value ??
                      User.FindFirst("sub")?.Value;

    if (Guid.TryParse(userIdString, out var userId))
        return userId;

    throw new UnauthorizedAccessException("Invalid user ID in token");
}

// 準備生產環境控制器標註
// [Authorize] // 生產環境時啟用
[AllowAnonymous] // 開發環境暫時保持
public class FlashcardsController : BaseApiController

驗收標準:

  • 開發環境認證邏輯保持不變
  • 生產環境認證代碼已準備
  • 環境切換機制正確
  • JWT Token 解析邏輯完整

3. 資料庫改進

3.1 Entity Framework 優化

任務 9: 新增資料庫索引遷移

影響檔案:

  • backend/DramaLing.Api/Data/DramaLingDbContext.cs - 索引配置
  • 新增 EF 遷移檔案

遷移步驟:

# 生成新的遷移
dotnet ef migrations add AddFlashcardSearchIndexes

# 更新資料庫
dotnet ef database update

索引策略:

  • 單欄索引Word, Translation, DifficultyLevel, PartOfSpeech
  • 複合索引:(UserId, IsArchived, IsFavorite)
  • 搜尋優化:全文搜尋索引 (如果 SQLite 支援)

驗收標準:

  • 索引正確創建
  • 查詢計劃顯示索引使用
  • 搜尋效能明顯提升

任務 10: 資料驗證增強

影響檔案:

  • backend/DramaLing.Api/Models/DTOs/CreateFlashcardRequest.cs - 新增驗證特性

驗證規則:

public class CreateFlashcardRequest
{
    [Required(ErrorMessage = "詞彙為必填項目")]
    [StringLength(255, ErrorMessage = "詞彙長度不得超過 255 字元")]
    public string Word { get; set; } = string.Empty;

    [Required(ErrorMessage = "翻譯為必填項目")]
    public string Translation { get; set; } = string.Empty;

    [Required(ErrorMessage = "定義為必填項目")]
    public string Definition { get; set; } = string.Empty;

    [StringLength(255, ErrorMessage = "發音長度不得超過 255 字元")]
    public string Pronunciation { get; set; } = string.Empty;

    [RegularExpression("^(noun|verb|adjective|adverb|preposition|interjection)$",
                      ErrorMessage = "詞性必須為有效值")]
    public string PartOfSpeech { get; set; } = "noun";

    [Required(ErrorMessage = "例句為必填項目")]
    public string Example { get; set; } = string.Empty;

    public string? ExampleTranslation { get; set; }

    [RegularExpression("^(A1|A2|B1|B2|C1|C2)$",
                      ErrorMessage = "CEFR 等級必須為有效值")]
    public string? DifficultyLevel { get; set; } = "A2";
}

驗收標準:

  • 所有輸入資料驗證完整
  • 錯誤訊息本地化和友善
  • 驗證失敗時返回具體錯誤信息
  • 防止無效資料進入資料庫

4. API 文檔與測試

4.1 Swagger 文檔增強

任務 11: 完善 API 文檔

影響檔案:

  • backend/DramaLing.Api/Extensions/ServiceCollectionExtensions.cs - Swagger 配置

Swagger 增強:

services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new() {
        Title = "DramaLing API - 詞卡管理",
        Version = "v1",
        Description = "DramaLing 詞卡管理功能的完整 API 文檔"
    });

    // XML 註解檔案
    var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
    var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
    c.IncludeXmlComments(xmlPath);

    // API 範例
    c.SchemaFilter<ExampleSchemaFilter>();
});

XML 註解增強:

/// <summary>
/// 取得用戶的詞卡列表,支援搜尋和篩選
/// </summary>
/// <param name="search">搜尋關鍵字,搜尋範圍:詞彙、翻譯、定義、例句</param>
/// <param name="favoritesOnly">僅顯示收藏詞卡</param>
/// <param name="cefrLevel">CEFR 難度等級篩選 (A1-C2)</param>
/// <param name="partOfSpeech">詞性篩選</param>
/// <param name="masteryLevel">掌握度篩選 (high/medium/low)</param>
/// <returns>詞卡列表和數量</returns>
[HttpGet]
public async Task<ActionResult> GetFlashcards(...)

驗收標準:

  • Swagger UI 顯示完整 API 文檔
  • 所有參數和回應格式有詳細說明
  • 提供 API 使用範例
  • 錯誤代碼和狀態碼說明完整

4.2 API 測試套件

任務 12: 整合測試實現

影響檔案:

  • 新增 backend/DramaLing.Api.Tests/Controllers/FlashcardsControllerTests.cs

測試涵蓋範圍:

[TestClass]
public class FlashcardsControllerTests
{
    [TestMethod]
    public async Task GetFlashcards_WithSearch_ReturnsFilteredResults()
    {
        // 測試搜尋功能
    }

    [TestMethod]
    public async Task CreateFlashcard_WithValidData_CreatesSuccessfully()
    {
        // 測試詞卡創建
    }

    [TestMethod]
    public async Task CreateFlashcard_WithDuplicateWord_ReturnsDuplicateError()
    {
        // 測試重複詞卡檢測
    }

    [TestMethod]
    public async Task GetFlashcards_WithCefrFilter_ReturnsCorrectLevel()
    {
        // 測試 CEFR 等級篩選
    }
}

驗收標準:

  • 所有 API 端點有對應測試
  • 測試覆蓋率 > 80%
  • 包含邊界條件和錯誤情況測試
  • 測試可在 CI/CD 中自動執行

5. 實施時程

5.1 開發階段規劃

第一階段:核心功能增強 (預估2-3小時)

  1. 擴展搜尋功能 (45分鐘)
  2. 新增進階篩選參數 (60分鐘)
  3. 資料驗證增強 (45分鐘)
  4. 測試和驗證 (30分鐘)

第二階段:效能優化 (預估2-3小時)

  1. 資料庫索引優化 (60分鐘)
  2. 快取機制實現 (90分鐘)
  3. 效能測試和調整 (30分鐘)

第三階段API 增強 (預估3-4小時)

  1. 批量操作 API (120分鐘)
  2. 統計資料 API (90分鐘)
  3. Swagger 文檔完善 (30分鐘)

第四階段:測試和部署準備 (預估2-3小時)

  1. 整合測試實現 (120分鐘)
  2. 生產環境認證準備 (60分鐘)

5.2 里程碑檢查點

里程碑 1: 基礎功能完善

  • 搜尋和篩選功能完整
  • 資料驗證機制健全
  • 基本測試通過

里程碑 2: 效能達標

  • 查詢響應時間 < 200ms
  • 快取命中率 > 70%
  • 無明顯效能瓶頸

里程碑 3: API 完整性

  • 所有計劃 API 端點實現
  • Swagger 文檔完整
  • 錯誤處理標準化

里程碑 4: 生產準備

  • 整合測試覆蓋率 > 80%
  • 生產環境配置準備
  • 部署文檔更新

6. 品質保證

6.1 程式碼審查檢查清單

API 設計檢查

  • RESTful 設計原則遵循
  • HTTP 狀態碼正確使用
  • 回應格式標準化
  • 查詢參數命名一致

安全性檢查

  • 輸入驗證完整
  • SQL 注入防護
  • 用戶資料隔離
  • 敏感資訊保護

效能檢查

  • 查詢優化
  • 索引使用合理
  • 記憶體使用最佳化
  • 併發處理安全

6.2 測試策略

📋 測試策略參考

單元測試

  • Controller 方法邏輯測試
  • 資料驗證規則測試
  • 錯誤處理機制測試

整合測試

  • API 端點完整流程測試
  • 資料庫操作測試
  • 快取機制測試

效能測試

  • 大量資料載入測試
  • 並發請求壓力測試
  • 記憶體洩漏檢測

7. 部署與監控

7.1 部署準備

環境配置

# 生產環境變數
export ASPNETCORE_ENVIRONMENT=Production
export DRAMALING_DB_CONNECTION="Data Source=production.db"
export USE_INMEMORY_DB=false

健康檢查

// 增強健康檢查
services.AddHealthChecks()
    .AddDbContextCheck<DramaLingDbContext>()
    .AddCheck<CacheHealthCheck>("cache")
    .AddCheck<ApiHealthCheck>("api");

7.2 監控指標

關鍵效能指標 (KPI)

  • API 響應時間平均值 < 200ms
  • API 成功率 > 99.5%
  • 資料庫連接健康度 > 99%
  • 快取命中率 > 70%

業務指標

  • 每日 API 呼叫次數
  • 詞卡創建成功率
  • 搜尋查詢頻率
  • 使用者活躍度

計劃版本: v1.0 制定日期: 2025-09-24 預估完成時間: 9-13小時 (分 4 個階段) 負責開發: 後端開發團隊 審核負責: 技術主管

📋 開發前必讀文檔

🔧 主要規格參考

🏗️ 架構約束

📋 業務需求