思维能力是比解决具体问题更重要的能力。问题也许各有不同,但思维方式可以复制和迁移。正所谓:"有道无术,术尚可求也,有术无道,止于术"。
引言
本书的首要目的就是打破“不知道自己不知道”的思维禁锢,把软件设计中会用到的各种思维能力显性化地呈现出来,让你意识到原来有这么多思维模型在软件设计中发挥着至关重要的作用。
尝试思考下面的问题
最初,我认为这样的问题很虚,工作完成就行了,不需要那么多道理。
然而随着时间的推移,我发现这的确是一个好问题。因为它可以区分出你是碰巧把事情做对了,还是你具备了一直做对事情的能力,二者是有本质区别的。碰巧做对,说明你的能力可能还不足,换一种情景,你就不一定能应付。因此,对于一个职场人来说,不仅要考查成绩,更重要的是考查能力。对从事脑力劳动的技术人员来说,“能力”主要指的是“思维能力”。
你是否还在认知盲区中?
认知水平有4个层次,从低到高依次是“不知道自己不知道、知道自己不知道、知道自己知道、不知道自己知道”。“不知道”并不糟糕,最糟糕的是“不知道自己不知道”,而因为缺少对自身思维的观察和培养,所以很多人对思维的认知尚处于“不知道自己不知道”的层次。
这种无意识会导致我们很多时候盲目地做事。虽然一些人“996”工作很辛苦,但也许大部分工作内容是无意义的重复,在工作过程中,思维能力并没有得到锻炼和提高。没有好的思维模型,再多的知识积累也是低水平的重复。成人学习的目的不是获取更多的信息量,而是学习更好的思维模型。
面向思维做事
基础思维能力
这部分主要介绍解决日常问题的基础思维能力。这些思维能力不受行业的局限。
-
比如我们在解决数学问题时需要动用抽象思维和逻辑思维;
-
结构化思维更多地被用在写作和表达中;
-
在当今信息爆炸的时代,每个人都需要有一些批判精神,这是批判性思维;
-
化繁为简是我们要一直追寻的目标,这需要具备简单思维;
-
面对困难,要有成长型思维;
01 抽象思维
抽象=抽离+具象
为了更直观地理解抽象,让我们先来看一幅毕加索的画。图的左边是一头水牛,是具象的;右边是毕加索的画,是抽象的。怎么样,是不是感觉自己一下子理解了抽象的含义?
图1-1
这种对细节的舍弃使得“抽象牛”具有更好的泛化(Generalization)能力。可以说,抽象概念更接近问题的本质。也就是说,所有的牛都逃不过这几根线条。
抽象的层次性
除抽象概念之外,另一个我们必须要深入理解的概念就是抽象的层次性。
回到毕加索的抽象画,如果映射到面向对象编程,抽象牛就是抽象类(Abstract Class),代表了所有牛的抽象。抽象牛可以被泛化成更多的牛,比如水牛、奶牛、牦牛等。每一种牛都代表了一类(Class)牛,对于每一类牛,我们可以通过实例化,得到一个具体的牛实例(Instance)。
图1-2
从这个简单的案例中,我们可以总结出抽象的3个特点。
(1)抽象是忽略细节的。抽象类是最抽象的,忽略的细节也最多,就像抽象牛,只是几根线条而已。在代码中,这种抽象既可以是抽象类,也可以是接口(Interface)。
(2)抽象代表了共同性质。类代表了一组实例的共同性质,抽象类代表了一组类的共同性质。对于上面的案例来说,共同性质就是抽象牛的那几根线条。
(3)抽象具有层次性。抽象层次越高,其内涵越小、外延越大,也就是说它的含义越小、泛化能力越强。比如,牛就要比水牛的抽象层次更高,因为它可以表达所有的牛,水牛只是牛的一个种类。
锻炼抽象思维能力
勤总结
对工作当中的事情做阶段性总结,相信你已经用到。这样不仅可以让我们加深理解,还可以提升抽象思维能力。
语文老师为什么总是要求我们总结段落大意、中心思想,现在回想起来,其实质就是帮助学生提升抽象思维能力。
领域建模训练
我们可以对自己工作中的问题域进行建模,当然也可以通过研究一些优秀源码背后的模型设计来学习如何抽象、如何建模。除此之外,我们还可以进一步深入思考:它为什么要这么抽象?这样抽象的好处是什么?
02 逻辑思维
逻辑就是关系
“无逻辑”就是没有建立起事物之间的正确关系,即“有逻辑”就是能建立事物之间的正确关系。
逻辑链
通常情况下,你会觉得什么样的人说话特别有深度呢?是不是那种他一说话会让你有茅塞顿开的感慨,甚至忍不住发出“Aha”的惊叹的人?这种人通常会有深度思考的习惯,他们的逻辑链比普通人要长,更擅长深度思考,因此他们可以挖掘事物的根本原因,推断事物的深远发展结果。
在现实中,不是所有的逻辑链路都是简单的“因为……,所以……”,而是有可能在“因”和“果”两个方向上进行拓展。
5Why思考法
大多数情况下,我们的思维逻辑链都比较短,短就意味着肤浅,找不到问题的根本原因。延长思维逻辑链的方法之一是5Why思考法,它能够帮助我们找到问题的根本原因。
图2-1 思考的逻辑
凡事我们要多问几个“为什么”,有一个著名的提问法叫作5Why提问法。对于任何问题,如果你能扛得住5个以上的“为什么”,那么说明你真正理解了这个问题。
在我们的实际工作中也是如此,凡事多问几个为什么,做到知其然,亦知其所以然。这种触达问题本质的思考会显著提升我们的认知水平和解决问题的能力。
5So思考法
5So思考法,是指对一个现象连续追问其产生的结果,以探求它对未来可能造成的深远影响。凡事多问几个“所以呢”,能让我们拥有推演事物长远影响的能力。
图2-2 5Why和5So对比
如果说5Why是在“因”的方向上进行拓展,回溯问题的根本原因,那么5So就是在“果”的链路上进行拓展,旨在洞悉事物未来的发展趋势。
当年,年轻的马云访问美国,在朋友家第一次接触到互联网,他在电脑上小心翼翼地输入“beer”并按下回车键,电脑上出现了美国的啤酒、日本的啤酒、德国的啤酒……唯独没有中国的啤酒,这个场景深深触动了马云。
如果我们站在马云的角度,他当时内心的思考过程也许是这样的。
“互联网这么方便,可以快速获取这么多信息,所以呢?”(1So)“
互联网技术就是未来。”“所以呢?”(2So)
“中国当前还没有像样的互联网公司。”“所以呢?”(3So)
“随着改革开放,中国必将拥有大型互联网公司。”“所以呢?”(4So)
“我回国后要顺应大势,创办中国的互联网公司。
”在这样的背景下,马云开启了他的第一次创业——创办中国黄页。
03 结构化思维
从无序到有序
结构化思维是一种以逻辑(事物内在规律)为基础,从无序到有序搭建结构的思维过程。如下图,其目的是降低复杂度和认知成本,因为大脑更喜欢概念少、有规律的信息。
图3-1 结构思考
金字塔中逻辑
在金字塔结构中,总体上有两个方向的逻辑关系,即纵向逻辑关系和横向逻辑关系。如图3-1,一个好的金字塔结构,需要在纵向关系上满足结论先行、以上统下;在横向关系上,满足归类分组、逻辑递进这4个基本原则。用一句话概括,就是“论证类比”。
(1)纵向关系:纵向是层次关系,上一层思想是对其下一层思想的概括,下一层是对上一层的解释和支持。
• 结论先行(“论”):所谓结论先行,就是要先抛结论。这一点在与人沟通的时候尤其重要,就像很多人铺垫了半天,也不说结论。写代码也一样,主方法是中心论点,子方法是对主方法的结构化分解。
• 以上统下(“证”):金字塔是一种层次结构,上一层是对下一层的统领和抽象,比如水果是对苹果、橘子的抽象,所以在上一层。
(2)横向关系:横向是关联关系,每组中的思想必须属于同一逻辑范畴,并按照逻辑顺序组织。
• 归类分组(“类”):将内容相似的思想归为一类,为进一步归纳抽象做好准备。
• 逻辑递进(“比”):分组中的思想需要有逻辑递进关系,即它们必须属于同一个逻辑范畴,且满足一定的逻辑顺序。
如何搭建结构
我们在解决问题的时候,一般有两种方法:
-
一种是从目标出发,沿着不同的路径分解,探求问题的答案;
-
另一种是把各种信息聚合起来,得出一个正确结论或解决方案。
这两种方法也是我们搭建金字塔结构时仅有的两种方法:
-
一是自上而下地搭建金字塔结构,即问题分解,也叫作疑问回答分解;
-
二是自下而上地搭建金字塔结构,即概括总结做聚合。
04 批判性思维
未经审视的人生不值得过。
——苏格拉底
理解批判
批判性思维是我们较为缺乏的一种思维能力,这在一定程度上和我们的文化有关系。我们的文化比较讲究经验和直觉,而批判性思维比较注重理性和逻辑;我们的文化比较讲究包容和认同,而批判性思维常常需要反驳和质疑。尤其是对自己的质疑,这是非常困难的,不仅需要理性,更需要勇气。然而在今天,批判性思维已经越来越重要,主要有以下两个方面的原因。
-
信息太多,我们的辨别能力需要加强。
-
选择变多,我们需要更加理性和谨慎地做出决策。
05 维度思维
这个世界不是只有是非黑白,还有很多灰色地带。
——白岩松
当问题变得复杂,其复杂性往往不是在一个维度上,而是在多个维度上。
多维度思考
一个人能进行思考的维度越多,对一个问题的理解就会越全面、越深入,进而超越那些只会单一维度思考的人。
一个人的思维层级与其思考的维度是正相关的。这一点可以通过我们的日常语言得到佐证,如图5-1所示。当我们说这个人很“轴”“一根筋”的时候,实际上是在说他只有一维的线性思维;高手的思考会更加“全面”,因为涉及“面”,所以至少是两个维度的思考;而真正的高手,其思考是成“体系化”的,“体”至少是三维的,也就是说他考虑到了“方方面面”。
图5-1 思维的维度
06 分类思维
设计就是分类。
——“微信之父”张小龙
分类的本质
寻找共同属性:本质上就是对象之间的交集。这个交集要么是共同的属性,要么是共同的行为。
分类的方式
经典分类方式:“所有具有某一个或某一组共同属性的实体构成了一个分类,而这个属性对于定义这个分类是必要且充分的”。对于可以枚举的属性,我们通常可以比较容易地按照属性分类,比如已婚人士和未婚人士,因为关于是否结婚,只有“是”和“否”两个选项;再比如红色的苹果和绿色的苹果,颜色也是可以枚举的。
概念聚集分类:概念聚集是经典分类的变种,这种分类首先是概念描述,然后根据这些描述对实体进行分类。例如,我们先声明了“爱情歌曲”这个概念,但它超越了一个属性,因为歌曲的“爱情歌曲”特质不是可以被准确测量的东西,我们只能通过某个歌曲更像一首爱情歌曲来对其进行分类。概念聚集更多地代表了对象聚集的可能性,同样,我们在电商平台中看到的“猜你喜欢”也是如此。
最后,如果让你对整个互联网产业进行分类,你会怎么分呢?
07 分治思维
要把大象装进冰箱,拢共分几步?
——小品《钟点工》
分治的价值在于,我们不应该试着在同一时间把整个问题域都塞进自己的大脑,而应该试着以某种方式去组织问题,以便能够在一个时刻专注于一个特定的部分。这么做的目的是尽量减少在任意时间内所要思考问题的复杂度。
解决问题的黄金三步
-
第一步:定义问题,弄清楚我们要解决的问题究竟是什么。
-
第二步:分解问题,把一个大问题拆解成多个子问题。
-
第三步:合并问题,对拆解后的子问题,我们有必要再进行一次合并归类。
图7-1 解决问题黄金三步
08 简单思维
一旦做到了简洁,你将无所不能。
——乔布斯
减少选择
简单的做法往往难以实现,一方面受制于工程师的认知和能力,有时无法把复杂的问题抽丝剥茧进行简化;另一方面,迫于晋升的压力,特别是在大公司,要想法设法地证明自己的技术价值,重复造轮子,做所谓的技术沉淀,从而把简单的事情复杂化。
把事情做简单的确是一件不容易的事情,它需要我们有打破常规、不破不立的勇气;有洞察事物本质、化繁为简的能力。当然,它更需要我们有一颗不骄不躁、朴素的匠心。 作为有追求的程序员,我们应该尽量把复杂留给自己,把简单留给他人,而不是反过来。
简单不是简陋。简单是一种洞察问题本质、化繁为简的能力,简陋是对问题不加思考地简单处理,二者有本质区别。简单需要我们付出很多的精力,对问题深入思考,进行熵减逆向做功。往往需要经历简单—复杂—简单的演化过程。
09 成长性思维
想要让自己获得成长和改变,就一定要学会用成长型思维去看待和处理问题,其关键在于不要自我设限。
比如,总是觉得自己没有准备好。事实上,无论什么事情,我们都很难一次性做到尽善尽美,通常只能是通过一次次的试错、一次次的调整,才能让事情趋近于完美。
又比如,觉得为时已晚而止步。“种一棵树的最好时间是十年前,其次是现在”,只要你想、你愿意,什么时候开始都不晚。
持续精进
人生的进度条,不会出现从0到1的突然跃迁,而是要0.1%、0.2%地慢慢往前递进。不管是1万小时定律,还是成长型思维,都在教导我们做好“持久战”的准备。
图9-1 精进的力量
守住平常心
也许你也时常能听到这样的说法:“某某炒股赚了100万。”“谁谁都晋升到副总了,你都30岁了,怎么还在写代码?”在这个时代,人极易变得浮躁。也难怪,同龄人之间巨大的竞争压力,家庭沉重的经济负担……即使是“佛系”的技术男,也难逃世俗的漩涡。
平和的心态是我们持续成长的基础,因为人的专注力是有限的,内心平和的人可以更多地专注在学习和工作上;而内心挣扎的人,需要支配更多的精力去应付内耗,那么投入在学习和工作上的精力自然就少了。因此,拥有一颗平常心,不患得患失,不急功近利,非常重要。这样在你遇到困难时,才知道怎样与自己和解,并知道如何应对焦虑,把精力专注在解决问题而不是内耗上。
专业思维能力
这部分主要结合软件行业的特点介绍其特有的专业思维能力。比如,契约思维、模型思维、工具化思维、量化思维、数据思维、产品思维等都是在软件领域中非常重要且经常会用到的思维能力。
10 解耦思维
人生最难熬的痛苦,就是你跟本该远离的东西纠缠在了一起。
依赖倒置解耦
依赖倒置是SOLID设计原则中的“D”,全称是Dependence Inversion Principle,即依赖倒置原则,其定义如下。
-
(1)上层模块不应该依赖底层模块,它们都应该依赖于抽象。(High level modules should not depend upon low level modules.Both should depend upon abstractions.)
-
(2)抽象不应该依赖于细节,细节应该依赖于抽象。(Abstractions should not depend upon details.Details should depend upon abstractions.)
图10-1 依赖倒置解耦
可是为什么要依赖倒置呢?反转依赖的方向,从依赖具体到依赖抽象又有什么好处呢?
抽象比具体更灵活
例如,小张是某高校计算机专业的应届毕业生,他热爱编程,学习成绩也很好,期望毕业之后能去阿里巴巴工作,并对自己信心十足,在找工作之前就放出狠话——“非阿里不去”。
然而天不遂人愿,小张在面试阿里的过程中遇到了一些麻烦,HR觉得他比较傲慢,并没有给他发offer。与此同时,小张在华为的面试倒还挺顺利的,拿到了令人满意的offer。这下就尴尬了,难道就为了一句“非阿里不去”而拒绝华为这么好的机会吗?
这么做显然是不明智的,而起因正是因为小张一开始把话说得太满(太具体),没有给自己回旋的余地。如图10-2所示,实际上,作为一名应届毕业生,小张想要的无外乎只是一份好工作而已,具体这个工作是在阿里、华为,还是腾讯,这并不是最关键的。
图10-2 依赖具体和依赖抽象比
11 契约思维
人是生而自由的,但却无往不在枷锁之中。——卢梭
“写代码是自由的,但无往不在规则之下。”这里的规则包括工程师必须要遵守的程序语言语法、编程规范,以及协议标准。
契约思维有规范和标准两个方面的重要价值。
-
(1)规范价值:一致性可以降低认知成本和复杂度,一个系统如果没有任何的规范约束,那么呈现出来的结果就是混乱。面对混乱,再优秀的程序员也会寸步难行。
-
(2)标准价值:大规模社会分工协作离不开标准,如果螺丝钉没有标准,那么每个企业就不得不自己生产适合自己的螺丝钉。同样,如果浏览器没有标准,那么针对不同的浏览器的同一个功能,就要写多份不同的代码。所以我们说,“一流的企业定标准,二流的企业做品牌,三流的企业卖产品”。
12 模型思维
在软件工程中,有两个高阶工作,一个是架构,另一个是建模。如果把写代码比喻成“搬砖”,那么架构和建模就是“设计图纸”了。相比于编码,建模的确是对设计经验和抽象能力要求更高的一种技能。例如,在当前很火的人工智能和机器学习领域,建模就是最难,也是最重要的工作。
领域模型
领域模型将现实世界抽象为了信息世界,把现实世界中的客观对象抽象为某一种信息结构,而这种信息结构并不依赖于具体的计算机系统。领域模型不是对软件设计的描述,和技术无关。
领域模型对软件开发至关重要。因为从本质上来说,软件开发就是从问题空间到解决方案空间的映射转化,而领域模型是连接问题和解决方案的桥梁。
图12-1 领域模型的桥梁作用
领域模型与数据模型
领域模型关注的是领域知识,是业务领域的核心实体,体现了问题域中的关键概念,以及概念之间的联系。领域模型建模的关键在于模型能否显性化、清晰地表达业务语义,其次才是扩展性。
数据模型关注的是数据存储,所有的业务都离不开数据,以及对数据的CRUD。数据模型建模的决策因素主要是扩展性、性能等非功能属性,无须过多考虑业务语义的表征能力。
二者的确有一些共同点,有时领域模型和数据模型会长得很像,甚至会趋同,这很正常。但更多的时候,二者是有区别的。正确的做法应该是有意识地把这两个模型区别开来,分别进行设计,因为它们建模的目标有所不同。数据模型负责数据存储,其要义是扩展性、灵活性、性能;而领域模型负责业务逻辑的实现,其要义是业务语义显性化的表达,以及充分利用面向对象的特性增强代码的业务表征能力。
图12-1 领域模型和数据模型的区别
容易犯的错误是: 一个是错把领域模型当数据模型,另一个是错把数据模型当领域模型。切记不要把这两种模型作用搞混。
13 工具化思维
懒人的逻辑中也有其合理的一面,勤劳奋斗的逻辑中也必定有其荒唐的一面。——张方宇
我们可以把“懒”分为3个境界。
-
(1)最低境界是“实在懒”,拖延症,不到万不得已,不去完成任务。
-
(2)其次是“开明懒”,迅速做完不喜欢的任务,以摆脱之。
-
(3)最高境界是“智慧懒”,使用工具完成不喜欢的任务,以便再也不用做无谓的重复工作,从而一劳永逸。
你我都是“工具人”
这里的“工具人”,说的是我们都是可以制造工具的人。软件工程师和其他工程师的重要区别之一在于需要自己制造工具。而软件工程师的工作是写代码,工具所需要的要素也是代码,因此制造工具是其能力范围内的事情。
很多程序员每天要重复做N次这样的工作,这时不愿意做机械重复工作的“懒人”开始反问自己:我为什么要一遍一遍地重复敲这些命令呢?这些手动操作都是必需的吗?测试是否可以自动化呢?部署是否可以自动化呢?
由此可见,工具化并不是可有可无的,其本身就是我们工作的一部分。从某种意义上来说,自动化运维、DevOps就是通过工具化不断提升研发效率的成果。
14 量化思维
No measurement,no improvement.(没有量化,就无法优化。)——“科学管理之父”温斯洛·泰勒
量化工作本身是一件非常困难和极具挑战的事情,但量化思维要求我们不要轻易放弃关于量化的思考和尝试。没有量化的目标,就像是断了线的风筝,没有方向,缺少指引,飞到哪里是哪里,而量化后的目标可以为我们清楚地指引方向。
量化的步骤
-
(1)定义指标:仔细分析问题,找到那个可以用来量化问题的关键指标。
-
(2)将指标数字化:围绕关键指标,明确需要哪些数据来实现指标的计算,通过数据收集、数据存储、数据展现去呈现指标,也就是数字化的过程。
-
(3)优化指标:有了数据指标之后,要围绕指标数据迭代优化,达成业务目标。
15 数据思维
一切业务数据化,一切数据业务化。——阿里巴巴
用数据说话
数据如此重要,涉及的内容那么多,工程师需要对数据掌握到什么程度才算合格呢?我认为,我们不一定要做到像数据分析师(Data Analyst, DA)那样精通数据分析,也不一定要像算法专业的博士那样精通算法,但是至少要做到以下两点。
-
(1)要了解公司的数据技术体系。比如,对大数据处理框架、数据仓库、数据分析等有基本的认知,知道其背后的基本原理和运行逻辑。有了这个认知之后,我们就能更好地与数据工程师、数据分析师、商业智能分析师等人员进行分工协作。
-
(2)要知道用数据去说话。我们要学会用数据作为决策的依据,而不是靠猜测、“拳头”或“屁股”去做决策。
“用数据说话”的效果最好,最有说服力。
16 产品思维
产品就是用来解决某个问题的东西。——苏杰《人人都是产品经理》
工程思维和产品思维是不一样的。工程师追求技术至上,产品经理追求商业价值和用户体验;工程师关注细节,产品经理关注全局;工程师关注How(如何做),产品经理关注Why(为什么)。结合两种思维方式,可以让思考更全面和系统化。
作为技术人员,我们必须要具备一定的产品思维,这样才能辨别产品需求的真伪,把伪需求挡在外面,从而可以把时间放在真正有价值的项目上,少做一些无效的投入。对于团队的技术负责人来说,这种把关尤为重要。
另外,产品思维是工具化思维的进阶,对于一些好用的技术工具,我们可以通过产品化、平台化让其更易用,发挥更大的价值。
图16-1 产品的价值
词语解释
内涵: 适合这个概念的一切对象的范围
外延: 所反映的对象的本质属性的总和
其他推荐文章
学会自我投资:美团四大名著之<高效能人士的七个习惯>
附录
《程序员的底层思维》