Table of Contents
理解固态原则
SOLID原则是五条面向对象的设计准则,帮助开发者创建更方便维护,扩展和测试的系统. 这些原则是罗伯特·C·马丁在2000年代初提出的,此后成为现代软件架构的基石. 每一个原则都涉及软件设计的一个特定方面:
- 单一责任原则: 类只应有一个改变的理由,即它应负责一个单一的功能.
- 开放/关闭原理(OCP):[类应该开放扩展但关闭修改——你可以添加新的行为而不修改现有的代码.
- 利斯科夫替代原则(LSP): 子类型必须可以替代其基型,而不打破系统.
- 界面隔离原则(ISP):客户端不应被迫依赖他们不使用的界面;最好拥有许多小而具体的界面,而不是一个大的,通用的接口.
- 依赖性反演原理(DIP):[ 高层次模块不应依赖于低层次模块;两者都应依赖于抽象. 抽象性不应依赖于细节——细节应依赖于抽象性.
UML 在软件架构可视化中的作用
统一建模语言(UML)为可视化系统设计提供了标准化的注解. 图表在开发者,建筑师和利益相关者之间充当了一种共享语言,使得复杂结构的交流更加方便. UML图在应用到符合SOLID的架构时,揭示设计如何很好地坚持原理,并突出可能需要重构的区域.
UML包括14个图型,但SOLID可视化最相关的是类图,组件图,序列图,以及包图. 每个图型可以强调原理的不同方面——例如类图显示类责任和接口,而组件图则突出依赖方向和扩展点.
将 UML 图表映射到每个 SOLID 原则
单一责任原则和分类图
类图是验证SRP合规性的理想. 精心设计的类图显示了每个类都有清晰,突出的属性和方法集. 如果类有多重责任,则其图中的框将包含不相关的操作——一个用于SRP违规的红旗.
例如,一个名为 " IvoiceManger " 的类别既处理发票计算,又处理电子邮件发送,这违反了SRP,该类别图将显示同一箱内 " 计算Total() " 和 " sendEmail() " 等方法,表明需要将这一类别分为 " Ivoice计算器 " 和 " EmailService " ,标记责任界限有助于各小组及早发现违规行为。
打开/关闭原则和组件图
组件图说明了一个系统的高层结构,显示了组件(如模块,子系统)如何通过接口连接. 要坚持OCP,组件应该暴露固定的接口,同时允许新的执行而不修改现有的接口.
在组件图中,您可以通过使用提供的和所需的接口来表示这一点. 例如,“支付处理器”组件可以定义“支付”接口,新的支付方法(信用卡,PayPal)作为执行该接口的单独组件而添加,该图表明核心处理器不需要改变——它只取决于抽象度.
利斯科夫替代原则和继承等级
具有继承关系的类图直接测试LSP. 如果子类以违反预期行为的方式超越了基础类方法,则等级是可疑的. UML允许您使用限制(如在注释或OCL — Object Control Language)来建模先决条件,条件和不变量.
违反《固定资产法》的典型做法是继承`矩形 ' 的`平方 ' 类,在图中,如果`方形 ' 更改`setWidth()',以设定`高',则违反`矩形 ' 合同,图中应显示`方形 ' 并非真正可以替代的,为了解决这个问题,你可能使用一个共同的`形状 ' 界面,与单独的`矩形 ' 和`方形 ' 实施相连接,则该类图将表明它们之间没有直接的继承。
界面分隔原则和界面图
UML 可以明确使用接口框(带有‘<
例如,与`印刷()'、`扫描()'、`传真()'的`多功能插件 ' 接口不同,而是分为`Printable'、`scannable'和`Faxable',分类图显示`BasicPrinter'只执行`Printable',而`AdvancedPrinter ' 则执行所有三项,这种方法使接口保持精准,防止客户被迫依赖无关的业务。
依赖性 颠倒原则和依赖性图
类图和包图都可以说明DIP的遵守. DIP指出,高级模块(如商业逻辑)不应该依赖于低级模块(如数据库驱动程序),相反,两者都应该依赖于抽象(界面或抽象类).
在包依赖图中,您可以显示依赖性的方向。如果一个高层次包直接指向一个低层次包,则图会警告一个 DIP 违反。解决方案是在高层次包中引入抽象(界面),低层次包取决于该界面。更新的图显示了反向依赖性——一个SOLID符合性的明显标志。
为 SOLID 架构创建 UML 图表的最佳做法
遵循这些准则,制作清洁、信息丰富的UML图,加强固态化原则:
- 使用定型观念和注释: 应用`<
、< 和< 的定型观念。 - 保持图表的焦点: 单一的图表应涉及一个原理或一组小的相关原理。避免将每个类别拼凑成一个巨大的图表。
- 选择仅相关关系: 显示继承,关联,聚合,和依赖箭头的位置,它们很重要. 过度加载不相关的箭头会模糊SOLID的遵守.
- 突出的违反: 使用不同的颜色或虚线标记问题关系,例如,从高阶到低阶的红色依赖箭头可以标出DIP违反.
- 与重构:] 重构设计以与SOLID相遇时,更新图. UML是活的文物——把它当作代码的伴奏,而不是一次性的草图.
常见的陷阱和如何避免它们
即使是有经验的开发者在使用UML设计SOLID架构时也可能陷入陷阱。这里经常出现错误和回避的方法:
- 过度吸收早期: 太多的接口或类可以违反YAGNI(You An't Gond It). 以简单的类图开始,然后只在SOLID原则要求时添加抽象——典型的重构时.
- 协调UML注解: 滥用箭头类型(例如,在依赖箭头正确的情况下使用概括箭头)可能导致误解. 研究UML 2.5规格基础以避免模糊. OMG UML规格是最终的参考.
- 在序列图中忽略 LSP :[ 序列图显示运行时的相互作用。如果一个子类对象被替换为一个基类对象,而相互作用会意外改变行为,则LSP 会被打破。验证序列中包含子类实例 。
- 忽略依赖方向: DIP 是关于依赖方向的。在包图中,总是从客户端到服务器绘制箭头。如果看到周期或箭头指向错误方向,请重构抽象。
- 使图表过于详细: 显示每个获取和设置的图会模糊视图的类图。侧重于执行SOLID原理的公共界面和关键关系。
创建 UML 图表的工具
多个工具可以帮助您创建与代码同步的UML图。 选择一个符合您工作流程的工具 :
- PlantUML: 一个与版本控制整合的基于文字的图解工具。 写入纯文本描述并自动生成图解。 理想是给想要将图解作为代码的团队。 在PlantUML 中学习更多 。
- Draw.io (diagrams.net): 一个免费的基于网络的图表编辑器。支持UML stencils和方便导出。 用于协作白板的很好。
- Lucidchart: 付费平台,带有UML模板和实时协作. 提供与Coeffication和Jira的集成.
- Modelio: 一个支持UML和BPMN的开源模型工具,可以从类图和逆向引擎的现有代码生成代码.
- IntelliJ EIDO Ultimate: 包括类、包和依赖性图的内置图样。直接与您的代码库同步。
为了更深入地理解SOLID原理和UML整合,可以参考罗伯特·C·马丁在"OD原理(PDF)"和维基百科中的相关条目:SOLID原理["的原始写作.
结论
UML 图表将抽象的 SOLID 原理转换为具体的视觉模型,开发者可以检查、讨论和改进。通过将每个原理映射到合适的图表类型 — — 用于 SRP和ISP的类图,用于 OCP和DIP的组件图,以及用于 LSP 的继承等级,您可以系统验证您的架构仍然灵活、可维护、可缩放。
关键是使用UML 并不是官僚主义的文物,而是随您的代码而演变的活工具。结合自动图生成和常规代码审查,UML 成为建设符合SOLID的系统,经受时间考验的强大盟友。