你好!我是郑晔。

我又一次写到了结束语,也许你也是又一次来到我的结束语。当初写《10x 程序员工作法》结束语时的感觉,依然历历在目。这一次,《软件设计之美》也写到了尾声。

学习了两个专栏的小伙伴对我的风格可能有一些了解,我总是试图把尽可能多的知识以结构化的方式呈现在你面前。因为,就我自己的学习而言,我也总是可以很快学会细节的东西,但知识结构却不是一朝一夕就可以建立的。

我曾把《10x 程序员工作法》比作藏经阁的目录,因为它是我已经结构化了的软件开发的各种最佳实践,而《软件设计之美》则是我构建软件设计知识大厦的一种尝试。我总是努力提供尽可能大的知识密度,保证看到这些内容的你,在学了我的专栏之后,还可以有继续扩展学习的空间。

我在下面附上了总结图,把专栏里提到的知识做了一个整理,方便你更好地进行复习。

但是,在这个专栏中,虽然我把软件设计相关的核心知识都讲了一遍,可还有一些内容是我没有在专栏中呈现出来的。那么,在这个专栏的结束语中,我们就来说说那些没讲的事儿。

设计需要沟通

你能感受到,我在这个专栏里给你讲的大部分内容都是技术性的,然而,在真实的软件开发过程中,软件设计工作有很大一部分内容却是非技术性的,比如,沟通。

也许你会觉得,设计不就是改改代码吗,跟沟通有什么关系啊?

我在专栏之初就说过,软件设计是要构建模型,打造规范。但是那时候,我没说的是,模型的理解需要沟通,规范的执行同样也需要沟通。

因为无论是模型还是规范,软件设计最终是要落实到代码上的。具体落实成什么样,是依赖于人的,依赖于人的理解和人的执行。那如何才能让人的理解达成一致?唯有不断反复地沟通。

为什么有些人并不觉得沟通很重要,或许只是因为他们所做的工作是局部代码的调整,涉及到人的比较少,沟通的重要性没有那么凸显。但只要我们在成长,我们负责的模块规模就会变大,牵扯到的人就会增多。如果你想要让其他人能够理解你的设计,就需要靠沟通了。

我们都知道,好的设计一定是易于理解的,而这个理解指的就是别人如何理解。所以,一个好的设计只做到自己心知肚明是不够的,酒香也怕巷子深。

一个好的设计是需要讲给别人、取得别人认同的。虽然我们说,条条大路通罗马,达到同一个目标的路径有很多,设计没有一条标准的路径。可是,当人数多起来,思想不一致几乎是一种必然。所以,只有通过沟通,我们才有可能让大家对某一种路径达成一致。

这样的话,设计才能保持一致,否则,你写结构化编程的 for 循环,我写函数式编程的 map、reduce;你留扩展点,我来硬编码,代码就注定是无法维护的。

不过,如果我把沟通放在软件设计的课表上,估计很多人看到课表就直接放弃了。因为沟通这件事太不够“硬核”。而我在《10x 程序员工作法》中,把沟通反馈作为了一项重要的工作原则。后来,我从同学们的反馈中也看出,沟通确实是程序员成长过程中一个重要的阻碍

其实,在软件设计中,确实有一个工具是关于沟通的,那就是UML,叫作统一建模语言。不过,现在很多程序员更习惯随手画个图,因为这种表达方式更简单,这让 UML 的用武之地就少了许多。

所以,有空的时候,我还是建议你去了解一下 UML,至少你要知道有几种类型的图。这样,以后你在随手画图时,不至于把静态结构和动态交互画在一起。

很多程序员会习惯性地把自己的职业只当作一个技术工种,认为只要技术足够深厚,便能够通行天下。但实际上,只要我们是在一个组织中工作,沟通能力就是非常重要的,而且,随着职位的上升,沟通能力的重要性会越发显现。

所以,如果你在实际工作中发现别人很难理解你的美妙设计,一种可能是你的设计没有你以为的那么好;而另一种可能就是,你的沟通还不够好,其他人并没有理解你

经验的积累

关于软件设计,我还有一件事是没法教给你的,那就是经验的积累。

如果你有机会和我一起写代码,我可能会在一些地方要求你去增加一些类、把类写小;在另外一些地方要求你把一些类合并、减少类的数量;有时候,我还会告诉你这个地方要留一个扩展点,把变化隔离开来;还有的时候,我会让你别考虑扩展,先把功能实现了。

你可能会困惑,这里的一对对操作完全是相反的,到底哪个才是软件设计该做的呢?但是,如果你和我在一起工作,有了相应的上下文,你就会理解这些要求的合理之处。

所以说,即便我们掌握了相同的软件设计知识,但是在一个具体的场景下,该做怎样的判断、如何作出判断,都是需要我们经验积累的。

软件设计的基础,无论是设计模式,还是设计微调的技巧,你都可以通过课程去学习,甚至可以通过短期的训练营去锻炼。但是,如果你想要把这些内容熟练地运用到实际的工作中,那就需要你有大量经验的积累,需要你经历或者见过许多不同的使用场景。

不过,一切经验积累的前提条件是,先有软件设计的意识

对于大多数人而言,软件设计是知与不知的差别。知道的人就会有意识地积累经验,而不知道的人即使做过再多的项目,也无非是不断地在重复增删改查。《软件设计之美》这个专栏首先帮助你解决了知的问题,只有知道了,你才能开启积累的道路,踏上个体成长的阶梯。

我在专栏中反复在说,软件设计关注的是长期变化。可是,实际上,没有任何一个专栏或是一个训练营可以让你真正地感受到一个软件的长期变化,唯有真实的项目可以。

每当来了一个新的需求,我们就会有一个对应的解决方案。但是,我们最好先问自己一个问题,这种实现方案是不是一个好的设计呢?这么做就可以给自己的直觉思维加上一个缓冲。

普通程序员和高手之间的差别就在于此,普通程序员凭直觉做事,高手却是把专业的做法训练成直觉。所以,你能看到很多人在不经意间写出的代码就非常漂亮,而漂亮的背后,其实是一次又一次的思考和训练。

我有幸在职业生涯之初就接触了软件设计,当时我所在的部门正面临着对系统的调整,所以,当时的技术负责人每天研读《设计模式》,然后就在部门里做分享,分享他的读书心得。

虽然我当时还不能完全理解他在说什么,但本着对他的信任,我整个过程都听得很认真。我竟然从中听出了一些美感,我发觉软件设计是个好东西,这种印象深深地印在了我的脑海中。

从那之后,我也会有意识地去找设计的书去读,会有意识地去反复思考设计的优劣。我经常问自己的一个问题就是,如果我把这段代码重写一遍,我该怎么做。久而久之,我几乎每次都能发现自己代码写得不够好的地方,找到那些值得改进的地方。

也正是因为这样,我的代码风格每隔一段时间,就会发生一些变化。尽管在外人眼中,我实现的功能都是差不多的功能。但我知道,它的设计已经变得更好了。因为它更容易测试了,也更容易扩展了。

对于一个好程序员来说,品味是尤为重要的。要想有一个好的品味,就一定要见过好东西。遗憾的是,大多数人在日常工作见到的代码都很难称得上有品味,唯一的优点就是可以运行。

所以,我们要多向好的开源项目学习,这是一种帮助我们打破限制的好方法。

开源项目有很多,但是很多人的关注点一般都是这些项目如何实现了一个功能,却少有人关注它的设计,这会让我们错过很多风景。我们可以先从一些不那么复杂的项目入手,关注它的设计。

如果让我推荐,我会推荐我熟悉的,而且让我能从中感受到美感的几个项目:

编写代码也是一门手艺,手艺是要不断打磨锤炼的。鸟巢的每个焊接处都镌刻着焊工的名字,因为主事者希望记录下来他们对这件历史工程做出的贡献。

程序员的工作天生也会被源码控制工具记录下来。所以,作为一个程序员,我希望自己写下的代码能成为自己的骄傲,而不是别人的槽点。唯有不断精进的手艺才能成为我们努力过的证明。

结束了吗?

结束了吗?

丘吉尔在阿拉曼战役庆功宴上发表的演讲中,说过这样一段话:这不是结束,甚至不是结束的开始,而可能是开始的结束。(Now this is not the end. It is not even the beginning of the end. But it is perhaps the end of the beginning.)

没错,我想说的是,这个专栏只是你学习软件开始的结束。

《软件设计之美》这个专栏只是帮助你开启了软件设计的大门,但能真正让软件设计成为自己的一部分,对每个人来说,都有很长的路要走。即便我写程序已经二十多年了,我依然不敢说,自己的程序已经写到无懈可击的地步,偶尔的新需求依然会让我陷入思索。

我对《软件设计之美》的预期,就是我可以把我体验到的思考乐趣告诉你,让你产生对于软件设计的兴趣。如果你希望学了这个专栏之后,还能更进一步地学习,不妨找一找我在专栏中推荐的书,几乎每一本都值得你去深入学习,而这个专栏已经给了你一张地图,保证你不会在茂盛的软件设计丛林中迷失。

与此同时,我也知道,《软件设计之美》在给你开启了新的知识大门之后,也让你产生了许多困惑。不要紧,即便这个专栏结束了,并不等于我为大家的服务结束了,你依然可以在专栏里留言提问,我会努力回复你的留言。

关于软件设计,我其实还有很多想说的东西。也许在后面,我还会把自己的一些思考与你分享。

在这个专栏的最后,我要特别感谢一下我的催稿小分队。疫情期间,我赋闲在家写作这个专栏。我自认为自己不是一个行动力超强的人,于是,我组织了一个催稿小分队,邀请了《10x 程序员工作法》的一些读者以及专栏相关的工作人员,一起监督我写稿。

每天向催稿小分队汇报进度,成了那段时间我的一大乐趣。催稿小分队的各路神仙每天的插科打诨也给我无聊的写稿生活平添了许多乐趣,有你们真好!

如果以后有机会,我会再来与你分享我对软件开发的理解,这次的《软件设计之美》之旅就暂告一段落了!

再见!

《软件设计之美》课程结束了,这里有一份毕业问卷,题目不多,希望你能花两分钟填一下。期待能听到你说一说,你对这个课程的想法和建议。