Files
knowledge-kit/Chapter6 - Design Pattern/6.31.md
2023-11-02 16:06:38 +08:00

6.1 KiB
Raw Blame History

设计模式怎么应用?如何避免过度设计、又如何避免设计不足

现状

面对代码,经常存在两种情况。

一种是过度设计在开始写代码之前会花很长时间做技术方案上技术方案时间长短没有统一标准会花很多时间在代码设计上打算用到各种设计模式美其名曰“未雨绸缪、面向未来、业务可迁移”但可能伴随的问题是未来的业务需求怎么演进是个未知数领域如何发展也是未知数在最早期就过度设计会导致大大增加代码复杂度以后的开发都要站在这套复杂的设计之上进行开发、设计、维护、修改了举个例子Redux 分层太多、角色太多的好处之一是角色清晰、各司其职,但坏处也是显而易见的,简单的场景,杀鸡用了牛刀)

另一种是不咋设计,技术/业务项目以来,简单分析后,立马操刀就干,代码能跑就行,业务项目甚至是面向 PRD 编程PRD 罗列的 case 直接用代码翻译一下,没有设计思想,谈何面向未来、高内聚低耦合、开闭、里氏替换?不存在的。改动一个小点,可能要改很多处代码,前一发而动全身,后人接手也不敢碰。

那如何做到不过度设计,也避免设计不足的问题?

设计初衷是提高代码质量

马斯克经常会提到“第一性原理”,我也赞同这个研究方式和思维方式。写代码,包括应用设计模式也是如此。设计模式只是方法,只是工具,最后的目的,核心的诉求是:提高代码的可读性、可拓展性、可维护性。所有的设计都围绕这个目的来展开。

所以拿到项目或者问题,先问几个问题:为什么要这样设计、为什么要用这个设计模式、这样做是否真正的提高代码质量、提高代码哪些方面的质量、怎么样提高可维护性、可拓展性。如果这几个问题回答清楚了,那基本就没什么问题了(为什么是基本?软件工程需要考虑 ROI。如果答案是觉得还行但是解决的问题不够痛、价值没那么大那可能当前的方案有点为了设计而设计了。

换个角度思考,设计模式是招式、设计原则/思想是心法。低阶的江湖侠客追求的是招式大宗师追求的是心法。掌握心法以不变应万变无招胜有招。所以掌握设计思想更重要设计思想比设计模式更普适23种设计模式是之前的人总结出来的说不定过个几十年又诞生几种新的设计模式掌握设计思想的话可以面向未来甚至你之前写的某个设计刚好和新诞生的设计模式有异曲同工之妙甚至后来才意识到我的这个实现原来是最近新出来的某某某设计模式

先有问题,再有方案

如果我们把写出的代码看作产品,那做产品的时候,我们先要思考痛点在哪里,用户的真正需求在哪里,然后再看要开发哪些功能去满足,而不是先拍脑袋想出一个花哨的功能,再去东搬西凑硬编出一个需求来。

代码设计也是类似的。我们先要去分析代码存在的痛点,比如可读性不好、可扩展性不好等等,然后再针对性地利用设计模式去改善,而不是看到某个场景之后,觉得跟之前在某本书中看到的某个设计模式的应用场景很相似,就套用上去,也不考虑到底合不合适,最后如果有人问起了,就再找几个不痛不痒、很不具体的伪需求来搪塞,比如提高了代码的扩展性、满足了开闭原则等等

设计的应用场景是复杂的代码

很多设计模式相关的书籍都会举一些简单的例子,这些例子仅仅具有教学意义,只是为了讲解设计模式的原理和实现,力求在有限篇幅内给你讲明白。而很多人就会误以为这些简单的例子就是这些设计模式的典型应用场景,常常照葫芦画瓢地应用到自己的项目中,用复杂的设计模式去解决简单的问题,还振振有词地说某某经典书中就是这么写的。在我看来,这是很多初学者因为缺乏经验,在学完设计模式之后,在项目中过度设计的首要原因。

设计模式要干的事情就是解耦,也就是利用更好的代码结构将一大坨代码拆分成职责更单一的小类,让其满足高内聚低耦合等特性。创建型模式是将创建和使用代码解耦,结构型模式是将不同的功能代码解耦,行为型模式是将不同的行为代码解耦。而解耦的主要目的是应对代码的复杂性。设计模式就是为了解决复杂代码问题而产生的

对于复杂代码,比如项目代码量多、开发周期长、参与开发的人员多,我们前期要多花点时间在设计上,越是复杂代码,花在设计上的时间就要越多。 不仅如此,每次提交的代码,都要保证代码质量,都要经过足够的思考和精心的设计,这样才能避免烂代码效应(每次提交的代码质量都不是太好,最终积累起来整个项目的质量就变得很差)。

持续重构能有效避免过度设计

比如一个很简单的场景简单的 MVC 加几个 Handler 就可以实现,但是有些小伙伴学完前端 Redux 觉得好酷,就要在客户端落地这个实现,导致平白增加几个角色,带来的好处就是角色多、各司其职、边界清晰、增加可拓展性,但缺点也很明显,降低代码的可读性、提高复杂度。一旦引入新的某个设计,不可能就可以随意下掉,也就是说在接下来的很长一段时间里,修改、维护某个简单的功能就需要遵循这个复杂的设计(框架苦开发久已)

所以为了避免过度设计,避免因需求误判而导致的过度设计,推荐持续重构的方法。持续重构不仅可以保证代码质量,也可以避免过度设计。面对真正有痛点的设计,再去用合适的设计模式去解决,而不是一下子全部推翻,从项目管理上和质量方面来说,这个做法很冒险、不够健康