设计模式给我们的,不仅仅是一些问题的解决方案,更有追求完美“理型”的渴望。——《重构》译者熊节
2 年前作为一个前端菜鸟,初次接触设计模式,对其作用的描述得比较笼统。然后前几天,职级考官问了我一个问题:
设计模式没有产生决定性的效果,看起来不用也行吧?
当时只回答了“维护性更好”,没有答出本质。今天再来更新下我对它的看法。
🪄 设计模式到底是什么
Dan 说,开发者之间有着一些“共同语言”,来作为传递理念的基础。设计模式就是这些“语言”其中之一。(以下简称设计模式 Design Patterns 为 DP)
DP 基于 OO(源自 Java)的经验浓缩的模型,用于开发可维护和扩展的设计。但是其出发点也决定了其终点:
- 本质是 SOLID 原则中,某项原则的强化,或者几项组合后,得到的代码形式。
- 它比抽象稍微高一层。
- 基于 OO,回到 OO。脱离 OO 也能应用,但是要真正地理解其原理。
- 有理论认为,DP 是语言缺陷的补丁
- 颗粒度较小,只能用于承载纯粹的设计。要容纳业务(比如浏览器事件模型)则需要上升到框架。
40 年中都被奉为软件世界的真理,支撑起了全世界各个行业大大小小的业务。设计模式绝对算得上 CS 中的牛顿定理。我们学习这些抽象,也是设计更大的系统的基石。比如 Vue、Axios 的源码基本就是 DP 的组合或者变种。没人能仅靠底层语法完成优秀设计的。
不少自学程序员认为,设计模式属于“花里胡哨的技巧”,因为它不像算法解决实际问题。
🤔️ DP 解决实际问题吗?
我们就要定义一下,什么是“实际问题”了。回想一下,算法的特性是高效地利用时间、空间解决问题,不然堆一坨 for 完成搜索算法,我们 Google 一个词条都要花上一天。同样的,暴力堆代码也照样能完成功能,不过维护性就让其他人头痛。会想一下,有多少次我们被层层堆叠的 if..else 绕到头晕目眩。
反思一下我们的工作:80% 的时候,都是在维护,而不是开发新功能。DP 针对维护性和扩展性,恰好就是解决这 80% 场景下的问题。
令人悲伤的是,大部分程序员只需要在框架内,完成 if...esle & for 的堆砌即可完成工作。只考虑工期,不考虑维护性。
所以,DP 解决的,不是 Big O 层面的问题,而是设计和合作的问题。
不愿意学习 DP 的人,暴露了两个弱点:
- 不接触复杂设计,不关注优秀开源项目,满足于低级堆砌代码的业务
- 工作不需要合作,或者合作能力低下,编码只考虑自己
复杂的软件必须有清晰合理的架构,否则无法开发和维护。假如你的工作中一直用不到 DP 或者其它难度稍高的概念,我觉得应该是时候反思一下,这份工作是否能带来足够的成长。
❓ 反问:不写 DP,能怎么写?
有新人问我,为何不把 React 框架的项目里的函数,全都写成 Hooks,以此践行函数式呢?
我回答他,
- 函数式不是这个意思,有 Hooks 的样子不代表就是纯函数
- 纯函数在业务逻辑中很难使用。单输入单输出的情况,只适用于 lib 里的函数,比如 getId(length) 这样的生成 id 的函数;业务里最常见情况,比如一个输入事件然后搜索的函数 onSearch(event),首先参数就是复杂对象,然后输出值是毫不重要的 void,函数内部大量的对外部作用域的修改(改变 state、提交请求)才是它的真正任务
- 业务编程的主流仍是 OOP。此处不赘述。
还是回到了 OOP,而 OOP 的最佳实践们就是 DP。你对 OOP 构成对业务,无论做出何种优化——创建的、结构的、行为的方面,最终都会落入到 DP 中去。
因为它就是社区里众多程序员,多年的经验总结。你很难再超越它。
🌛 总结,与下一步
DP 为代码设计注入了生命力,使项目能够长久、稳定地发展。它也是我们进入更大的世界的敲门砖。
但也有人指出,前期就使用 DP,容易导致“过度工程”,而忽略了实用性——这个代码最应该关注的特性。
《重构》一书的核心,就是实用性。我将继续尝试从中找到更深层的答案。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。