| name | code-style-architecture |
| description | DI + RxJS + 命令模式架构的通用编码规范。适用于任何基于依赖注入(redi 或同类容器)、RxJS 响应式、插件化的 TypeScript 项目。编写 Service/Controller/Plugin/Command、DI 注入(createIdentifier/@Inject/@Optional/@DependentOn)、Observable($ 后缀/Subject 封装)、Disposable 生命周期、拦截器责任链、错误处理与日志、test bed 测试时使用。 |
通用架构规范 — DI / 服务化 / 插件化 / 命令模式
概述
三大支柱:DI 注入(跨模块通信)、RxJS 响应式(状态传播)、命令驱动(状态变更)。适用于任何采用该体系的项目(示例中 @<core> 代指项目的 core 包)。
前置:code-style-core(命名与类型基线)。
关键规则速查 (违反必改)
分层与职责
common → models → services → commands → controllers → views (只能依赖左侧)
- Service 持状态与能力(被注入、可复用);Controller 只做编排(订阅流、注册命令/菜单/UI、是叶子不被注入);Plugin 只做装配(注册依赖 + 生命周期激活)
- 跨模块通信三通道:同步调用走 DI、状态变化走 Observable、动作变更走命令监听。禁止 EventEmitter / 全局事件总线 / 全局单例
Observable 命名与封装
private readonly _xxx$ = new BehaviorSubject<T>(init);
readonly xxx$: Observable<T> = this._xxx$.asObservable();
get xxx(): T { return this._xxx$.getValue(); }
接口里只暴露 Observable<T>,绝不暴露 Subject。有状态用 BehaviorSubject,纯事件用 Subject。
订阅清理
- 默认:
Disposable + this.disposeWithMe(observable$.subscribe(fn))(接受 Subscription / 函数 / IDisposable,无需 toDisposable)
- 仅 pipe 内多流需同时短路时才用
RxDisposable + takeUntil(this.dispose$)
dispose() 顺序:super.dispose() → complete() 所有 Subject → clear() 所有集合
DI 标识符与注入
export interface IXxxService { ... }
export const IXxxService = createIdentifier<IXxxService>('<包名>.<kebab-名>-service');
constructor(
@ICommandService private readonly _commandService: ICommandService,
@Inject(Injector) private readonly _injector: Injector,
@Optional(XxxController) private readonly _xxx?: XxxController,
) { super(); }
- 一律 parameter property,禁止拆字段 + 构造体内赋值
- 循环依赖:优先事件解耦(订阅对方 Observable),次选惰性
injector.get();不用 DI forwardRef
@Many/@Self/@SkipSelf/@WithNew 约定不用
命令系统
命令 id: '<包名>.<command|mutation|operation>.<kebab-动作>'
- Mutation = 可落盘、可协同的原子数据变更(同步);Operation = 不落盘的 UI/瞬态变更;Command = 业务编排(生成并执行 Mutation/Operation,可异步)
- Undo/Redo = 反向 Mutation 序列,不用快照
- 简化变体:无协同/undo 需求的项目可只保留 Command 一种,但 id 三段格式不变
插件
- 插件是装配器:
@DependentOn(...) 声明依赖 → 构造器写入 config → onStarting 注册依赖 → 各生命周期钩子 touchDependencies 激活
- 生命周期四阶段单调推进:
Starting → Ready → Rendered → Steady;晚注册插件自动补跑已过阶段
- 每插件一个顶级配置键
<插件名>.config + config.schema.ts(KEY + 接口 + default)
章节索引 — 按需打开
| # | 主题 | 文件 | 何时查阅 |
|---|
| 1 | 分层与依赖方向 | references/01-layering.md | 设计新模块、判断职责归属时 |
| 2 | 依赖注入 (DI) | references/02-di.md | 创建 service、写构造注入、处理循环依赖时 |
| 3 | RxJS 响应式 | references/03-rxjs.md | 用 Observable、操作符选择、shareReplay 等 |
| 4 | 生命周期与 Disposable | references/04-lifecycle.md | 继承 Disposable、写 dispose()、选生命周期阶段时 |
| 5 | Service 编写规范 | references/05-service.md | 新建 *.service.ts(附模板 + checklist) |
| 6 | Controller 编写规范 | references/06-controller.md | 新建 *.controller.ts、派生状态时 |
| 7 | Plugin 编写规范 | references/07-plugin.md | 新建 plugin、配置键设计、钩子选择时 |
| 8 | 命令系统 | references/08-command.md | 新建 command/mutation/operation、undo/redo 时 |
| 9 | 拦截器模式 | references/09-interceptor.md | 责任链、横切增强、HTTP 拦截时 |
| 10 | 错误处理与日志 | references/10-errors-logging.md | throw vs 返回值、ILogService、专用 Error 时 |
| 11 | 测试规范 | references/11-testing.md | 写 *.spec.ts、搭 test bed 时 |
使用流程
- 写之前 — 查章节索引对应文件,确认模板和检查清单
- 写之中 — 按速查卡执行,违反就地修正
- 写之后 — 对照对应章节 checklist 自查