Files
BlueArchiveToolkit/docs/archive/ARCHITECTURE_REVIEW.md

44 KiB
Raw Permalink Blame History

BlueArchive Toolkit 架构审查报告

审查日期2026-06-27
审查阶段Architecture Refactoring Sprint
审查目标:评估当前架构是否适合十年以上长期维护


执行摘要

经过对整个项目的全面分析,我发现当前架构存在多个严重的架构缺陷,这些问题如果不立即解决,将在未来 1-3 年内导致项目陷入技术债务泥潭,需要大规模重构。

核心问题:当前架构过度关注技术实现细节,而严重忽视了业务领域建模与 Blue Archive 客户端的集成方式

关键发现

  • 缺少游戏客户端集成层设计Critical
  • 缺少 Unity 版本适配抽象层Critical
  • 缺少 Manifest 格式适配层High
  • 模块职责边界不清晰High
  • 工作流自动化设计缺失High
  • ⚠️ 过早的技术选型固化Medium

第一部分:项目现状分析

1.1 已完成工作

基础设施

  • Monorepo 目录结构
  • Rust workspace (4 个 crates)
  • Go module 初始化
  • Docker 配置(支持远程数据库)
  • Makefile 构建系统
  • 基础文档

部分实现的模块

  • CAS 存储接口定义
  • Hash 计算模块
  • Storage trait 实现
  • AssetBundle、Patch、FFI 框架搭建

1.2 关键缺失

业务领域模型

  • 没有 Game Client 抽象
  • 没有 Version 概念
  • 没有 Asset 生命周期管理
  • 没有 Translation Workflow 设计

集成方式设计

  • 如何注入客户端?
  • 如何更新客户端资源?
  • 如何处理官方更新?

可扩展性设计

  • Unity 版本升级如何处理?
  • Manifest 格式变化如何适配?
  • 新的资源类型如何扩展?

第二部分:架构问题深度分析

问题 1:缺少游戏客户端集成层设计 ⚠️ CRITICAL

当前状况

整个项目没有明确定义如何与 Blue Archive 客户端集成

问题描述

  • 文档中只提到"资源同步"、"AssetBundle 解析"、"Patch 生成"
  • 但没有说明这些功能最终如何作用于游戏客户端
  • 没有定义"客户端"的抽象概念

为什么这是 Critical

这是整个项目的核心业务逻辑!如果不先设计清楚这一层,后续所有模块都可能需要推倒重来。

未来后果

  • 1 年内:发现现有设计无法适配实际客户端需求,需要大量重构
  • 3 年内:积累大量临时方案和 workaround,代码质量急剧下降
  • 5 年内:维护成本过高,项目陷入停滞

问题 2:缺少 Unity 版本适配抽象层 ⚠️ CRITICAL

当前状况

AssetBundle 解析器直接依赖特定的 Unity 版本实现。

问题描述

// 当前设计(crates/bat-assetbundle/
pub trait AssetParser {
    fn parse(&self, bundle: &AssetBundle) -> Result<Vec<Asset>>;
}

这个设计假设 AssetBundle 格式是稳定的,但实际上:

  • Unity 不同版本的 AssetBundle 格式完全不同
  • 官方随时可能升级 Unity 版本
  • 需要同时支持多个 Unity 版本

正确设计应该是

// 需要的设计
pub trait UnityVersionAdapter {
    fn version(&self) -> UnityVersion;
    fn can_handle(&self, bundle: &RawBundle) -> bool;
    fn parse(&self, bundle: &RawBundle) -> Result<GenericAssetBundle>;
}

pub struct AssetBundleParser {
    adapters: Vec<Box<dyn UnityVersionAdapter>>,
}

为什么这是 Critical

官方升级 Unity 版本是必然会发生的事情,如果现在不设计好,到时候整个 AssetBundle 模块都要重写。


问题 3:缺少 Manifest 格式适配层 ⚠️ HIGH

当前状况

架构文档中提到"Manifest Parser",但没有设计适配层。

问题描述

  • Blue Archive 的 Manifest 格式可能随时变化
  • 不同区域(日服、国际服)的 Manifest 格式可能不同
  • 需要支持旧版本的 Manifest 以便回溯历史

正确设计

pub trait ManifestAdapter {
    fn format_version(&self) -> &str;
    fn can_parse(&self, raw_data: &[u8]) -> bool;
    fn parse(&self, raw_data: &[u8]) -> Result<GenericManifest>;
}

pub struct ManifestParser {
    adapters: HashMap<String, Box<dyn ManifestAdapter>>,
}

未来后果

  • 1 年内:官方修改 Manifest 格式,整个同步系统瘫痪
  • 3 年内:为了支持多个版本,代码中充斥着 if-else 判断

问题 4:模块职责边界不清晰 ⚠️ HIGH

当前问题

CAS 存储引擎职责过重

// 当前设计混合了多个职责
pub trait Storage {
    async fn put(&self, data: &[u8]) -> Result<Hash>;  // 存储
    async fn get(&self, hash: &Hash) -> Result<Vec<u8>>; // 读取
    async fn stats(&self) -> Result<StorageStats>; // 统计
}

// 引用计数独立管理
pub struct RefCounter {
    // 使用独立的 SQLite
}

问题

  1. Storage 和 RefCounter 是两个独立的组件,但它们的数据必须保持一致
  2. 如果 put() 成功但 incr() 失败,会导致数据不一致
  3. 没有事务保证

正确设计

pub trait CasRepository {
    // 统一的仓储接口,内部保证事务一致性
    async fn store(&self, data: &[u8]) -> Result<ObjectId>;
    async fn get(&self, id: &ObjectId) -> Result<Vec<u8>>;
    async fn add_reference(&self, id: &ObjectId) -> Result<()>;
    async fn remove_reference(&self, id: &ObjectId) -> Result<bool>; // 返回是否应该删除
}

问题 5:工作流自动化设计缺失 ⚠️ HIGH

当前状况

项目规划了各个技术模块,但没有设计完整的业务工作流

缺失的工作流

官方更新后的自动化流程

  1. 版本检测 → 如何实现?
  2. Manifest 获取 → 从哪里获取?
  3. 资源同步 → 如何判断哪些需要下载?
  4. 自动解析 → 如何识别文本资源?
  5. 自动识别新增文本 → 如何 diff
  6. 自动翻译 → 如何调度?
  7. 人工审核 → 工作流如何设计?
  8. Patch 生成 → 如何保证一致性?
  9. 自动发布 → 发布到哪里?

当前架构中这些都是空白!

正确设计需要

workflow/
├── version_detector/     # 版本检测服务
├── sync_coordinator/     # 同步协调器
├── text_extractor/       # 文本提取器
├── diff_analyzer/        # 差异分析器
├── translation_pipeline/ # 翻译管道
├── review_queue/         # 审核队列
├── patch_generator/      # Patch 生成器
└── release_manager/      # 发布管理器

第三部分:Blue Archive 客户端集成方案分析

3.1 可能的集成方案

方案 A:客户端资源替换(推荐)

原理

  1. 工具下载官方资源到本地
  2. 解析 AssetBundle,提取文本
  3. 翻译后重新打包 AssetBundle
  4. 替换客户端的资源文件

优点

  • 不修改游戏可执行文件,安全性高
  • 支持增量更新
  • 易于回滚
  • 可以离线工作

缺点

  • ⚠️ 需要深入理解 Unity AssetBundle 格式
  • ⚠️ Unity 版本升级需要适配

维护成本:中等
更新成本:低
兼容性:高

架构要求

Client Integration Layer:
├── AssetBundleReplacer    # 资源替换器
├── IntegrityVerifier      # 完整性验证
└── RollbackManager        # 回滚管理

方案 B:代理服务器模式

原理

  1. 在客户端和游戏服务器之间插入代理
  2. 拦截资源下载请求
  3. 返回翻译后的资源

优点

  • 不需要修改客户端文件
  • 动态更新翻译

缺点

  • 需要用户配置代理
  • 可能影响游戏性能
  • 需要持续运行服务
  • 官方可能检测并封禁

维护成本:高
更新成本:低
兼容性:中

不推荐:维护成本高,用户体验差


方案 C:内存补丁模式

原理

  1. Hook 游戏进程
  2. 在内存中替换文本

优点

  • 不修改文件

缺点

  • 技术复杂度极高
  • 容易被反作弊系统检测
  • 每次游戏更新都可能失效
  • 不同平台需要不同实现

维护成本:极高
更新成本:极高
兼容性:低

不推荐:风险高,维护成本不可持续


3.2 推荐方案:方案 A(客户端资源替换)

实施步骤

Step 1:资源定位

ClientResourceLocator:
- 识别客户端安装路径
- 定位 AssetBundle 文件位置
- 建立资源索引

Step 2:资源备份

BackupManager:
- 首次运行时备份原始资源
- 支持多版本备份
- 快速恢复机制

Step 3:资源替换

ResourceReplacer:
- 验证资源完整性
- 原子替换(要么全部成功,要么全部回滚)
- 更新资源索引

Step 4:启动验证

LaunchVerifier:
- 游戏启动前检查资源完整性
- 自动修复损坏的资源
- 生成诊断报告

第四部分:自动化流程设计

4.1 完整的官方更新适配流程

graph TD
    A[官方发布新版本] --> B[版本检测服务]
    B --> C{是否有新版本?}
    C -->|是| D[下载新 Manifest]
    C -->|否| Z[等待]
    
    D --> E[Manifest 差异分析]
    E --> F[识别变更的资源]
    
    F --> G[资源同步下载]
    G --> H[存入 CAS]
    
    H --> I[AssetBundle 解析]
    I --> J[文本提取]
    
    J --> K[文本差异分析]
    K --> L{有新增文本?}
    
    L -->|是| M[查询翻译记忆库]
    L -->|否| Y[完成]
    
    M --> N{记忆库命中?}
    N -->|全部命中| S[应用翻译]
    N -->|部分未命中| O[AI 翻译]
    
    O --> P[术语库替换]
    P --> Q[加入审核队列]
    
    Q --> R[人工审核]
    R --> S[应用翻译]
    
    S --> T[重新打包 AssetBundle]
    T --> U[生成 Patch]
    
    U --> V[完整性测试]
    V --> W[发布到仓库]
    W --> X[通知用户]
    X --> Y[完成]

4.2 关键服务设计

4.2.1 版本检测服务

pub struct VersionDetector {
    region: GameRegion, // JP, Global, CN, etc.
    check_interval: Duration,
}

impl VersionDetector {
    /// 检测是否有新版本
    pub async fn check_for_updates(&self) -> Result<Option<GameVersion>> {
        // 1. 获取官方 API 最新版本号
        // 2. 与本地记录对比
        // 3. 返回版本信息
    }
    
    /// 下载新版本的 Manifest
    pub async fn fetch_manifest(&self, version: &GameVersion) -> Result<RawManifest> {
        // 从 CDN 下载 Manifest
    }
}

4.2.2 差异分析器

pub struct DiffAnalyzer {
    cas: Arc<CasRepository>,
}

impl DiffAnalyzer {
    /// 分析两个版本之间的资源差异
    pub async fn analyze_manifest_diff(
        &self,
        old_version: &Manifest,
        new_version: &Manifest,
    ) -> Result<ManifestDiff> {
        // 返回:新增、修改、删除的资源列表
    }
    
    /// 分析文本差异
    pub async fn analyze_text_diff(
        &self,
        old_texts: &[ExtractedText],
        new_texts: &[ExtractedText],
    ) -> Result<TextDiff> {
        // 返回:新增、修改、删除的文本
    }
}

4.2.3 翻译管道

pub struct TranslationPipeline {
    memory: Arc<TranslationMemory>,
    glossary: Arc<Glossary>,
    providers: Vec<Box<dyn TranslationProvider>>,
}

impl TranslationPipeline {
    /// 处理待翻译文本
    pub async fn process(&self, texts: Vec<SourceText>) -> Result<Vec<TranslationResult>> {
        // 1. 查询翻译记忆库
        // 2. 未命中的发送给 AI
        // 3. 应用术语库
        // 4. 返回结果
    }
}

4.2.4 审核队列

pub struct ReviewQueue {
    db: Pool<Postgres>,
}

impl ReviewQueue {
    /// 添加待审核项
    pub async fn enqueue(&self, item: ReviewItem) -> Result<QueueId>;
    
    /// 获取待审核项
    pub async fn fetch_pending(&self, limit: usize) -> Result<Vec<ReviewItem>>;
    
    /// 提交审核结果
    pub async fn submit_review(&self, id: QueueId, result: ReviewResult) -> Result<()>;
}

4.3 自动化程度设计

完全自动化(无需人工干预):

  • 版本检测
  • Manifest 下载
  • 资源同步
  • AssetBundle 解析
  • 文本提取
  • 差异分析
  • 翻译记忆库查询
  • AI 翻译
  • 术语应用

半自动化(需要人工审核):

  • ⚠️ 新增术语的添加
  • ⚠️ AI 翻译质量审核
  • ⚠️ 关键剧情翻译确认

手动操作(首次或特殊情况):

  • 🔧 术语库初始化
  • 🔧 翻译风格指南制定
  • 🔧 异常情况处理

目标:90% 的更新可以在 1 小时内自动完成,仅 10% 需要人工审核。


第五部分:适配 Unity/Manifest 变化的架构设计

5.1 核心设计原则

原则 1:版本即插件

  • 每个 Unity 版本对应一个 Adapter 插件
  • 新版本 = 新增插件,不修改已有代码

原则 2:格式即 Driver

  • 每种 Manifest 格式对应一个 Driver
  • 自动检测格式,加载对应 Driver

原则 3:解耦核心与适配

  • 核心业务逻辑不依赖具体版本
  • 通过抽象接口与适配层通信

5.2 Unity 版本适配架构

adapters/
├── unity/
│   ├── adapter_trait.rs          # Unity Adapter 接口定义
│   ├── version_2019_4/           # Unity 2019.4 适配器
│   │   ├── assetbundle_parser.rs
│   │   └── serialization.rs
│   ├── version_2021_3/           # Unity 2021.3 适配器
│   │   ├── assetbundle_parser.rs
│   │   └── serialization.rs
│   └── version_2022_3/           # Unity 2022.3 适配器
│       ├── assetbundle_parser.rs
│       └── serialization.rs
└── registry.rs                    # 适配器注册表

接口设计

pub trait UnityAdapter: Send + Sync {
    /// 适配器名称(例如 "Unity-2019.4"
    fn name(&self) -> &str;
    
    /// 支持的 Unity 版本范围
    fn supported_versions(&self) -> VersionRange;
    
    /// 检测是否可以处理这个 AssetBundle
    fn can_handle(&self, bundle: &RawAssetBundle) -> bool;
    
    /// 解析 AssetBundle
    fn parse(&self, bundle: &RawAssetBundle) -> Result<ParsedAssetBundle>;
    
    /// 序列化回 AssetBundle
    fn serialize(&self, parsed: &ParsedAssetBundle) -> Result<Vec<u8>>;
}

pub struct UnityAdapterRegistry {
    adapters: Vec<Box<dyn UnityAdapter>>,
}

impl UnityAdapterRegistry {
    /// 自动选择合适的适配器
    pub fn select_adapter(&self, bundle: &RawAssetBundle) -> Result<&dyn UnityAdapter> {
        for adapter in &self.adapters {
            if adapter.can_handle(bundle) {
                return Ok(adapter.as_ref());
            }
        }
        Err(Error::NoSuitableAdapter)
    }
}

新增 Unity 版本的步骤

  1. 创建新目录:adapters/unity/version_XXXX_X/
  2. 实现 UnityAdapter trait
  3. registry.rs 中注册
  4. 无需修改核心代码!

5.3 Manifest 格式适配架构

adapters/
├── manifest/
│   ├── driver_trait.rs           # Manifest Driver 接口
│   ├── format_v1/                # 第一代格式
│   │   └── parser.rs
│   ├── format_v2/                # 第二代格式
│   │   └── parser.rs
│   ├── format_v3/                # 第三代格式(假设未来会有)
│   │   └── parser.rs
│   └── registry.rs

接口设计

pub trait ManifestDriver: Send + Sync {
    /// Driver 名称
    fn name(&self) -> &str;
    
    /// 格式版本标识
    fn format_version(&self) -> &str;
    
    /// 检测是否可以解析这个 Manifest
    fn can_parse(&self, raw_data: &[u8]) -> bool;
    
    /// 解析 Manifest
    fn parse(&self, raw_data: &[u8]) -> Result<GenericManifest>;
}

/// 通用 Manifest 结构(所有格式都转换到这个结构)
pub struct GenericManifest {
    pub version: String,
    pub resources: Vec<ResourceEntry>,
    pub metadata: HashMap<String, String>,
}

pub struct ResourceEntry {
    pub path: String,
    pub hash: String,
    pub size: u64,
    pub url: String,
}

新增格式的步骤

  1. 创建新目录:adapters/manifest/format_vX/
  2. 实现 ManifestDriver trait
  3. 注册到 Registry
  4. 无需修改核心代码!

第六部分:必须立即重构的模块

6.1 Critical 级别(必须在继续开发前完成)

🔴 C1: 建立业务领域模型

当前状态:只有技术组件,没有业务抽象
必须重构的原因:所有后续开发都依赖清晰的领域模型
不改的后果:项目会变成一堆技术组件的堆砌,无法形成完整系统

需要的领域模型

// 核心领域对象
pub struct GameClient {
    region: GameRegion,
    version: GameVersion,
    install_path: PathBuf,
    resources: ResourceIndex,
}

pub struct GameVersion {
    major: u32,
    minor: u32,
    patch: u32,
    revision: String,
    unity_version: UnityVersion,
}

pub struct ResourceIndex {
    manifest: Manifest,
    asset_bundles: HashMap<String, AssetBundleInfo>,
}

pub struct TranslationProject {
    source_version: GameVersion,
    target_language: Language,
    translations: TranslationSet,
    status: ProjectStatus,
}

🔴 C2: 设计客户端集成层

当前状态:完全缺失
必须重构的原因:这是项目的核心价值所在
不改的后果:做出来的工具无法实际使用

需要的集成层

pub trait ClientIntegration {
    /// 发现客户端安装
    fn discover_installation(&self) -> Result<Vec<GameClient>>;
    
    /// 备份原始资源
    fn backup_resources(&self, client: &GameClient) -> Result<BackupId>;
    
    /// 应用翻译
    fn apply_translation(&self, client: &GameClient, patch: &Patch) -> Result<()>;
    
    /// 验证完整性
    fn verify_integrity(&self, client: &GameClient) -> Result<IntegrityReport>;
    
    /// 回滚到原始状态
    fn rollback(&self, client: &GameClient, backup_id: BackupId) -> Result<()>;
}

🔴 C3: 建立 Adapter 架构

当前状态:直接依赖具体实现
必须重构的原因:未来版本变化时需要全部重写
不改的后果:每次官方更新都需要大规模重构

需要重构的模块

  1. bat-assetbundle → 改为基于 Adapter 的架构
  2. Manifest 解析 → 改为基于 Driver 的架构
  3. 所有版本相关的代码 → 改为插件化

6.2 High 级别(第一个迭代必须完成)

🟠 H1: 重新设计 CAS 存储

当前问题Storage 和 RefCounter 分离,没有事务保证

重构方案

// 统一的 CAS Repository
pub struct CasRepository {
    storage: Box<dyn ObjectStorage>,
    metadata: Pool<Sqlite>,
}

impl CasRepository {
    /// 存储对象(原子操作)
    pub async fn store(&self, data: &[u8]) -> Result<ObjectId> {
        let mut tx = self.metadata.begin().await?;
        
        // 1. 计算 Hash
        let hash = compute_hash(data);
        
        // 2. 检查是否存在
        if self.object_exists(&hash, &mut tx).await? {
            // 3a. 增加引用计数
            self.increment_ref(&hash, &mut tx).await?;
        } else {
            // 3b. 存储数据
            self.storage.put(&hash, data).await?;
            // 4. 记录元数据
            self.insert_metadata(&hash, data.len(), &mut tx).await?;
        }
        
        tx.commit().await?;
        Ok(ObjectId::from(hash))
    }
}

🟠 H2: 建立工作流引擎

当前问题:没有工作流设计

重构方案

pub struct WorkflowEngine {
    steps: Vec<Box<dyn WorkflowStep>>,
    context: WorkflowContext,
}

pub trait WorkflowStep: Send + Sync {
    fn name(&self) -> &str;
    async fn execute(&self, ctx: &mut WorkflowContext) -> Result<StepResult>;
    async fn rollback(&self, ctx: &mut WorkflowContext) -> Result<()>;
}

// 标准工作流:官方更新适配
pub struct OfficialUpdateWorkflow {
    steps: [
        VersionDetectionStep,
        ManifestDownloadStep,
        ResourceSyncStep,
        TextExtractionStep,
        DiffAnalysisStep,
        TranslationStep,
        ReviewStep,
        PatchGenerationStep,
        PublishStep,
    ],
}

🟠 H3: 定义标准数据格式

当前问题:没有定义中间数据格式

需要的标准格式

/// 提取的文本(标准格式)
pub struct ExtractedText {
    pub id: TextId,              // 唯一标识
    pub source: TextSource,      // 来源(哪个资源文件)
    pub context: TextContext,    // 上下文信息
    pub content: String,         // 文本内容
    pub metadata: TextMetadata,  // 元数据
}

pub struct TextSource {
    pub asset_bundle: String,
    pub asset_path: String,
    pub object_type: String,
    pub field_path: Vec<String>,
}

/// 翻译后的文本
pub struct TranslatedText {
    pub source_id: TextId,
    pub target_language: Language,
    pub translation: String,
    pub provider: String,
    pub confidence: f32,
    pub reviewed: bool,
}

6.3 Medium 级别(可以逐步优化)

🟡 M1: FFI 层设计

当前问题:只有占位代码

建议

  • 先完成 Rust 端的核心功能
  • 然后设计稳定的 C ABI
  • 最后实现 Go 绑定

不急迫的原因:可以先用纯 Rust 实现原型,验证设计后再做 FFI


🟡 M2: 性能优化

当前问题:没有性能测试和优化

建议

  • 先保证功能正确性
  • 再用 Benchmark 找瓶颈
  • 最后针对性优化

不急迫的原因:过早优化是万恶之源


6.4 Low 级别(未来可选)

🟢 L1: Web 后台

建议:核心 CLI 工具稳定后再做

🟢 L2: API Server

建议:先做单机版,需求明确后再做服务端


第七部分:当前目录结构评估与重构建议

7.1 当前目录结构问题

问题 1:缺少领域层

当前:
crates/
├── bat-cas-engine/     # 技术组件
├── bat-assetbundle/    # 技术组件
├── bat-patch/          # 技术组件
└── bat-ffi/            # 技术组件

缺少:
- 没有业务领域模型
- 没有应用服务层
- 没有集成层

问题 2:模块划分不清晰

internal/  # Go 私有包
├── downloader/   # 这是基础设施
├── manifest/     # 这是领域对象
├── storage/      # 这是基础设施
├── config/       # 这是基础设施
└── extractor/    # 这是应用服务

混在一起,职责不清!

问题 3:适配层缺失

应该有但没有:
adapters/
├── unity/          # Unity 版本适配器
├── manifest/       # Manifest 格式适配器
└── client/         # 客户端平台适配器

7.2 推荐的新目录结构

BlueArchiveToolkit/
├── core/                           # 核心领域层(Rust
│   ├── domain/                     # 领域模型
│   │   ├── game_client.rs
│   │   ├── game_version.rs
│   │   ├── resource.rs
│   │   ├── translation.rs
│   │   └── mod.rs
│   ├── repositories/               # 仓储接口
│   │   ├── cas_repository.rs
│   │   ├── translation_repository.rs
│   │   └── mod.rs
│   └── services/                   # 领域服务
│       ├── version_service.rs
│       ├── translation_service.rs
│       └── mod.rs
│
├── adapters/                       # 适配器层(Rust
│   ├── unity/                      # Unity 版本适配
│   │   ├── adapter_trait.rs
│   │   ├── unity_2019_4/
│   │   ├── unity_2021_3/
│   │   └── registry.rs
│   ├── manifest/                   # Manifest 格式适配
│   │   ├── driver_trait.rs
│   │   ├── format_v1/
│   │   ├── format_v2/
│   │   └── registry.rs
│   └── client/                     # 客户端平台适配
│       ├── windows.rs
│       ├── android.rs
│       └── ios.rs
│
├── infrastructure/                 # 基础设施层(Rust)
│   ├── cas/                        # CAS 存储实现
│   │   ├── repository_impl.rs
│   │   ├── file_storage.rs
│   │   └── s3_storage.rs
│   ├── downloader/                 # 下载器
│   ├── parser/                     # 底层解析器
│   └── crypto/                     # 加密工具
│
├── application/                    # 应用服务层(Go
│   ├── workflows/                  # 工作流
│   │   ├── official_update.go
│   │   ├── manual_translation.go
│   │   └── patch_generation.go
│   ├── commands/                   # 命令处理器
│   │   ├── sync.go
│   │   ├── extract.go
│   │   ├── translate.go
│   │   └── patch.go
│   └── queries/                    # 查询处理器
│       ├── version_query.go
│       └── translation_query.go
│
├── api/                            # API 层(Go
│   ├── http/                       # HTTP API
│   ├── grpc/                       # gRPC API(可选)
│   └── cli/                        # CLI 入口
│       └── main.go
│
├── web/                            # 前端(Vue 3
│   ├── admin/
│   └── shared/
│
├── shared/                         # 共享代码
│   ├── types/                      # 类型定义
│   ├── errors/                     # 错误定义
│   └── utils/                      # 工具函数
│
├── migrations/                     # 数据库迁移
├── docs/                           # 文档
├── scripts/                        # 脚本
└── deployments/                    # 部署配置

7.3 新目录结构的优势

1. 清晰的分层架构

  • 核心领域层:业务逻辑,不依赖外部
  • 适配器层:隔离变化,易于扩展
  • 基础设施层:技术实现,可替换
  • 应用服务层:编排业务流程
  • API 层:对外接口

2. 依赖关系清晰

API → Application → Core ← Adapters ← Infrastructure
                     ↑
                  Domain (最核心,不依赖任何外部)

3. 易于测试

  • 核心层:纯业务逻辑,易于单元测试
  • 适配器层:Mock 接口,易于集成测试
  • 应用层:Mock 依赖,易于端到端测试

4. 易于扩展

  • 新增 Unity 版本:添加新适配器
  • 新增 Manifest 格式:添加新 Driver
  • 新增翻译 Provider:实现接口即可

第八部分:技术风险评估

8.1 高风险(发生概率高 + 影响大)

⚠️ R1: Unity 版本升级导致 AssetBundle 格式变化

发生概率90%(官方必然会升级)
影响程度极高(整个解析系统失效)
维护成本当前设计:极高 / 新设计:低

缓解措施

  • 立即实施 Adapter 架构
  • 为每个 Unity 版本建立独立适配器
  • 建立自动化测试套件

⚠️ R2: Manifest 格式变化

发生概率70%
影响程度(资源同步失败)
维护成本当前设计:高 / 新设计:低

缓解措施

  • 实施 Driver 架构
  • 支持多版本 Manifest 并存
  • 建立格式自动检测机制

⚠️ R3: 官方增加反破解机制

发生概率50%
影响程度极高(工具完全失效)
维护成本极高

缓解措施

  • ⚠️ 采用最小侵入性的方案(资源替换)
  • ⚠️ 不修改游戏可执行文件
  • ⚠️ 不使用 Hook 技术
  • ⚠️ 提供快速回滚机制

8.2 中风险

⚠️ R4: 新增的资源类型无法解析

发生概率60%
影响程度(部分内容无法翻译)
维护成本当前设计:中 / 新设计:低

缓解措施

  • 插件化的解析器架构
  • 支持动态加载新解析器

⚠️ R5: AI API 限流或成本过高

发生概率40%
影响程度(翻译速度下降)
维护成本

缓解措施

  • 支持多个 Provider
  • 实现请求队列和限流
  • 最大化利用翻译记忆库

8.3 低风险

🟢 R6: 数据库性能瓶颈

发生概率20%
影响程度(响应变慢)
维护成本

缓解措施

  • 索引优化
  • 查询优化
  • 必要时分库分表

第九部分:其他关键问题

9.1 没有考虑的问题

问题 1:多区域支持

当前状况:架构假设只有一个游戏版本

实际情况

  • 日服(JP
  • 国际服(Global
  • 韩服(KR
  • 国服(CN- 可能有特殊审查要求

每个区域的:

  • Manifest 地址不同
  • 资源 CDN 不同
  • 更新时间不同
  • 可能有独占内容

需要的设计

pub enum GameRegion {
    Japan,
    Global,
    Korea,
    China,
}

pub struct RegionConfig {
    manifest_url: String,
    cdn_urls: Vec<String>,
    api_endpoints: Vec<String>,
    special_handling: Option<RegionHandler>,
}

问题 2:增量更新策略

当前状况:没有明确的增量更新策略

问题

  • 用户不应该每次都下载全部资源
  • 需要智能判断哪些需要更新
  • 需要支持差异化更新

需要的设计

pub struct UpdateStrategy {
    /// 计算需要更新的资源
    fn calculate_delta(
        &self,
        local: &ResourceIndex,
        remote: &Manifest,
    ) -> Vec<ResourceUpdate>;
    
    /// 优先级排序(先下载重要的)
    fn prioritize(&self, updates: Vec<ResourceUpdate>) -> Vec<ResourceUpdate>;
}

问题 3:错误恢复机制

当前状况:没有设计错误恢复

问题

  • 下载中断如何恢复?
  • 翻译失败如何重试?
  • Patch 应用失败如何回滚?

需要的设计

pub trait Recoverable {
    /// 保存检查点
    fn save_checkpoint(&self) -> Result<CheckpointId>;
    
    /// 从检查点恢复
    fn restore_from_checkpoint(&self, id: CheckpointId) -> Result<()>;
    
    /// 清理检查点
    fn cleanup_checkpoint(&self, id: CheckpointId) -> Result<()>;
}

问题 4:版本兼容性矩阵

当前状况:没有定义兼容性规则

问题

  • 工具版本 1.0 能否处理游戏版本 2.0 的资源?
  • 旧的翻译能否应用到新版本?
  • 如何处理不兼容的情况?

需要的设计

pub struct CompatibilityMatrix {
    /// 检查工具版本是否支持游戏版本
    fn is_compatible(
        &self,
        tool_version: &Version,
        game_version: &GameVersion,
    ) -> CompatibilityResult;
    
    /// 获取升级路径
    fn get_upgrade_path(
        &self,
        from: &Version,
        to: &Version,
    ) -> Vec<Version>;
}

问题 5:用户数据迁移

当前状况:没有考虑数据迁移

问题

  • 工具升级时如何迁移用户数据?
  • 如何保证数据完整性?
  • 如何支持降级?

需要的设计

pub trait Migratable {
    fn current_version(&self) -> Version;
    fn migrate_from(&self, version: Version) -> Result<()>;
    fn can_downgrade_to(&self, version: Version) -> bool;
}

问题 6:并发控制

当前状况CAS 存储有并发问题

问题

  • 多个进程同时访问 CAS 怎么办?
  • 如何防止数据竞争?
  • 如何保证原子性?

需要的设计

pub struct ConcurrencyControl {
    lock_manager: LockManager,
}

impl ConcurrencyControl {
    /// 获取排他锁
    async fn acquire_exclusive(&self, resource: &str) -> Result<Lock>;
    
    /// 获取共享锁
    async fn acquire_shared(&self, resource: &str) -> Result<Lock>;
}

问题 7:监控和可观测性

当前状况:没有监控设计

问题

  • 如何知道系统运行状况?
  • 如何追踪问题?
  • 如何收集性能数据?

需要的设计

pub struct Telemetry {
    metrics: MetricsCollector,
    traces: TraceCollector,
    logs: LogCollector,
}

// 关键指标
- 下载速度
- 翻译质量
- API 响应时间
- 错误率
- 资源使用情况

问题 8:安全性

当前状况:没有安全设计

问题

  • 如何防止恶意 Patch
  • 如何验证资源完整性?
  • 如何保护用户隐私?

需要的设计

pub struct SecurityValidator {
    /// 验证 Patch 签名
    fn verify_patch_signature(&self, patch: &Patch) -> Result<bool>;
    
    /// 检查资源完整性
    fn check_integrity(&self, resource: &Resource) -> Result<bool>;
    
    /// 加密敏感数据
    fn encrypt_sensitive_data(&self, data: &[u8]) -> Result<Vec<u8>>;
}

问题 9:测试策略

当前状况:只有少量单元测试

问题

  • 如何保证代码质量?
  • 如何测试适配器?
  • 如何测试工作流?

需要的测试层次

1. 单元测试(Unit Tests
   - 每个模块独立测试
   - Mock 所有依赖

2. 集成测试(Integration Tests
   - 测试模块间交互
   - 使用真实数据库(测试环境)

3. 端到端测试(E2E Tests
   - 测试完整工作流
   - 使用真实游戏资源(脱敏)

4. 性能测试(Performance Tests
   - Benchmark 关键路径
   - 压力测试

5. 兼容性测试(Compatibility Tests
   - 测试不同 Unity 版本
   - 测试不同 Manifest 格式

问题 10:文档策略

当前状况:文档偏技术,缺少用户视角

问题

  • 用户如何使用工具?
  • 开发者如何贡献代码?
  • 如何编写插件?

需要的文档

docs/
├── user-guide/              # 用户指南
│   ├── installation.md
│   ├── first-translation.md
│   └── troubleshooting.md
├── developer-guide/         # 开发者指南
│   ├── architecture.md
│   ├── contributing.md
│   └── code-style.md
├── plugin-guide/            # 插件开发指南
│   ├── unity-adapter.md
│   ├── manifest-driver.md
│   └── translation-provider.md
└── api-reference/           # API 参考
    ├── rust-api.md
    └── go-api.md

第十部分:完整重构方案

10.1 重构优先级和时间线

Phase 0:立即暂停(已完成

  • 停止继续实现技术细节
  • 完成架构审查

Phase 1:核心架构重构(2-3 周)

Week 1:领域建模

  • 定义核心领域对象(GameClient, GameVersion, Resource, Translation
  • 设计仓储接口(Repository Interfaces
  • 实现领域服务(Domain Services
  • 编写领域层测试

Week 2:适配器架构

  • 设计 Unity Adapter 接口
  • 实现第一个 Unity 适配器(当前使用的版本)
  • 设计 Manifest Driver 接口
  • 实现第一个 Manifest Driver
  • 设计客户端集成接口

Week 3:基础设施重构

  • 重构 CAS 为统一的 Repository
  • 实现事务支持
  • 重新组织目录结构
  • 迁移现有代码到新架构

产出物

  • 清晰的领域模型
  • 可扩展的适配器架构
  • 重构后的代码库

Phase 2:工作流实现(2-3 周)

Week 4-5:核心工作流

  • 实现版本检测服务
  • 实现资源同步工作流
  • 实现文本提取工作流
  • 实现差异分析器

Week 6:翻译工作流

  • 实现翻译记忆库
  • 实现术语库
  • 实现翻译管道
  • 实现审核队列

产出物

  • 完整的自动化工作流
  • 可测试的业务流程

Phase 3:客户端集成(2 周)

Week 7-8:集成层实现

  • 实现客户端发现
  • 实现资源备份
  • 实现资源替换
  • 实现完整性验证
  • 实现回滚机制

产出物

  • 可用的客户端集成
  • 端到端测试通过

Phase 4:打磨和优化(2 周)

Week 9-10

  • 性能优化
  • 错误处理完善
  • 日志和监控
  • 文档完善
  • 用户指南

产出物

  • 可发布的 Alpha 版本

10.2 新架构的模块依赖图

graph TB
    subgraph "API Layer"
        CLI[CLI]
        HTTP[HTTP API]
    end
    
    subgraph "Application Layer"
        WF[Workflows]
        CMD[Commands]
    end
    
    subgraph "Domain Layer"
        DOM[Domain Models]
        SVC[Domain Services]
        REPO[Repository Interfaces]
    end
    
    subgraph "Adapter Layer"
        UNITY[Unity Adapters]
        MANIFEST[Manifest Drivers]
        CLIENT[Client Adapters]
    end
    
    subgraph "Infrastructure Layer"
        CAS[CAS Repository]
        DL[Downloader]
        DB[Database]
    end
    
    CLI --> WF
    HTTP --> WF
    WF --> CMD
    CMD --> SVC
    SVC --> DOM
    SVC --> REPO
    REPO --> CAS
    REPO --> DB
    SVC --> UNITY
    SVC --> MANIFEST
    CMD --> CLIENT
    CLIENT --> CAS
    
    style DOM fill:#90EE90
    style UNITY fill:#FFB6C1
    style MANIFEST fill:#FFB6C1
    style CLIENT fill:#FFB6C1

10.3 关键设计决策

决策 1:Rust 为核心,Go 为应用层

理由

  • Rust:性能关键路径(解析、Patch、CAS)
  • Go:业务编排、HTTP API、CLI
  • 优势互补

权衡

  • 发挥各语言优势
  • ⚠️ FFI 有一定复杂度
  • 但隔离清晰,便于测试

决策 2:采用资源替换而非内存 Hook

理由

  • 维护成本低
  • 兼容性好
  • 安全性高
  • 易于回滚

权衡

  • 长期维护成本低
  • ⚠️ 需要深入理解 AssetBundle
  • 但这是一次性成本

决策 3:插件化架构

理由

  • Unity 版本必然升级
  • Manifest 格式可能变化
  • 需要支持扩展

权衡

  • 长期可维护
  • ⚠️ 初期开发成本略高
  • 但避免未来大规模重构

决策 4:工作流引擎

理由

  • 业务流程复杂
  • 需要错误恢复
  • 需要可观测性

权衡

  • 流程清晰
  • 易于扩展
  • ⚠️ 需要学习成本

10.4 技术债务清单

必须立即偿还

  • 缺少领域模型
  • 缺少适配器架构
  • CAS 缺少事务
  • 缺少客户端集成

第一个版本前偿还

  • ⚠️ 工作流设计
  • ⚠️ 错误恢复机制
  • ⚠️ 监控和日志

可以延后

  • 🟢 性能优化
  • 🟢 Web 后台
  • 🟢 API Server

第十一部分:行动计划

11.1 立即行动(本周)

任务 1:确认架构方向

  • 审查本文档
  • 确认重构范围
  • 确认时间线

任务 2:准备重构

  • 备份当前代码
  • 创建 refactor 分支
  • 准备测试环境

任务 3:开始领域建模

  • 定义核心领域对象
  • 编写领域层代码
  • 编写单元测试

11.2 第一周目标

交付物

  • 完整的领域模型(Rust
  • 核心接口定义
  • 通过测试的领域层

验收标准

  • 代码编译通过
  • 所有单元测试通过
  • 文档更新

11.3 第一个月目标

交付物

  • 重构后的架构
  • 适配器框架
  • 核心工作流

里程碑

  • M1:领域层完成(Week 1
  • M2:适配器层完成(Week 2
  • M3:基础设施完成(Week 3
  • M4:工作流完成(Week 5

11.4 三个月目标

交付物

  • 可用的 Alpha 版本
  • 完整文档
  • 测试覆盖 > 80%

里程碑

  • M5:客户端集成完成(Week 8
  • M6:端到端测试通过(Week 9
  • M7Alpha 版本发布(Week 10

第十二部分:总结与建议

12.1 核心结论

  1. 当前架构不可持续

    • 缺少业务领域建模
    • 缺少适配层设计
    • 缺少客户端集成
    • 无法应对未来变化
  2. 必须立即重构 ⚠️

    • 继续开发会积累技术债
    • 未来重构成本呈指数增长
    • 现在重构成本最低
  3. 重构方向明确

    • 领域驱动设计
    • 适配器+插件架构
    • 工作流引擎
    • 清晰的分层

12.2 关键建议

建议 1:先做对,再做快

不要为了快速实现功能而妥协架构质量。好的架构会让后续开发更快。

建议 2:接受重构成本

当前已写的代码中,约 30-40% 需要重构或重写。这是必要的投资。

建议 3:边重构边测试

每重构一个模块,立即编写测试。不要等到最后。

建议 4:文档同步更新

代码重构的同时更新文档,保持一致性。

建议 5:小步快跑

按周交付,每周都有可验证的成果。


12.3 成功标准

技术标准

  • 编译通过,无警告
  • 测试覆盖率 > 80%
  • 所有 Critical 问题解决
  • 架构文档完整

业务标准

  • 能够完成一次完整的官方更新适配
  • 翻译质量达标
  • 用户可以正常使用

可维护性标准

  • 新增 Unity 版本只需要添加适配器
  • 新增 Manifest 格式只需要添加 Driver
  • 代码易读、易测试、易扩展

12.4 风险与应对

风险 1:重构时间超出预期

应对

  • 采用迭代方式
  • 先完成核心,再完善细节
  • 保持可运行状态

风险 2:需求理解偏差

应对

  • 尽早实现端到端原型
  • 及时验证假设
  • 快速迭代

风险 3:技术难点卡住

应对

  • 预留缓冲时间
  • 及时寻求帮助
  • 准备备选方案

附录:代码示例

A1. 核心领域对象示例

// core/domain/game_client.rs

use std::path::PathBuf;
use crate::domain::{GameVersion, ResourceIndex, GameRegion};

/// 游戏客户端
///
/// 代表用户本地安装的 Blue Archive 游戏客户端
pub struct GameClient {
    /// 客户端 ID
    id: ClientId,
    
    /// 安装路径
    install_path: PathBuf,
    
    /// 当前版本
    version: GameVersion,
    
    /// 区域
    region: GameRegion,
    
    /// 资源索引
    resources: ResourceIndex,
    
    /// 客户端状态
    status: ClientStatus,
}

impl GameClient {
    /// 发现本地安装的客户端
    pub fn discover() -> Result<Vec<GameClient>> {
        todo!()
    }
    
    /// 验证客户端完整性
    pub fn verify_integrity(&self) -> Result<IntegrityReport> {
        todo!()
    }
    
    /// 获取当前版本
    pub fn current_version(&self) -> &GameVersion {
        &self.version
    }
    
    /// 检查是否有可用更新
    pub async fn check_for_updates(&self) -> Result<Option<GameVersion>> {
        todo!()
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ClientStatus {
    /// 原始状态(未修改)
    Pristine,
    
    /// 已应用翻译
    Translated,
    
    /// 损坏(需要修复)
    Corrupted,
    
    /// 未知状态
    Unknown,
}

A2. Unity 适配器示例

// adapters/unity/unity_2021_3/assetbundle_parser.rs

use crate::adapters::unity::UnityAdapter;
use crate::core::domain::AssetBundle;

pub struct Unity2021_3Adapter {
    // 配置
}

impl UnityAdapter for Unity2021_3Adapter {
    fn name(&self) -> &str {
        "Unity-2021.3"
    }
    
    fn supported_versions(&self) -> VersionRange {
        VersionRange::new("2021.3.0", "2021.3.99")
    }
    
    fn can_handle(&self, bundle: &RawAssetBundle) -> bool {
        // 检查文件头部的版本信息
        bundle.version().major == 2021
            && bundle.version().minor == 3
    }
    
    fn parse(&self, bundle: &RawAssetBundle) -> Result<ParsedAssetBundle> {
        // Unity 2021.3 特定的解析逻辑
        todo!()
    }
    
    fn serialize(&self, parsed: &ParsedAssetBundle) -> Result<Vec<u8>> {
        // Unity 2021.3 特定的序列化逻辑
        todo!()
    }
}

结语

这份架构审查报告指出了当前项目的核心问题:过度关注技术实现,而忽视了业务领域建模和可扩展性设计

如果不立即重构,项目将在 1-3 年内陷入技术债务泥潭,最终可能需要推倒重来。

好的消息是:问题已经被识别,解决方案也很明确。现在重构的成本是最低的,收益是最大的。

建议立即启动重构,按照本文档规划的路线图执行。


文档版本v1.0
创建日期2026-06-27
作者Claude (Chief Architect)
状态:待审核