SuperAPI AI 工具集

solid-principles

编程与开发

查看项目

更新于 10-15 18:09

技能介绍

用途

SOLID Principles 技能用于在编写代码的实现阶段,帮助设计模块、函数和组件,以获得可维护、灵活的代码架构。它围绕 SOLID 五项设计原则提供具体模式与检查清单。

五项原则与内容

1. 单一职责原则(SRP)

一个模块应当只有一个、且仅有一个变更理由。资料给出 Elixir 与 TypeScript 的正反示例:

  • Elixir 反例:一个 UserManager 模块同时负责创建用户、发送欢迎邮件、记录分析、更新缓存;正例拆分为 User、UserNotifier、UserAnalytics 等模块。
  • TypeScript 反例:一个 UserComponent 类同时包含渲染、取数、格式化日期、校验输入;正例拆分为 UserProfile 组件、useUserData Hook、formatUserDate 函数。

自问:“这个模块做的那一件事是什么?”

2. 开闭原则(OCP)

软件实体应当对扩展开放、对修改关闭。资料给出:

  • Elixir 模式(Behaviours):定义 PaymentProvider 接口,StripeProvider 与 PayPalProvider 分别实现,新增提供方无需修改调用代码。
  • TypeScript 模式(组合):以渲染器映射替代 if/else 判断类型,新增类型只需在映射中增加条目,无需修改 renderItem。

自问:“我能否在不修改现有代码的情况下增加新功能?”

3. 里氏替换原则(LSP)

子类型必须能够替换其基类型。资料给出:

  • Elixir 反例:calculate_total 缺少空列表子句,会抛异常;正例:对任意列表返回 Enum.sum,空列表返回 0。
  • TypeScript 反例:Penguin 继承 Bird 后在 fly 中抛错,破坏契约;正例:抽象为 Bird 接口的 move,FlyingBird 与 SwimmingBird 各自实现。

自问:“我能否在不破坏行为的前提下用其父类/接口替换它?”

4. 接口隔离原则(ISP)

客户端不应被迫依赖其不使用的接口。资料给出:

  • Elixir 反例:User 行为包含 work、take_break、eat_lunch、clock_in、clock_out 等所有回调;正例:拆分为 Workable、Breakable、TimeTrackable,按需实现。
  • TypeScript 反例:一个包含全部方法的 User 接口;正例:拆分为 Workable、TimeTrackable、BenefitsEligible,并按需组合为 FullTimeUser、ContractUser、TaskUser。

自问:“这个接口是否强迫实现方定义未被使用的方法?”

5. 依赖倒置原则(DIP)

依赖抽象,而非具体实现。资料给出:

  • Elixir 反例:UserService 直接调用 PostgresRepo.insert;正例:通过默认参数注入 repo,或使用行为与配置决定实现。
  • TypeScript 反例:UserManager 内部直接 new StripeAPI;正例:构造函数注入 PaymentAPI 接口实现。

自问:“我能否在不修改依赖方代码的情况下替换实现?”

应用清单

资料提供三个阶段的清单:

  • 编写新代码之前:识别单一职责;为扩展点(behaviours、interfaces)做设计;先定义抽象再实现;保持接口最小且聚焦。
  • 实现期间:每个模块只有一个变更理由(SRP);新功能靠扩展而非修改(OCP);实现遵守契约(LSP);接口保持最小(ISP);依赖可注入/可配置(DIP)。
  • 代码审查期间:职责是否清晰分离;能否不修改既有代码就添加功能;所有实现是否履行契约;接口是否聚焦最小;依赖是否已抽象。

代码库中常见违规

  • SRP:GraphQL resolver 中混入业务逻辑(应使用 command handlers);组件同时取数与渲染(应使用 hooks + 展示组件)。
  • OCP:针对类型的长 if/else 或 case 语句(应使用 behaviours/多态);硬编码的提供方逻辑(应使用依赖注入)。
  • LSP:实现中在基类型会返回 nil/error tuple 时抛异常;不同实现之间改变返回类型。
  • ISP:要求所有字段的臃肿 GraphQL 类型(应使用 fragments);单体式组件 props(应拆分为聚焦接口)。
  • DIP:直接调用外部服务(应包装为 behaviours);硬编码 Repo 调用(应注入 repository)。

与其他技能的集成

资料说明本技能可与以下技能配合:

  • boy-scout-rule:在改进代码时应用 SOLID。
  • test-driven-development:为每个职责编写测试。
  • elixir-code-quality-enforcer:Credo 会强制部分 SOLID 原则。
  • typescript-code-quality-enforcer:TypeScript 接口支持 ISP/DIP。

注意事项

资料强调:SOLID 关注的是管理依赖与职责,而非制造更多代码;良好设计来自务实而非教条地应用这些原则。

限制

资料未提供本技能的安装方式、命令、运行平台或具体调用步骤,这些问题暂未提供。