专栏首页DDDSOLID总结

SOLID总结

之前已经把SOLID的每人原则都阐述过一遍,此篇主要是从全局角度复述一下SOLID,对于细节概念再做少许补充

SOLID原则的历史已经很悠久,早在20世纪80年代末期,都已经开始逐渐成型了

通常来讲,想构建一个好的软件系统,应该从写整洁的代码开始做起。毕竟如果建筑的砖头质量不佳,那么架构所能起到的作用也会很有限。反之亦然,如果建筑的架构设计不佳,那么其所用砖头质量再好也没用

SOLID原则的主要作用就是告诉我们如何将数据和函数组织成为类,以及如何将这些类链接起来成为程序,类似于指导我们如何将砖块彻成墙与房间

对照几张前辈们画的图,看图说话

这张图把SOLID的整体关系描述清楚了,不再是把各个原则单独看待

单一职责是所有设计原则的基础,开闭原则是设计的终极目标。

里氏替换原则强调的是子类替换父类后程序运行时的正确性,它用来帮助实现开闭原则。

而接口隔离原则用来帮助实现里氏替换原则,同时它也体现了单一职责。

依赖倒置原则是过程式编程与OO编程的分水岭,同时它也被用来指导接口隔离原则


这些原则每个单独看都是简单的,但他们却是优秀代码的指导思想,不得不常读,常思;犹如设计模式,很多时候你感觉懂了,不过只是懂了介绍模式的示例,并没有真正理解模式

反观这些原则,道理类似

如SRP:是公认最容易理解的原则,却是被违反得最多的设计原则之一;再比如ISP,看着简单,更小和更具体的瘦接口比庞大臃肿的胖接口好,很多时候都没有明白接口的定义

在实现编写代码时,只要是service都会加上一个 service interface,但想想,从项目开启到后期维护,几乎没有一个 service interface 有一个以上的实现,那为什么要加个接口呢?美其名曰面向接口编程,其实是人云亦云,让自己也让别人看着是那么一回事而已

面向接口编程所指的“接口”并非Java语言中的interface类型,而是指面向调用者对外暴露的接口,代表一种交互与协作,是对信息的隐藏和封装,而不是具体的interface类型。即使是普通的java方法仍然满足隐藏细节的原则,如果是public的,就可以认为该方法是“面向接口设计”中的接口,也就是说:不要针对实现细节编程,而是针对接口编程

接口之所以存在,是为了解耦。开发者常常有一个错误的认知,以为是实现类需要接口。其实是消费者需要接口,实现类只是提供服务,因此应该由消费者(客户端)来定义接口。理解了这一点,才能正确地站在消费者的角度定义Role interface,而不是从实现类中提取Header Interface。

对于Role interface 与 header interface , Martin Fowler给出了定义:

A role interface is defined by looking at a specific interaction between suppliers and consumers. A supplier component will usually implement several role interfaces, one for each of these patterns of interaction. This contrasts to a HeaderInterface, where the supplier will only have a single interface

如果你先定义了一个类,然后因为你需要定义接口对其抽象,然后就简单地将这个类的所有公有方法都提取到抽象的接口中,这样设计的接口,被Martin Fowler称为Header Interface,这种接口也正是胖接口的来源,而 Role interface 才是能达到瘦接口目标

想起一位投资前辈说的话,成功就是对简单道理的深刻理解和灵活运用;我们很多时候有种无力感,为什么这么简单的道理都做不好,落地不了呢?其实是没有深刻理解而自以为懂了


Kent Beck对软件设计的定义:软件设计是为了在让软件在长期范围内容易应对变化

为了软件更容易应对变化,就需要符合软件的道:高内聚低耦合

单一职责和开放封闭,更多的在强调类划分时的高内聚;而里氏替换,依赖倒置,接口隔离则更多的强调类与类之间协作接口(即API)定义的低耦合,单独应用SOLID的某一个原则并不能让收益最大化。应该把它作为一个整体来理解和应用,从而更好地指导软件设计。

这个同心圆的原图本来是:

要实现道就得遵循正交设计四原则:

1.消除重复2.分离关注点3.缩小依赖范围4.向稳定的方向依赖

「正交设计」的理论、原则、及其方法论出自前ThoughtWorks软件大师「袁英杰」先生。这一块对我来讲很新颖,消化之后再总结


这幅图揭示了模块化设计的全部:首先将一个低内聚的模块首先拆分为多个高内聚的模块;然后再考虑这多个模块之间的API设计,以降低这些高内聚的软件单元之间的耦合度。

除了内聚与耦合之外,上面这幅图还揭示了另外一种关系:正交。具备正交关系的两个模块,可以做到一方的变化不会影响另外一方的变化。换句话说,双方各自独自变化,互不影响。

而这幅图的右侧,正是我们模块化的目标。它描述了永恒的三方关系:客户,API,实现,以及它们之间的关系。这个三方关系图清晰的指出了我们应该关注的内聚性,耦合性,以及正交性都发生在何处

总结:

软件的复杂性已经是世界性难题,但最原始的道是相当简单的,就是要高内聚低耦合,在追求道的过程中,前人总结出了很多原则,这些原则相互协作、相互碰撞,我们需要平衡,取舍,这考验架构师的功力,也要求架构师对这些基本概念有深刻理解

References

[1] 《正交设计,OO 与 SOLID》: https://www.infoq.cn/article/orthogonal-design-oo-and-solid [2] 你真的了解SOLID吗?: https://insights.thoughtworks.cn/what-is-solid-principle/ [3] RoleInterface: https://www.martinfowler.com/bliki/RoleInterface.html

本文分享自微信公众号 - 码农戏码(coder-game),作者:朱先生

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-06-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • SOLID之SRP

    单一职责原则 SRP,single responsibility principle

    码农戏码
  • SOLID之OCP

    其实这也是研究软件架构的根本目的。如果对原始需求的小小延伸就需要对原有的软件系统进行大幅修改,那么这个系统的架构设计显示是失败的

    码农戏码
  • SOLID之DIP

    依赖反转原则 DIP, Dependency inversion principle

    码农戏码
  • SOLID之LSP

    LSP是继承关系设计基本原则,也是使OCP成为可能的主要原则之一。正是子类型的可替换性才使得使用基类类型的模块在无需修改的情况下就可以扩展,对于LSP的违反常常...

    码农戏码
  • SOLID之ISP

    接口隔离原则,ISP,Interface Segregation Principle

    码农戏码
  • css绘制常见的几何图形

      前言:终于我的大一生活结束了,迎来了愉快的暑假,大家都开始了各自的忙碌。一直忙着一些项目的事情,终于决定今天要更新一篇博客了,对上一阶段的学习做简单的总结。...

    okaychen
  • 符合标准的有序列表分页源码示例

    一个符合标准的有序列表分页源码示例。 你可以根据你所应用的不同程序语言,打包生成一个符合标准的分页控件。 DOM结构: <ul class="paginatio...

    练小习
  • 谈谈 SOLID 原则

    面向对象编程(OOP)给软件开发领域带来了新的设计思想。很多开发人员在进行面向对象编程过程中,往往会在一个类中将具有相同目的/功能的代码放在一起,力求以最快的方...

    用户1516716
  • SOLID原则(OOD&OOP)

    SOLID原则是面向对象编程和面向对象设计的头五大原则。学习及应用这五大原则可以构建一个易于维护和扩展的应用程序,我们一起看看到底是那五大原则。

    小世界的野孩子
  • CSS3的loading制作,让页面加载时不再单调

    页面的loading效果一直都是个比较重要的制作,往往一个好的加载效果可以有效的提升用户体验。而实际开发中,loading效果具体该如何制作?前端工程师又会有哪...

    HTML5学堂
  • 无脑用CSS制作三角形及高级应用,看完别说你还不会!

    看到这里小伙伴可能就有思路了,那我把盒子的宽和高变小一点呢?或者说直接没有宽和高呢?

    阿年、嗯啊
  • 【自然框架】js版的QuickPager分页控件 V2.0

    优点: 1、  通过更换模板可以控制各个分页元素(比如首页、末页,页号导航等)的位置和是否显示。 2、  通过更换css可以实现各种UI风格和效果。(附带24套...

    用户1174620
  • 【译】Understanding SOLID Principles - Dependency Inversion

    当我们在读书,或者在和一些别的开发者聊天的时候,可能会谈及或者听到术语SOILD。在这些讨论中,一些人会提及它的重要性,以及一个理想中的系统,应当包含它所包含的...

    littlelyon
  • 【译】Understanding SOLID Principles - Single Responsibility

    之前的第一篇文章阐述了依赖倒置原则(DIP)能够使我们编写的代码变得低耦合,同时具有很好的可测试性,接下来我们来简单了解下单一职责原则的基本概念:

    littlelyon
  • 【译】浅谈SOLID原则

    SOLID原则是一种编码的标准,为了避免不良设计,所有的软件开发人员都应该清楚这些原则。SOLID原则是由Robert C Martin推广并被广泛引用于面向对...

    Jackeyzhe
  • 走进Sass殿堂

    最近在学习sass,从sass新手的角度做一个简单的总结,总结的不对的地方期望各位大大们能多多指点,本文是针对sass3.4做的一个总结~ 一、变量篇 1.1 ...

    IMWeb前端团队
  • 如何实现一个圆弧倒计时进度条

    最近的项目中,需要实现一个圆弧形倒计时进度条,对于本来 css 知识薄弱的我当场就懵逼,脑海里总是不断思考如何实现,不幸的是脑袋里没能蹦出半个想法。然后立马百度...

    WecTeam
  • 动态内容的等高布局实现

    首先不同内容的固定高度等高布局没有任何难度,本文讲的不是这种。本文讲的是,不同行级或者浮动元素具有不定高度时,将其他元素的高度填充为最大高度元素的高度这种场景。

    RobinsonZhang
  • 走进Sass殿堂

    最近在学习sass,从sass新手的角度做一个简单的总结,总结的不对的地方期望各位大大们能多多指点,本文是针对sass3.4做的一个总结~

    IMWeb前端团队

扫码关注云+社区

领取腾讯云代金券