设计模式学习:KISS、YAGNI、DRY原则

KISS原则:尽量保持简单

  • Keep It Simple and Stupid.
  • Keep It Short and Simple.
  • Keep It Simple and Straightforward.

代码的可读性,可维护性是衡量代码质量非常重要的标准。
代码足够简单,就意味着容易读懂,bug比较难隐藏。

代码行数越少就越“简单”吗?

同一个功能,一段代码使用的复杂的技术,比如正则,代码量最少;一段代码使用简单的工具类代码量次之;一段代码自己实现逻辑代替工具类,代码量最多;
使用正则增加了代码的维护成本,同时写出没有bug的正则也不是一件容易的事。不是简单的代码
全部自己实现逻辑,可读性不高,不是简单的代码
使用简单的工具类,中等量的代码是简单的代码。

代码逻辑复杂就违背 KISS 原则吗?

对于复杂的问题,用复杂的方法解决,并不违背KISS原则。看是否符合KISS原则,是对具体问题而言。

如何写出满足 KISS 原则的代码?

  • 不要使用同事可能不懂的技术来实现代码。比如前面例子中的正则表达式,还有一些编程语言中过于高级的语法等。
  • 不要重复造轮子,要善于使用已经有的工具类库。经验证明,自己去实现这些类库,出 bug 的概率会更高,维护的成本也比较高。
  • 不要过度优化。不要过度使用一些奇技淫巧(比如,位运算代替算术运算、复杂的条件语句代替 if-else、使用一些过于底层的函数等)来优化代码,牺牲代码的可读性。

在做开发的时候,一定不要过度设计,不要觉得简单的东西就没有技术含量。实际上,越是能用简单的方法解决复杂的问题,越能体现一个人的能力。

YAGNI原则,不要做过度设计

比如,我们的系统暂时只用 Redis 存储配置信息,以后可能会用到 ZooKeeper。根据 YAGNI 原则,在未用到 ZooKeeper 之前,我们没必要提前编写这部分代码。当然,这并不是说我们就不需要考虑代码的扩展性。我们还是要预留好扩展点,等到需要的时候,再去实现 ZooKeeper 存储配置信息这部分代码。

再比如,我们不要在项目中提前引入不需要依赖的开发包。对于 Java 程序员来说,我们经常使用 Maven 或者 Gradle 来管理依赖的类库(library)。我发现,有些同事为了避免开发中 library 包缺失而频繁地修改 Maven 或者 Gradle 配置文件,提前往项目里引入大量常用的 library 包。实际上,这样的做法也是违背 YAGNI 原则的。

从刚刚的分析我们可以看出,YAGNI 原则跟 KISS 原则并非一回事儿。KISS 原则讲的是“如何做”的问题(尽量保持简单),而 YAGNI 原则说的是“要不要做”的问题(当前不需要的就不要做)。

DRY原则,不要写重复的代码

判断是否重复

判断是否重复需要看三个方面:

  1. 实现逻辑是否重复
  2. 功能语义是否重复
  3. 代码执行是否重复

当语义不同的时候,哪怕逻辑一样,不能重用代码,比如:校验用户名和校验搜索词,可能在逻辑实现上一致的。但是语义不同,不能重用
当功能语义重复的时候,实现逻辑可能不同,也需要注意查看是否可以进行代码复用,语义重复的代码是最容易在后期维护的时候造成bug的地方。
当代码的执行调用前后有重复的时候也需要进行代码的整理,去除重复的代码。

代码的复用性

  1. 首先不重复不代表可复用。在一个项目代码中,可能不存在任何重复的代码,但也不表示里面有可复用的代码。
  2. 其次,复用和可复用性关注的角度不同,代码可复用性是从代码开发者的角度来讲的,复用是从代码使用者的角度来讲的。比如,A 同事编写了一个 UrlUtils 类,代码的“可复用性”很好。B 同事在开发新功能的时候,直接“复用”A 同事编写的 UrlUtils 类。

怎么提高代码的复用性

  • 减少代码的耦合
    • 高度耦合的代码会影响到代码的复用性
  • 满足单一职责原则
    • 越细粒度的代码,代码的通用性越好,越容易被复用
  • 模块化
    • 独立的模块就像一块一块的积木,更加容易复用,可以直接拿来搭建更加复杂的系统。
  • 业务与非业务逻辑分离
    • 越是跟业务无关的代码越是容易复用,越是针对特定业务的代码越难复用
  • 通用代码下沉
    • 从分层的角度来看,越底层的代码越通用、会被越多的模块调用,越应该设计得足够可复用。通用代码尽量下沉到更下层
  • 继承、多态、抽象、封装
    • 在讲面向对象特性的时候,我们讲到,利用继承,可以将公共的代码抽取到父类,子类复用父类的属性和方法。利用多态,我们可以动态地替换一段代码的部分逻辑,让这段代码可复用。除此之外,抽象和封装,从更加广义的层面、而非狭义的面向对象特性的层面来理解的话,越抽象、越不依赖具体的实现,越容易复用。代码封装成模块,隐藏可变的细节、暴露不变的接口,就越容易复用。
  • 应用模板等设计模式
    • 模板模式利用了多态来实现,可以灵活地替换其中的部分代码,整个流程模板代码可复用。

我们在第一次写代码的时候,如果当下没有复用的需求,而未来的复用需求也不是特别明确,并且开发可复用代码的成本比较高,那我们就不需要考虑代码的复用性。在之后开发新的功能的时候,发现可以复用之前写的这段代码,那我们就重构这段代码,让其变得更加可复用。

相比于代码的可复用性,DRY 原则适用性更强一些。我们可以不写可复用的代码,但一定不能写重复的代码。

posted @ 2019-12-20 15:00  司霖  阅读(945)  评论(0编辑  收藏  举报