mcpField
S
solid

solid

github.com/marcioaltoe开发049 次安装1 天前更新
代码仓库

关于 solid

solid 是一项介绍 SOLID 五项原则的开发技能,供设计、重构和审查软件结构时参考。它提供检测问题的检查项、不同层级的应用方式和常见反模式。

主要功能

  1. 01说明 SRP、OCP、LSP、ISP、DIP
  2. 02提供类与模块检查清单
  3. 03涵盖函数到服务的应用方式
  4. 04列出常见反模式及修正方向
  5. 05给出接口与依赖设计建议

适用场景

  1. 01设计新的类、模块或接口
  2. 02重构职责过多的代码
  3. 03审查 PR 中的架构问题
  4. 04拆分大型类或精简接口

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/marcioaltoe/skills --skill solid

安装后在 Claude Code 中输入/solid确认已加载。

附带文件agents/openai.yamlreferences/PRINCIPLES.md

详细介绍

SOLID 原则

构建易于理解、扩展和维护的软件的五项原则。它们可以降低耦合、提高内聚性,并让代码更易于测试。

适用场景

在以下情况下参考这些原则:

  • 设计新的类、模块或接口
  • 重构职责过多的代码
  • 从架构角度审查 PR
  • 拆分上帝对象或臃肿接口
  • 确定模块边界
  • 提高代码的可测试性

快速参考

原则一句话概括警示信号
SRP一个变更理由“这个类既处理 X 又 处理 Y 还 处理 Z”
OCP扩展而非修改针对不同类型的 if/else 或 switch 链不断增长
LSP子类型可替换调用代码中进行类型检查或特殊处理
ISP小而专注的接口空方法实现或 throw new Error("Not implemented")
DIP依赖抽象业务逻辑中出现 new ConcreteClass()

详细说明和 TypeScript 示例请参阅 references/PRINCIPLES.md。

检查清单

针对每个类和模块,提出以下问题:

问题违反的原则
这个类是否有多个变更理由?SRP
添加新变体时,我是否需要修改现有代码?OCP
调用代码是否需要针对子类型进行类型检查或特殊处理?LSP
实现类是否被迫为未使用的方法提供空实现?ISP
高层逻辑是否直接实例化基础设施?DIP

在不同层级应用 SOLID

层级SRPOCPLSPISPDIP
函数只做一件事———将抽象作为参数传入
类一个变更理由通过组合扩展子类型遵守契约只实现实际使用的内容构造函数注入
模块一个有界上下文插件架构实现可互换精简的公共 API依赖方向向内
服务单一领域新功能 = 新服务API 契约稳定最小化 API 表面在边界处使用抽象

原则之间的关系

  • SRP + ISP:拆分职责通常也意味着拆分接口
  • OCP + DIP:依赖抽象才能实现无需修改即可扩展
  • LSP + OCP:如果子类型可替换,就可以通过添加新子类型来扩展行为
  • DIP + ISP:小而专注的接口让依赖倒置切实可行

常见反模式

反模式违反的原则修复方法
什么都做的上帝类SRP提取职责专一的类
整个代码库中都按类型使用 switchOCP、LSP改用多态
抛出“not supported”的子类LSP、ISP重新设计继承层次,拆分接口
包含 20 个方法的臃肿接口ISP拆分为按角色划分的接口
业务逻辑导入数据库驱动DIP注入存储库接口
服务自行创建依赖项DIP使用构造函数注入

最佳实践

应该
  • 从 SRP 开始——它是其他原则的基础
  • 使用接口定义组件之间的边界
  • 让违规问题从实际问题中显现,再加以修复
  • 扩展行为时优先使用组合,而非继承
  • 保持接口精简,并与具体角色相对应
  • 通过构造函数注入依赖项
不应该
  • 教条式地将 SOLID 用于琐碎代码(5 行的实用工具不需要接口)
  • 在至少有两个实现之前就创建抽象
  • 将 SRP 误解为“单个方法”——它关注的是变更理由,而非大小
  • 强迫本不该处于同一继承层次的类遵循里氏替换原则
  • 在一组内聚的方法更合理时,将接口过度拆分为单方法片段

评论

支持 Markdown