44 KiB
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
}
问题:
- Storage 和 RefCounter 是两个独立的组件,但它们的数据必须保持一致
- 如果 put() 成功但 incr() 失败,会导致数据不一致
- 没有事务保证
正确设计:
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
当前状况
项目规划了各个技术模块,但没有设计完整的业务工作流。
缺失的工作流
官方更新后的自动化流程:
- 版本检测 → 如何实现?
- Manifest 获取 → 从哪里获取?
- 资源同步 → 如何判断哪些需要下载?
- 自动解析 → 如何识别文本资源?
- 自动识别新增文本 → 如何 diff?
- 自动翻译 → 如何调度?
- 人工审核 → 工作流如何设计?
- Patch 生成 → 如何保证一致性?
- 自动发布 → 发布到哪里?
当前架构中这些都是空白!
正确设计需要
workflow/
├── version_detector/ # 版本检测服务
├── sync_coordinator/ # 同步协调器
├── text_extractor/ # 文本提取器
├── diff_analyzer/ # 差异分析器
├── translation_pipeline/ # 翻译管道
├── review_queue/ # 审核队列
├── patch_generator/ # Patch 生成器
└── release_manager/ # 发布管理器
第三部分:Blue Archive 客户端集成方案分析
3.1 可能的集成方案
方案 A:客户端资源替换(推荐)⭐
原理:
- 工具下载官方资源到本地
- 解析 AssetBundle,提取文本
- 翻译后重新打包 AssetBundle
- 替换客户端的资源文件
优点:
- ✅ 不修改游戏可执行文件,安全性高
- ✅ 支持增量更新
- ✅ 易于回滚
- ✅ 可以离线工作
缺点:
- ⚠️ 需要深入理解 Unity AssetBundle 格式
- ⚠️ Unity 版本升级需要适配
维护成本:中等
更新成本:低
兼容性:高
架构要求:
Client Integration Layer:
├── AssetBundleReplacer # 资源替换器
├── IntegrityVerifier # 完整性验证
└── RollbackManager # 回滚管理
方案 B:代理服务器模式
原理:
- 在客户端和游戏服务器之间插入代理
- 拦截资源下载请求
- 返回翻译后的资源
优点:
- ✅ 不需要修改客户端文件
- ✅ 动态更新翻译
缺点:
- ❌ 需要用户配置代理
- ❌ 可能影响游戏性能
- ❌ 需要持续运行服务
- ❌ 官方可能检测并封禁
维护成本:高
更新成本:低
兼容性:中
不推荐:维护成本高,用户体验差
方案 C:内存补丁模式
原理:
- Hook 游戏进程
- 在内存中替换文本
优点:
- ✅ 不修改文件
缺点:
- ❌ 技术复杂度极高
- ❌ 容易被反作弊系统检测
- ❌ 每次游戏更新都可能失效
- ❌ 不同平台需要不同实现
维护成本:极高
更新成本:极高
兼容性:低
不推荐:风险高,维护成本不可持续
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 版本的步骤:
- 创建新目录:
adapters/unity/version_XXXX_X/ - 实现
UnityAdaptertrait - 在
registry.rs中注册 - 无需修改核心代码!
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,
}
新增格式的步骤:
- 创建新目录:
adapters/manifest/format_vX/ - 实现
ManifestDrivertrait - 注册到 Registry
- 无需修改核心代码!
第六部分:必须立即重构的模块
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 架构
当前状态:直接依赖具体实现
必须重构的原因:未来版本变化时需要全部重写
不改的后果:每次官方更新都需要大规模重构
需要重构的模块:
bat-assetbundle→ 改为基于 Adapter 的架构- Manifest 解析 → 改为基于 Driver 的架构
- 所有版本相关的代码 → 改为插件化
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)
- M7:Alpha 版本发布(Week 10)
第十二部分:总结与建议
12.1 核心结论
-
当前架构不可持续 ❌
- 缺少业务领域建模
- 缺少适配层设计
- 缺少客户端集成
- 无法应对未来变化
-
必须立即重构 ⚠️
- 继续开发会积累技术债
- 未来重构成本呈指数增长
- 现在重构成本最低
-
重构方向明确 ✅
- 领域驱动设计
- 适配器+插件架构
- 工作流引擎
- 清晰的分层
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)
状态:待审核