草庐IT

经典设计原则

程序员翔仔 2023-03-28 原文

经典设计原则除了 SOLID 之外,常见的还包括 KISS、YAGNI、DRY、LOD、CRP 等几种:

  • KISS(Keep It Simple & Stupid, 尽量保持简单)
  • YAGNI(You Ain't Gonna Need It, 你不会需要它)
  • DRY(Don't Repeat Yourself, 不要重复自己)
  • LOD(Law Of Demeter, 迪米特法则)
  • CRP(Composite Reuse Principle, 合成复用原则)

KISS 原则

理解

KISS 原则的英文描述有很多版本,如下:

  • Keep It Simple & Stupid
  • Keep It Sweet & Simple
  • Keep It Short & Simple
  • Keep It Simple & Straightforward

它们的含义都差不多,其实就是“尽量保持简单”。

但是,并不是代码行数越少就越“简单”,还要考虑逻辑复杂度、实现难度、代码的可读性等。并且,有些本身就复杂的问题,用复杂的方法解决,并不能算是违背 KISS 原则。

优点

遵循 KISS 原则,将会有以下的优点:

  • 简单地编写代码,理解该代码不会有任何困难,将更容易修改,而且花费的时间也会大大减少

最佳实践

在实际开发中,可以通过以下情况判断代码是否满足 KISS 原则:

  • 不要使用协作者可能不懂的技术来实现代码
  • 不要重复造轮子,要善于使用已经有的工具类
  • 不要过度优化,牺牲代码的可读性

YAGNI 原则

理解

YAGNI 原则的核心思想就是不要过度设计,即不要去设计当前用不到的功能,不要去编写当前用不到的代码。

优点

遵循 YAGNI 原则,将会有以下的优点:

  • 过度设计往往会延缓开发的迭代速度,减少过度设计将能支持创业公司的快速迭代
  • 编写只符合当前场景的代码质量可能会更高,这也是 KISS 原则的另一种实践

最佳实践

虽然说,在不需要某功能前,不要提前去实现此功能。但是,在可预见的情况下,需要预留好扩展点,等到实现此功能时能无缝接入。

比如,系统在当前只需要使用 Redis 存储配置信息,以后有可能会用到 ZooKeeper 存储配置信息。根据 YAGNI 原则,当前没有必要编写 ZooKeeper 的代码,但是可以通过抽象出统一的配置存储接口作为扩展点,方便后续可以快速接入。

DRY 原则

理解

DRY 原则可以理解成不要写重复的代码,解决的是代码的复用性问题。

优点

遵循 DRY 原则,将会有以下的优点:

  • 对于频繁更改需求的情况,重复代码将会增加修改代码的痛苦
  • 遵循 DRY 原则要求开发者具备高度抽象思维,高度抽象的代码具备高可维护性、高扩展性

最佳实践

常见代码重复情况

实现逻辑重复,但功能语义不重复的代码,并不违反 DRY 原则。

比如说,一个检验用户名和检验密码的代码在编写上完全一致,因此写了 isValidUserName()isValidPassword() 两个函数,但其实这两个函数并不能算作违反 DRY 原则。

功能语义重复,但实现逻辑不重复的代码,视为违反 DRY 原则。

其原则在于,对于完全相同的功能,不允许出现两个及其以上的对外接口,更不允许出现不同的代码表示同一个功能。

隐藏的执行重复被认定违反 DRY 原则。

即当运行完一个代码流程之后,出现相同的函数被无意义地执行过两次及其以上,则被称为执行重复,这是一种隐藏的违反 DRY 原则的行为。

代码复用性

总结有以下方法可以提高代码的可复用性:

  • 减少代码耦合
  • 满足单一职责原则
  • 善于模块化
  • 业务与非业务逻辑分离
  • 通用代码下沉
  • 善用面向对象的特性
  • 应用设计模式

事不过三

“3”是一个非常神奇的数字,“事不过三”是它的一种特殊用法,这个原则可以应用在编写可复用代码的时候。

可以这么理解:第一次写代码时,如果当下没有复用的需求,而未来的复用需求也不是很明确,并且开发可复用代码的成本比较高,那就不需要考虑代码的复用性;第二次遇到复用场景的时候,再进行重构使其变得可复用。

LOD 原则

理解

LOD(迪米特) 原则也被叫作最小知识法则(Least Knowledge Principle, LKP),其含义是不该有依赖的模块之间不要有依赖,有依赖关系的模块之间尽量只依赖必要的接口。

迪米特原则有点类似于接口隔离原则,希望能减少类之间的耦合,让类越独立越好。

优点

遵循迪米特原则,将会有以下的优点:

  • 降低类之间的耦合度,提高了模块的相对独立性
  • 提高类的可复用率和系统的扩展性

最佳实践

迪米特原则还有几种定义形式:不要和陌生人“说话”,只与你的直接朋友通信等。

在迪米特原则中,对于一个对象,其“朋友”包括以下几类:

  • 当前对象本身
  • 以参数形式传入到当前对象方法中的对象
  • 当前对象的成员对象
  • 如果当前对象的成员对象是一个集合,那么集合中的对象也都是朋友
  • 当前对象所创建的对象

CRP 原则

理解

CRP 原则又称为组合/聚合复用原则,其含义是,尽量使用对象组合,而不是继承来达到复用的目的。

通过继承来进行复用的主要问题在于,继承复用会破坏系统的封装性。当基类发生了改变,继承基类的子类也会不可避免地发生改变,从基类继承而来的实现是静态的,不可能在运行时发生变化,没有足够的灵活性。

通过组合或聚合关系可以将已有的对象纳入新对象中,使之成为新对象的一部分,因此新对象可以调用已有对象的功能,这样关系不会将已有对象的实现细节暴露给新对象。

相对继承而言,组合和聚合复用的耦合度更低,相互之间的影响不大,实际开发中可以有选择性地调用需要的功能。

优点

遵循 CRP 原则,将会有以下的优点:

  • 系统更加灵活,降低了类与类之间的耦合度,一个类的变化对其他类造成的影响相对较小

最佳实践

一般而言,如果两个类之间是“Has-A”的关系,应使用组合或聚合;如果是“Is-A”的关系,可以使用继承。

有关经典设计原则的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  3. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

  4. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  5. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  6. Hive SQL 五大经典面试题 - 2

    目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类

  7. ruby-on-rails - 设计注册确认 - 2

    我在我的项目中有一个用户和一个管理员角色。我使用Devise创建了身份验证。在我的管理员角色中,我没有任何确认。在我的用户模型中,我有以下内容:devise:database_authenticatable,:confirmable,:recoverable,:rememberable,:trackable,:validatable,:timeoutable,:registerable#Setupaccessible(orprotected)attributesforyourmodelattr_accessible:email,:username,:prename,:surname,:

  8. ruby - 最佳原则中的原则 - 2

    我似乎经常遇到一些设计问题,但我不知道是什么是真的很合适。一方面我经常听到我应该限制耦合和坚持单一职责,但当我这样做时,我常常发现它很困难到在需要时将信息获取到程序的一部分。为了例如,classSingerdefinitialize(name)@name=nameendattr:nameend那么Song应该是:classSongdefnew(singer)@singer=singerendend或classSongdefnew(singer_name)@singer_name=singer_nameendend后者耦合性小,按道理应该用。但如果我以后发现宋有什么需要了解更多歌手,我的

  9. ruby-on-rails - 设计通过 reset_password_token 获取用户 - 2

    我正在尝试创建密码规则来设计可恢复的密码更改。我通过passwords_controller.rb做了一个父类(superclass),但我需要在应用规则之前检查用户角色,但我所拥有的只是reset_password_token。 最佳答案 假设您的模型是用户:User.with_reset_password_token(your_token_here)Source 关于ruby-on-rails-设计通过reset_password_token获取用户,我们在StackOverflow

  10. ruby-on-rails - Rails 5,公寓和设计 : sign in with subdomains are not working - 2

    我已经使用Apartment设置了一个Rails5应用程序(1.2.0)和Devise(4.2.0)。由于某些DDNS问题,应用只能在app.myapp.com下访问(请注意子域app)。myapp.com重定向到app.myapp.com。我的用例是每个注册该应用的用户(租户)都应该通过他们的子域(例如tenant.myapp.com)访问他们的特定数据。用户不应限定在其子域内。基本上应该可以从任何子域登录。重定向到租户的正确子域由ApplicationController处理。根据Devise标准,登录页面位于app.myapp.com/users/sign_in。这就是问题开始的

随机推荐