参与相关讨论,请在公众号回复关键词:读者群。
未经审视的人生不值得过。
——苏格拉底
在我的工作经历中,会发现有一些技术人员成长很快,能够迅速成为团队的骨干,也有一些技术人员总是在原地踏步,工作十年和工作一年的区别并不大。渐渐地,我发现这些优秀的技术人员都有一些共同的特质和素养,从而帮助他们不断进步,脱颖而出。
在软件的世界里没有“银弹”,在技术人的众多素养中,“不教条”占有重要的地位。我在工作过程中看到过太多教条主义的错误,例如,我曾见过一个团队为了做微服务,将本来的一个不大的应用拆分成了几十个微服务应用。
教条的主要原因是我们还停留在有样学样的阶段,导致我们忘记了软件的第一性原理是“控制软件复杂度”。但凡能提高代码可读性、可扩展性和可维护性的方法,都是值得考虑的,并不一定要拘泥于某种特定的开发过程或者编程范式。
就像Effective Java一书的作者Joshua Bloch说的,“同大多数学科一样,学习编程艺术首先要学会基本的规则,然后才能知道什么时候去打破规则”。
选择软件开发过程绝不是要么瀑布(Waterfall),要么敏捷(Agile)这么简单。实际上,软件开发的生命周期风格类似一个连续光谱——有从瀑布式到敏捷,以及它们之间的多种可能性。
以我的工作经验来看,软件开发过程并不是软件工程中最大的障碍,不是你花了大量时间在需求分析和设计上,项目就一定会失败;也不是你每天早上花5分钟讨论“昨天做了什么,遇到什么问题,今天做什么”,项目就一定能成功。
敏捷开发是基于迭代模型发展起来的一套软件开发指导原则。我们在实际操作中应重视指导原则,弱化方法论。
就像Scrum的创始人Jeff Sutherland在其敏捷宣言中说的,“我建立Scrum模型就是为了把敏捷的价值观糅进一套工具集以便于更好地实践,敏捷模型没有方法论。”
敏捷还有一个误区,就是弱化设计。其实我对此事的认知也是有一个过程的,我是敏捷的极力拥护者,非常感激敏捷让我们摆脱了软件能力成熟度集成模型(Capability Maturity Model Integratio,CMMI)的沉重枷锁。凡事过犹不及,实施敏捷就可以“无设计”吗?设计可以在敏捷过程中自然涌现吗?实践告诉我们,似乎不能。就像盖房子,在盖之前要打牢地基,如果地基还没完工就匆忙建造房子,那么就很难摆脱糟糕的地基了。类似地,系统架构中的基础改动起来会变得困难,从而不得不做出各种妥协和临时方案。
因此,我们需要在大设计和无设计之间找到一种平衡。一个软件从无到有,不管你是瀑布、迭代,还是敏捷,一般会经历下面的过程。
(1)需求:对于系统该做什么,建立并保持与客户和其他涉众的一致意见,定义系统的边界。
(2)分析与设计:将需求转化为系统设计,设计将作为在特定实现环境中的规格说明,包括逐渐形成一个健壮的系统架构,建立起系统不同元素必须用到的共同机制。
(3)实现:编码、单元测试以及对设计进行集成,得到一个可执行的系统。
(4)测试:对实现进行测试,确保它实现了需求,通过具体的展示来验证软件产品是否像预期的那样工作。
(5)部署:确保软件产品能被它的最终用户使用。
基于此,我推荐一种综合了瀑布模式、迭代模式和敏捷思想的软件开发过程。在此提倡根据迭代所处阶段的不同,在不同科目上花不同的时间,如图10-1所示,灰色部分代表一个阶段在当前迭代中所花时间的比重。
图10-1 改良的迭代开发
一提到事务脚本(Transaction Script)和DDD,人们就习惯性地给它们扣上贫血[1]和充血的帽子。简单来说,贫血模式提倡模型对象只包含数据,并提供简单的Getter和Setter;而充血模式提倡数据和行为放在一起,是一种更加面向对象的做法。两种模式都有自己的道理,也都有人支持。
在我看来,这种争执是没有必要的,因为没有抓住问题的本质。问题的核心不在于行为和数据是否在一起,而在于你能否有效地控制复杂度。如果你有很好的面向对象思维,使用贫血也可以写出好的代码;没有面向对象思维,即使采用DDD,也会陷入复杂性的泥潭。
纠结于贫血还是充血,一方面是因为没有抓住问题的本质,另一方面也源于一种非黑即白的教条思维。就像4.2节中的Rectangle案例所展示的,行为和数据是否放在一起,只是表现形式的差别,并不是用来区分面向对象和面向过程的关键区别。
在业务发展早期,因为用户少、流量少,功能相对简单。如图10-2所示,基本上单体(Monolithic)应用架构就足以支撑业务的发展。
图10-2 单体应用架构
然而,随着业务的发展和用户的增加,单体应用的局限性开始显现。具有水平扩展性(scale out)的分布式系统架构几乎已经变成互联网公司的标配,如图10-3所示。
图10-3 分布式应用架构
虽然面向服务的架构(Service Oriented Architecture,SOA)和微服务有一统天下之势,但是并不代表单体架构就会退出历史舞台,特别是在中台概念提出来以后。中台要求通过集中式的中台管控来提升软件系统的复用,避免趋同的业务重复造轮子的现象。中台的目的就是要通过中台能力来赋能前线业务,提升对前线业务的支撑效率,其架构如图10-4所示。
图10-4 中台架构
可以看到,中台虽然也是对业务进行聚合,但并不是对单体架构的简单回归,而是综合了分布式理念之后升级版的“超级单体”。正是这种不教条和辩证的发展思维,才推动互联网架构不断地向前发展演进。
批判性思维(Critical Thinking)是一种谨慎运用推理去断定一个断言是否为真的能力。它要求我们保持思考的自主性和逻辑的严密性,不被动地全盘接受,也不刻意地带着偏见去驳斥一个观点。批判性思维也是一项能够被习得,并且通过训练和运用来提高的能力。
技术人员虽然有很强的逻辑推理能力,但不见得都有很强的逻辑思维,我也是如此。在知晓批判性思维之前,我曾吃过很多亏,明知道对方在强词夺理,可就是找不到很好的反驳理由。无论是在公司和同事争辩,还是在家里和老婆斗嘴,几乎没有赢过。后来我学习了一些批判性思维的知识,情况才有所改观,可以抓住对方的一些逻辑漏洞和推理谬误进行反驳,这使我在职场上拿回了不少话语主动权。不过在家里,我依然是输多赢少,后来我才发现,原来家不是一个讲逻辑的地方。
关于训练批判性思维的书有很多,我重点推荐两本,一本是尼尔•布朗写的被誉为批判性思维领域经典读物的《学会提问》,另一本是樊登读书会推荐的《思辨与立场:生活中无处不在的批判性思维工具》。我在读这两本书的时候,经常会有aha moment(顿悟时刻),真的很有收获。
在《学会提问》一书中,有这样一个案例。
小张:“小王真不是个男人,酒吧里那个醉汉威胁说要揍他一顿,他吓得屁滚尿流。”
小李:“他要不是男人,你怎么解释他身上那些鼓鼓的二头肌呢?”
你觉得小李的话有道理吗?如果你觉得有点道理,但又觉得有点不对劲,那么就应该去好好读读这本书。这里小李犯了一个典型的推理谬误——偷换概念谬误(Equivocation Fallacy),小张说的“男人”是指“男子气概”,而小李说的“男人”是指“男人生理”,这两个概念是不一样的,这就是问题所在。
成长的过程中不可能是一帆风顺的,肯定会有痛苦、有阻力、有挫折。面对逆境,我们应该怎么做?有些人也许不堪重负,就此沉沦了,而有些人可以越挫越勇,把每一次失败都当成学习的机会。研究发现,成长型思维(Growth Mindset)和固定型思维(Fixed Mindset)会极大地影响我们面对逆境的处理方式。我在最低迷的时候,正是成长型思维帮我渡过了难关。
斯坦福大学心理学教授卡罗尔•德韦克在经过数十年的研究后,发现了思维模式的力量。她在《终身成长》中提醒我们:我们获得的成功并不是能力和天赋决定的,更多受到我们在追求目标的过程中展现的思维模式的影响。
成长型思维和固定型思维体现了应对成功与失败、成绩与挑战时的两种基本心态。你认为才智和努力哪个更重要、能力能否通过努力改变,决定了你是会满足于既有成果,还是会积极探索新知。通过了解自己的思维模式并做出改变,人们能以最简单的方式培养对学习的热情,以及在任何领域内取得成功都需要的抗压力。
具有成长型思维的人相信自己可以通过学习来提升自我,相信学习和成长的力量,相信努力可以改变智力和能力。我们可以通过图10-5所示的对比来判断一个人是“成长型思维”还是“固定型思维”。
图10-5 成长型思维和固定型思维对比图
我曾经就是一个典型的固定型思维的人,在遇到困难和挫折时很容易引发自我怀疑和自我否定。在了解了成长型思维之后,我开始逐渐转变思维模式,会用更加理性的态度看待一时的成败得失,内心坚定地相信成长和学习的力量。从某种意义上来说,你正在读的这本书也是我在习得了成长型思维之后,才得以写出来的。
技术人员的工作面临着很多的挑战,我们需要具备成长型思维才能应对工作和生活中的压力,这样在遇到问题时,我们才不会轻言放弃,而是会积极主动地去学习,去寻找解决方案。即使最终还是失败了,我们也不会一蹶不振,而是把失败当作学习的机会。
在日常工作中,我们时常会碰到有的人讲一件事情的逻辑非常混乱,前后没有逻辑性关联,甚至无法把一件事情说清楚。思维混乱是缺少结构化思维的典型表现。实际上,我们不仅在表达上要结构化,在分析问题时更要有结构化思维,这样才能分析得更全面、深刻。
什么是结构化思维呢?我给结构化思维的定义就是“逻辑+套路”。
所谓逻辑,是指结构之间必须是有逻辑关系的。例如,你说话时用“第一、第二、第三”这个逻辑顺序是合理的,而如果用“第一、第二、第四”就会显得很奇怪。实际上,组织思想的逻辑只有4种。
(1)演绎顺序:比如“大前提、小前提、结论”的演绎推理方式就是演绎顺序的。
(2)时间(步骤)顺序:比如“第一、第二、第三”和“首先、再者、然后”等,大多数的时间顺序同时也是因果顺序。
(3)空间(结构)顺序:比如“前端、后端、数据”和“波士顿、纽约、华盛顿”等,化整为零(将整体分解为部分)等都是空间顺序。在做空间分解时,要注意满足“相互独立,完全穷尽”(Mutually Exclusive Collectively Exhaustive,MECE)原则。
(4)程度(重要性)顺序:比如“最重要、次重要、不重要”等。
只要我们的思想和表达在这4种逻辑顺序之内,就是有逻辑的,否则就是没有逻辑的。
套路是指我们解决问题的方法论、路径和经验。比如,5W2H分析法就是非常好的,是可以帮助我们分析问题的一个“套路”。试想一下,面对任何一个问题,你如果都能从“Why、Who、When、Where、What、How和How much”(如图10-6所示)这7个方面去思考,是不是比不知道这个方法论的人用点状模式思考要全面得多呢?
图10-6 5W2H问题分析法
逻辑是一种能力,而套路是方法论、经验;逻辑属于道,而方法论属于术。二者都很重要,只有熟练地掌握二者,我们才能有更好的结构化思维。接下来,通过两个案例来介绍结构化思维在实际工作场景中的应用。
想象这样一个场景,你刚刚入职一家新公司或者转岗到一个新团队,作为一个技术人,你将如何落地开展工作呢?
这里就能用上结构化思维来帮助我们理清思路,从而有条不紊地开展工作。要知道对一个企业来说,核心要素无外乎就是业务、技术和人。我们所要做的就是如何去熟悉业务、熟悉技术、熟悉人,然而每一部分又可以进行进一步的结构化拆解,如图10-7所示。
图10-7 落地新团队的策略
(1)了解产品形态:任何一个团队都有自己要负责的产品,申请一个测试账号去用一下产品,是熟悉产品比较好的方式。
(2)了解业务流程:任何业务都有自己的业务流程,而业务流程中的核心是信息流。我们可以通过人员采访了解关键节点的信息输入和信息输出;通过画一些泳道活动图来理清楚系统的主要角色,以及它们之间的交互关系。
(3)走访客户:通过走访客户,我们可以获得业务的第一手资料,更加贴近业务和客户诉求。
(1)了解系统架构:可以让团队的技术人员介绍他们当初做系统设计和架构时的思路。
(2)了解领域模型:查看关键的核心表结构和系统API,快速了解系统的领域模型。
(3)了解代码结构:下载系统工程,熟悉整个工程结构和模块职责;以一个最重要的流程为入手点,阅读代码,看清楚核心的执行逻辑;做一个小需求,掌握相关的流程和权限。
(1)了解组织结构:查看公司的组织树,知道公司大概是如何运作的,以及哪些是关键人(Key Person,KP)。比如,一个典型的电商公司会包括产品部、运营部、销售部、技术部、人力资源部、财务部和法务部等。
(2)了解人员角色:了解公司都有哪些岗位,以及各岗位的职责范围。
(3)勤沟通:找出和自己工作息息相关的岗位,比如产品和运营,积极和这些同事沟通,向他们请教业务问题,多多交流。这样既可以建立良好的人际关系,也可以更快地熟悉业务。
我在阿里巴巴已经做了多年的晋升评委,发现很多人都缺乏结构化思维,讲着冗长的PPT,却不能很好地把一件事情说清楚。实际上,做工作汇报或者述职是很容易结构化的。
最清晰和实用的结构化表达是“提出问题,定义问题,分析问题,解决问题,最后展望未来”。如果按照这个逻辑顺序去阐述一件事情,会比不知道这个“套路”的效果好得多。这也是麦肯锡常用的解决问题的框架。
另一个有用的思维框架是“zoom in/zoom out”。我们说事情时,应该像电影镜头一样,先从远拉近,再由近拉远。“zoom in”是先从宏观背景开始,首先让大家知道你的事情发生的背景,为什么这件事情很重要?然后讲到具体细节,怎么做成的?解决了什么问题?后端思考是什么?最后“zoom out”,从细节调回到整体,结果是什么?带来的客户价值是什么?你对未来的思考是什么?
可以看到,这些结构化的方法论可以帮助我们做到事半功倍,经常锻炼结构化思维可以极大地提升我们的职场竞争力。
本文选自《代码精进之路:从码农到工匠》,作为建飞的朋友和读者,特别推荐本书。
《代码精进之路:从码农到工匠》
张建飞
本书是一本专门为专业程序员而写的书,主线是介绍如何化解代码复杂度,帮助程序员写出可读性好、可维护性好的代码。
本书共有13章内容,主要分为技艺部分、思想部分和实践部分。技艺部分详细介绍了编程技巧和方法论,并配以详尽的代码案例,有助于读者提高编写代码的能力,优化代码质量。思想部分主要包括抽象能力、分治思想,以及程序员应该具备的素养等内容。实践部分主要介绍了常见的应用架构模式,以及COLA架构的设计原理。
最后再给大家安利一场直播分享
本周三晚19:00,博文视点直播间聚集云风、陈皓、唐巧、孙玄、程军5位
国内神级程序员大咖,现场论道,妙解趣谈,进行关于传奇程序员修炼之道
主题的分享。
l 领军人物亲述从小工到专家
l 程序员务实最高境界之我见
l 宗师相对论与现场答疑解惑
强烈推荐一波!建议大家一定不要错过!
进入读者群讨论,公众号后台回复:读者群
进入读者群讨论,公众号后台回复:读者群
- END-
往期推荐
从业务架构梳理到技术架构设计
DDD如何讲清楚,做出来?
技术琐话
以分布式设计、架构、体系思想为基础,兼论研发相关的点点滴滴,不限于代码、质量体系和研发管理。本号由坐馆老司机技术团队维护。