3

【架构设计】保持简单轻量设计的三个原则——DRY,KISS, YAGNI - JAVA旭阳

 1 year ago
source link: https://www.cnblogs.com/alvinscript/p/17013676.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一个软件轻量简单的软件架构是非常重要的,它可以让我们花最小的代价就能满足业务上的需求。那如何保证轻量简单呢?那今天就和大家分享下这其中的秘密,也就是3个重要的指导原则,KISS原则,YAGNI原则和DRY原则,你们都知道并且理解吗?

欢迎关注微信公众号「JAVA旭阳」交流和学习

KISS原则

KISS原则, 英文全称Keep it simple and stupid。核心思想就是尽量保持简单

KISS原则指导我们在软件设计的时候要尽量保持简单,使用一些成熟的、适合业务的技术方案。另外从一个使用者的角度来思考,你设计时要思考如何让自己的架构设计变得简单,足够易用,比如你开发的框架是不是对于接入成本低甚至0成本? 你设计的框架是否不侵入业务代码?

不仅软件架构设计层面,在代码层面也处处要体现KISS原则。代码的可读性和可维护性是衡量代码质量非常重要的两个标准。而 KISS 原则就是保持代码可读和可维护的重要手段。代码足够简单,也就意味着很容易读懂,bug 比较难隐藏。即便出现 bug,修复起来也比较简单。

我们来看下面校验IP是否合法的3种实现方式哪个最“KISS”,大家觉得是哪个呢?

ca8fb02c19514da681009eae9037ec1a~tplv-k3u1fbpfcp-zoom-1.image
a5f01149403a4a1e8c9eeff0c27758a3~tplv-k3u1fbpfcp-zoom-1.image
72530fcdc30b4dc695d88dd0c35f3505~tplv-k3u1fbpfcp-zoom-1.image
  • 方式一代码量最少,正则表达式本身是比较复杂的,写出完全没有 bug 的正则表达本身就比较有挑战;另一方面,并不是每个程序员都精通正则表达式。对于不怎么懂正则表达式的同事来说,看懂并且维护这段正则表达式是比较困难的。这种实现方式会导致代码的可读性和可维护性变差,所以,从 KISS 原则的设计初衷上来讲,这种实现方式并不符合 KISS 原则。
  • 方式二使用了 StringUtils 类、Integer 类提供的一些现成的工具函数,来处理 IP地址字符串,逻辑清晰,可读性好。
  • 方式三不使用任何工具函数,而是通过逐一处理 IP 地址中的字符,来判断是否合法,容易出bug,不好理解。

小结: 综合来看,第二种方式更符合KISS原则。并不是代码越少越好,还要考虑代码是否逻辑清晰、是否容易理解、是否够稳定。

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

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

YAGNI原则

YAGNI 原则的英文全称是:You Ain’t Gonna Need It。中文大意是说你根本不需要这么做。核心思想就是不要过度设计

那什么是过度设计呢?比如说你的应用,现在还是处在一个单体应用的阶段,那么这时候我就考虑啊,分布式事务该怎么做,那或者说你的数据库还是一个单库的时候,我就在思考。如何去做数据异构,甚至是你的业务逻辑在并不复杂的阶段的时候,你就再去思考如何去上一个工作流引擎,或者是规则引擎。那再比如现在图形数据库非常的火,那你就在想方设法的把图形数据库引入到你自己的项目当中。那这些是什么呢啊?说好听点叫面向简历编程,说难听点就是什么?脱裤子放屁,多此一举。我们提倡面向未来的架构是什么意思啊?是去规划你未来技术发展的路线,当这一天需要到来的时候,你有能力去实现它。而不是说你现在就把未来不需要的东西去搬到自己的项目当中。

所以千万不要为了技术而技术,一定要让技术服务于业务,谨遵YAGNI原则,过度设计是灾难。

DRY原则

DRY原则,英文全称Don’t Repeat Yourself,直译过来就是不要重复你自己。那这里的重复是什么意思?就是指代码一模一样的才算重复吗?实际不是的,我这里从实现逻辑重复、功能语义重复和代码执行重复三个点来理解重复的意思。

  1. 实现逻辑重复

我们看下下面的例子:

  • 校验用户名
0c11e4dba02b411f9cf3a4183505e4b3~tplv-k3u1fbpfcp-zoom-1.image
293bb1d3a78f472a854f7d4b892889f9~tplv-k3u1fbpfcp-zoom-1.image

虽然上面两个方法的代码逻辑是重复的,但是他们语义不重复,一个是用来校验用户名,一个是用来校验密码的,所以是符合DRY原则。如果我们强行把他们封装成isValidUsernameOrPassword()方法,反而不符合单一职责原则,万一哪天密码的校验逻辑变了怎么办呢?所以并不是说代码一样就一定违反了DRY原则。反而有时候代码不一样,恰好违反了DRY原则。

  1. 功能语义重复

直接上例子,项目中不同的同事由于不知道就写了两个校验IP的方法。

dd5e27d84cca46ac90399070fd0f9609~tplv-k3u1fbpfcp-zoom-1.image
47046d192d8b4ed5a0d626cea9aa41f7~tplv-k3u1fbpfcp-zoom-1.image

尽管两段代码的实现逻辑不重复,但语义重复,也就是功能重复,我们认为它违反了 DRY 原则。我们应该在项目中,统一一种实现思路,所有用到判断 IP 地址是否合法的地方,都统一调用同一个函数。不然哪天校验规则变了,很容易只改了其中一个,另外一个漏改,就会出现莫名其妙的bug。

  1. 代码执行重复

我们看下面一个登录的代码例子。

eee9df1e0411435d8579e77894ab9c16~tplv-k3u1fbpfcp-zoom-1.image
6ff6e35f709a4fe998dc199dd965f2a6~tplv-k3u1fbpfcp-zoom-1.image

你有没有发现email的校验逻辑被执行了2次,这种重复执行的情况我们也可以认为违反了DRY原则。

说了这么多,那有什么好的办法提高代码复用性,保证DRY原则呢?

  • 使用现成的轮子,不轻易造轮子

其实最关键的就是写代码带脑子,用到一个方法先看看有没有现成的,不要看看不看,就动手在那里造轮子。

  • 减少代码耦合

对于高度耦合的代码,当我们希望复用其中的一个功能,想把这个功能的代码抽取出来成为一个独立的模块、类或者函数的时候,往往会发现牵一发而动全身。移动一点代码,就要牵连到很多其他相关的代码。所以,高度耦合的代码会影响到代码的复用性,我们要尽量减少代码耦合。

  • 满足单一职责原则

我们前面讲过,如果职责不够单一,模块、类设计得大而全,那依赖它的代码或者它依赖的代码就会比较多,进而增加了代码的耦合。根据上一点,也就会影响到代码的复用性。相反,越细粒度的代码,代码的通用性会越好,越容易被复用。

这里的“模块”,不单单指一组类构成的模块,还可以理解为单个类、函数。我们要善于将功能独立的代码,封装成模块。独立的模块就像一块一块的积木,更加容易复用,可以直接拿来搭建更加复杂的系统。

  • 业务与非业务逻辑分离

越是跟业务无关的代码越是容易复用,越是针对特定业务的代码越难复用。所以,为了复用跟业务无关的代码,我们将业务和非业务逻辑代码分离,抽取成一些通用的框架、类库、组件等。

  • 通用代码下沉

从分层的角度来看,越底层的代码越通用、会被越多的模块调用,越应该设计得足够可复用。一般情况下,在代码分层之后,为了避免交叉调用导致调用关系混乱,我们只允许上层代码调用下层代码及同层代码之间的调用,杜绝下层代码调用上层代码。所以,通用的代码我们尽量下沉到更下层。

  • 继承、多态、抽象、封装

在讲面向对象特性的时候,我们讲到,利用继承,可以将公共的代码抽取到父类,子类复用父类的属性和方法。利用多态,我们可以动态地替换一段代码的部分逻辑,让这段代码可复用。除此之外,抽象和封装,从更加广义的层面、而非狭义的面向对象特性的层面来理解的话,越抽象、越不依赖具体的实现,越容易复用。代码封装成模块,隐藏可变的细节、暴露不变的接口,就越容易复用。

  • 应用模板等设计模式

一些设计模式,也能提高代码的复用性。比如,模板模式利用了多态来实现,可以灵活地替换其中的部分代码,整个流程模板代码可复用。

本文和大家介绍了软件工程领域中保持简单架构设计的三个原则,其实所有的这些原则就是为了达到一个很简单的目的,try everything to keep it simple,软件设计上的简单轻量是非常重要的。

欢迎关注微信公众号「JAVA旭阳」交流和学习
更多学习资料请移步:程序员成神之路


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK