关于 code-structure
code-structure 是一份架构指南,主张将 Action 编排与可复用的 Service 操作分层。它适用于尚无既定约定的项目,强调依赖显式、职责清晰,并且只有在确有收益时才提取共用逻辑。
主要功能
- 01分离编排逻辑与共用操作
- 02由既有职责方管理策略和事务
- 03设计可组合的能力模块
- 04使用显式输入和结构化结果
- 05逐个调用方迁移
- 06避免不必要的抽象
适用场景
- 01为缺少 Service 约定的项目确定结构
- 02从 Action 文件提取重复操作
- 03明确持久化和事务的职责归属
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ michaelshimeles/ rstack --skill code-structure安装后在 Claude Code 中输入/code-structure确认已加载。
详细介绍
服务层架构
概述
本集合倾向于采用两层分离:操作负责协调领域规则,而服务负责实现可复用的操作。在项目尚无既定约定时,使用此模式。如果现有领域服务、存储库、事务边界和框架模式已适用于当前任务,则予以保留。
这样可以避免代码重复、行为不一致,以及某条路径修复了错误、其他路径却仍有问题的情况。
适用场景
- 多个调用方需要相同的底层操作(创建沙箱、发送电子邮件、处理付款)
- 你正在多个操作文件之间复制粘贴操作逻辑
- 某个工作流中的错误修复没有应用到执行相同操作的其他工作流
- 添加与现有流程共用机制的新功能
避免为了抽取而抽取,导致增加间接层却没有实际收益。重复是一个有用的信号,但即使只有一个调用方,也可能需要划定边界,以便测试、隔离提供方、处理事务或管理复杂逻辑。
核心模式
Orchestration Layer (Actions) Service Layer (Shared Mechanics)
├── owns business rules ├── owns reusable operations
├── owns state transitions ├── owns provider/SDK interactions
├── owns auth/ownership checks ├── owns command execution details
├── owns failure classification ├── owns health checks / readiness
├── owns retries / user-facing errors └── returns structured results
└── calls service functions
经验法则:
- “这个产品流程的含义” → 保留在操作中
- “如何可靠地执行这项操作” → 移至服务层
快速参考
| 设计原则 | 应做 | 不应做 |
|---|---|---|
| API 形状 | 可组合的能力模块 | 一个包办一切的巨型方法 |
| 输入/输出 | 明确的依赖项和有意义的结果 | 隐式全局状态或未记录的副作用 |
| 迁移 | 抽取一个模块,替换一个调用方,验证后再迁移其余部分 | 一次性重构所有内容 |
| 领域逻辑 | 将策略和事务交由项目中既定的所有者处理 | 在多个调用方之间散布相同策略 |
| 抽取触发条件 | 重复机制或能带来明确收益的边界 | 当前没有实际收益的臆测性抽象 |
设计服务函数
应设计为能力模块,而非巨型函数:
// Good: composable, each caller chooses what to use
createManagedSandbox(...)
prepareRepo(...)
detectPackageManager(...)
installDependencies(...)
runBuildCommand(...)
startSandboxRuntime(...)
每个函数都应:
- 通过显式参数接收所有必需数据
- 返回结构化输出(例如
{ ready, previewUrl, proxyPort }) - 如果根据项目架构,由服务负责持久化,则注入数据库或存储库访问。明确说明状态写入和事务边界。
- 通过有类型的结果或已记录的异常明确表示失败
这样,调用方就能根据各自流程选择严格或宽松的行为。
迁移检查清单
抽取共享逻辑时:
- 确定策略、持久化和事务的现有所有者
- 标记重复操作,或能带来明确当前收益的边界
- 抽取与这些所有者职责一致的内聚操作
- 替换一个调用方 → 验证 → 替换其余调用方
- 保留身份验证、状态转换、错误处理和事务行为
- 运行验证:类型检查、代码检查,并确认所有流程仍正常工作
反模式
| 反模式 | 问题 |
|---|---|
| 上帝服务 | 一个巨型函数隐藏了所有控制流程 |
| 泄漏的服务 | 状态变更隐蔽,或事务所有权不明确 |
| 不一致的 API | 每个函数使用不同的参数风格和错误语义 |
| 过度抽象 | 增加间接层,却没有复用、可测试性或边界方面的收益 |
示例:电子邮件服务(简单示例)
// emailService.ts — shared mechanics
export async function sendWelcomeEmail(params: { to: string; name: string }) {
const html = `<h1>Welcome ${params.name}</h1>`;
await emailProvider.send(params.to, "Welcome", html);
}
// userSignup.ts — orchestration (owns WHEN to send)
if (user.marketingOptIn) {
await sendWelcomeEmail({ to: user.email, name: user.name });
}
// adminInvite.ts — orchestration (different business rule, same mechanic)
await sendWelcomeEmail({ to: invitee.email, name: invitee.name });
思维模型
Existing architecture? → Follow its boundaries
No convention? → Prefer actions for orchestration and services for operations
Extraction? → Name its concrete benefit before adding another layer
明确职责,显式声明依赖项,并让副作用清晰可见。
评论
支持 Markdown