🎯 问题描述
在 chatapps/setup.go:292-302 中存在 provider-specific branching,违反了 Open/Closed 原则:
// 当前实现:硬编码 OpenCode Server 特殊处理
if pCfg.Type == provider.ProviderTypeOpenCodeServer && pc.Engine.WorkDir != "" {
if pCfg.OpenCode == nil {
pCfg.OpenCode = &provider.OpenCodeConfig{}
}
pCfg.OpenCode.WorkDir = pc.Engine.WorkDir
logger.Debug("Injected work directory to OpenCode Server config",
"work_dir", pc.Engine.WorkDir)
}
问题根源
- Leaky abstraction:
setup.go 需要知道特定 provider 类型的内部配置结构
- Open/Closed violation: 每增加一个需要特殊配置的 provider,都需要修改
setup.go
- Scalability issue: 如果其他 provider 也需要 work directory,会演变成 switch-case 瑞士军刀
📊 影响范围
当前影响
- ✅ 功能正常:OpenCode Server work directory 注入工作正常
- ⚠️ 可维护性降低:架构违反 SOLID 原则
- ⚠️ 扩展性受限:新 provider 需要修改 setup.go
潜在风险
如果有更多 provider 需要特殊配置(如 Pi, Claude Code),代码会变成:
// 未来可能的反模式
if pCfg.Type == provider.ProviderTypeOpenCodeServer {
// OpenCode Server 逻辑
} else if pCfg.Type == provider.ProviderTypePi {
// Pi 逻辑
} else if pCfg.Type == provider.ProviderTypeClaudeCode {
// Claude Code 逻辑
}
// ... 无限扩展
✅ 建议的解决方案
方案:WorkDirConfigurable 接口
核心思路: 让 provider 自己声明是否需要 work directory,而不是 setup.go 硬编码判断
1. 在 provider/provider.go 中定义接口
// WorkDirConfigurable is an optional interface that providers can implement
// to receive work directory configuration from the engine.
type WorkDirConfigurable interface {
// SetWorkDir configures the working directory for the provider.
// This is called during provider initialization before CreateProvider().
SetWorkDir(workDir string)
}
2. OpenCodeConfig 实现接口
// provider/provider.go
func (c *OpenCodeConfig) SetWorkDir(workDir string) {
c.WorkDir = workDir
}
3. 重构 setup.go
// chatapps/setup.go - 简化后的通用实现
if pc.Engine.WorkDir != "" {
// Try to inject work directory if provider supports it
if configurable, ok := prv.(provider.WorkDirConfigurable); ok {
configurable.SetWorkDir(pc.Engine.WorkDir)
logger.Debug("Injected work directory to provider config",
"provider", pCfg.Type,
"work_dir", pc.Engine.WorkDir)
}
}
优势
- ✅ Open/Closed: 新增 provider 无需修改 setup.go
- ✅ Interface segregation: 可选接口,不影响不需要的 provider
- ✅ Single responsibility: setup.go 只负责调用接口,不关心具体实现
- ✅ Extensibility: 未来其他 provider 可轻松实现该接口
🔄 迁移路径
Phase 1: 准备(Non-breaking)
- 添加
WorkDirConfigurable 接口定义
- 让
OpenCodeConfig 实现该接口
- 保留旧的 if 分支作为 fallback
Phase 2: 重构(Backward compatible)
- 在
setup.go 中添加接口调用逻辑
- 移除旧的 provider-specific 分支
- 添加单元测试验证接口行为
Phase 3: 验证
- 运行完整测试套件
- 验证 OpenCode Server 仍然正常工作
- 确认其他 provider 不受影响
🧪 验收标准
📚 参考资料
相关代码
chatapps/setup.go:292-302 - 当前的 provider-specific branching
provider/provider.go:198-224 - OpenCodeConfig 定义
provider/transport_http.go:26 - HTTPTransport.workDir 字段
设计原则
优先级: Low (P3) - 不影响当前功能,属于代码质量改进
工作量: Medium (1-3 days) - 接口设计 + 重构 + 测试
标签: type/enhancement, priority/low, size/medium
🎯 问题描述
在
chatapps/setup.go:292-302中存在 provider-specific branching,违反了 Open/Closed 原则:问题根源
setup.go需要知道特定 provider 类型的内部配置结构setup.go📊 影响范围
当前影响
潜在风险
如果有更多 provider 需要特殊配置(如 Pi, Claude Code),代码会变成:
✅ 建议的解决方案
方案:WorkDirConfigurable 接口
核心思路: 让 provider 自己声明是否需要 work directory,而不是 setup.go 硬编码判断
1. 在
provider/provider.go中定义接口2. OpenCodeConfig 实现接口
3. 重构 setup.go
优势
🔄 迁移路径
Phase 1: 准备(Non-breaking)
WorkDirConfigurable接口定义OpenCodeConfig实现该接口Phase 2: 重构(Backward compatible)
setup.go中添加接口调用逻辑Phase 3: 验证
🧪 验收标准
WorkDirConfigurable接口定义在provider/provider.goOpenCodeConfig实现该接口setup.go使用接口替代硬编码判断📚 参考资料
相关代码
chatapps/setup.go:292-302- 当前的 provider-specific branchingprovider/provider.go:198-224- OpenCodeConfig 定义provider/transport_http.go:26- HTTPTransport.workDir 字段设计原则
优先级: Low (P3) - 不影响当前功能,属于代码质量改进
工作量: Medium (1-3 days) - 接口设计 + 重构 + 测试
标签:
type/enhancement,priority/low,size/medium