From team-standards
Enforces DDD-lite layering, feature modularity, and one-way dependencies before writing business code in Java, Python, Dart, React, or Vue. Prevents business logic in controllers/UI and maintains clear architectural boundaries.
How this skill is triggered — by the user, by Claude, or both
Slash command
/team-standards:architecture-ddd-lite-fullstackThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
该项目采用 DDD-lite + Feature 模块化架构,目标是:代码结构清晰、易于维护、低耦合、高内聚、可复用、可扩展、适合 AI 协作开发。
该项目采用 DDD-lite + Feature 模块化架构,目标是:代码结构清晰、易于维护、低耦合、高内聚、可复用、可扩展、适合 AI 协作开发。
本 SKILL 与语言无关——所有核心原则(分层+单向依赖 / Feature 模块化 / focused service per branch / 跨分支编排独立 / 横切走中间件 / 命名 taxonomy 项目级统一 / 聚合边界)是 SOLID + Clean Architecture + DDD-lite 的应用级表达,在 Java、Python、Dart、TypeScript 上都一致适用。SKILL 内的代码示例多用 Java 写法是因为它能精确表达事务/AOP/注解等机制,但所有规则都有对应的 Python(decorator / contextvar / middleware)、Dart(class + middleware / Riverpod provider)、TypeScript(decorator / NestJS Pipe)等价实现,见各章节后端机制对照表与「Python 后端约束」「Dart 后端约束」节。
任何业务代码,必须先判断属于哪一层,再实现;不允许直接写在 Controller / UI / Page 中。
清晰结构不是"代码写完后再优化"的附加项,而是第一行代码前的门禁。AI 不得为了快速完成而新增难读、难测、难替换、职责混杂的实现。
在以下场景必须主动调用本 Skill:
| 场景 | 动作 |
|---|---|
| 准备编写 Java / Python / Dart / TypeScript / React / Vue / Flutter 业务代码 | 先判断代码所属层级与 feature 模块 |
| 根据设计文档或 coding.md 开始实现 | 在第一行源码改动前完成分层检查 |
| 新增接口、页面、UseCase、Service、Repository、DAO、HTTP Client | 明确职责边界和调用链 |
| 重构现有业务逻辑 | 先识别现有逻辑应沉到 Application / Domain / Infrastructure 的哪一层 |
| 代码审查发现跨层调用、巨型 Service、重复业务逻辑 | 用本规范判定违规类型 |
| 代码实现可能继续沿用低质量旧结构 | 先判断是否会增加耦合、职责混杂或维护成本 |
UI / Controller / Page
↓
Application(UseCase / Service)
↓
Domain(业务规则)
↓
Repository(数据抽象)
↓
Infrastructure(DB / HTTP / MQ / Storage)
所有业务代码必须按 feature 组织,而不是按技术层全局平铺。
features/
{feature_name}/
presentation/ # UI / Controller / Page
application/ # UseCase / Application Service / Composable Service
domain/ # Entity / Value Object / Rule / Policy / State Machine
repository/ # Repository 接口定义
infrastructure/ # Repository 实现、DB、HTTP、MQ、Storage
api/ # 前端 HTTP 请求封装
dao/ # Flutter 本地数据访问
components/ # 前端纯展示组件
hooks/ # React Hook / Vue Composable / 状态编排
types/ # DTO / ViewModel / 类型定义
| 项目复杂度 | 允许简化 | 禁止事项 |
|---|---|---|
| 简单项目 | 可省略独立 Domain 目录,把简单规则放在 Application 内部私有方法 | 不能让 UI / Controller 直接访问 DB / HTTP |
| 中型项目 | 使用完整 DDD-lite 分层 | 不能把所有逻辑塞进单个 Service |
| 复杂系统 | DDD-lite + 状态机 + 领域事件 + 原子能力沉淀 | 不能跨 feature 随意 import 内部实现 |
职责:
禁止:
职责:
要求:
职责:
禁止:
职责:
示例:
OrderRepository
findById()
save()
findRefundableItems()
禁止:
职责:
禁止:
所有通用业务能力必须抽象为可复用的原子能力,避免多个 UseCase 重复实现同一段业务逻辑。
命中任一条件,应沉淀为原子能力:
| 条件 | 示例 |
|---|---|
| 被两个及以上 UseCase 复用 | 退款金额计算、订单可退校验 |
| 代表稳定业务规则 | 状态流转校验、会员价计算 |
| 需要独立测试 | 手续费分摊、优惠抵扣拆分 |
| 未来可能被接口、定时任务、消息消费共同调用 | 退款终态登记、库存释放 |
RefundService
validateRefundable()
calculateRefundAmount()
createRefundTransaction()
callRefundChannel()
registerRefundFinalState()
禁止在多个 UseCase 中重复写同一份退款、支付、库存、订单状态流转逻辑。
立场:focused service 拆分回答的是"业务分支怎么分",聚合边界回答的是"数据一致性边界怎么分"——这是两个正交但配套的决策。一个 focused service 的方法体内修改了哪些数据、能不能在同事务里完成、跨聚合需要不需要发 Domain Event,取决于这些数据落在哪几个聚合里。本节给出实用判定规则,不展开 DDD 教科书全套。
@Transactional 标注的方法,只允许修改一个聚合的状态(及其内部 Entity / VO)。跨聚合的"同时修改"必须改为:事务内只改一个聚合 + 发 Domain Event + 异步另一聚合订阅消费。| # | 判定问 | 答 Yes → Refund 是独立聚合 | 答 No → Refund 是Order 聚合内动作 |
|---|---|---|---|
| A1 | Refund 有独立生命周期吗?(待退 → 已退 → 已撤销,与 Order 状态机不重合) | ✓ 独立聚合 | 跟 Order 状态机绑死 |
| A2 | Refund 需要独立查询吗?(列表页 / 详情页能脱离 Order 单独打开) | ✓ 独立聚合 | 只通过 Order 详情页展开 |
| A3 | Refund 需要独立审计 / 版本号 / 乐观锁吗? | ✓ 独立聚合 | 跟 Order 共审计 |
| A4 | Refund 会被其它业务流程独立引用吗?(对账 / 财务 / 风控独立拉取) | ✓ 独立聚合 | 只在 Order 流程内使用 |
| A5 | Refund 改动量和频次 ≥ Order 主表?或独立扩展字段持续增加? | ✓ 独立聚合 | 共表或单字段足够 |
判定输出:
RefundRepository、refund_order 表、Refund 实体;RefundService 操作 Refund 聚合,与 OrderService 通过 OrderRefundedEvent / Saga 协同。RefundService 仍然是 focused branch service,但内部直接通过 OrderRepository 修改 Order 聚合,事务内完成。| 场景 | focused service 的形态 |
|---|---|
| Order 聚合内动作(refund / cancel / reject 都修改 Order 状态) | focused service 直接通过 OrderRepository 修改 Order;同事务;不发 Domain Event(除非外部需要监听) |
| Refund 是独立聚合 | RefundService 通过 RefundRepository 操作 Refund 聚合;不直接修改 Order;Order 状态变化通过订阅 RefundCompletedEvent 异步更新 |
| 跨 ≥2 聚合的复合动作(approveAndRefund 改 Order + Refund + Inventory) | 走 Saga / Orchestrator:事务内只改一个聚合,其余通过 Event / 补偿动作 |
@Transactional 方法同时修改 ≥2 个聚合根(Order + Refund + Inventory 同事务硬改) → 走 Domain Event 或 SagaOrchestrator / Saga 命名,在本节的"跨聚合协同"语境下复用同一套类——一个 Saga 既可能是跨分支编排,也可能是跨聚合最终一致性载体,两者本质同源(都是"协调多个不能放同事务的动作")。backend-knowledge-graph-required 的全景 ER / 表关系图是聚合判定的输入证据;判定结果反过来更新该图谱(标注哪些表属于同一聚合)。详细规则见 rules/structure-quality-gates.md。该子文档覆盖:
编码前必读该子文档,再回到下方各栈专属约束。下方仅保留四原则速记,详细规则请翻子文档。
上一条「Service 业务动作扩展」管 service 粒度;本条管「函数粒度 → service 粒度」之间的判定阶梯——函数内出现按业务类型 if-else / switch 堆叠 ≥2 分支时,先判定分支差异本质:
- 阶梯 1(同业务定位):分支共享同一状态机 / 校验 / 补偿 / 团队 → 抽
_handleTypeA()/_handleTypeB()私有方法,主方法只做分流派发- 阶梯 2(不同业务定位):分支差异本质是不同业务实体(独立状态机 / 独立 PRD 模块 / 独立团队)→ 升级到 service 级拆分,按上一条「Service 业务动作扩展铁律」建
AService/BService1,共享逻辑沉到原子能力层判定锚点是「业务定位」而非「代码相似度」——长得像但业务定位不同就是阶梯 2;业务定位相同即使代码差异较大也是阶梯 1。
详细判定锚点表(PRD 视角 / 状态机 / 下游 / 校验 / 补偿 / 团队 6 个信号)+ Java + Dart 双示例 + 1-100 期反惯性话术清单见 rules/structure-quality-gates.md § 函数级业务场景分流。
适用于 React / Vue。
标准调用链:
Page
↓
Hook / Composable
↓
Service
↓
API
强制规则:
api/ 层。标准调用链:
Widget
↓
ViewModel / Provider / StateNotifier
↓
Application Service / UseCase
↓
Repository
↓
Infrastructure / DAO / HTTP
强制规则:
适用于 Spring Boot / Spring Cloud。
标准调用链:
Controller
↓
Application Service / UseCase
↓
Domain Service / Policy / Entity
↓
Repository Interface
↓
Infrastructure Mapper / Client / MQ Adapter
强制规则:
OrderService 同时承载 refund/cancel/reject)不允许追加任何 public 业务方法——无论新方法是新业务分支(reverseCheckout)还是同分支变种(partialRefund)。新业务分支新建该分支的 focused service;同分支变种进该分支的 focused service(若分支散落在 god service 则新建并把既有方法+变种一并迁过去)。god service 只保留 1 行 delegate 入口。详见「Service 业务动作扩展铁律」节。适用于 FastAPI / Django(含 DRF) / Flask。
标准调用链:
Endpoint(FastAPI router / Django view / Flask route)
↓
Application Service / UseCase (XxxService class)
↓
Domain Service / Policy / Entity (纯业务规则,无 IO)
↓
Repository Interface(协议 / Protocol / ABC)
↓
Infrastructure(SQLAlchemy / Django ORM / httpx / aio-pika)
强制规则:
@router.post(...) / views.py / @app.route(...))只处理协议适配、Pydantic / DRF Serializer 校验、响应包装。with session.begin(): / @transaction.atomic / async with db.transaction():),Domain 不感知 session / transaction;事务跨聚合时改走 Domain Event(blinker / Celery / Kafka)+ Saga。Depends() / Django app 配置 / DI 容器,禁止在 Service 内部 import 具体 Infrastructure 实现;Service 只依赖 Repository 协议(Protocol / ABC)。async,Service / Repository 接口同步异步选定一种贯彻。横切机制对照(同上「横切关注点不计入 god service 判定」节的 Python 列):FastAPI Depends / decorator / middleware 等价 Spring 的 @Aspect + AOP,横切实现类不计入 god service。
适用于 Serverpod / Shelf / koreposBackendService / Aqueduct 等。
Flutter 客户端约束见上面「Flutter 约束」节;本节专管 Dart 服务端 / Flutter backend 模块的业务代码。
标准调用链:
Endpoint(Shelf router / Serverpod Endpoint class / koreposBackendService backend)
↓
Application Service / UseCase (XxxService class)
↓
Domain Service / Policy / Entity (纯 Dart class / freezed model)
↓
Repository Interface(abstract class)
↓
Infrastructure(Drift / sqflite / dio / Serverpod db)
强制规则:
Endpoint 子类 / koreposBackendService 的 backend/ 目录入口)只处理协议适配、freezed / json_serializable DTO 反序列化、响应包装。korepos-backend-service 的"一接口一 service"是它在 Flutter backend 侧的更强表达。db.transaction(() async { ... }) / Drift transaction() / Serverpod session.db.transaction()),Domain 不感知 transaction;跨聚合走 Serverpod stream / Riverpod provider 通信 + Saga。new 具体 Infrastructure 实现;Service 只依赖 Repository 抽象。korepos-backend-service 强约束:wire DTO 必须 @JsonSerializable(explicitToJson: true),禁 @freezed);DTO ↔ Domain ↔ DB Entity 三态分离,在 Application / Infrastructure 边界做转换。dynamic / Object? / Map<String, dynamic> 容忍多形态(详见 korepos-backend-service Step 2/3 通用章节),所有字段声明唯一确定类型。横切机制对照见上面「横切关注点不计入 god service 判定」节的 Dart 列:Shelf middleware / Riverpod ProviderObserver / Serverpod future hooks 等价 Spring AOP,横切实现类不计入 god service。
立场:Application 层的"业务容器类"在不同流派下有不同叫法——CQRS 流派叫
XxxCommandHandler/XxxHandler、Clean Architecture 流派叫XxxUseCase/XxxInteractor、传统 Spring 流派叫XxxService。三种叫法语义等价(都是 focused 业务分支容器),但同一项目内必须选定一种贯彻,不能RefundService/CancelUseCase/ReverseCheckoutHandler三种混用。本节给出选型矩阵 + 强制映射,把"叫法之争"封死。
1. 选型矩阵(项目级选定一种,后续所有 focused service 沿用):
| 项目主流派 | 语言典型框架 | 选用命名 | 理由 |
|---|---|---|---|
| 传统 Spring Boot / 主流 Java 后端 | Spring Boot / Spring Cloud | XxxService | 与 @Service 注解 + Spring 教科书 + 团队既有命名一致 |
| Python Web 后端(主流) | FastAPI / Django / Flask | XxxService | Python 社区主流命名(FastAPI 文档、cosmic-python 等),与 Java 跨栈一致 |
| Dart 后端(跨端 + Flutter backend) | Serverpod / Shelf / korepos-backend-service(kpay-daily-plugin) | XxxService(与 kpay-daily-plugin 的 korepos-backend-service 对齐) | 已有强约束 + Flutter 社区主流 |
| TypeScript 后端 | NestJS / tRPC | XxxService | NestJS @Injectable() 标准命名 |
| CQRS / 命令-查询分离 / EventSourcing | Axon(Java) / MediatR(.NET) / cqrs(Python) | XxxCommandHandler(写)/ XxxQueryHandler(读) | CQRS 教科书命名 |
| Clean Architecture / Hexagonal / 强调用例 | 跨语言通用 | XxxUseCase / XxxInteractor | Robert Martin 命名,与 Use Case Driven Design 一致 |
多语言项目原则:全栈选同一种命名(默认
XxxService),避免 Java 项目用XxxService、Python 项目用XxxUseCase、Dart 项目用XxxHandler这种"按语言切换叫法"——团队 onboarding 成本太高。CQRS 流派除外(它本身就是跨语言一致的)。
2. 跨分支编排类(orchestrator)统一叫法(与上面 focused service 命名解耦):
| 编排类型 | 统一命名 | 用途 |
|---|---|---|
| 跨分支同步编排 | XxxOrchestrator | 调用 ≥2 个 focused service,同事务边界 |
| 跨分支异步编排 / 失败补偿 | XxxSaga | 长事务 / 补偿动作 / 跨服务最终一致性 |
| Application 层用例聚合(可选) | XxxUseCase | 注意:若 focused service 已选 XxxUseCase,则 orchestrator 用 XxxOrchestrator 区分 |
3. 其它角色命名(全局统一):
| 类型 | 命名示例 | 备注 |
|---|---|---|
| Domain Service / 原子能力(纯业务规则,无 IO) | RefundCalculator / RefundPolicy / RefundValidator | 避免与 focused service 同名;用 Calculator / Policy / Validator / Resolver 等表达"纯规则" |
| Repository 接口 | OrderRepository | 业务语义命名 |
| Repository 实现 | OrderRepositoryImpl / MybatisOrderRepository | 实现可带技术前缀 |
| Controller | RefundController | RESTful 路由对应 |
| React Hook | useRefund | 复用业务流程 |
| Vue Composable | useRefund | 同上 |
| Flutter ViewModel | RefundViewModel | 状态编排 |
| 横切实现(AOP / Filter) | AuditAspect / LoggingInterceptor / SecurityFilter | 用 Aspect / Interceptor / Filter / Middleware 后缀标明横切机制 |
4. 反模式(禁止):
RefundService + CancelUseCase + ReverseCheckoutHandler 三种叫法并存,后续 AI / 新人不知道该建哪种 → 选定一种贯彻XxxApplicationService 容器化命名:这个名字暗示"一个 aggregate 一个 service 含多方法"的传统 DDD 模式,与本 SKILL 的"每分支一 focused service"相反,禁止新建;若历史代码已有,按 god service 处置(对应分支抽到独立 focused service)XxxManager / XxxHelper / XxxUtil:语义模糊,容易演化成 god class → 改用 XxxService / XxxCalculator / XxxPolicy 等表意命名RefundService(application 编排)与 RefundService(domain 规则)冲突 → Domain 侧改 RefundCalculator / RefundPolicy 等写第一行业务代码前,必须逐项确认:
AuditAspect 等)不算 god service。Service / UseCase / CommandHandler 三种叫法只选一种贯彻)?Orchestrator / Saga 命名是否与 focused service 区分?禁止 XxxApplicationService / XxxManager / XxxHelper 等模糊命名。@Transactional 内硬改 ≥2 个聚合根。当本 Skill 参与编码时,AI 在动手前必须先给出简短分层判断:
分层判断:
- Feature:{feature_name}
- Presentation:{是否涉及,文件/类}
- Application:{是否涉及,文件/类}
- Domain:{是否涉及,文件/类}
- Repository:{是否涉及,文件/类}
- Infrastructure:{是否涉及,文件/类}
- 原子能力复用/新增:{说明}
- 结构质量:{清晰性 / 可维护性 / 低耦合 / 高内聚判断}
如果无法判断层级,必须先读取项目结构或设计文档;仍无法判断时,向用户确认,不得直接把逻辑写进 UI / Controller。
| 想法 | 正确处理 |
|---|---|
| "这个逻辑很短,直接写 Controller 里" | 先判断是否是业务规则;是则下沉 Application / Domain |
| "页面直接调 API 更快" | API 封装到 api 层,页面调用 hook / service |
| "Repository 实现里顺便编排业务流程" | 编排放 Application,Infrastructure 只做技术实现 |
| "多个 UseCase 复制一段计算逻辑" | 抽成原子能力并补测试 |
| "Domain 里注入 HTTP Client / Mapper" | Domain 保持纯业务,技术依赖放 Infrastructure |
| "一个 Service 什么都管" | 按 UseCase / 原子能力拆分,职责单一 |
| "原 service 才 200 行,反正还没到巨型,加个 reverseCheckout 没事" | 错。Service 业务动作扩展看的不是行数,是新方法属于哪个业务分支 + 该分支有没有 focused service。多分支 god service 一律不允许加业务方法,只允许 1 行 delegate |
| "新增方法只有几十行,先在原 service 加,以后再拆" | "以后再拆"几乎不会发生;一旦塞进去,下次再加新分支时上一个先例就成了借口,会持续向同一容器堆叠。第一次扩展就建 focused sub-service |
| "partialRefund 和 refund 共享状态机,所以可以放 OrderService" | 错。共享状态机说明它们属于同一退款分支——两者都应该在 RefundService 里,不是都留在 god service。若既有 refund 还在 god service,本次扩展就是把它+新变种一并迁出的契机 |
| "把既有 refund 也迁出去太大动静,先把新方法塞 god service" | strangler pattern 的目的就是逐步迁出,这次扩展就是迁出契机。如果只迁新方法、既有方法还留在 god service,既有方法以后永远迁不出去 |
| "先能跑,结构以后再说" | 结构质量是编码前门禁,先拆职责和依赖边界再写 |
| "复制旧实现最快" | 先判断旧实现是否值得参考;低质量旧结构不能扩散 |
npx claudepluginhub exception-coder/team-standards --plugin team-standardsProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.