Files
fzu-product/3.编程思维体系构建/3.X 聊聊设计模式和程序设计.md
2023-08-24 10:31:27 +08:00

82 lines
6.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 3.X 聊聊设计模式和程序设计
*Author: yyl
Last revised 2022/08/07*
## 前言
在开始讲内容之前,我觉得我得首先聊一聊到底为什么我们需要这些东西。为什么我们会需要设计模式呢?
这个问题并不可笑也不幼稚事实上很多东西红极一时最终却被历史证明是不被需要的。类似的事情太多了可以是一种理念比如日心说可以是一种产品比如软驱、RAMBUS 内存,等等。历史已经丢弃了太多不被需要的东西了。
学习本身是有成本的事情,如果在开始之前能够理解为什么要开始就更好,尽管很多时候我们做不到这件事,但也不能忘了这件事。
上个世纪 80~90 年代的时候,人们试图通过“设计模式”这一工具,抽象总结所有的软件设计方法,构建一个无敌的知识库。最终使得软件工程就像堆积木一样简单,避免软件随时间变得杂乱的熵增问题,但毫无疑问这是失败的,你永远无法抽象总结所有东西,设计模式的巅峰,可能是在 JDK 之中。在阅读 Java 自身提供的诸多 API 时你会发现其中蕴藏了大量的设计模式而且是赤裸裸地把使用了的设计模式写在了类名中如“XXXListener”很少有另一个语言也是这样的。
设计模式并没有完全成功,但也没有完全失败。他现在以一种“术语”的形式存在,帮助人们理解常见的编程范式。——这是什么意思呢?举个例子,如果你尝试和同事说明你的一个设计时,你说,它首先有两个类,一个类提供了一个通用的接口,可以被另一个类注册,另一个类则负责把所有的动作通知给已经注册的类。这种说法显然非常繁琐,对方也未必能理解你的意思。但如果你说,这里使用了监听者模式,如果你的同事碰巧学习过一些设计模式,他就能立即理解你的意思。即使他没有学习过相关知识,只要简单百度一下也能理解个大概。这是当今设计模式的一个重要作用。
另一个重要作用则是它的本源了,用于总结抽象程序设计的范式。但并不是说要你写的所有代码能用设计模式的就都用设计模式,这更多是提供给你一种选项,让你能够充分权衡。关于这部分,下文还会有说明。
目前的设计模式,主要集中在如何避免程序复杂度上。
什么是程序复杂度呢?就是说你今天写了个软件,明天给他加功能的时候发现这个程序不怎么可维护,于是直接在之前的逻辑上加了个 if你的一个 if 通常不会有什么大问题,程序复杂性问题是日积月累的。随着大家都在不同的地方写自己的 if整个程序最终会变得不可维护。可能一个微小的改动会导致很多地方的 if 出现不符合预期的判断,可能终有一天有一个需求无法再用 if 来实现,等等。
为了解决这个问题,设计模式使用的方法是原则,通过制定一系列的原则,并确保大家都遵守,来避免代码腐烂。
## 拿个锤子,见什么都是钉子
设计模式,或者说广义的程序设计架构的初学者,很多都会想去设计一个“完美的架构”。
当就像计算机程序设计本身是关于权衡的艺术一样,学习程序架构也不能看见什么都上架构。下面举例子具体说明。
你要设计一个小程序给自己用,这个程序的作用是定时读取一边本地硬盘上的全部文件,通过 sha256 算法生成每个文件的文件摘要,比对文件是否遭到篡改,如果遭到了篡改就报个警。
如果你没有学习过这些乱七八糟的设计模式,我想你大概会这么做:
main():
walk("/");
walk(String path):
For file : os.listfile(path):
// 检查文件摘要
For dir : os.listdir(path):
walk(dir);
但如果你很不幸,学习过一些设计模式,或者说有一些程序设计经验,你会开始考虑一下问题:
1. 我用什么语言实现?这个语言的代码文件组织有没有推荐的架构?(比如,第三方包引用了放在哪里?文件加密的 util 是放在内部还是封装成可供其他人引用的三方包?)
2. 选用什么样的依赖管理机制?
3. 编译最终产物的时候用什么工具make 还是 maven 还是 gradle 还是 shell 还是 python...
4. walk 能不能兼容不同平台的系统?在 win 下面能不能用?
5. 有没有什么设计模式可以用?(开始翻书)
6. 卧槽,用官方推荐的组织架构的话这个程序有点单薄啊,要不要加点功能上去
7. ...
要明白,拿着个锤子绝不能看什么都是钉子。
设计模式本身也是权衡的艺术,我们今天经常说的东西,比如 DDDSOA微服务monorepo也都是一种广义的设计模式。权衡什么呢权衡的是是要维持程序在发生功能变动时的可拓展性、降低程序维护复杂度还是追求程序的快速实现。
拿上文的例子来说,如果你的所有程序都是在运行 Linux 上的,这个也只是给你自己快速检查文件完整性,之后也几乎不存在增加新的功能的可能,为什么不随便找个脚本语言快速十几行写完呢?
## 如何学习
个人认为,现在所谓的设计模式分两种,第一种是狭义的设计模式,就是各种设计模式的堆积。
此外,还有广义的设计模式,这块内容就很多了,但也是讨论如何降低代码复杂度的,包括:
1. 程序代码怎么组织(在开发 web 应用时这块经常有争议,可以参考 [浅析整洁架构之道 (二) 初步了解 The Clean Architecture](https://cloud.tencent.com/developer/article/1837487)
2. 程序之间怎么组织(是放在一个编成个大的,还是微服务,还是用 FaaS 之类的变体)
3. 一些帮助减少程序复杂度的代码原则:[设计模式之 SOLID 原则](https://zhuanlan.zhihu.com/p/82324809)
这部分的学习不能操之过急。个人的建议是:
1. 学习一些设计模式,看完两次肯定没什么感觉,甚至会觉得看了个寂寞(可以先看看 Head first 设计模式)
2. 忘了他,去写你自己的代码,遇到复杂度诅咒了再考虑如何解决
3. 读他人的优秀代码,想一想这里他为什么要这么写,换成是你的话会怎么写,各自有什么利弊
4. 重复 1