关于 nestjs-oop-design-patterns
面向 NestJS 项目的面向对象设计技能,帮助开发者依据实际问题选择职责划分、设计模式与安全重构方式。强调先检查现有架构和行为,再决定是否引入抽象。
主要功能
- 01检查对象职责与设计压力
- 02以 SOLID 原则分析设计
- 03根据实际变化选择模式
- 04规划保持行为的重构
- 05按边界制定测试方案
- 06检查指令冲突与变更条件
适用场景
- 01梳理 NestJS 提供者的职责
- 02为重复变化的算法选择策略
- 03隔离外部供应商模型
- 04在重构前锁定现有行为
- 05评估设计模式带来的复杂度
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ amirtaherkhani/ nestjs-skills --skill nestjs-oop-design-patterns安装后在 Claude Code 中输入/nestjs-oop-design-patterns确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
evals/evals.jsonreferences/nestjs-native-patterns.mdobject-design.mdoop-solid.mdpattern-catalog.mdsmells-refactoring.md详细介绍
NestJS OOP 与设计模式
通过明确职责、封装不变量和有意识的协作,提升可变更性与正确性。使用模式解决实际观察到的问题,切勿将其当作装饰。
执行前冲突检查
编辑文件或运行任何会改变状态的命令之前,先协调当前有效的指令。只读检查可以继续。
前提条件
检查仓库指令、已安装版本、调用方、测试、模块接线和观察到的设计压力。保留现有行为和用户更改;在了解架构与运行时约束之前,不要选择设计模式。仅当其他有效技能的决策与当前工作重叠时,才阅读这些技能。
主要职责范围
本技能负责对象职责、不变量、封装、协作者契约、SOLID 权衡、设计模式和保持行为不变的重构。在已安装且相关时,与以下技能协作:
nestjs-architecture-principles:模块、依赖、数据和事务边界。nestjs-features-performance:生命周期、API/安全、测试、运行时和性能。nestjs-professional-software-engineering:实现与验证。nestjs-code-audit:只读质量证据与去重报告。nestjs-feature-audit:针对分支的路线图门禁与功能报告。nestjs-git-commit-pr-message:经授权的 Git 发布与 CI 跟进。
这些是决策边界,并非必需依赖。将工作交接给其他工作流时,仍要保留领域职责。
冲突测试
检查是否存在不兼容的编辑或契约、命令顺序或副作用、职责归属竞争,以及版本、证据、授权或仓库前提未满足的情况。按照明确的用户意图、仓库契约、已验证的运行时约束,再到职责范围最窄的所有者来解决。每项决策指定一名负责人;不要为了满足不兼容的建议而创建并行设计。如果仍存在重大冲突,在变更前停止,并询问最少的缺失决策。审计必须保持只读;明确的修复授权仅适用于单独的实现阶段。
先检查,再给出建议
- 阅读相关 controller/provider/entity,以及其调用方、测试、模块接线、DTO 和持久化映射。
- 确定对象的角色:传输适配器、应用协调器、领域对象/策略、基础设施适配器或组合根。
- 明确实际痛点:不变量泄漏、变更分散、难以替换、依赖隐藏、决策逻辑重复或与框架耦合。
- 在添加新抽象之前,检查仓库约定和现有抽象。
- 在高风险重构之前,先用特征测试保留现有行为。
不要仅凭文件长度推断设计不佳。复杂度、内聚性、公共接口范围、依赖数量和变更历史是更有力的证据。
OOP 默认原则
- 封装不变量;不要只把数据移到 getter 和 setter 后面。
- 优先采用组合和委托,而非继承。
- 将可变状态设为私有,并尽量缩短其生命周期。
- 当稳定操作确实存在不同实现时,使用多态。
- 注入有副作用的操作和易变因素;让确定性计算保持纯粹。
- 当领域值足以证明类型合理时,让无效状态难以构造。
- 在类型、方法、测试和错误中始终使用一致的领域语言。
- 让 Nest 的容器构造 providers;不要在业务方法中实例化依赖图。
有关 OOP 和 SOLID 的详细指南,请参阅 references/oop-solid.md;有关实体、值对象、策略、服务和 DTO 边界,请参阅 references/object-design.md。
将 SOLID 用作诊断问题
单一职责
此单元是否拥有一个内聚的策略或变更维度?用例可以协调多个协作者,同时仍只承担一项职责。把每个方法都拆成一个提供者,只会增加导航成本,并不会增强内聚性。
开闭原则
是否存在真正的变化,导致同一个条件判断反复修改?围绕这种变化提取策略、策略对象或适配器。不要为假设中的提供者构建扩展点。
里氏替换原则
每种实现是否都能遵守相同的输入、输出、错误、副作用、时序假设和不变量?如果不能,就缩小契约范围,或改用组合而不是继承。
接口隔离原则
每个使用方是否只依赖自己用到的能力?优先使用由应用定义的小型端口,而不是一个 CommonService 或通用仓库接口。
依赖倒置原则
高层策略是否依赖应用契约,而由 Nest 模块选择基础设施实现?应为易变的副作用设置边界,而不是为每个本地类都创建接口。
根据问题选择模式
使用 references/pattern-catalog.md 和 references/nestjs-native-patterns.md。
将模式目录视为发现工具,而不是实现检查清单。架构风格、框架生命周期机制、提供者生命周期和 GoF 对象模式解决的是不同类型的问题,即便某篇文章把它们归为一类也是如此。某种模式很流行、广为人知,或被称为“可扩展”,都不能证明当前仓库需要它。
| 信号 | 可考虑 | 以下情况应避免 |
|---|---|---|
| 相同操作存在真正可互换的算法 | 策略模式 | 算法稳定不变 |
| 构造方式因配置或类型而异 | 工厂模式 | 构造函数已经足够简单 |
| 复杂构造包含有序步骤、可选步骤或需要验证的步骤 | 建造者模式 | 对象字面量或构造函数仍然清晰 |
| 供应商模型渗入应用代码 | 适配器模式 | 库 API 已在边界处隔离 |
| 抽象和实现有两个独立的变化维度 | 桥接模式 | 适配器或策略模式已能处理唯一的变化 |
| 复杂子系统需要一个精简入口 | 外观模式/应用服务 | 它会变成无关的上帝服务 |
| 稳定的工作流有少量有意设置的扩展步骤 | 模板方法模式或组合式流水线 | 继承会成为使用它的唯一理由 |
| 横切请求行为 | 拦截器、守卫、管道、过滤器 | 核心业务策略属于领域对象或应用对象 |
| 对已完成事实作出彼此独立的响应 | 领域事件/集成事件 | 调用方需要立即获得事务性结果 |
| 显式用例消息能够带来价值 | 命令/查询处理器 | 基础 CRUD 只增加了间接层 |
| 数据库写入需要可靠地发布事件 | 事务性发件箱 | 进程内的尽力通知已经足够 |
采用某种模式之前,请说明问题是什么、为什么直接方案不够,以及它会增加哪些运维或认知成本。
重构工作流
- 使用有针对性的测试锁定当前行为。
- 在当前代码中标出职责和副作用。
- 在提取抽象之前,先将位置不当的行为移交给其归属方。
- 围绕已观察到的变化或边界提取一个接缝。
- 通过 Nest 提供者重新接线,尽量不改变公共契约。
- 移除过时的分支、包装器和抽象。
- 根据变更边界,按适当范围运行单元、模块、集成和端到端检查。
使用 references/smells-refactoring.md 获取从症状到重构的指导。
测试规则
- 测试公开行为和不变量,而不是私有方法调用。
- 对领域对象和策略使用普通单元测试。
- 如果构造函数依赖简单,直接实例化用例;如果测试需要验证 Nest wiring 或 provider 覆盖,则使用
TestingModule。 - Mock 或伪造由你负责的边界,而不是被测类。
- 如果多个适配器实现同一个端口,则添加契约测试。
- 端到端测试仅用于传输、验证、授权、序列化和真实模块 wiring。
当行为可以逐步表达时,TDD 很有用;但修改现有实现时,不要谎称先编写了一个失败测试。遵循仓库要求的工作流。
拒绝僵化的伪规则
不要强制执行任意限制,例如方法不超过十行、类不超过五十行、对象最多两个字段、每个基本类型都必须使用值对象,或禁止使用 else 语句。只把这些限制作为检查内聚性和可读性的提示。
不要强行要求:
- 当组合更清晰时仍使用继承;
- 在已有合适的持久化边界上再封装一层仓储;
- 为一个简单直接的构造函数创建工厂;
- 将同步返回值改为领域事件;
- 在无关的外部契约之间复用 DTO;
- 使用会抹去功能特定不变量的通用
BaseService<T>。
参考资料路由
| 任务 | 加载 |
|---|---|
| 应用封装、组合、多态或 SOLID | oop-solid.md |
| 设计实体、值对象、策略、服务和 DTO 映射 | object-design.md |
| 使用 19 个实用示例、Nest wiring、权衡和行为检查来选择模式 | pattern-catalog.md |
| 将模式映射到 Nest 模块、providers、guards、pipes、interceptors、filters 和 CQRS | nestjs-native-patterns.md |
| 诊断异味并选择安全的重构方式 | smells-refactoring.md |
预期回复
对于设计或审查,请报告:
- 角色与职责: 对象应负责什么。
- 依据: 具体的耦合、不变量泄漏或变更压力。
- 模式或直接设计: 一项建议及其适用原因。
- 权衡: 引入的间接层、生命周期、一致性或测试成本。
- 变更: 最小的安全重构。
- 验证: 行为和契约检查。
如果某个模式缺乏充分依据,请建议直接实现。