如何做笔记?

笔记的作用是让知识放心丢下,放空自己,但是又能及时的捡起来,减少自己的心智负担。一份好的笔记可以让知识简化、压缩,一目了然,然后在一段时间后在需要的情况下能轻易的捡起来,做到能放能收的程度,起到整理学习内容的作用。

最优秀的笔记可以做到将一本书压缩成一张纸或者几页纸,从而轻易的回忆、联想出全部内容。压缩的过程需要将书本的知识转换成自己的语言,只有自己的语言才能记住。压缩成一页纸是理想情况,一些专业书籍往往内容非常多,可以一个章节压缩成一页纸。但是一些畅销书有很多废话,只能提炼出非常少的东西,一页纸都用不上。

自己语言的标准是能轻易复述一遍,不是背诵,能用自己的话把这套知识讲通,说明完全理解了这套知识。这就是费曼学习法的精髓,费曼学习法并不是一定要将自己的学到的东西做成 PPT 讲授给别人,而是说需要将知识内化、提炼、复述,讲给别人只是检验复述能力的一种手段。

从这个角度看待笔记的话,做笔记的过程比最终的笔记更有价值。做笔记就是在复述压缩内化。阅读别人做好的笔记毫无意义,有时候会因为信息被裁剪弄得一头雾水。得到 APP 中拆书的本质就是分享笔记,所以这些笔记看起来学到了知识,其实只是感觉自己学习到了。

好的笔记有几个要求:

  1. 用自己的语言来描述知识,而不是照着书本的内容抄写。复述是背诵的前提,不是自己的语言很难记忆。
  2. 用线条串联知识点,形成知识网。
  3. 压缩信息,结合自己的上下文保留关键信息。
  4. 最好用图形的方式做笔记。我喜欢用格子背景的 keynote 来记笔记。

笔记可以做很多事情。除了整理学习内容之外还可以记录自己的想法。每天将自己的想法记录下来,每个人都有一些好的想法迸发出来,养成记录想法的习惯可以收获很多。一些作家就时常带上小本子和笔,有灵感时就记录下来。元末陶宗仪外出时有灵感就写在树叶子上,汇集成《南村辍耕录》。

通过把想法写下来可以大大降低自己的思维负担,更适合深度思考。每天写想法的时候可以深入多挖一点,多问一些问题,多问几个为什么?从问题驱动,深度思考。比如:

  • 为什么书店摆出来的书和图书馆不一样,说明了什么?
  • 我们能否从中得到启发?
  • 从中能得到什么价值?

从这些问题中可以得到,书店是面向大众消费者人群的。为了赚钱,选择的都是消费者喜爱的书籍,从而可以了解到大众想要的是什么。根据观察,现在书店往往不再有专业书籍,更多的成功学、简单的心理学等更多的畅销书。在书店看书的时候,需要注意这些书专业性并不强,更多的是科普作用。

通过这些想法加上深度思考,这样可以拓展出一篇小文章,这种短文作为自己的心得总结还是很有价值。不过需要注意不要花费太多的时间,丢失自己当前的工作目标。不要过于在乎这些小文章的连贯性,很多看似没有连贯的东西,时间久了就会连贯起来。这就是量变产生质变。

记笔记还可以提高学习力。笔记是学习中很重要的一环,并不是简单记录下知识点,而是对知识再加工。最好不要边学边记,如果是课堂上这样做会丢失学习的注意力,如果是看书学习,会难以同时兼顾阅读和记录。

记笔记前应该先大量获取知识作为输入,如果是课堂就记录一些关键词,如果是看书就用记号笔做标记。完成输入后,理解、联系、类比这些知识,并用自己的语言整理成笔记。尽可能压缩这些信息,便于记忆。

完成笔记后,在必要时回顾它加强记忆,比较好的方式可以是在睡前通过类似闪卡的方式记忆。在记忆时就能体会图形化笔记的好处了,通过图形化和线条的联系,可以在大脑中通过空间位置检索知识点。比如,我在学习《八段锦》时做了一页纸的笔记,将八段锦的八个动作和人体的空间位置联系起来,很容易的记住了八段锦的八个动作。

所以,好的笔记可以帮助整理学习内容、记录日常想法、提高学习力的作用。用图形法、压缩信息的方法记录笔记可以结构化的表示知识点,从而帮助记忆和降低心智负担。

more >>

敏捷过程中的软件持续建模

敏捷方法追求单件工作流和响应变化,需求按照故事卡拆分,容易造成业务模型、架构设计碎片化。

在按照敏捷方法运作的团队工作时,比较麻烦的事情是怎么继续坚持软件建模的这些实践。BA (业务分析师)们按照迭代把分析好的用户故事给到开发,开发会按照情况认领任务并开始开发。

因为每个用户故事都是单独计算工作量,有单独的生命周期,所以使用用户故事来描述业务需求,会造成业务需求的整体性缺失。

但是,软件开发的本质是知识性工作,如果没有整体性设计的过程,软件架构会很快腐化和混乱。

软件建模,在软件开发过程中指的是数据库设计、UML 图例的更新、架构的调整和领域对象的设计。建模的专业性,往往决定了一个项目的成败。建模清晰的开发团队,效率和开发成本都会小很多。

软甲项目很小时,不太能体会到建模的优势,当业务复杂到几十上百个数据库表、几百个用例、7-8 个服务时,没有有效的建模,软件项目将无法继续。

因此,必须想办法既要敏捷迭代式的开发,也要持续维护模型的完整和一致性。

解决敏捷项目中整体性设计的问题有几种运作方法:

  1. 将用户故事拆解粒度变大
  2. 固定的人认领批量的用户故事
  3. 在迭代期间增加软件设计和持续建模的过程
  4. 增加专门的软件建模任务卡,并排在每个迭代前

1、2 两种方法可以看做一体,是对当前的敏捷过程调整,对敏捷的一些实践进行裁剪。固定的人批量的认领一些任务,由一个人来负责整体性设计。

3、4 两种方法是我从一种叫做 RUP 的软件开发方法中受到的启发,对敏捷过程进行改进。每个迭代都应该进行模型的修正,并持续建模。

软件建模,也需要迭代更新,这就是持续建模。

持续建模方法

其实 UML、ER 图等常用软件建模的方法使用起来都比较简单,也很容易学会。但是实际开发过程中很少看到有团队再认真的画 UML 相关图形来设计对象,也基本上很难看到大规模使用 E-R 图的情况。

原因很简单,这些图形难以随着代码和业务的变更而同步更新。如果一个软件模型不能正确的表达业务逻辑和真实的架构情况,团队就很难有动力去更新它了。软件建模大多数都发生在项目启动的时候,以及大规模重构的时候,难以持续整个软件周期。

背后的逻辑分为技术、开发过程两个方面:

  1. 从管理上,敏捷方法中每个迭代周期没有一个过程留给去做架构调整、更新模型这些事。
  2. 从技术上,模型的更新成本比较高,修改代码时需要记得同步更新模型,尤其是一些图形的方式更新就更麻烦了。

简单来说,模型的创建很简单,但是保持和代码同步更新很麻烦。这也是很多代码生成器难以发展的根本原因,使用代码生成器会造成一旦手动修改部分生成的代码,就无法再使用代码生成器了。

RUP 方法

先说从开发过程上解决每个迭代模型更新和架构调整的问题。

RUP(Rational Unified Process),即 Rational 统一过程。它是一种比较重的开发方法,并提供了一整套软件工程相关的文档、规范,以及相关的工具。

正是因为 RUP 比较重,需要每个团队的项目经理根据自己的情况进行裁剪,所以在竞争中不如敏捷方法。我们不必学习 RUP,只需要提取出 RUP 中有价值的的方法和实践到敏捷开发中。

RUP 将开发过程划分为了初始阶段、细化阶段、构造阶段和交付阶段 4 个阶段。RUP 按照迭代的方式运行,商业建模、需求、分析和设计、实现、测试、部署 6 个步骤,每个迭代都有这 6 个步骤。

RUP 和敏捷的不同是,敏捷强调单个用户故事的流动(WIP),RUP 可以理解为每个迭代内实际上还是瀑布的方式在运作。

其中:

  • 商业建模和需求的过程为 BA 或者产品经理输出原型图、用户故事、业务用例等
  • 分析和设计步骤为开发人员进行系统设计的过程,前期迭代为初始话系统设计,后期的迭代为修正系统设计的过程。系统设计的输出为 E-R 图、UML 中的类图等整体性设计。

RUP 的几个步骤都发生在同一个迭代。敏捷的一些实践,实际上是穿插完成的。

比如以两周一个迭代为例,前一个迭代的第二周,BA 们应该开始为下一个迭代的工作进行业务分析工作,完善功能的细节和约束条件。迭代的末尾 2 - 3 天应该进入封包整体回归和修复 bug 阶段,可以开始下个迭代的系统设计和模型修正。

img

代码化的 UML 工具

再从技术的角度来说,如何持续维护模型。

表达模型的工具很多,Microsoft Visio、draw.io、starUML 都是比较好的选择。但是,持续建模要求每个迭代都对模型进行修正,因此模型最好能通过版本管理工具管理。

在调研各种绘图工具后,能通过代码化的方式表达 UML 图形的工具不多,其中有 markdown 的 UML 拓展、plantuml。实际使用的情况来看,比较建议使用 plantuml。

plantuml 可以绘制基本的时序图、类图等,以及架构图、E-R 图等非 UML 规范的图形。在实际工作中,我们绘制的图形中,有 5 种比较常用于表达软件模型:

  • 用例图
  • 类图
  • 时序图
  • E-R 图
  • 架构图

用例图、时序图在分析业务逻辑时使用,架构图、E-R 图在做整体性设计时候使用,类图则往往用于具体实现阶段。从维护成本的考虑,保持架构图和 E-R 图持续维护,其他图例在必要时使用即可。

使用 plantuml 非常简单,只需要安装 Java,并现在一个 jar 文件就可以将文本的 UML 代码转换成图形,还可以借助一些工具进行代码生成。 除时序图和活动图以外的图,还需要需要安装 Graphviz 依赖。

以 Mac 为例,安装 graphviz:

brew install graphviz

下载 planuml :

wget https://nchc.dl.sourceforge.net/project/plantuml/plantuml.jar

用官网的例子绘制一个时序图,将下列文本保存为 sequence.txt。

@startuml
用户 -> 认证中心: 登录操作
认证中心 -> 缓存: 存放(key=token+ip,value=token)token

用户 <- 认证中心 : 认证成功返回token
用户 -> 认证中心: 下次访问头部携带token认证
认证中心 <- 缓存: key=token+ip获取token
其他服务 <- 认证中心: 存在且校验成功则跳转到用户请求的其他服务
其他服务 -> 用户: 信息
@enduml

然后用 java 执行 plantuml.jar 即可运行,并得到序列图。

java -jar plantuml.jar sequence.txt

总结

为了解决敏捷项目中,业务模型和架构碎片化的问题,可以通过开发过程和技术两方面进行优化。

过程方面,可以在敏捷过程中加入建模的环节,实际上在一些大的公司类似于方案评审环节。技术方面,可以尝试改进模型的维护方式,竟可能的将模型简化,并通过代码化的方式持续演进。

参考文章

more >>

必须教给孩子的几种思维模型

写给以后的小孩,也写给现在的自己。

清单思维

提高效率最简单的思维,列一个清单并完成它。这个思维已经成为很多人的默认选项,拆任务、贴便签,然后逐个突破。

比较有意思的是,网上还有清单思维的课程,和很厚的书籍,其实大可不必。很多培训都只是为了参训的人感觉学到了东西,其实过段时间就忘了,很多操作方法过重反而不利于习惯的培养。

列清单很简单,可以无处不在,最根本的好处是让清单把脑袋中的内容腾下来,放空大脑的同时,也可以防止遗忘。写在清单上 ,不用随时惦记这,把精力都留给要做的事情。

一场会议,一次培训,甚至做一个菜,或者写一篇文章都可以使用清单。

很多职场人士都无法离开清单,可以使用滴答清单、便利贴或者在笔记中列一个清单都可以。我也做了一个简单的网页,可以存储清单,打开就可以使用。http://todo.printf.cn/

模型思维

世界是复杂的,要想理解一件事情必须要进行简化,简化后找到和自己知识背景有联系的事物进行类比就能理解。

抽象的概念经过简化,并找到一个经历过的事物进行类比,才能得到理解,这就是人类认知的基本逻辑。

如果给幼儿园的孩子讲解 -1 * -1 = 1?

用双重否定等于肯定,孩子是理解不了的。一个方法是 -1 代表的是向后转,-1 * -1 意思是向后转,再向后转,最后面向了哪里呢?

这就是类比,类比不是准确,但是可以让人理解抽象的概念。

用手指学习数数,手指就是模型,而数字只是人们创造出来的概念。

数学老师让我们理解什么是集合,集合很好理解,就是一堆事物的整体。那么什么是空集呢?空集就是爸妈给你了一个钱包,但是拿走了所有的钱。

辩证思维

为什么所有人都觉得《老子》非常牛逼,非常有道理?

《老子》中充满了朴素的辩证思维,高下、前后、美丑,随处可见的辩证思维让这本书闪闪发光。“有无相生,难易相成,长短相形,高下相倾,音声相和,前后相随。” 这类的描述非常多,也非常具体。

老子的辩证思维是一种朴素辩证法,辩证唯物主义又进了一步,毛主席的《矛盾论》就是其中的代表。

辩证思维,可以让人从不同的角度思考问题。比如有人给你推销保险,会给你讲所有有关保险的优点,根据辩证思维,有好处就有坏处,它们是客观存在的。

通过辩证法,可以减少很多上当受骗的机会。

逻辑思维

逻辑思维不是罗振宇的《逻辑思维》,而是指哲学的逻辑思维。

我们无论是认识世界还是和人辩论,都需要遵守一些思维规律,掌握了这些思维规律,就可以让自己的逻辑更为严密。

现代逻辑思维有三大规律:

  1. 同一律。同一段论述中,概念的内涵和外延不能发生变化,否则就是偷换概念。比如 A: 学生可以同时学习数学、语文。 B: 不对,人不可以同时学习两门课,比如你不可以同时看两本书。这里的“同时”概念发生了变化,无法继续讨论了。
  2. 矛盾律。在同一段论述中,不能出现两个相互矛盾的说法,比如“我有一个任何矛也无法刺穿的盾,还有一个可以刺穿任何盾的矛。”
  3. 排中律。排中律指同一个思维过程中,两个思想不能同假,必有一真。比如老妇人拜菩萨,求天不要下雨,不然买扇子的女儿没有生意,一会儿又求天要下雨,不然另外一个卖伞的女儿也没有生意。

掌握逻辑学三大规律,可以避免一些诡辩,可以跟正确的理解道理。

目标思维

人有时候无法专注,并不是想偷懒,而是缺少目标思维。

用目标思维随时提醒自己当前工作的意义,避免写着文章搜索材料的时候,进入八卦专区灌水去了。

目标思维的建立是通过各种问题,比如 5w1H 方法。

  • why(为什么)
  • What(是什么)
  • Where(在哪儿)
  • Who(谁)
  • When(什么时候)
  • 1H是指:How(如何)

通过 5w1H 方法,可以让自己做的事情更有意义,具体,而有焦点。

同理心思维

同理心思维是人与人相处的思维,通俗来说就是同情的能力。

比如说出某句话会对对方造成反应?

某个行为对方会产生如何的感受?

产生同理心思维的方法是“精神分裂”,想象自己是另外一个人 B,旁观自己的处境 A。作为 B 去考察 A 在某个场景下的行为,以及对方的额感受,就可以获得同理心。同理心分为个体、群体同理心。

同理心思维不是为了一味的照顾、迁就别人的感受,而是应该作为一个旁观者 B,如果利用同理心影响、感知对方,并在人群中做出适当的社交行为 。

more >>

35岁过后做什么呢(二)?

去做了种植牙齿的手术,回来后除了肉疼,还有心疼。华西的教授技术完全没话说,唯一一点不好就是贵。

为了打发牙疼的时间把 《35岁过后做什么呢?》中没有说完的东西再写一点。

医院的见闻

给我治疗的人是一个教授,因为之前在小的牙科医院吃过亏,即使价格比较贵也选择了华西口腔。

华西口腔可以说是世界上前列的口腔医院,国内大部分的口腔医院创始的过程都和华西口腔有关,华西口腔真的是博士遍地走,研究生不如狗。

在我完成治疗后,楼下在自助收费机器旁边帮助患者操作自助机的志愿者都是川大的研究生。

在拍摄牙片 CBCT 时,看到了墙上关于放射科的介绍,研究生学历,3-4个头衔一样也是每天重复的拍摄 CT,被患者骂。

在收费窗口,收费员是一个 40 岁左右的中年人,不耐烦的叫我把处方递给他,从他的神情来看,对 35 岁后的生活并不满意。

牙医的工作模式是围绕着主任医师为中心,以助理医师、护士、规培生为主要组成的团队工作的。受人尊重的当然是主任医师了,华西口腔种植科的主任医师只有十多个。

曾经遇到过一个华西口腔的博士,给我吐槽华西口腔的工作压力相当大,可以类比于做技术的在华为,做咨询的在麦肯锡。如果在华西口腔不能持续上升,就会被淘汰,机会留给后面的博士生。

按照现在的说法,内卷的厉害。

焦虑来自不恰当的类比

我们的焦虑来自于比恰当的对比。

虽然 IT 行业不敢膨胀到和医疗行业做比较,但是看看医疗行业的情况。我们只看到了主任医师这种级别的人,每年拿到很多越来越吃香。在 IT 行业中能与之对比的是计算机学院的教授和老师,拿着国家的科研经费,做着自己的校企合作项目,一样越老越吃香。

顶级的和顶级的类比。

一般的和一般的类比。

对于普通的程序员而言,能类比的其实只是私立医院的医护团队中的一员。

对于主程序而言,能类比的其实只是私立医院的某个科室主任医师。

对于软件公司的财务人员来说,类比的就是医院的收费员,甚至拿的更多。

对于软件公司的测试人员来说,和护士、CT医生也差不多。

我们有时候犯得错误是,盯到的只是,容易看到的一面。主任医师很亮眼,助理、护士和收费员,谁会多注意呢。

more >>

35岁过后做什么呢?

中年危机

35 岁后程序员就要失业了。

程序员的中年危机说法从我入行的时候就有了,而且还是互联网行业方兴未艾的 7 - 8 年前。

即便如此我还是义无反顾的投入到了程序员大军,虽然当时也有进入体制的机会。选择程序员的原因其实很简单,我希望能从网络上赚到钱,然后找一个小城市生活。

虽然这个理想还没有实现,但是已经被被同学嘲笑过很多遍。高中的时候我就告诉同学,等我赚到 10W 能买套房子的时候,我就拉一根网线回农村,一边写代码一边种地。

回过头来一看,除了医生、教师和公务员之外,哪一个行业没有中年危机呢。

一份特别的 35 岁计划

我给自己的制定了一个 35 岁后被软件行业淘汰后的打算。听起来很蠢,但是又具有理想主义。

我想成为一名英语老师,而且是回到出生的小镇的英语老师。如果被软件公司淘汰后,在回到小镇上,通过网络应该能接到一些小活儿,混口饭吃应该没有问题。

如果我英语还行的话,就能远程的接到一些海外的任务,通过汇率的放大效应,不需要特别辛苦就可以维持一个简单的生活。

我是一个喜欢阅读的人,在我们的镇上甚至没有一家书店,只有卖教辅的文具店。

甚至没有一个阅览室、没有图书馆,只有几家破烂的网吧和台球室。

如果回到小镇上,寻找到一处便宜的场地或许很容易,然后在网上的二手书店采购数千本图书,其实也就是那些文艺青年去趟西藏旅游的费用。如果能得到政府的支持就更好了,没有也无所谓。

我想把这个图小型的图书馆或者叫做阅览室免费开放给全镇的孩子们,也包括我以后的孩子。当慢慢有人知晓这个地方时,我就来教授孩子们英语口语,然后把书籍和英语的世界带给闭塞的西部乡村小镇,并维持这个“图书馆”的运转。

我从小英语很差,因为没有一个真正会说英语的老师,也没有一个不大不小的图书馆,令人悲伤的是 20 年后那个地方依然没有。

焦虑是怎么来的

我曾经有一段时间非常焦虑,不过好在只有一小段时间。

那段时间我在从事咨询和培训工作,偶尔回归到一个开发项目之后,发现自己的手非常生疏,甚至对一些编程中的常用语法都忘记了。

那段时间非常焦虑,疯狂的学习,复习之前的知识,过了大概 2 个月,慢慢的感觉又找回来了。

编程,对于一个软件工程师来说,应该是每日必须练习的,一点都不能丢下。

当我的双手在键盘上能写出自己满意的代码后,焦虑感消失了,我知道不管怎么样,都能找到一家公司能混口饭吃。

焦虑的来源是多方面的。

一些是对未来的害怕。程序员的高溢价很难持续维持,总有一天是会跌回去的,当人习惯了往上走的时候,难以承担往下走。害怕自己没有足够的实力,面对未来的成长。因为软件工作的变化过于迅速,所以这种压力无处不在。其实相比之下,压力更大的是做销售、培训、市场和运营的,程序员的工作至少还能掌握手上,而其他行业的工作都是靠天吃饭。

一些对自己的不满足。对自己的不满足往往都是和别人对比出来的,比如同学、同事和朋友。觉得自己没有什么成就,工作多年也没有什么自己的作品,非常的颓废。对于这一点 ,我们需要知道的是,人的能力是有边界的。无论鸡汤喝的再多,寻求能力边界之外的事情,都会很痛苦,何不做好自己的能力边界的事情呢,让能力强的人去做更多的事情。

看着自己碗里的,盯着别人的锅里的,忘记把自己的饭吃好。程序员就是一个为别人做软件的手艺人,何必天天操心其他老板的生意呢,做软件也是一门生意而已嘛。

最后一些是消费的升级和自我膨胀。程序员是比其他行业多赚了那么一点钱,但是其实也不多。如果程序员被套上了“中产阶级”的圈套,然后进行所谓的消费升级,消费着红酒、咖啡和每年几次的旅游。由俭入奢易,由奢入俭难,消费升级了,就很难降下来。不膨胀,存好钱,过好原本的日子,“手里有粮,心中不慌”。

程序员的降级论

2012年的时候,阅读到一篇文章,是 meditic《降级论》。其中心思想是,如果程序员或者说其他高智力密集性的人,往技术含量更高的领域进军并不一定有优势,而且会混的灰头土脸。

如果转变思路,程序员的逻辑思维能力、分析能力和学习能力在其他领域发展,会得到意想不到的效果。

在 IT 行业里面处处是精英,这些人都是现在说的天龙人,进外企、考CPA、做咨询、云计算各种高大上的领域,用上了各种牛逼的思维。一步一步升级后才发现,身边到处都是精英,自己一点优势没有,还是拿着打工的钱。

反而是小学同学,毕业就在某个作坊跑腿,然后有了自己的作坊,慢慢的那个行业混的风生水起。在高级圈子里混久了,除了焦虑、秃头、挫折,几乎没有什么收获,还不如把高级圈子里面的高级思维带到其他领域去。

程序员如果去培训班教教数学那应该也是很厉害,如果开个水果店,利用自己的写程序能力,说不定也能运转的高效。在追求升级的过程中,会做的很累,因为你在每一次升级都是进入这个级别中的最低线。meditic 的比喻是,升级为大学生的中学生,实际上并不是大学生,而是刚刚完成升学的中学生,他的能力还只是中学生,是无法和大学生竞争的。

如果人生一直在升级,那么就没有时间和精力做点自己该做的事情。不要一直升级,而是应该找到自己的合适的级别,并做到最好。

查理芒格说,“你永远无法赚到超出自己认知以外的钱”。对我们而言,如果一直在升级,就一直无法去把这个级别的事情做到最好。

为什么不尝试降级呢?

more >>

作为 Tech Lead 应该操心什么?

认清 Tech Lead 的位置

对于软件工程师做技术经理是一件好的事情,可以从另外一个更高的角度观察自己现在正在做的事情。

成长为技术经理并不是一件很值得得意的事情,我接触到的技术经理压力都非常大,所以很多人还是愿意做一个纯粹的开发。软件开发行业很其他行业有一个不同的地方就是,会出现 Tech Lead 的角色没人愿意做的现象。

那么 Tech Lead 所处的位置是什么呢?

实现领导的开发目标。软件工程师的职责就是为老板构建可用的软件,至于老板拿这个软件在市场上赚钱和赔钱是市场和老板需要关心的事情。Tech Lead 能够把控产品经理的需求,并对老板给出估算,这事儿靠谱还是不靠谱,需要多久的时间。对老板来说,他不关心具体的技术实现和细节,Tech Lead 能帮他拿捏好,这需求能做还是不能做,能做的话最终能保证出活儿。对老板来说,靠谱是最重要的。

安排好项目的进展情况。如果没有项目经理专门带队做软件研发,Tech Lead 也需要关心项目管理的事情。项目管理并不是发布任务,设定目标,保证目标的达成这么简单。要需要考虑技术选型、技术决策和移除项目的困难点和阻塞点。

关心好团队的成员。 开发人员往往除了工作挣钱之外还有一些自我成长的诉求,所以还需要关心人员的成长,以及帮他们搭舞台唱戏。Tech Lead 不仅仅是给他们分配任务的人,还一定能引导他们的兴趣,尽可能帮他们找到资源,分配给他们感兴趣的任务。毕竟成就他人就是成就自己。

所以在 Thoughtworks 把 Tech Lead 这个角色赋予了四种能力:

  • Expert:是这个项目和产品的核心专家,必须保证有足够的业务知识和技术知识,能把握项目上的一些关键问题
  • Manager:能拆分任务,讲活儿分给其他同事做,并且管理项目的进展
  • Coach: 具有发展他人、团队的能力,能给其他团队成员提供指导和帮助
  • Leader:知道如何用正确的方式达成目标,激励人,知道团队的业务和技术目标

从这四个方面来看,操心的事情不少,后面部分整理了一下作为 Tech Lead 经常要操行的事情。

应该操心什么事情?

技术选型和决策

  • 能根据业务需求做出合理的技术选型
  • 技术选型能满足未来一段时间的业务和架构演进目标
  • 技术选型需要考虑成本
  • 技术选型需要考虑团队人员素质和背景

软件架构和搭架子

  • 服务设计和领域划分
  • 数据库设计
  • 分层架构和包结构的设计
  • 错误码规范和定义
  • API 规划
  • 一些常见操作的例子供开发人员参考
  • 日志和监控设计

需求评审

  • 需求是否合理,业务逻辑上是否自洽
  • 交互设计的性价比
  • 设计的一致性,和项目现有的逻辑是否一致
  • 是否会影响安全
  • 是否会造成性能的大幅度降低

基础设施和运维把控

  • devops 基础设施,例如流水线、制品库、跳板机等
  • 建立运维手册,例如定期拨测和数据备份
  • 定期防灾演练
  • 定期检查系统健康状态,密匙、证书、域名有效期
  • 制定上线流程和规范

非功能性需求

  • 关注需求的性能指标
  • 关注兼容性需求
  • 关注容量和弹性伸缩的需求

代码质量

  • 配置静态代码扫描,例如 checkstyle、find bugs
  • 设计团队代码规范
  • 进行代码评审

安全

  • 安全规范,例如密匙的要求
  • 安全建模
  • 定期的安全扫描工具异常处理
  • 预防技术方案中的潜在安全问题,比如数据和隐私泄露

团队

  • 制定团队协作策略,例如分支策略
  • 制定版本策略
  • 制定团队契约,例如 codereview 时间和主持人、技术例会
  • 对团队新人进行 onboarding 和维护团队 onboarding 文档
  • 人员梯队建设、管理人员流动的任务交接
  • 团队矛盾和冲突处理

知识共享

  • 制定团队技术分享机制
  • 制定文档存放契约
  • 更新系统架构图、部署图和数据库模型等项目架构材料

项目管理

  • 工时估算和迭代计划
  • 技术债的评估和分析
  • 项目风险评估
  • 跟踪第三方依赖的时间点
  • 收集项目反馈

more >>

模型学习法

通过模型学习

我不是一个善于学习的人,我的大脑发展并不均衡:喜欢把一些问题载入大脑慢慢思索,但是记忆力非常差。

用计算机来类比的话,我是那种 CPU 尚可但是硬盘极差,以至于很长一段时间内成绩都不是很好,但是遇到喜欢的科目成绩有特别好。于是在读书生涯中成绩总是起起伏伏。

学习,不仅仅是读书时候的事,工作以后大部分人都必须成为一个终生学习者,否则就会被当前的岗位淘汰。我们应该见过各种各样的学习方法,这篇文章不会成为一种新的学习方法,而是总结前人的经验。

在读书和工作后,我使用过各种各样的学习方法,包括但不限于:

  • 思维导图
  • 费曼学习法
  • 联想法学习英语
  • 写作驱动法

这些方法都非常有效,但不得不承认人的学习能力和智力水平从客观上是有一定差距的,有时候别人可以通过一节课学会微积分的基本方法,而我却需要整整一年去理解和消化微积分到底是什么回事。

智力不够,方法来凑。

硬件不够,软件来凑。

于是我了解了各种各样的学习方法,通过寻找方法来弥补理解能力、记忆方面的不足。慢慢的我了解到,这些学习方法只是一种形式,其背后都是在建立一种让人容易理解的模型。

回忆一下我们的幼儿园是怎么学习算数的?老师会让我们用手指来代替数字,并进行计算。一个中学老师把联想、比喻使用的越好,对学生来说学习效果越好。我们天生难以理解抽象的概念,因为抽象的内容是人定义出来的,是建立在他人的知识背景之上的。对从来没有社会经历的高中生来说,没有为资本家工作过的经历,难以理解什么是“资本主义对人的异化”。在无法理解的情况下,就只能死记硬背,记忆力不好的人处于学习的劣势。

联想和比喻是我们理解事物最重要的方法之一,我们研究的对象是需要学习的知识,被用来联想和比喻的事物就是模型。

模型是什么样的?

在我细致的观察中发现,模型有一些有趣的特点。

模型是多样的。能帮助人理解知识的东西都是模型。教学条件好的地方老师会有各种各样的教具,地理课上老师会拿来地球仪,化学课老师会拿来分子模型,生物学老师会拿来人体模型。因为这些模型和教具,在理解一些知识的时候变得更加容易。但是给了我们一个印象,只有摸得着的东西,用塑料、木材等实物制作而成的才是模型。

这限制了我们的思维。中学时,我特别喜欢物理,为了理解物理学的一些知识,偶然间我在网上找到了一些关于物理学公式的 gif 动图,很多难以理解的东西变得容易理解了。

模型生活中无处不在,只要能拿来联想和比喻的东西都可以作为模型,或纸上、或电脑里。实际上数学、物理公式也是数学、物理的模型,而数学、物理则是宇宙的模型。

模型是简单的。因为知识和概念是复杂、难以理解的,因此我们需要通过类比、比喻来理解,如果我们找了一个模型,本身也很复杂和难以理解,可以说这个比喻并不恰当,或者这个模型并不成功。

模型的简单性是帮助理解的基础,所思维导图做得过于复杂还不如不做,简单性随之而来的是,模型都是错的。模型只能帮助理解知识,但是不能代替知识。

六祖慧能说过:“真理是与文字无关的,真理好像天上的明月,而文字只是指月的手指,手指可以指出明月的所在,但手指并不是明月”。对我们学习来说,模型是手指,而知识是天上的月亮。

什么可以当做模型?

书的目录就是一种模型。

我们把思维导图转换成文字版本就会发现,它和书的目录没有什么区别,只不过突出的重点不同。

对于工作后的人来说,大部分学习都是在电脑上完成的,用来承载知识模型的途径很多。

  1. 思维导图
  2. PPT、keynote 或者一些在线画图工具
  3. markdown 的清单

如果不使用电脑,小抄是一种很好的表达模型的方法。我在一些考试的时候发现,小抄不是为了作弊,而是为了让自己对知识有一个全局的印象,并记住关键知识点,以及知识点之间的练习。

最巧妙的记录小抄的方法是使用一张 A4 纸(只能用一张,不能多),把尽可能关键的信息写在这个纸上。如果写不下,说明这个模型太过于复杂,换一张纸重新整理知识点,直到必要的知识点能在一张 A4 纸上呈现才算完成。

操作方法

模型法学习的关键在于知识的压缩和形象化。压缩是为了提炼出最重要的信息,形象化是为了能真正理解知识。

金岳霖先生在《知识论》中提到过很多处理知识的方法,简单来说,学习就是把凌乱的信息整理成有序的知识,并加以实践和应用的过程。

所以模型学习法有几个过程:

  1. 输入
  2. 压缩、理解、内化
  3. 建立模型
  4. 应用

输入

学习首先得有信息来源,不然理解和内化无法发生,即使能发生也是自己空想。最简单的输入过程就是阅读,除了阅读外和别人交谈、问问题都可以。

刚开始学习一个新东西的时候,需要大量的泛读,即使部分内容无法理解也可以跳过,先积累和寻找大量语料库。我的阅读速度一直都很快,也坚持阅读了大量的材料,有时候会发现前面无法理解的东西,读到后面就能理解了,所以不能因为部分无法理解就停滞不前,因为学习是一个整体性的过程。

个人建议在刚开始泛读时候不要过于在乎笔记,这样会让自己的思维被打断,可以用笔做一些标记或者折叠相应的页码。

压缩、理解、内化

当大量的速读和泛读之后,在脑海中可能会建立起来一个对知识的模糊轮廓。这个时候,需要尝试理解学习的知识到底是个什么?这个时候需要寻找能类比的事物,建立联系。比如 DNA 双螺旋结构的分子式非常像两条缠绕在一起的蛇;波尔的原子模型,可以类比为太阳系的行星结构,它的形象和能级结构非常相似。

理解这些知识后,尝试按照上面的说法,做出思维导图或者写在一张 A4 纸上,我一般喜欢压缩到一页 keynote 中,超过一页的内容就缺乏全局观和简单性。

建立模型

压缩后的知识点可以作为模型的草稿,如果没有什么问题其实就可以当做模型了。不过为了让模型起到帮助记忆和理解的作用,可以通过连线建立起元素之间的关系,画出概念之间的关系,这有点概念图的味道。

删减掉无关重要的的信息,尽可能的让模型保持简单。

应用

除了应试的用途外,如果我们学习到的知识不是为了拿来应用,那么知识也没有什么用处。

应用和实践是让知识记忆的更牢固,“纸上得来终觉浅,绝知此事要躬行”。并且我们建立的模型在实际使用过程中会遇到这样或者那样的问题,当模型并不能很好指导实际应用的时候,我们需要进行修正,并重新投入实践。

应用中获得的反馈也可以作为第一个步骤的输入,而且这个输入更为准确和重要。

写在后面

这篇文章相当于也是我对学习方法建立的一个模型,通过写作来检验这个模型发现还是有效的,所以可以将学习过程总结为:输入、内化、建模和应用。

当然,如果这篇文章对你有用的话,你也可以建立一个自己的学习模型。

more >>

如何提高对自己情绪的控制力?

情绪的亏

我吃过太多被情绪控制,大多数人应该都和我一样。

和家人相处中,明明因为一个小事而已,因为自己的烦躁和不安,表达出厌恶和不喜欢,情绪的传染导致争吵。当冷静下来只有发现完全没有必要争吵。

在工作中,因为同事或者客户一些对自己不好的地方,比如客户无端的额外需求。心生抱怨,除了暴露出去不专业的态度而外,对事情并没有好处。

还会给人留下喜好抱怨的印象。当情绪开始主导人的生活时,自己就成了情绪的奴隶,很难掌控生活的的方方面面。在情绪影响自己的过程中,就好像丢失个人意识,处于一种昏头的状态,只有当事后才能发觉自己当时的行为和决策不是在清醒的状态下做出的。

我相信在生活中因为情绪 “失智” 的状态越来越少时,生活也会更加如意。理解情绪其实还会带来收益,有一些岗位,工资中带有一些对抗情绪压力的成分。因为容易挨骂,所以工资低没人愿意来,只能提高待遇,如果意识到只需要抵抗不良情绪就有收益的,心态是不是马上不一样?

本我、自我、超我

情绪一直是心理学研究的对象之一。

虽然弗洛伊德的理论已经不再是心理学的主流方向,但是他的 “本我、自我和超我”理论还是影响着很多的人。在这个模型下,

  • 本我代表着感性、情绪是一个人做出的自然反应。
  • 自我代表着理性、逻辑是一个人做出利弊分析后的反应。
  • 超我在西方世界观中,代表着神性,用中文语境来说就是贤者模式。

对于情绪的机制来说,情绪是客观的,一直存在的,不因为个人意志而转移。只能说在一定程度上可以被控制、消化,不影响人做出理性的决策和行为。

当一个人的自我和超我大于本我时,他就能掌控自己的情绪。甚至能拿起情绪作为武器达到自己的目的。

利用情绪作为武器,是各种故事不错的桥段。

在三国演义的故事里面,诸葛亮骂王司徒,王司徒被激怒,最终情绪崩溃,一口气上不来倒地了。诸葛亮在他的表现里,自我和超我达到了极致,目标明确,情绪稳定,因此能把情绪作为武器使出。

在《让子弹飞》中有多次利用情绪武器的地方。胡万通过激怒六爷,然后利用六爷的正义感情绪,诱导六爷剖腹取粉,这种情绪的利用非常歹毒。最后麻子利用发钱,黄老爷抢钱唤起群众的反抗情绪,又通过枪毙黄老爷替身的方法消除民众的恐惧情绪,最终推翻黄老爷。

六爷的自我弱于本我,麻子的自我强于本我,事情发展的结果也不一样。

识神、元神

在西方世界中有本我、自我和超我,在中国古代也有类似的理论。就是识神和元神。

中文语境下的“神”代表着意识、精神,比如下笔如有神、失了神等说法

  • 识神,识是佛教用语,六识是“眼耳鼻舌身意”。识神可以简单理解为来自感官的感受和一个人情绪的自然反应。
  • 元神,识神之外的意识,也就是不受外界影响下的清醒理智。

古代的修行的人早就意识到识神和元神构成人的意识,所以需要不断排除识神,而让元神显现。

酒色财气都会让元神受到麻痹,识神被放大。所以古人认为在酒色财气之下是做不出正确的判断,并常常有失格的表现。酒色财气这四样东西都是很危险的。

训练

掌控情绪用中国古代的说法就是识神退位,元神显现。用西方心理学的说法就是强化自我、超我,抵抗本我。

作为一个依然被情绪无时不刻掌控的俗人,给不出好的方法,只能拾人牙慧,随便聊一聊。

世俗的历练

想要成为一个能掌控情绪的人,最终处变不惊,需要有来自大量的世俗经历,见的多了,也就看的淡了。人生经历就像一次一次脱敏训练,情绪反应阈值不断提高,也不会那么咋咋呼呼。

所以那些能在酒桌子上还能清醒自如,实现酒局的目标和价值的人多么厉害。见到过一些政商老江湖,喝的半醉不醉,借着酒劲把话说开,但是内心还是极其清醒。

每次经历都会沉淀为宝贵的人生经验,这是任何情商训练难以达到的。

危险性

对抗情绪,是有危险的。

曾经有一段时间陷入一定的强迫症行为,于是触发了我的好奇心,留意身边的人是否也有类似的行为。发现很多人的强迫行为是因为和情绪对抗造成的。

明明是一件很生气的事情,需要装作没什么事,但是从他的表情中知道并不是真的没事。如果细心观察到的话,会发现大多数人抵抗他们的情绪时显得并不轻松。

后来反思让我走出强迫症的原因,其实非常简单。认识到了自己能力的边界 ,不良情绪是客观存在的,到了一个边界就不再是我的能力可以完全控制的了。撑不下去还强撑,不仅对事情于事无补,而且对身心造成极大损害。

所以学会放弃成了治疗强迫症最好的方法,用流行的话说叫做和内心和解。

more >>

软件工程师的"吵架"文化

吵架的团队更有生命力

看一家软件公司是否靠谱很简单,在开放式的办公室中有没有随处可以使用到的白板就行。

一个好的软件开发团队往往看起来没那么”和谐“,程序员和产品经理之间,程序员和程序员之间是不是会发生”争吵“。好的软件公司没有不吵架的,不吵架的软件公司要么大家都在划水,要么大家为了维护 ”职业形象“处处小心翼翼不敢献计献策。

刚开始和华为的人合作可能会有一些不适应,他们说话的方式简单而直接,往往让人不知所措。这种直接的背后是一种撸着袖子干的企业文化,把”职场文化“变成了团队协作。

软件公司吵架不是管理不善,往往代表着开放、包容的文化,以及团队成员心无芥蒂的通力合作。

回想一下,我们是不是往往都是和陌生人和和气气,和信任的人才大大咧咧呢。

文吵和武吵

不过吵架这事儿还有一些讲究。在公司吵架这事儿分为文吵和武吵:武吵是比谁的嗓门大,谁说话的分量重;文吵讲究的逻辑、推理和归纳。

而武吵和文吵各有用处。

武吵需要的是一个敢于担责,能在关键时候拿出主意的人。在很多讨论会中,群众容易陷入只对自己认知匹配的细节,然后各执一词,都很有道理,也各无过错。这个时候,文吵的逻辑难以派上用场,因为现实世界中没有完美的、正确的方案,只有不那么差的方案。那就需要武吵的人发挥他的影响力,给团队拿个主意,先结束这次讨论,得到一个基本可用的方案来,才能让事情继续。

文吵则不一样,软件开发毕竟是一门科学,大多数情况下需要用到逻辑,通过分析、归纳、总结得到方案。需要收集足够的信息,给出足够的理由,并对方案中的概念给出清晰地定义,最后通过因果分析,证明自己的想法。在大多数情况下,我们更多的需要文吵,通过分析和证明解决遇到的问题。

不管是文吵还是武吵,都需要讲逻辑。只有当团队对这些基本的逻辑规律达成共识的时候,”吵架“才能高效,并且避免落入谬误的陷阱。

逻辑学的三个基本规律

逻辑学的三个基本规律可以让吵架更加准确,避免无意义的争论,减少逻辑矛盾,让吵架有所产出。这三个重要的规律是:同一律、矛盾率、排中律。

同一律

在同一段论述(命题和推理)中使用的概念含义不变,这个规律就是同一律。形式化的表述是 A -> A。

”概念“在逻辑学中的意义非常重要,概念有两个逻辑学规律:内涵和外延。内涵指的是这个概念区别于其他概念的本质属性,例如大熊猫是指的生物学中某一个物种。外延指的是这个概念所能描述的事物的范围,比如白马比马这个概念外延要小,是不同的两个概念。

所以白马非马的本质争论在于自然语言的不确定性:

  • 从概念上说,白马这个概念不是马这个概念。所以白马非马。
  • 从谓词(”是“ 这个谓词)逻辑来说,白马这个概念代表的事物集合属于马这个概念代表的事物集合。所以白马是马(白马属于马,但是白马这个概念不是马这个概念)。

同一律描述的是在一段论述中,需要保持概念的稳定,否则会带来谬误。我在大学辩论赛中利用了这个规律,赢了一次辩论。

当时的论题是”网络会让人的生活更美好吗?“,两个论点主要的论点是:

  • 网络让人们的生活更方便。
  • 网络让人们沉溺虚拟世界。

我们选择的论点是 ”网络让人们的生活更方便“。在辩论赛的前期,另外一方为了论证 ”网络让人们沉溺虚拟世界“,描述了打电话、写信也可以让人生活很美好,并不会沉溺。这刚好落入了我们的逻辑陷阱。我们指出,邮政、电话网络也是网络的一种,对方的逻辑不攻自破。

这属于典型的 ”偷换概念“,我们偷换了“计算机网络”和“网络”这几个概念。

矛盾律

矛盾律应用的更为普遍,几乎所有人都能认识到矛盾律。它的含义是,在一段论述中,互相否定的思想不能同时为真。形式化的描述是: ”A 不能是非 A“。

矛盾律这个词的来源就是很有名的 ”矛和盾“ 的典故,出自《韩非子·难势》中。说有一个楚人卖矛和盾,牛皮吹的过大,说自己的盾在天底下没有矛能刺破,然后又说自己的矛,天底下的盾是不能穿透的。前后矛盾是一个众所周知的逻辑规律,但是并不是一开始马上就能看出来,需要多推理几步才能看出来。即使如此,在同一个上下文中,出现了矛盾的逻辑论述也被认为是不可信的。

具有矛盾的论述有时候又被称为悖论。尤其是宗教领域充满了大量的悖论,例如是否存在一个万能的神,做一件自己不能完成的事情。

矛盾律的用处可以驳斥不合理的论断,也可以用于反证法。在软件开发过程中,我们时常遇到这种情况,需要开发过程中才能发现矛盾。这个很难避免,除非有充足经验的工程师。

需要注意的是逻辑学中的矛盾律和毛泽东思想中的矛盾论不是一回事,前者是逻辑学规律,后者是辨证唯物的一种方法。

排中律

排中律是逻辑规律中最难理解的一个规律。它的表述是:同一个思维过程中,两个互相否定的思想必然有一个是真的。用形式化的表述就是,A 或者非 A。

排中律的意义在于,明确分析问题的时候不能含糊其辞,从中骑墙。比如有人讨论:人是不是动物。不能最终得到一个人既是动物又不是动物,这种讨论是没有意义的。

比如在一次技术会议中,需要选择使用的数据库,只能使用一种数据库。如果采用了 MySQL 就不能说没有采用 MySQL。

排中律看起来好像没有意义,但具有非常大的价值,让讨论最终有结论,而不是处于似是而非的中间状态。

如何诡辩

在争吵中,人们会下意识的引入谬误,从而主动或者被动的诡辩。诡辩的方法非常多,下面聊几个有意思的诡辩方法,认识到诡辩的存在,让吵架的输出更可信。

偷换概念

偷换概念是一种利用同一律的诡辩方法。往往是利用一个词语的多义性来制造诡辩,这种例子相当常见,再一次日常对话中:

朋友:为了让自己的判断和认知更为客观,我们应该同时学习多个学科的东西。

我(故意抬杠):人不能同时学习多个学科的东西。

朋友:为什么,学生不都是同时学习数学、语文、英语么。

我:你现在正在看手上这本书,能同时看我手上这本么。

朋友:。。。(感觉被套路)

我偷换了概念,把 ”同时“ 这个词的时间精度调低了,导致这次对话变了味。

偷换概念在生活中无处不在。《武林外传》

中的秀才利用 ”我“这个概念的偷换,让姬无命莫名其妙并自杀了。

相关性不等于因果性

这个是一个不得不提的诡辩手法,我们从小深受其害。

最经典的例子是,很多父母信佛,然后娃高考的时候天天去求神问佛。如果小孩考上了大学,那么就是拜佛的功劳,如果没有考上,那就是小孩不努力。多么完美的逻辑闭环,完全无懈可击。

同样的桥段在各种电视、电影中存在。某一伙人闯入了一个村子,然后这个村子发生了瘟疫,群众认为是这些人带来了不详。

程序员圈子也会有类似的议论,因为大公司都用的 Java 而不是 PHP,所以 PHP 是一个垃圾语言,我们要成为大公司,所以要把 PHP 换成 java。所以很多公司明明可以苟一下,然后因为折腾死掉了。

我们需要时刻记住,相关性不等于因果性,才能认识到一些微妙的逻辑关系。

因果倒置

”可怜之人必有可恨之处。“ 这是很多人挂到嘴边的话,支持者甚多。

我小的时候对这句话记忆深刻。小学的时候被年长的同学欺负,后来因为打架老师知道了,其他同学都表明我是个被欺负的可怜鬼,老师还是对我们都做出同样的处罚。

说出了一句举世名言:“为什么欺负你,不欺负别人”。

为什么只欺负你,不欺负别人,所以你也不对,同样要受到惩罚。这是典型的强盗逻辑,从结果推导出原因,但是这个原因并不成立,因为我们知道原命题为真,逆命题不一定为真。

归纳法的局限

逻辑学上把个别的知识推广到一般的知识规律叫做归纳推理。归纳推理是一种朴素的认识方法,在逻辑学中,归纳推理有其意义,但是需要注意的是逻辑学从来没有把归纳法得出的结论当做真理。

归纳法的问题和类比谬误类似。古人认识的到了一个规律,鸡叫三遍天会亮,但是后来出去旅游发现其他地方的鸡不是这样的,真的是应了那句,“东方不亮西方亮,黑了南方有北方。”

中国太大了,甚至二十四节气的规律都不能适用于每一个地方。归纳法只能有限的反应某种规律,不能广泛、绝对的得到真理,也不能从个体推出一般。

算命先生希望从四柱八字、面相分析、掌纹、笔迹这些中归纳真理,如果认识到归纳法的局限性,就不会平白无故交这些智商税了。

责任转移

证明神存不存在,保健品有没有功效,壮阳药有没啥作用是科学界三大难题。

从逻辑上证明有其实很容易,只需要找出一个例子即可,比如证明天鹅是白色的,只需要找出一个白色的天鹅即可。但是证明黑色的天鹅不存在,是非常困难的,除非穷举世界上所有的天鹅,才能得出这个结论。

人们的思维中,天生偷懒,所以人们才会有 “宁可信其有,不可信其无”。

所以有一种诡辩,我姑且称之为责任转移,就是在辩论中把举证的责任推给别人,然后再来挑对方的毛病。这是一种非常高级且隐晦的诡辩手段。

比如有神论要求无神论者给出证据,证明神不存在,但是证明无非常困难。对方只能举出一些例子,但是这些例子非常脆弱,如果再结合偷换概念就更无懈可击了。

大师:神会保佑你的。

无神论者:神不存在。

大师:你怎么证明神不存在呢。

无神论者:我从来没看到过神。

大师:没看到过神,不代表神不存在。

无神论者:看都没看见,怎么能说神存在呢。

大师:神是一种信念,它无处不在,慢慢体悟吧。

无神论者:。。。

责任转移大法是不断把举证的责任推给对方,然后在挑错,让对方自顾不暇。

总结

逻辑学中的内容非常多,还有很多有趣规律,比如三段论、命题和演绎等。

但对生活来说,本文介绍的一些方法用于吵架足够了,当然不是为了学习怎么制造诡辩,而是为了分辨诡辩。当我们在工作中交流时,能注意概念的统一和尊重同一律、矛盾律、排中律等逻辑学基本要素时,沟通会变得更加高效,吵架也更加有理有据,并从中得到成长。

more >>

如何克服害怕失败的心理

害怕失败是所有人的共性

”失败是成功之母“。从高中每个月蹭同桌的《青年文摘》中没少看到这类鸡汤。

为什么还想写一篇这样的文章呢,因为我想揭露一个事实,说这话的人不是矫情就是个棒槌。

为什么家庭背景好的人创业人数和成功的几率大很多呢?很多书籍中给出的答案是富人思维、穷人思维等等。其实答案非常简单,就是家庭条件好的人能出去折腾,并有人能兜底。

有人兜底是一个非常重要的因素,比各种 xxx 思维实在很多。正是有人兜底,知道创业失败了还可以回去啃老,不至于流落街头。我毕业时,其中一个室友就被 xxx 国际创业培训坑的没边,毕业后带着几千块跑到沿海城市做互联网思维创业,失败后灰溜溜的又跑回来。所幸家庭条件不差,在家里人的安排下混的不差。

换做当时的我是没这个胆子,毕竟失败了还得租房子、还助学贷款,所以害怕失败是必然的。

害怕是从远古人类就遗传下来保护我们的优良基因,毕竟胆子肥的人都没能活下来。男性对异性的害怕是来源于被种群首领揍的记忆,虽然现在谈恋爱不容易被揍了,但是这种基因还在,所以害怕失败是每个人共同的心理。但现代社会的背景已经发生了变化,原始基因中害怕失败的因子在现代社会中并不是对我们都有利,它让人不敢做出更多的尝试,并失去很多机会。

我一直是一个害怕失败的人,因为我是一个爱多想的人,每一次多想就会放大失败的后果。有趣的是当失败发生在生活中别人的身上时,发现后果并没有那么严重。

故事一,搞出线上事故的程序员

刚毕业工作时候,每次上线都心惊胆战,害怕弄出一个线上问题,然后就被扫地出门了。

这个怂样让当时的老板看不下去了,说了一句至今难忘的名言,”没折腾出线上事故的程序员都还不成熟“。当时不以为然,一个专业的软件工程师怎么能弄出线上事故呢?

工作的阅历告诉我,线上不出事故的软件无非两种情况:1. 软件基本没什么人用,搞出事故也没人发现。2. 技术选择极其保守,稍微不放心的东西都不往生产丢。生产环境的稳定性是很重要,但是过度的保守,害怕新技术的失败会导致项目一潭死水,无法成长。

害怕失败和害怕改变去重构代码的是同一种人。但有一些人的心理素质非常好,不得不佩服,也值得承担更大的责任。

几年前在一个项目上,有一位同事因为上线过程中误操作,造成服务中断,虽然事后也进行了事故回顾,但对他并没有额外的惩罚。实际上其他人也不会对他怎么责备。

其背后的逻辑很简单:

  • 能经常进行生产环境操作的往往都是比较重要的角色,因为生产环境操作比其他同事多,那么造成工作失误的概率自然更大。
  • 换一个人不见得就不会出错。
  • 不害怕出错敢于生产环境操作比其他人更能担责,毕竟有风险的操作总得找一个人做。

所以现实中对失败往往没有那么苛责,完全没失败过的人更可能是没有承担过有风险的工作。敢于直面风险,比逃避得到的不失败更可贵。有时候失败的代价并没有那么大。

故事二,玩垮苏联的戈尔巴乔夫

如果人人害怕失败,将不会有外科医生,因为随便一点失误代表一条命丢在自己手上。

如果人人害怕失败,将不会有国家领导人,可能因为一个错误的决策导致一个国家的命运被葬送。

在读世界的历史中感到非常困惑的一件事,戈尔巴乔夫宣布苏联解体,一个国家的消失,随之带来的是社会的动荡和人民生活的困苦。但是历史上并没有对戈尔巴乔夫追责,甚至他自己也不觉得这种巨大的失败有多了不起。在苏联解体后,戈尔巴乔夫生活的很好,甚至活到现在,并投身政治经济的研究,出了自己的书,还代言了几个著名的品牌。

了解更多苏联的历史后才认识到,戈尔巴乔夫并不是导致苏联解体主要原因,当历史的车轮滚滚向前时,换一个人并不会比戈尔巴乔夫做的更好。戈尔巴乔夫只是让苏联在解体的过程中平滑的失败,虽然苏联最终解体,但是并不剧烈,否则会带来内战。

我们往往把客观的责任主动或者被动的揽到自己身上,一个公司的失败,一个软件项目的失败,往往有它内在的原因。

人们往往以为失败是某一个决策,某一个决策是因为自己做出的,实际上是一种典型的认知错误。失败往往是各种因素的综合结果,决策往往也是因为在当时的历史背景、生活背景下做出的。

过度自责是害怕失败的罪魁祸首。

故事三,害怕失败的技术分享者

软件开发项目往往都会培养技术氛围,会做一些技术分享。有一个项目一个毕业生找我聊天,说自己害怕做分享,觉得要是做得不好太丢人。我问为什么呢?他说其他人的分享内容多么有深度、PPT有多么精美,他自己的分享达不到这个水平,自己一对比相形见绌。

然后发生了一段有意思的对话:

我:你每一天出门都洗头么?

他:不会吧。为什么问这个?

我:你看哈,如果你们组别人洗头了,你某天没洗头,其他人会注意你并笑话你吗?

他:应该不会吧。。。

我:是吧。其实每个人都只关心自己的事情,对别人没那么上心。就算你讲的特别不好,别人也只会在心里笑话你一小会儿,出于礼貌不会笑话你。即使实在是忍不住笑话你,过了第二天大家也就忘了。

他:。。。

然后他还是勇敢的做了一次自己的分享,当然不可能很差了,越是害怕失败的人,鼓起勇气的时候肯定做了最充分的准备。

不要过于在乎别人对自己的评价上,实际上,不洗头出门也没有太多人注意到你。

总结

通过三个简单的小故事,总结下害怕失败的原因和克服害怕失败心理的方法。

害怕失败的原因

  • 没人兜底,确实无法承受失败的后果
  • 生性敏感,过于在乎别人的评价
  • 过于自责,主动或者被动的归责

克服害怕失败的心理的方法

  • 故意犯错,提高害怕的阈值(不是阀值,也不是阙值)
  • 尝试一次不洗头出门,感受下其实别人没那么在乎你
  • 预演失败,如果失败确实是自己无法承受的失败,这种情况下害怕是对的

more >>

软件建模中的逻辑学基础

大家都知道编程需要软件工程师具有很好地的思维逻辑,但是有意思的是,在讨论需求和业务建模过程中,会出现互相指责对方没有逻辑。在我经历过相当多次的同事的争吵中,发现了一个规律:每个人都有自己的思维方式和“逻辑”,并排斥其他人的逻辑。

大多数有经验的开发者、系统分析师都具备一定的辩证思维和方法,要说谁没有逻辑,这件事情很难说得过去。如果每个人都是用自己的思维方式和 “逻辑”,让软件建模的统一语言非常困难。我疑惑的是每个人都相信逻辑是很重要的,但几乎没有文章讨论过软件设计和开发过程中如何使用现代逻辑学。

“每个人都有自己的逻辑“ 这件事情从古希腊、先秦、古印度时期就有了,各种思想家、哲学家用自己的逻辑体系互相辩论,他们的争辩和我们普通人在日常讨论中的争辩没有特别的不同:概念的含混不清、归因谬误、偷换概念等。

本文抽取一些基本的逻辑学知识,讨论其软件建模中的应用。公认的逻辑学之父是亚里士多德,但我们现在使用的逻辑学基础来源于弗雷格、黑格尔以及莱布尼茨等人的工作。

什么是概念?

这个”设备“ 和你说的 ”设备“ 是一回事吗?

曾经参与一个物联网系统的模型设计,”设备“ 这个词在不同的开发者眼里有不同的概念,为此,讨论 ”设备“ 这个词花费了不少的功夫,最终依然没有怎么定义清楚。

逻辑学中非常重要的一项就是 ”概念“,将概念梳理清楚,软件设计也就非常清楚了。我们来讨论下 ”概念“。

”概念是反映对象特有属性或本质属性的思维形式。“

概念不仅是自然世界中的花花草草、风雨雷电等事物,还有社会经济中的商品、货币、阶级和国家等抽象事物,以及人类精神和思维活动中的思维、意识和情感的等。通俗的来说概念就是人们可以认识世界的对象。

柏拉图的 “洞穴神话” 可以让我们对概念的产生进一步认识。假设有些人住在地下的洞穴中,他们是一群囚徒,生来就在地下,坐在地上背对洞口,不能转头看到洞口,只能面向洞壁。在他们身后有一矮墙,墙后面有些人形的生物走过,手中举着各种不同形状的人偶。人偶高过墙头,被一把火炬照着,在洞穴后壁上投下明明灭灭的影子。这些人终生都只能看到这些影子,会认为这些影子就是具体的事物。

“洞穴神话” 告诉了我们我们每天争论的概念,都是每个人技术、生活背景投射的影子。概念会随着人们对事物认识的加深而变化,尊重逻辑的人不会强行要求某个概念比如按照自己的解释(类比中世纪教会对经书的解释权)。

通过属性认识概念和区分概念

正是因为朴素的概念是来源于个人背景和理解,因此概念统一。后来哲学家认识到人们认识概念是由一些更为基础的属性构成的,那可以认为概念就是由属性组成的。比如 ”人“ 这个概念,属性有四肢、直立行走的行为、皮肤光滑等属性。

这些基本的属性又是一些更基本的概念,如果我们对这些基本的概念达成共识,那么我们就有机会对概念进行统一。类似于 Java 中的类有各种属性,这些属性最终都可以通过 8 种基本的数据结构描述。

因此属性是认识概念非常重要的一件事。属性包含了事物自身的性质、行为,比如黑白、高矮,是否能飞行,是否独立行走。事物除了自身的性质外,还与其他事物发生一定的关系,比如大于、相等、对称、属于等。事物的性质、行为以及和其他事物的关系,统称为事物的属性。

通过属性就能找到概念的边界。 具有相同属性的概念是同一个概念,即使是叫法不同也不应该分为不同的概念。比如土豆、马铃薯,一旦属性的增加和移除都算作不同的概念,比如小土豆是土豆吗?通过属性就就能发现生活中的命名谬误,比如小熊猫并不是小的熊猫,而是小浣熊。

概念的表达

概念只是我们对所认识的事物起的一个名字,词语是概念的自然语言形式,概念是词语的思想内容。

一个概念可以具有多种表达方法,对于软件设计来说,我们可以用自然语言描述概念。也可以通过定义一个类来描述,并在程序运行时实例化这个概念。通过数学或者数理逻辑,我们可以使用集合来描述一个概念。

比如 ”商品“ 这个概念,可以通过不同的方法表达。

自然语言中,商品是指可以通过货币或者其他物品交易的物品,可以是自然实体,也可以是虚拟物品。这是社会经济中对商品的描述,商品具有一个核心属性就是价格,有价格意味着可以交易。

自然语言中,概念和词语之间并不是一一对应的,这是需要日常特别注意的。

  1. 自然语言中,任何概念都必须通过词语来表达,但不是所有的词语都表达概念。在语言中,基本上都会将词分为虚词和实词两大类,只有实词(注意不是名词)可以表达概念。
  2. 同一个概念可以由不同的词语表达,比如前面提到的土豆、马铃薯。
  3. 一个词在不同的的情况下(上下文),可以用来表达几个不同的概念,多义词就是这样,同一个词表达不同的概念,叫做这个词的词项。

如果通过计算机语言来描述一个概念,其实就是面向对象中的一个类,这里定义商品有两个属性名称和价格:

public class Goods{
  private String name;
  private int price;
}

如果用集合的枚举法来表述就是商品就是:

Goods{name,price}

计算机语言和数学语言是一种形式化的语言,是可以精确的描述一个概念,但是自然语言只能通过模糊的给出概念的描述。自然语言翻译成计算机语言的不确定性,带来了无休无止的争吵,但这也是软件设计者的主要工作。

概念的内涵和外延

正是因为自然语言的这种模糊性,为了更加具体的描述一个概念。哲学上概念的共识是概念有两个基本的逻辑特征,即内涵和外延。概念反应对象的特有属性或者本质属性,同时也反映了具有这种特有属性或者本质属性的对象,因而概念有表达属性的范围。

  • 概念的内涵是指反映在概念中的对象特有属性或本质属性。
  • 概念的外延是指具有这些属性的所有对象,即囊括对象的范围。

例如商品这个概念的内涵是 ”能进行交换的商品“,本质属性是能进行交换,从本质上区别产品。它的外延就是投入市场能卖的所有事物。

对概念的外延的清晰描述对我们设计软件产品的定位非常有帮助,我们购买软件服务无非两种情况,生活娱乐使用,或者工作使用。马克思社会经济学精妙的描述为生产资料、生活资料。这其中的逻辑完全不同,按照生活资料的逻辑设计一款生产资料的产品注定要走弯路。

概念的内涵和外延在一定条件下或者上下文中被确定的,这取决于参与人的共识。严格锁定概念的内涵和外延,不能帮助我们讨论问题和改进软件模型。随意修改内涵和外延这是典型的偷换概念和诡辩。

概念的内涵和外延是一个此消彼长的兄弟。当内涵扩大时,外延就会缩小,概念就会变得越具体。当内涵缩小时,外延就会扩大,反映的事物就会越多。

在面向对象软件建模中的影响非常明显。对象特有属性或者本质属性越少,那么这个对象能被复用的场景越多,也就是内涵越小。反之,特有属性越多,能被复用的情况就越少了。软件建模过程中随意修改概念往往意识不到,但是每一次属性的添加和移除都带来概念的内涵和外延发生变化。

非常典型的一个例子发生在订单模型中。一般来说,我们会把支付单和订单分开设计,订单的概念中没有支付这个行为,但有时候觉得支付单的存在过于复杂,会将支付单的属性放到订单中,这个时候订单的内涵和外延变了。

内涵和外延发生变化但是设计人员没有意识到,会使用同一个词语。一旦使用同一个词语就会产生二义性,二义性的存在对软件建模是致命性打击。比如用户维护的地址、地址库中的地址、订单中的地址,这三个 ”地址“ 虽然名字相同,但是内涵和外延不同。

意识不到概念的内涵和外延,是无法设计好逻辑良好的软件模型的。

对象命名就是下定义

变量命名和缓存失效是编程中最让人头疼的两件事。

变量命名其实就是在给一个概念下定义。定义是揭示概念的内涵和外延的逻辑方法,一个准确的定义需要反映出对象的本质属性或特有属性。下定义困难普遍有两个痛点:

  1. 不懂好的下定义的逻辑方法。
  2. 对业务概念或者领域不熟悉。

对于第一个痛点,根据概念的属性、内涵和外延,逻辑学中有一些很好地下定义方法。

属加种差定义法。这种下定义的方法通俗来说就是先把某一个概念放到另一个更广泛的概念中,逻辑学中将这个大的概念叫做 ”属概念“,小的概念叫做 ”种概念“。从这个属概念中找到一个相邻的种概念,进行比较,找出差异化本质属性,就是”种差“。比如,对数学的定义,数学首先是一种科学,和物理学处于同类,它的本质属性是研究空间形式和数量关系。于是可以得到数学这个概念定义:数学是一种研究现实世界的空间形式和数量关系的科学。

用这种方法给订单、支付单、物流单下一个定义:

  • 订单是一种反映用户对商品购买行为的凭据。属概念是”凭据“,种差是”反映用户对商品购买行为“。
  • 支付单是一种反映用户完成某一次支付行为的凭据。属概念是”凭据“,种差是”用户完成某一次支付行为“。
  • 物流单是一种反映管理员完成某一次发货行为的凭据。属概念是”凭据“,种差是”管理员完成某一次发货行为“。

在逻辑中可以参考下面的公式:

被定义的概念 = 种差 + 属概念

对于第二个痛点,这不是软件建模能解决的问题,需要充分和领域专家讨论,获取足够的业务知识。人们对概念的定义或者认识是随着对事物的认识不断加深而变化的。一个完全对某个领域没有基本认识的软件工程师很难做出合理的软件建模,例如银行、交易所、财会等领域的软件需要大量的行业知识。

我们做消费者业务的互联网开发时,往往因为和我们的生活相关,所以这种感受并不明显。当做行业软件时,领域知识对软件模型的影响甚至是决定性的。

总结

软件是现实世界在计算机领域的投影,而面向对象建模是软件的骨架。理解面向对象实际上就是在理解哲学、逻辑学,理解概念在现实世界中内涵和外延。也需要理解概念在现实世界中的上下文,也就是逻辑学中的 ”论域“。

对业务模型明确的给出定义,就能给出清晰地对象设计,划分出软件模块。

more >>

程序员的美德:克制、简单和笨拙

Perl 语言的发明人 Larry Wall 一个经典叙述:优秀程序员应该有三大美德:懒惰、急躁和傲慢。

在他的世界观里,懒惰可以驱使你善于利用工具,减少重复劳动;急躁可以驱动你写出高效运行的程序;而傲慢可以让你写出让别人挑不出毛病的程序。

这几项是我进入编程行业一直信奉的真理,这些 “美德” 对于新手来说是很好的提醒。工作很久之后,见识过各种项目以及所谓的最佳实践,对编程有了不同的认识。

我想加上程序员需要坚持的另外一面:克制、简单和笨拙。

克制

技术发展的如此之快,JSP 已经几乎被淘汰了,取而代之的是前后端分离、微服务系统等时髦技术。面对这些新技术时,克制是让你远离很多麻烦的第一步。

曾经有一个客户需要一个简单的信息录入系统,用于管理一些基础的业务需求。我们准备构建一个后端服务来提供 API,团队中一名同事提出想要使用微服务,并坚信所有的新项目都不应该使用 “传统”的单体系统。

后来我们花了半个月的时间构建了后台服务,又花了一周的时间构建了 BFF 为浏览器提供 API 调用,同时以为这两个服务分离开来,又不得不做出一些额外的工作完成鉴权能力。

那位同事显然没有意识到 “微服务” 的本质是一种分布式系统,满足同样的业务需求需要付出巨大的成本。

简单

IT 行业有一个有趣的现象。

每一次技术潮流的到来,并不是这项技术有多大的创新。而是产生了某一个框架让原本高深晦涩的技术变得简单,从而让我们这种低端的程序员也能掌握。

Spring 对于 Java EE开发的简化,让复杂的企业级开发变得足够简单。

深度学习框架对于数学模型的简化,让人人都能参与 AI 开发,即使只是调参侠。

区块链框架对于分布式合约的简化,避免应用开发者需要下场处理分布式问题。

ElasticSearch 对于搜索引擎的简化,让搜索引擎应用得以普及。

这些技术能普及,最基本的原因就是简单。

相反的例子就是传统 Java EE 中的各种设计模式,以及 DDD 中的各种概念,工厂、facade、Event Sourcing,这些模式和概念必然难以在实际项目中推动。

当我在现实中听到某个程序员说在项目中使用了多少种设计模式并引以自豪时,最好的方法就是远离他。

笨拙

笨拙是最难的一个美德。

有太多的程序员,包括我,脑袋里装满了各种高大上的想法,见到一个高级技巧或者技术便如获至宝。

JavaScript 的语言中充满了各种精巧的设计和技术,闭包、原型链等高阶知识是面试必问的。

《代码整洁之道》和《重构》中各种高级的编码技巧。

Scala 中各种不同的编程范式,C++ 中的模板、运算符重载等高科技。

我以为我永远到不了编程大师的水平。直到后来阅读了一些源码, Backbone.js 和 Redis 让我印象深刻。朴实无华的设计,有很多逻辑判断写的非常普通,没有过多的设计模式。

当我知道 Intellij IDE 是用 Swing 开发而成的时候,惊叹不已,用最简单的食材做出最美味的食物,这才是真正的编程大师吧。

more >>