26 作为程序员,你也应该聆听用户声音

在前面的专栏内容中,我们讨论过几次与产品经理的交流:你应该问问产品经理为什么要做这个产品特性,要用 MVP(最小可行产品)的角度,衡量当前做的产品特性是不是一个好的选择。

但还有一个问题可能困扰着我们:怎么判断产品经理说的产品特性是不是用户真的需要的呢?

很多时候,产品经理让你实现一个产品特性,你感觉这么做好像不太对,却又说不出哪不对,想提出自己的看法,却不知道从哪下手。

之所以会遇到这样的问题,一个重要的原因就是,你少了一个维度:用户视角,你需要来自真实世界的反馈

吃自家的狗粮

产品经理无论要做什么,他都必须有一个立足的根基:为用户服务。

所以,如果你了解了用户怎么想,你就有资本判断产品经理给出的需求,是否真的是用户需要的了。

而作为一个程序员,欠缺用户视角,在与产品经理的交流中,你是不可能有机会的,因为他很容易用一句话就把你打败:“这就是用户需求。”

很多程序员只希望安安静静地写好代码,但事实上,对于大多数人来说,安安静静是不太可能写好代码的,只有不断扩大自己的工作范围,才可能对准“靶子”。

今天我们讨论的角度,就是要你把工作范围扩大,由听产品经理的话,扩大成倾听用户的声音。

作为程序员,你应该听说过一个说法“Eat your own dog food”(吃自家的狗粮)。

这个说法有几个不同的来源,都是说卖狗粮的公司真的用了自家的狗粮。

从1988年开始,这个说法开始在 IT 行业流行的,微软的保罗·马瑞兹(Paul Maritz)写了一封“Eating our dog food”的邮件,提到要“提高自家产品在内部使用的比例。”

从此,这个说法在微软迅速传播开来。

如今,自己公司用自己的产品几乎成了全行业的共识。抛开一些大公司用这个说法做广告的因素,不断使用自家的产品,会让你多出一个用户的视角

在挑毛病找问题这件事上,人是不需要训练的,哪里用着不舒服,你一下子就能感受到。

所以,不断地使用自家产品,你自己就是产品的用户,这会促使你不断去思考怎么改进产品,再与产品经理讨论时,你就自然而然地拥有了更多的维度。

比如,前面在讨论 MVP 时,我曾经讲过一个我做 P2P 产品的经历。

在这个项目中,我就作为用户在上面进行了一些操作。当自己作为用户使用时,就发现了一些令人不爽的地方。

比如,一开始设计的代金券只能一次性使用,如果代金券金额比较大,又没那么多本金,只能使用代金券的一部分,就会让人有种“代金券浪费了”的感觉。

于是,我就提出是不是可以把代金券多次使用。

很快,产品就改进了设计。这种改进很细微,如果你不是用户,只从逻辑推演的角度是很难看到这种差异的。

当你吃不到狗粮时

不过,不是每家公司的产品都那么“好吃”。“吃自家狗粮”的策略对于那些拥有“to C”产品的公司来说,相对是比较有效的。

但有时候,你做的产品你根本没有机会用到。

我曾经与很多海外客户合作过,我做的很多产品,自己根本没有机会使用。比如,我做过五星级酒店的审计平台。

除了能对界面上的内容稍微有点感觉之外,对于使用场景,我是完全不知道的。

如果没有机会用到自己的产品,我们该怎么办呢?

我们能做的就是尽可能找机会,去到真实场景里,看看用户是如何使用我们软件的

比如,做那个酒店审计平台时,我就和客户一起到了一家五星级酒店,看着他们怎样一条一条地按照审计项核查,然后把审计结果登记在我们的平台上。

那些曾经只在写程序时见到的名词,这回就活生生地呈现在我眼前了。

后来再面对代码时,我看到就不再是一个死板的程序了,我和产品经理的讨论也就更加扎实了。

有的团队在这方面有比较好的意识,会主动创造一些机会,让开发团队成员有更多机会与用户接触。

比如,让开发团队到客服团队轮岗。接接电话,听听用户的抱怨,甚至是谩骂。你会觉得心情非常不好,但当你静下来的时候,你就会意识到自己的软件有哪些问题,如果软件做得不好,影响会有多大。

这时,你也就能理解,为什么有的时候,很多业务人员会对开发团队大发雷霆了,因为他们是直接面对用户“炮火”的人。

我们为什么要不断地了解用户的使用情况呢?

因为用户的声音是来自真实世界的反馈。

不去聆听用户声音,很容易让人自我感觉良好。还记得在 “为什么世界和你的理解不一样” 中,我们提到的那个只接收好消息的花剌子模国国王的例子吗?

我们要做一个有价值的产品,这个“价值”,不是对产品经理有价值,而是要对用户有价值。

华为总裁任正非就曾经说过,“让听得见炮声的人来做决策。”

我们做什么产品,本质上不是由产品经理决定的,而是由用户决定的。

只有听见“炮声”,站在一线,我们才更有资格判断产品经理给出的需求是否真的是用户所需。

当产品还没有用户时

如果你的团队做的是一个新的产品,还没有真正的用户,那又该怎么办呢?

你可以尝试一下“用户测试”的方法。

之前我做过一个海外客户的项目。因为项目处于启动阶段,我被派到了客户现场。

刚到那边,客户就兴高采烈地告诉我,他们要做一个用户测试,让我一起参加。

当时,我还有点不知所措,因为我们的项目还没有开始开发,一个什么都没有的项目就做用户测试了?

是的,他们只做了几个页面,就开始测试了。

站在今天的角度,我前面已经给你讲过了精益创业和 MVP,你现在理解起来就会容易很多。

是的,他们就是要通过最小的代价获取用户反馈。

他们是怎么做测试的呢?

首先是一些准备工作,找几个普通用户,这些人各有特点,能够代表不同类型的人群。准备了一台摄像机,作为记录设备,拍摄用户测试的全过程。还准备了一些表格,把自己关注的问题罗列上去。

然后,就是具体的用户测试了。他们为用户介绍了这个测试的目的、流程等一些基本信息。然后,请用户执行几个任务。

在这个过程中,测试者会适时地让用户描述一下当时的感受,如果用户遇到任何问题,他们会适当介入,询问出现的问题,并提供适当的帮助。

最后,让用户为自己使用的这个产品进行打分,做一番评价。测试者的主要工作是观察和记录用户的反应,寻找对用户使用造成影响的部分。做用户测试的目的就是看用户会怎样用这个网站,这样的网站设计会对用户的使用有什么影响。

当天测试结束之后,大家一起整理了得到的用户反馈,重新讨论那些给用户体验造成一定影响的设计,然后调整一版,再来做一次用户测试。

对我来说,那是一个难忘的下午,我第一次这么近距离地感受用户。他们的关注点,他们的使用方式都和我曾经的假设有很多不同。后面再来设计这个系统时,我便有了更多的发言权,因为产品经理有的角度,我作为开发人员也有。

最后,我还想说一个程序员常见的问题:和产品经理没有“共同语言。”

因为他们说的通常是业务语言,而我们程序员的口中,基本上是计算机语言。这是两个领域的东西,很难互通。

前面在讨论代码的时候,我提到要用业务的语言写代码,实际上,这种做法就是领域驱动设计中的通用语言(Ubiquitous Language)。

所谓通用语言,不只是我们写代码要用到,而是要让所有人说一套语言,而这个语言应该来自业务,来自大家一起构建出的领域模型

这样大家在交流的时候,才可能消除歧义。所以,如果你想让项目顺利进行,先邀请产品经理一起坐下来,确定你们的通用语言。

总结时刻

今天我们讨论了一个重要的话题:倾听用户声音。这是开发团队普遍欠缺的一种能力,更准确地说,是忽略的一种能力。

所以,“吃自家的狗粮”这种听上去本来是理所当然的事情,才被反复强调,成为 IT 行业的经典。

在今天这一讲,我给你介绍了“了解用户需求”的不同做法,但其归根结底就是一句话,想办法接近用户。

无论是自己做用户,还是找机会接触已有用户,亦或是没有用户创造用户。只有多多听取来自真实用户的声音,我们才不致于盲目自信或是偏颇地相信产品经理。谁离用户近,谁就有发言权,无论你的角色是什么。

如果今天的内容你只能记住一件事,那请记住:多走近用户。

最后,我想请你思考一下,在你的实际工作中,有哪些因为走近客户而发现的问题,或者因为没有走近客户造成的困扰呢?欢迎在留言区写下你的想法。

27 尽早暴露问题: 为什么被指责的总是你?

今天我准备讨论一个经常会让很多程序员郁闷的事情,为什么你已经工作得很辛苦了,但依然会被指责。在讨论这个问题之前,我们先来讲一个小故事。

程序员小李这天接到了一个新的任务。系统要做性能提升,原先所有的订单都要下到数据库里,由于后来有很多订单都撤了,反复操作数据库,对真正成交过程的性能造成了影响。所以,技术负责人老赵决定把订单先放到缓存里。

这就会牵扯到一个技术选型的问题,于是,老赵找了几个可以用作缓存的中间件。为了给大家一个交代,老赵决定让小李给这几个中间件做一个测试,给出测试结果,让大家一起评估。小李高兴了,做这种技术任务最开心,可以玩新东西了。

老赵问他:“多长时间可以搞定?”

小李说:“一个星期吧!”

老赵也很爽快,“一个星期就一个星期。不过,我得提个要求,不能是纯测中间件,得带着业务跑。”

“没问题。”小李一口答应下来。老赵怕小李做多了,还特意嘱咐他,只测最简单的下单撤单环节就好。

等真的开始动手做了,小李发现,带着业务跑没那么容易,因为原来的代码耦合度太高,想把新的中间件加进去,要先把下单和撤单环节隔离开来。而这两个操作遍布在很多地方,需要先做一些调整。

于是,小李只好开始不分白天黑夜地干起来。随着工作的深入,小李越发觉得这个活是个无底洞,因为时间已经过半了,他的代码还没调整完。

这时,老赵来问他工作进展,他满面愁容地说,估计干不完了。老赵很震惊,“不就是测试几个中间件吗?”

小李也一脸委屈,“我们为啥要带着业务跑啊?我这几天的时间都在调整代码,以便能够把中间件的调用加进去。”

老赵也很疑惑,“你为啥要这么做?”

“你不是说要带着业务跑吗?”

“我是说要带着业务跑啊!但你可以自己写一个下单撤单的程序,主要过程保持一致就好了。”

小李很无奈,心里暗骂,你咋不早说呢?

是啊!你咋不早说呢?不过,我想说不是老赵,而是小李。

谁知道有问题?

我们来分析一下问题出在哪。

在这个故事里,小李和老赵也算有“以终为始”的思维,在一开始就确定了一个目标,做一个新中间件测试,要带着业务跑。

小李可以说是很清楚目标的,但在做的过程中,小李发现了问题,原有代码很复杂,改造的工作量很大,工作可能没法按时完成。

到此为止,所有的做法都没有错。但接下来,发现问题的小李选择了继续埋头苦干,直到老赵来询问,无奈的小李才把问题暴露出来。

在老赵看来,这并不是大事,调整一下方案就好了。但是小李心生怨气,在他看来,老赵明明有简单方案,为啥不早说,害得自己浪费了这么多时间。

但反过来,站在老赵的角度,他是怎么想的呢?

“我的要求是带着业务跑,最理想的方案当然是和系统在一起,你要是能搞定,这肯定是最好的;既然你搞不定,退而求其次,自己写一个隔离出来的方案,我也能接受。”

你看出来问题在哪了吗?

老赵的选择没有任何问题,问题就出在,小李发现自己可能搞不定任务的时候,他的选择是继续闷头做,而不是把问题暴露出来,寻求帮助。

作为一个程序员,克服技术难题是我们工作的一个重要组成部分,所以,一旦有困难我们会下意识地把自己投入进去。

但这真的是最好的做法吗?并不是,不是所有的问题,都是值得解决的技术难题。

在工作中遇到问题,这简直是一件正常得不能再正常的事儿了,即便我们讲了各种各样的工作原则,也不可避免会在工作中遇到问题。

既然是你遇到的问题,你肯定是第一个知道问题发生的人,如果你不把问题暴露出来,别人想帮你也是有心无力的。

如果老赵不过问,结果会怎么样?必然是小李一条路跑到黑。然后,时间到了,任务没完成。

更关键的是,通常项目计划是一环套一环的,小李这边的失败,项目的后续部分都会受到影响,项目整体延期几乎是必然的。这种让人措手不及的情况,是很多项目负责人最害怕见到的。

所以,虽然单从小李的角度看,这只是个人工作习惯的事,但实际上,处于关键节点的人可能会带来项目的风险。而小李的问题被提前发现,调整的空间则会大很多。

遇到问题,最好的解决方案是尽早把问题暴露出来

其实,这个道理你并不陌生,因为你在写程序的时候,可能已经用到了。

Fail Fast

写程序有一个重要的原则叫 Fail Fast,这是什么意思呢?

就是如果遇到问题,尽早报错。

举个例子,我做了一个查询服务,可以让你根据月份查询一些信息,一年有12个月,查询参数就是从1到12。

问题来了,参数校验应该在哪做呢?

如果什么都不做,这个查询参数就会穿透系统,传到你的数据库上。

如果传入的参数是合法的,当然没有任何问题,这个查询会返回一个正常的结果。但如果这个参数是无意义的,比如,传一个“13”,那这个查询依然会传到数据库上。

事实上,很多不经心的系统就是这么做的,一旦系统出了什么状况,你很难判断问题的根源。

在这个极度简化的例子里,你可以一眼看出问题出在输入参数上,一旦系统稍具规模,请求来自不同的地方,这些请求最终都汇集到数据库上,识别来源的难度就会大幅度增加。尤其是系统并发起来,很难从日志中找出这个请求的来源。

你可能会说,“为了方便服务对不同数据来源进行识别,可以给每个请求加上一个唯一的请求ID吧?”

看,系统就是这么变复杂的,我经常调侃这种解决方案,就是没有困难创造困难也要上。当然,即便以后真的加上请求ID,理由也不是现在这个。

其实,要解决这个问题,做法很简单。稍微有经验的人都知道,参数校验应该放在入口的位置上,不合法的请求就不让它往后走了。

这种把可能预见的失败拦在外面的做法就是 Fail Fast,有问题不可怕,让失败尽早到来。

上面这个例子很简单,我再给你举一个例子。

如果配置文件缺少了一个重要参数,比如,缺少了数据库最大连接数,你打算怎么处理?很多人会选择给一个缺省值,这就不是 Fail Fast 的做法。

既然是重要参数,少了就报错,这才叫 Fail Fast

其实,Fail Fast 也有一些反直觉的味道,很多人以构建健壮系统为由,兼容了很多奇怪的问题,而不是把它暴露出来。反而会把系统中的 Bug 隐藏起来。

我们都知道,靠 debug 来定位问题是最为费时费力的一种做法。所以,别怕系统有问题,有问题就早点报出来。

顺便说一下,在前面这个例子里,透传参数还有几个额外的问题。一是会给数据库带来额外的压力,如果有人用无意义查询作为一种攻击手段,它会压垮你的数据库。

再有一点,也是安全问题,一些SQL攻击,利用的就是这种无脑透传。

克服心理障碍

对我们来说,在程序中尽早暴露问题是很容易接受的。但在工作中暴露自己的问题,却是很大的挑战,因为这里还面临着一个心理问题:会不会让别人觉得自己不行。

说实话,这种担心是多余的。因为每个人的能力是强是弱,大家看得清清楚楚。只有你能把问题解决了大家才会高看你,而把问题遮盖住,并不能改善你在别人心目中的形象。

既然是问题,藏是藏不住的,就像最开始那个故事里的小李,即便他试图隐藏问题,但最后他还是不可能完成的,问题还是会出来,到那时,别人对他的评价,只会更加糟糕。

比起尽早暴露问题,还有更进一步的工作方式,那就是把自己的工作透明化,让别人尽可能多地了解自己的工作进展,了解自己的想法

如果能做到这一点,其他人在遇到与你工作相关的事情,都会给你提供信息,帮助你把工作做得更好。当然,这种做法对人的心理挑战,比尽早暴露问题更大。

从专栏开始到现在,我们讲了这么多原则和实践,其实,大多数都是在告诉你,有事先做。

一方面,这是从软件变更成本的角度在考虑;另一方面,也是在从与人打交道的角度在考虑。

越往前做,给人留下的空间和余地越大,调整的机会也就越充足。而在最后一刻出现问题的成本实在太高,大到让人无法负担。

总结时刻

我们今天讨论了一个重要的工作原则,把事情往前做,尽早暴露问题。

我们前面讲的很多内容说的都是这个原则,比如,要先确定结果,要在事前做推演等等。越早发现问题,解决的成本就越低,不仅仅是解决问题本身的成本,更多的是对团队整体计划的影响。

一方面,事前我们要通过“以终为始”和“任务分解”早点发现问题;另一方面,在做事过程中,一旦在有限时间内搞不定,尽早让其他人知道。

这个原则在写程序中的体现就是 Fail Fast,很多程序员因为没有坚持这个原则,不断妥协,造成了程序越来越复杂,团队就陷入了无尽的泥潭。

原则很简单,真正的挑战在于克服自己的心理障碍。很多人都会下意识地隐瞒问题,但请相信你的队友,大家都是聪明人,问题是藏不住的。

如果今天的内容你只记住一件事,那请记住:事情往前做,有问题尽早暴露。

最后,我想请你回想一下,如果遵循了这样的工作原则,你之前犯过的哪些错误是可以规避掉的呢?欢迎在留言区写下你的想法。

28 结构化:写文档也是一种学习方式

你写文档吗?

我知道,你可能并不喜欢写文档,因为在你眼中,写文档是繁琐的,是旧时代软件工程的产物。

最开始我对写文档的印象也不好。

我的职业生涯是从一个通过了 CMM 5级认证的大企业开始的。

可能今天很多程序员已经对 CMM 感到陌生了,它是能力成熟度模型(Capability Maturity Model for Software)的缩写,用来评估一个组织的软件开发能力,曾在国内风靡一时,许多软件公司都以拥有 CMM 认证为努力方向。

在这个极其重视过程的企业里,文档是非常重要的一环。但我看到的真实场景却是,一个软件已经上线运行了,大家才开始为了应付过程纷纷补写文档。

每个部门都有专门的过程负责人,要求你严格按照格式写文档,保证字体字号的正确性。然后,用 A4纸将文档打印出,封印在一个仓库里,再也无人问津。

然而,文档却是非常重要的。后来,我到过很多公司,凡是我能够比较快上手的,通常都是有比较详尽的文档,而那些文档缺失的公司,想要把信息梳理清楚,往往会花很长时间。

另外,我学习很多软件开发的相关知识,通常也是依赖各种各样的文档。对我们程序员这个走在时代前列的群体来说,大量阅读文档就是我们日常工作的一部分。

你发现矛盾了吗?

一方面,我们讨厌写文档,另一方面,文档却对我们的工作学习有着不可忽视的作用。

我们竟然如此依赖于一个我们讨厌的东西。问题出在哪呢?

你为什么不喜欢写文档?

很多人会说,自己不愿意写那些无聊的流程文档,文档无聊,这固然是一个原因。

不过,如今很多公司已经在这方面做得相当轻量级了,基本上只要求写必要的文档。那为什么依然有很多人不愿意写文档呢?

其实,很多人回避写文档的真正原因是,他掌握的内容不能很好地结构化。

在两种场景下,我们扮演的角色是不同的。写文档时,角色是作者;而读文档时,角色是读者。

作为读者,我们读文档,实际上就是按照作者梳理的结构在走,因为呈现出来的内容,多数是已经结构化的,读起来自然会比较顺畅;而作为作者,没有人告诉你结构应该是什么样,我们必须创造出一个结构来,而这正是很多人不擅长的。

想要成为一个好程序员,有一个良好的知识结构是极其重要的。

很多人抱怨程序员行业难,原因就在于,新技术层出不穷。

是的,当你的知识都是零散的,任何新技术的出现,都是新东西。

而当你建立起自己的知识结构,任何新东西都只是在原有知识上的增量叠加

举个例子,今天炒得沸沸扬扬的微服务,小粒度的理念脱胎于 Unix 哲学中的“只做一件事,把它做好”,而服务化的理念则是当年SOA(Service-Oriented Architecture)的产物。

理解了这些背后的动机,微服务就只剩下工具层面的问题。

有了这样的知识结构,当我要构建应用时,只是需要把工具适配进去,到时我再来学习相应的知识,这是非常有针对性的,学习的效率也会得到大幅度提高。

将零散的知识结构化,有很多种方式,但输出是非常关键的一环。

知识输出

不知道你小时候是不是有过给同学讲题的经历,有时候,明明你已经将知识学得很好,但给同学讲解起来时,却总是讲不明白。

因为你的同学总能从你想都没想过的角度问问题,这些角度和老师教的不一样。

输出的过程,本质上就是把知识连接起来的过程。自己以为自己懂的东西,当你真的需要把它按照一个完整的逻辑呈现出来时,那些缺失的细节就会冒出来,而补齐这些细节,一张知识地图就逐渐成型了。

这个模块的主题是“沟通反馈”,将知识对外输出就是一种获得反馈的方式。

很多人自以为对知识的理解已经很深入了,但给别人一讲,却发现自己怎么也讲不清楚,这就说明他理解的程度,远未到达他以为的高度。

输出的方式有很多,对于程序员来说,最常接触到的两种应该是写作与演讲。

你读到很多书、很多技术文章,这都是别人通过写作的方式进行输出的结果。而很多技术大会上,常常会有各路高手在台上分享自己的所得,这就是演讲的输出方式。

软件行业的很多大师级程序员都是对外输出的高手。

比如,开源概念的提出者 Eric Raymond,他的《大教堂与集市》推开了开源大门;前面多次提及的Kent Beck,他写了《极限编程解析》、《测试驱动开发》、《实现模式》几本书;

而 Martin Fowler,几乎是对外输出的典范,他重新整理了很多似是而非的概念,让人们的讨论有了更标准的词汇,比如,重构、依赖注入(Dependency Injection)等等。

再往前,就要提到《计算机程序设计艺术》的作者高德纳,他系统地整理了算法的概念,为了好好写作,他甚至创造了一个排版软件 TeX。

也许你会说,说得很有道理,但我真的不擅长啊!这是因为你没有掌握基本的方法。

金字塔原理

首先,需要明确一点,我们的第一目标不是成为作家或演讲家,而只是要求把事情说清楚,把自己的知识清晰地呈现出来。

那我们最好先来了解一下金字塔原理。

看看下面这张图,你就知道它是怎么回事了:

金字塔原理

首先,我们要确定想要表达的是什么,也就是找到中心论点,然后,再确定支撑这个论点的分论点,再来就是找到支撑每个分论点的论据

从中心论点、分论点至论据,这样一层层向下展开,从结构上看,就像金字塔一样,所以,这个方法称之为金字塔原理。

以我们的专栏为例,我们的中心论点就是“高效工作是有方法可循的”,那支撑起这个中心论点的分论点就是我们的四个原则,针对每个原则,我们给出了各种实践和思想,这是我们的论据。

前面我说过了,一个人不擅长输出,更多的是因为缺乏知识的结构化,现在通过这样一种方式,就可以帮助自己,将某个知识结构化起来,有了结构,剩下的就是怎么输出了。

具体怎么输出就可以根据自己的喜好进行选择:要么自上而下的进行表达,也就是先说中心论点,然后说分论点1,用论据证明分论点1,再说分论点2,用论据证明分论点2,以此类推。

或者是自下而上来表达,先用证据得出分论点1,然后再得出分论点2,最后再归纳总结出中心论点。

听上去很简单,但不要以为懂得了金字塔原理,天下就尽在掌握了,你还需要更多的练习。

无他,唯手熟尔

我自己也曾经很不擅长写作和公开演讲,但是,这些东西都禁不住你大量的练习。

我的对外输出,是从我刚开始工作不久开始的。那时候,市面上流行写 blog,我抱着好奇的心态开始了自己的 blog 之旅。

刚开始写 blog 的时候,我会把写好的东西分享给周边的朋友,他们会给我提出一些反馈,有赞许、有调侃、也有针对一些细节的讨论,这会让我觉得自己写的东西是有人看的,我也就有了坚持的原动力。

我也很羡慕那些很会写的人,于是,也经常会模仿他人的手法不断地改进自己的写作技巧。

慢慢地,我的读者就从身边的人逐渐扩展开来,我也就有了更多的反馈。

正是这些反馈,让我对很多东西有了全新的认识,也就有了更强的分享动力,一个正向循环逐渐建立起来。

到后来,写东西就成了我的习惯,坚持至今。

经过 blog 写作的锻炼,我写的东西有了自己的章法和套路,也就有了越来越多机会去在不同的地方写东西:给杂志写稿子,在网站上写东西,包括今天这个专栏,都起源于最初的 blog 写作。

除此之外,随着时间的累积,我收获的不仅仅是一些读者的赞许,还得到了更多的机会,比如,我人生中的第一次公开演讲,机会就来自于我 blog 的一个读者的邀请。

后来的一些职业机会,也是通过我写 blog 认识的朋友。考虑到我当时人在 IT 边缘的东北,能有后来的职业发展,很大程度都是常年坚持对外输出的结果。

同样,演讲能力也需要大量的练习。1977年《Book of List》杂志曾经有一个关于“最恐惧事物”的调查,结果显示,公开演讲名列第一,超过了死亡。所以,你害怕公开演讲是很正常的。

我至今依然记得我第一次公开演讲时手抖的样子,今天想想还是挺傻的。我第一次在几百人的大会上做演讲,居然有一段时间,只顾着看大屏,背对着听众,也是很糗的一段经历。

我一直很羡慕那些在台上侃侃而谈的人,比如,乔布斯。直到我读了《乔布斯的魔力演讲》,我才知道,即便强如乔布斯,他的演讲也是经过大量练习的。

我自己公开演讲看上去正常一些,是我在经过一个咨询项目的大量练习之后。

那时候,几乎每天要给客户讲东西,害得我只能不停地准备、不停地讲。

所以,本质上,对演讲的惧怕只是因为练习不足

好了,你现在已经了解获取这些技能的真谛了,无他,唯手熟尔!

总结时刻

程序员对文档有着一种矛盾的情感,一方面,需要依赖于文档获得知识,另一方面,很少有人愿意写文档。

文档在程序员心目中“形象不佳”,主要是传统的流程写了太多无用的文档。但对更多人来说,不愿意写文档,本质上是因为知识不能很好地结构化。

有结构的知识会让新知识的学习变得更加容易,今天很多人抱怨新知识层出不穷,就是因为知识过于零散,当知识有结构之后,学习新知识就只是在学习增量,效率自然就会大幅度提升。

输出是一种很好的方式,帮助你把知识连接起来,写作和做公开演讲都是很好的输出方式。

阻碍很多人进行知识输出的一个重要原因是缺乏输出的模型,金字塔原理就给出一个从中心论点到分论点,再到论据的模型,帮助我们将知识梳理出来。

而想要做好知识输出,还需要不断地进行练习,写作和做公开演讲都是可以通过练习提高的。

如果今天的内容你只能记住一件事,那请记住:多输出,让知识更有结构。

最后,我想请你分享一下,你的工作中,有哪些机会将自己的知识输出呢?欢迎在留言区写下你的想法。

29 “懒惰”应该是所有程序员的骄傲

经过前面几个模块的学习,我们的专栏终于进入到程序员看上去最熟悉的一个主题:自动化。

每每提及自动化,我就会想起 Perl 语言的发明人 Larry Wall 一个经典叙述:

优秀程序员应该有三大美德:懒惰、急躁和傲慢(Laziness, Impatience and hubris)

有人甚至为此专门打造了一个三大美德的网站,阐释这个初看起来匪夷所思的说法。

懒惰,是一种品质,它会使你花很大力气去规避过度的精力消耗,敦促你写出节省体力的程序,别人也能很好地利用,你还会为此写出完善的文档,以免别人来问问题。

急躁,是计算机偷懒时,你会感到的一种愤怒。它会促使你写出超越预期的程序,而不只是响应需求。

傲慢,极度自信,写出(或维护)别人挑不出毛病的程序。

不知道你是否感受到,程序员独有的幽默和透露出的那种骄傲:我做的东西就应该是最好的。

之所以要从 Larry Wall 的这段话开启“自动化”这个模块,因为只要一说到自动化,我就会情不自禁地联想到“偷懒”这个词。

是的,我们程序员的工作,本质上就是打造各种自动化的工具,让人们从各种繁复的工作中解脱出来,让人有机会“偷懒”。

不过,我也知道,从机器那里偷来的“懒”很快就被更多的工作填满了。但 Larry Wall 的这段话却可以鼓励我们不断地打造出更好的工具。

作为程序员,你当然知道“自动化”这件事的价值,在日常工作中,也实实在在地践行着打造自动化工具的任务,但很多人对自动化的理解可能有些单薄。

今天,我就从一个你可能会忽略的主题开始讨论:不要自动化。

不要自动化

我先给你讲一个让我印象深刻的“不自动化”的例子。

之前在 ThoughtWorks 工作时,我们有一项工作是,帮助其他公司启动一些新产品。

有一次,我的两个同事被一个公司请去启动一个视频网站的项目。那时候还不像如今的市场,已经由几大视频网站瓜分完毕,当时不少公司看到了视频网站的苗头,觉得自己有机会。这个来请我们的公司也不例外,觉得自己也能分一杯羹。

两个星期之后,我的两个同事回来了。我们饶有兴趣地去问项目的进展,因为项目启动之后,通常会有后续的开发合作,但结果令我们很意外,这个项目停止了。

“出了什么状况吗?”我们问。

“是我们建议用户停掉这个项目的。”他们回答道。

我们“恨恨地”问他们为什么丢掉了一个这么重要的机会。这两个同事的回答也很直白,他们结合着客户的想法算了一笔账:这个项目需要大量的资金投入,投入规模之大,是超出客户想象的,按照现有的规划投入,这个项目肯定会亏本。要么重新规划,要么取消这个项目。客户认真研究了一番,最终决定取消项目。

这件事大约发生在10年前,今天我们都看到各大视频网站在烧钱上的投入,以那个公司的实力,想要参加这场比拼,确实还差太多。

这件事之所以给我留下深刻印象,因为它是我职业生涯中见到的第一个通过“主动取消项目”获取项目成功的案例。

或许你不能理解我这里所说的“项目成功”。

在我看来,做有价值的事是重要的,这里面的有价值,不仅仅是“做”了什么,通过“不做”节省时间和成本也是有价值的

我的两个同事阻止了客户的浪费,所以,我将这个项目视为成功。

对于开发来说,也遵循同样的道理。程序员这个群体技术能力实在太强,做一个技术方案简直是太符合直觉的做法,我们就是忠实地把一个个需求做出来,把“全世界”都自动化了。

但事实上,这个世界太多的浪费就是做了不该做的东西。在我们的专栏里,我反复地说,我们要多问问题,目的就是为了不做那些不该做的事。

小心 NIH 综合症

你可以从需求的角度判断哪些工作是可以不做的,但我们也要防止程序员自己“加戏”,我再给你讲一个技术人员普遍存在的问题:NIH 综合症(Not Invented Here Syndrome)。

NIH 是什么意思?

就是有人特别看不上别人做的东西,非要自己做出一套来,原因只是因为那个东西不是我做的,可能存在各种问题。

这种现象在开源之前尤为流行,很多公司都要做自己的中间件,做自己的数据库封装。虽然很多公司因此有了自己特色的框架,但是因为水平有限,做出来的东西通常极为难用,很多人一边骂,一边还要继续在上面开发。

开源运动兴起之后,我以为这种现象会好一些,但事实证明,我想多了。

比如,这种乱象在前端领域也出现了,各种各样的框架,让很多前端程序员哭诉,实在学不动了。再比如,我曾经面试过一个接触 Go 比较早的程序员,他就是恨不得把所有框架都自己写。

因为他学 Go 的时候,确实框架比较少,但问题是,如今的 Go 已经不是他学习时的那个 Go 了,现在各种框架已经很丰富了,不需要什么都自己做。

当时我问他,如果有一天你离开了,公司怎么办呢?实际上,他从来没考虑过这个问题。

说了这么多,无非就是想说明一件事,写代码之前,先问问自己真的要做吗?能不做就不做,直到你有了足够的理由去做。

对应到 Larry Wall 的说法,你要懒惰,花大力气去规避精力消耗。

做好自动化

说完了不要自动化的部分,再来说说要自动化的部分。

我还是先从你可能会忽略的问题入手,你的日常工作是给别人打造自动化,但你自己的工作够自动化吗?

还是问一个更具体的问题吧!如果你写的代码要上线,会经过怎样的过程?

我先给你看一个极其糟糕的例子。刚开始工作不久,我有一次出差到客户现场。临近下班时,我发现了程序的一个Bug。

在那个年代,我们的程序是按照官方推荐做法编写的 EJB(Enterprise JavaBean),今天很多年轻的程序员可能不了解了,它只有部署到应用服务器才能运行。

我的解决方案就是加上一些打印语句,然后部署到应用服务器上,看输出的结果,再加上另外一些语句,再部署,如此往复。那时我们完全是手工打包上传,每次至少要十几分钟。最终,定位到了问题,只修改了一行代码。但几个小时的时间就这样被无谓的消耗了。

那之后,我花了很长时间研究怎么做自动化的增量部署,最终让这个过程简化了下来。

但这件事对我的影响很大,这是我第一次认识到一个部署过程可能对开发造成的影响,也让我对自动化在开发过程内的应用有了属于自己的认识

相比于我刚开始工作那会。现在在工具层面做类似的事已经容易很多了,在后面的内容中,我会结合着具体的场景介绍一下现在的最佳实践。

你要懂得软件设计

最后,我们再来说说我们的本职工作,给别人打造自动化工具中需要的能力:软件设计。

软件设计,是很多人既熟悉又陌生的一个词,说熟悉,很多人都知道,做软件要设计,还能顺嘴说出几个设计模式的名字;说陌生,是因为在我的职业生涯中,遇到真正懂软件设计的程序员少之又少。

大多数人都是混淆了设计和实现。

举个例子。有一次,我要在两个系统之间做一个连接器,让上游系统向下游系统发消息,或许你一听就知道了,这里需要的是一个消息队列。

但实际上,我们需要的能力要比消息队列更丰富一些,比如,要将重复的消息去除。一个同事给我推荐了 Kafka 当作这个连接器的基础,我欣然地接受了。

不过,在后续设计的讨论中,我们就经常出现话语体系的分歧。我说,这个连接器要有怎样的能力,他会说 Kafka 能够如何如何。

究其根因,我在讨论的是设计,而他说的是实现,所以,我们两个很难把问题讨论到一起。

为什么我会如此看重设计呢?

软件开发中,其它的东西都是易变的,唯有设计的可变性是你可以控制的

同样以前面的讨论为例,尽管 Kafka 在当下比较火热,但是我不敢保证 Kafka 在未来不会被我换掉。因为就在几年前,消息队列还是传统中间件的强项,现在也渐渐被人淡忘了。

我不想让我的设计随着某一个技术选型而不断摇摆。如果工作许多年,知识体系只能靠各种新框架新工具支撑,我们做程序员就只剩下疲于奔命了。

不懂软件设计,只专注各种工具,其结果一定是被新技术遗弃,这也是很多人经常抱怨 IT 行业变化快的重要原因。

回到 Larry Wall 的说法上,你要想写出一个别人挑不出毛病的程序,你先要懂得软件设计。

幸运的是,软件设计这些年的变化真不大,掌握了软件设计再来看很多框架和工具,学习起来就会容易很多。

在这个模块的后半部分,我会与你探讨软件设计的话题,降低自己给自己挖坑的概率。

总结时刻

Perl 语言的发明人 Larry Wall 曾经说过,优秀程序员应该有三大美德:懒惰、急躁和傲慢(Laziness, Impatience and hubris)。

想要成为一个优秀的程序员,就要让机器为自己很好地工作,而这需要对自动化有着很好地理解。

我们学习自动化,先要知道哪些东西不要自动化,尽最大的努力不做浪费时间的事。

一方面,我们要从需求上规避那些没必要做的事;另一方面,我们也从自身防止 NIH 综合症(Not Invented Here Syndrome),争取做一个懒惰的程序员。

对于要自动化的事,我们需要反思一下,在为别人打造自动化工具的同时,我们自己的工作过程有没有很好地自动化。而如果我们想拥有打造良好的自动化工具,我们需要对软件设计有着充分地理解。

如果今天的内容你只能记住一件事,那请记住:请谨慎地将工作自动化。

最后,我想请你分享一下,学习了本讲之后,你现在是怎样理解自动化的呢?

欢迎在留言区写下你的想法。

参考资料

http://learn.lianglianglee.com/%e4%b8%93%e6%a0%8f/10x%e7%a8%8b%e5%ba%8f%e5%91%98%e5%b7%a5%e4%bd%9c%e6%b3%95/26%20%e4%bd%9c%e4%b8%ba%e7%a8%8b%e5%ba%8f%e5%91%98%ef%bc%8c%e4%bd%a0%e4%b9%9f%e5%ba%94%e8%af%a5%e8%81%86%e5%90%ac%e7%94%a8%e6%88%b7%e5%a3%b0%e9%9f%b3.md