专注、坚持

10x 程序员工作法

2019.08.01 by kingcos
Name Author ISBN
10x 程序员工作法 郑晔 -
  • 本质复杂度(Essential Complexity)和偶然复杂度(Accident Complexity)。 简单来说,本质复杂度就是解决一个问题时,无论怎么做都必须要做的事,而偶然复杂度是因为选用的做事方法不当,而导致要多做的事。

  • 大部分程序员忙碌解决的问题,都不是程序问题,而是由偶然复杂度导致的问题。

  • 以终为始; 任务分解; 沟通反馈; 自动化。

  • 在我看来,所有做软件的人能力都很强,这些问题都只是因为不会工作造成的,但更可怕的是,许多人深陷泥潭而不自知。

  • 直觉是本能的,无需积累,而洞见是溯因推理(Abductive Reasoning),需要前期进行大量的积累之后,从中发现模式,方能形成洞见。

  • 你把结果当成了原因,优秀的程序员能够快速解决问题,是因为它已经做了大量积累,有自己的知识体系,任何领域想做到一定的水准都需要刻意练习,而且是大量的刻意练习。

  • 我希望专栏的读者在学过之后,遇到事情开始动脑想想为什么和怎么做,你的回复让我觉得我的初衷达成了。

  • t.cn/EGeYlAA,一个讲本质复杂度和偶然复杂度的视频

  • Where are we?(我们现在在哪?) Where are we going?(我们要到哪儿去?) How can we get there?(我们如何到达那里?) 这三个问题实际上是帮我们确定: 现状; 目标; 实现路径。 如果一个人能够清晰地回答出这三个问题,通常意味着他对要做的事有着清晰的认识。

  • 工作。比如,

  • 比如,当一个产品经理给我交代一个要开发的功能特性时,我通常会问他这样一些问题: 为什么要做这个特性,它会给用户带来怎样的价值? 什么样的用户会用到这个特性,他们在什么场景下使用,他们又会怎样使用它? 达成这个目的是否有其它手段?是不是一定要开发一个系统? 这个特性上线之后,怎么衡量它的有效性?

  • 给出思考框架是为了让你明白为什么要提出问题,而具体问题要怎么问,就可以遵循下面这四项原则: 以终为始; 任务分解; 沟通反馈; 自动化。

  • 以终为始就是在工作的一开始就确定好自己的目标。我们需要看到的是真正的目标,而不是把别人交代给我们的工作当作目标。

  • 任务分解是将大目标拆分成一个一个可行的执行任务,工作分解得越细致,我们便越能更好地掌控工作,

  • 沟通反馈是为了疏通与其他人交互的渠道。一方面,我们保证信息能够传达出去,减少因为理解偏差造成的工作疏漏;另一方面,也要保证我们能够准确接收外部信息,以免因为自我感觉良好,阻碍了进步。

  • 自动化就是将繁琐的工作通过自动化的方式交给机器执行,这是我们程序员本职工作的一部分,我们擅长的是为其他人打造自动化的服务,但自己的工作却应用得不够,这也是我们工作中最值得优化的部分。

  • 产品经理把要做的功能特性摆在我面前。站在以终为始的角度,我需要了解真正的目标是什么,所以,我会关心为什么要做这个特性。为了保证目标是有效的,我会关心它给用户带来的价值。

  • 以终为始,确定好真实目标; 任务分解,找到实施路径; 沟通反馈,解决与人打交道出现的问题; 自动化,解决与机器打交道出现的问题。

  • 面对问题时,用思考框架问问自己,现状、目标和路径。

  • 关于 X-Y problem,可以看下隔壁专栏作者耗叔的 https://coolshell.cn/articles/10804.html

  • 任何事物都要经过两次创造:一次是在头脑中的创造,也就是智力上的或者第一次创造(Mental/First Creation),然后才是付诸实践,也就是实际的构建或第二次创造(Physical/Second Creation)。

  • 对做软件的人来说,我们应该把“终”定位成做一个对用户有价值的软件,能够为别人带来价值,自己的价值才能体现出来。

  • 践行“以终为始”就是在做事之前,先考虑结果,根据结果来确定要做的事情。

  • 弥合差异的方式有很多,有一个最佳实践,它的名字叫 DoD(Definition of Done,完成的定义),

  • DoD 是一个清单,清单是由一个个的检查项组成的,用来检查我们的工作完成情况。

  • 但如果你的团队认为除了功能代码,其他都没价值,也许这是个信号,说明你的团队整体上是缺乏职业素养的,在这样的团队工作,前景并不乐观。

  • DoD 的检查项应该是实际可检查的。

  • 当我们有了 DoD,做事只有两种状态,即“做完”和“没做完”。

  • 在团队层面,我们也可以定义 DoD。 某个功能的 DoD,比如:这个功能特性已经开发完成,经过产品负责人的验收,处于一个可部署的状态。 一个迭代的 DoD,比如:这个迭代规划的所有功能已经完成。 一次发布的 DoD,比如:整个软件处于可发布的状态,上线计划已经明确。

  • DoD 是一个的思维模式,是一种尽可能消除不确定性,达成共识的方式。

  • 在做任何事之前,先定义完成的标准。

  • 信息的传递是会衰减的,你不可能把你理解的信息 100%传递给另外一个人,而这中间,如何传递,也就是如何描述将直接决定衰减的比例。

  • 这种功能列表式的需求描述方式,将一个完整的需求敲成了碎片。

  • 用户故事(User Story)是我最喜欢的一种方式。它是站在用户的角度来描述了一个用户希望得到的功能,关注用户在系统中完成一个动作需要经过怎样的路径。

  • 标题,简要地说明这个用户故事的主要内容,比如:注册用户使用用户名密码登录。 概述,简要地介绍这个用户故事的主要内容,一般会用这样的格式: As a (Role), I want to (Activity), so that (Business Value). 意思就是:作为一个什么角色,要做什么样的事,以便达成一种怎样的效果。其中最重要的是,告诉别人为什么要做这件事,虽然只有一句话,却往往是很多人欠缺的思考,只知做,不知为何做。 举个概述的例子:作为一个注册用户,我想要通过用户密码登录,以便我可以使用注册用户才能够使用的服务。 详述,详细地描述这个用户故事的完整流程,我们会把操作流程、用户界面等信息都放到这里。 比如:用户使用正确用户名和密码登录,就可以登录成功;如果密码不正确,则登录页面提示用户“用户名密码不正确”。基本上,看到这个部分,程序员就可以在心中描绘出这个用户故事的样子了。 超出范围的部分,比如:第三方登录不在范围内,这个部分主要是限定人们不要进一步发散。 验收标准,这个部分会描述一个正常使用的流程是怎样的,以及各种异常流程系统是如何给出响应的,这是程序员常常会欠缺的思考。它会把详述中很多叙述的部分变成一个具体的测试用例。比如,下面我给出的两个验收用例: 正常场景:给定一个注册用户张三,其用户名是 zhangsan,密码是 foobar,当张三使用 zhangsan 和 foobar 登录系统时,可以成功登录,登录成功后,跳转到用户中心。 异常场景:给定一个注册用户张三,其用户名是 zhangsan,密码是 foobar,当张三使用 zhangsan 和 wrong 登录系统时,登录失败,在登录页面上提示“用户名密码不正确”。 在前面的例子中,小张和小王之所以会对需求是否完成产生分歧,是因为大家对于需求完成的定义不同。对于这种情况,我们能怎么办呢?

  • 验收标准非常重要的一环是异常流程的描述。

  • 验收标准给出了这个需求最基本的测试用例,它保证了开发人员完成需求最基本的质量。如果你了解 BDD(Behavior-Driven Development,也就是“行为驱动开发”),就可以按照验收标准中给出的内容编写验收测试用例了。

  • 如果你的团队采用用户故事的格式进行需求描述固然好,如果不能,在功能列表中,补充验收标准也会极大程度地改善双方协作的效率。

  • 扮演不同角色的时候,我们的思考模式是不同的。

  • 最好维护的代码是没有写出来的代码。

  • 在做任何需求或任务之前,先定好验收标准。

  • 写代码是程序员的职责,但我们更有义务交付一个可运行的软件。

  • 尽早提交代码去集成。

  • IT 行业中大多数人的专业程度是不够的。

  • 软件开发的主流由面向确定性问题,逐渐变成了面向不确定性问题。

  • 精益创业就是在尽可能少浪费的前提下,面向不确定性创造新事物。

  • 最小可行产品,也就是许多人口中的 MVP(Minimum Viable Product)。简言之,少花钱,多办事。

  • 精益创业提供给我们的是一个做产品的思考框架,我们能够接触到的大多数产品都可以放在这个框架内思考。

  • 比较早成型的面向不确定创造新事物的方法论是精益创业,它提出了“开发(build)-测量(measure)-认知(learn)”这样一个反馈循环和最小可行产品的概念。

  • 默认所有需求都不做,直到弄清楚为什么要做这件事。

  • 不同角色工作上真正的差异是上下文的不同。

  • 虽然写的代码都一样,但你看到的是树木,人家看到的是森林,他更能从全局思考。

  • 我并不是靠技术能力解决了问题,而是凭借对需求的理解把这个问题绕过去了。

  • 而能想到问这样的问题,前提就是要跳出程序员角色思维,扩大自己工作的上下文。

  • 当你对软件开发的全生命周期都有了认识之后,你看到的就不再是一个点了,而是一条线。与别人讨论问题的时候,你就会有更多的底气,与那些只在一个点上思考的人相比,你就拥有了降维攻击的能力。

  • 扩大自己工作的上下文,别把自己局限在一个“程序员”的角色上。

  • 在动手做一件事之前,先推演一番。

  • 一些人说,自己靠直觉就能把事情做好,其实这是一种误解,因为那种所谓的直觉,通常是一种洞见(Insight),洞见很大程度上依赖于一个人在一个领域长期的沉淀和积累,而这其实是某种意义上的大数据。

  • 当事情复杂到一定程度时,简单地靠感觉是很难让人相信的。

  • 问一下自己,我的工作是不是可以用数字衡量。

  • 你会发现,我在建议用数字来发现问题和解决问题,但我不倾向用数字做为绩效,因为太具有误导性了,至少现在还没有哪个指标是令人信服的。我知道很多公司用代码量和 BUG 数,但我认为,这些指标应该用来发现问题,而不是当作绩效标准。

  • 这里给出的迭代 0,它的具体内容只是基本的清单。

  • 把测试当作规范确定下来的办法就是把测试覆盖率加入构建脚本。

  • 设计你的迭代 0 清单,给自己的项目做体检。

  • 说“不”,这是一个思想上的转变。很多人受到传统官本位思想的影响,对上级的服从达到了不健康的程度。勇于改变,是有效管理上级的前提条件。

  • 第一,管理上级的预期。

  • 这个过程,相当于我把自己看到的问题暴露给上级,让他选择。

  • 第二,帮助上级丰富知识。

  • 第三,说出你的想法。

  • 不合理的部分应该是他和老板去沟通的,而不是让开发团队来实现。

  • 竞争对手有这个特性,他为什么要做?他做这个特性与它其他特性是怎么配合的?我们做这个特性,在我们的产品里怎样发挥价值?作为产品经理,你必须给我讲清楚这些。

  • DoD,确定好完成的定义,减少团队内部的理解不一致。 用户故事,细化出有价值的需求。 持续集成,通过尽早集成,减少改动量,降低集成的难度。 精益创业,减少过度开发不确定性产品带来的浪费。 迭代 0,在项目开始之前,做好一些基础准备。

  • 任何事物都要经过两次创造:一次是在头脑中的创造,也就是智力上的或者第一次创造(Mental/First Creation),然后才是付诸实践,也就是实际的构建或第二次创造(Physical/Second Creation)。 在更大的上下文内发现自己的“终”。 通过推演,找到通往“终”的路径。 用可度量的“数字”定义自己的“终”。

  • 作为程序员,你可以管理你的上级; 拿老板说事的产品经理,你可以到老板面前澄清; 喜欢无脑抄袭的产品经理,让他回去先想清楚到底抄的是什么; 分清楚需求和技术,产品经理和开发团队各自做好各自的事。

  • 思考框架是道,原则是演化下的术,我们从 A → B,有无穷无尽的路径,最有效的唯有那条直线。本质上,各个维度、原则(不限于作者提到的四项原则)都是帮助我们更好地定位 A 在哪里,B 在哪里,那条直线在哪里。

  • “以终为始”,最常见的一个实践就是计划倒排了。先定时间,然后看功能是不是做不过来得砍掉一些,人力是不是不够需要补充一些,提前预知规避风险。

  • 推演可以发现达成目标会涉及到哪些部门、哪些利益相关者,需要哪些资源,以及他们需要何时怎样的配合。

  • 德雷克公式最大的作用在于:它将一个原本毫无头绪的问题分解了,分成若干个可以尝试回答的问题。

  • 不同的可执行定义差别在于,你是否能清楚地知道这个问题该如何解决。

  • 如今软件行业都在提倡拥抱变化,而任务分解是我们拥抱变化的前提。

  • 动手做一个工作之前,请先对它进行任务分解。

  • 一个软件是由它内部诸多模块组成的,测试人员只从外部保障正确性,所能达到的效果是有限的。

  • 软件变更成本,它会随着时间和开发阶段逐步增加。

  • 需求人员要确定验收标准,开发人员则要交出自己的开发者测试。这是一个来自于精益原则的重要思想:内建质量(Build Quality In)。 所以,对于每个程序员来说,只有在开发阶段把代码和测试都写好,才有资格说,自己交付的是高质量的代码。

  • 这种测试框架最大的价值,是把自动化测试作为一种最佳实践引入到开发过程中,使得测试动作可以通过标准化的手段固定下来。

  • 将测试分成关注最小程序模块的单元测试、将多个模块组合在一起的集成测试,将整个系统组合在一起的系统测试。

  • 越是底层的测试,牵扯到相关内容越少,而高层测试则涉及面更广。

  • 小事反馈周期短,而大事反馈周期长。

  • 因为涉及到的模块过多,任何一个模块做了调整,都有可能破坏高层测试,所以,高层测试通常是相对比较脆弱的。

  • 虽然冰淇淋蛋卷更符合直觉,但测试金字塔才是行业的最佳实践。

  • 多写单元测试。

  • 测试先行开发和测试驱动开发在第一步和第二步是一样的,先写测试,然后写代码完成功能。二者的差别在于,测试驱动开发并没有就此打住,它还有一个更重要的环节:重构(refactoring)。

  • 在之前的“蛮荒时代”,我们通常会写一个假的类,模拟被依赖那个类,因为它是假的,我们会让它返回固定的值,使用这样的类创建出来的对象,我们一般称之为 Stub 对象。

  • 写代码之前,请先想想怎么测。

  • 我们应该编写可测的代码。

  • Kent Beck 那本知名的软件工程之作《解析极限编程》(Extreme Programming Explained)。这是一本重要的作品,它介绍了一种软件开发方法:极限编程。

  • 极限编程之所以叫“极限”,它背后的理念就是把好的实践推向极限。

  • 前面提到持续集成时,我们已经介绍过这个理念,如果集成是好的,我们就尽早集成,推向极限每一次修改都集成,这就是持续集成。 如果开发者测试是好的,我们就尽早测试,推向极限就是先写测试,再根据测试调整代码,这就是测试驱动开发。 如果代码评审是好的,我们就多做评审,推向极限就是随时随地地代码评审,这就是结对编程。 如果客户交流是好的,我们就和客户多交流,推向极限就是客户与开发团队时时刻刻在一起,这就是现场客户。

  • Kent Beck 的做法清晰而有节奏,每个任务完成之后,代码都是可以提交的。

  • 大多数程序员之所以开发效率低,很多时候是没想清楚就动手了。

  • 如果你有了一个微习惯,坚持就不难了。

  • 一个经过分解后的任务,需要关注的内容是有限的,我们就可以针对着这个任务,把方方面面的细节想得更加清晰。很多人写代码之所以漏洞百出,一个重要的原因就是因为任务粒度太大。

  • 将任务拆小,越小越好。

  • 朋友。 精选留言: 葛聂 2019-01-30 07:26:21 很受启发 [5 赞] Y024 2019-02-03 20:22:07 Feature

  • Feature toggle(功能开关)分享两篇文章: https://martinfowler.com/articles/feature-toggles.html https://www.infoq.cn/article/function-switch-realize-better-continuous-implementations

  • 领域对象,这里就是用户。 数据访问层,在不同的项目里面叫法不一,有人从 J2EE 年代继承下来叫 DAO(数据访问对象,Data Access Obejct),有人跟着 Mybatis 叫 mapper,我现在更倾向于使用领域驱动设计的术语,叫 repository。 服务层,提供对外的应用服务,完成业务处理。 资源层,提供 API 接口,包括外部请求的合法性检查。

  • 很多人可能更习惯一个类一个类的写,我要说,最好按照一个需求、一个需求的过程走,这样,任务是可以随时停下来的。

  • 检验每个任务项是否拆分到位,就是看你是否知道它应该怎么做了。

  • 所有分解出来的任务,都是独立的。也就是说,每做完一个任务,代码都是可以提交的。只有这样,我们才可能做到真正意义上的小步提交。

  • 按照完整实现一个需求的顺序去安排分解出来的任务。

  • 建议:千万别上来就给表取名 users。https://codewithoutrules.com/2018/09/21/users-considered-harmful/?utm_source=wanqu.co&utm_campaign=Wanqu+Daily&utm_medium=website

  • 主要是因为这些测试不够简单。只有将复杂的测试拆分成简单的测试,测试才有可能做好。

  • 把测试写简单,简单到一目了然,不需要证明它的正确性。

  • 我把这段代码分成了四段,分别是前置准备、执行、断言和清理,这也是一般测试要具备的四段。

  • 这个测试一旦出错,就需要把所有相关的几个方法都

  • Automatic,自动化; Thorough,全面的; Repeatable,可重复的; Independent,独立的; Professional,专业的。

  • 要想写好测试,就要写简单的测试。

  • 测试里就不应该有 for 循环,你为什么要有那么多结果去检查呢?用少量数据也是可以的,你需要理解测试等价类的概念。

  • 基本上,闯入你脑海的需求描述是主题(epic),在敏捷开发中,有人称之为主用户故事(master story)。

  • 绝大多数问题都是由于分解的粒度太大造成的,少有因为粒度太小而出问题的。所以,需求分解的一个原则是,粒度越小越好。

  • Independent,独立的。一个用户故事应该完成一个独立的功能,尽可能不依赖于其它用户故事,因为彼此依赖的用户故事会让管理优先级、预估工作量都变得更加困难。如果真的有依赖,一种好的做法是,将依赖部分拆出来,重新调整。 Negotiable,可协商的。有事大家商量是一起工作的前提,我们无法保证所有的细节都能 100%落实到用户故事里,这个时候最好的办法是大家商量。它也是满足其它评判标准的前提,就像前面提到的,一个用户故事不独立,需要分解,这也需要大家一起商量的。 Valuable,有价值的。一个用户故事都应该有其自身价值,这一项应该最容易理解,没有价值的事不做。但正如我们一直在说的那样,做任何一个事情之前,先问问价值所在。 Estimatable,可估算的。我们会利用用户故事估算的结果安排后续的工作计划。不能估算的用户故事,要么是因为有很多不确定的因素,要么是因为需求还是太大,这样的故事还没有到一个能开发的状态,还需要产品经理进一步分析。 Small,小。步子大了,不行。不能在一定时间内完成的用户故事只应该有一个结果,拆分。小的用户故事才方便调度,才好安排工作。 Testable,可测试的。不能测试谁知道你做得对不对。这个是我们在前面已经强调过的内容,也就是验收标准,你得知道怎样才算是工作完成。

  • 用户故事,之所以是故事,就是要讲,要沟通。

  • 估算的结果是相对的,不是绝对精确的,我们不必像做科研一样,只要给出一个相对估算就好。

  • 一般来说,估算的过程也是大家加深对需求理解的过程。

  • 如果你对用户故事这个话题感兴趣,推荐阅读 Mike Cohn 的两本书《User Stories Applied》和《Agile Estimating and Planning》。

  • 想要管理好需求,先把需求拆小。

  • 先将需求分成用户故事,只有到达可以评估的大小,你才能更好地理解,才能开始做后续的工作。

  • 就凭一句“老板说的”,我们就可以判断出,产品经理缺乏对需求管理应有的理解。

  • 按照时间管理的理念,重要且紧急的事情要立即做。重要但不紧急的事情应该是我们重点投入精力的地方。紧急但不重要的事情,可以委托别人做。不重要不紧急的事情,尽量少做。 这个矩阵带给我们思维上最大的改变是,让人意识到事情和事情不是等价的。如果不把精力放在重要的事情上,到最后可能都变成紧急的事情。

  • 当员工想不明白的事,换成老板的视角就全明白了。

  • 很多所谓的人生难题不过是因为见识有限造成的。比如,如果你觉得公司内总有人跟你比技术,莫不如把眼光放得长远一些,把自己放在全行业的水平上去比较。因为你是为自己的职业生涯在工作,而不是一个公司。

  • 尽量做最重要的事。

  • 我们要做的是验证一个想法的可行性,甚至不是为了开发一个软件,开发软件只是一种验证手段。

  • 我们开发软件的目的是为了解决问题,如果不写软件就把问题解决了,岂不是更好。

  • 不是一个模块做得有多完整,而一条用户路径是否通畅。

  • 当时间有限时,我们需要学会找到一条可行的路径,在完整用户体验和完整系统之间,找到一个平衡。

  • 最小可行产品(Minimum Viable Product,MVP)。最小

  • 想要在实践中运用好最小可行产品的理念,就是要用最小的代价找到一条可行的路径。最小的代价就是能不做的事就不做,能简化的事情就简化。

  • 做好产品开发,最可行的方式是采用 MVP。

  • Spike 的作用就在于消除不确定性,让项目经理知道这里要用到一项全团队没有人懂的技术,需要花时间弄清楚。

  • 其次,我们要确定两件事:这项技术在项目中应用场景和我们的关注点。

  • 当你确定要使用这项技术时,请丢弃掉你的原型代码。

  • 把测试覆盖率检查加入到工程里,得到现有的测试覆盖率。 将测试覆盖率加入持续集成,设定当前测试覆盖率为初始值。测试覆盖率不达标,不许提交代码。 每周将测试覆盖率调高,比如,5%或 10%,直到测试覆盖率达到 100%。

  • 如果在一个分支上怎么做呢?可以考虑采用 Branch by Abstraction,简言之,再动手改造之前,先提取出来一个抽象,把原先的实现变成这个抽象的一个实现,然后,改造的过程就是提供这个抽象的一个新实现。

  • http://t.cn/EIjW8su

  • 只有理解清楚了自己的问题,才好应用新技术去解决,盲目地采纳新技术,只会让自己不断地纠结,小程序库还好,要是引入一个大框架,无穷的问题就会吞噬你的时间。

  • 测试金字塔 – 行业中测试组合的最佳实践。 – 多写单元测试是关键。 测试驱动开发 – 测试驱动开发的节奏是:红——绿——重构,重构是测试驱动开发区别于测试先行的关键。 – 有人把测试驱动开发理解成测试驱动设计,它给行业带来的思维改变是,编写可测的代码。 艾森豪威尔矩阵(Eisenhower Matrix) – 将事情按照重要和紧急进行划分。 – 重要且紧急的事情要立即做。重要但不紧急的事情应该是我们重点投入精力的地方。紧急但不重要的事情,可以委托别人做。不重要不紧急的事情,尽量少做。 最小可行产品 – “刚刚好”满足客户需求的产品。 – 在实践中,要用最小的代价找到一条可行的路径。

  • 尽量不写 static 方法; 主分支开发模型是一种更好的开发分支模型; 好的用户故事应该符合 INVEST 原则; 估算是一个加深对需求理解的过程,好的估算是以任务分解为基础的; 好的测试应该符合 A-TRIP。

  • 分而治之,是人类解决问题的基本手段; 软件变更成本,它会随着时间和开发阶段逐步增加; 测试框架把自动化测试作为一种最佳实践引入到开发过程中,使得测试动作可以通过标准化的手段固定下来; 极限编程之所以叫“极限”,它背后的理念就是把好的实践推向极限; 大师级程序员的工作秘笈是任务分解,分解到可以进行的微操作; 按照完整实现一个需求的顺序安排开发任务。

  • 对不了解技术的任务,先要去了解技术,然后再做任务分解; 通过一次技术 Spike ,学习新技术; 丢弃掉在 Spike 过程中开发的原型代码; 分清目标与现状,用目标作为方向,指导现状的改变; 多个功能并行开发可以考虑使用 Feature Toggle; 在遗留系统上做改造可以考虑使用 Branch by Abstraction 。

  • 我们努力地学习各种知识,为的就是更好地理解这个世界的运作方式,而沟通反馈,就是我们与真实世界互动的最好方式。

  • 信源(Information Source),它负责产生信息(Message)。 发送器(Transmitter),它会对信息进行某些操作,也就是对信息编码,产生信号(Signal)。 信道(Channel),它是信号传送的媒介。 接收器(Receiver),它是对信号执行发送器的逆操作,解码信号,提取出信息。 信宿(Destination),它负责接收信息。

  • 图中还有一个因素叫做噪声(Noise),指的是削弱信号的东西。

  • 信息的传达要经过编码和解码两个过程,无论是编码出现问题,还是解码出现问题,都会造成信息的不准确。

  • 因为每个人经历见识的差异,造成了各自编解码器的差异。世界是同一个世界,每个人看到的却是千姿百态。

  • 我们要想让自己更好地工作生活,就必须接纳真实世界的反馈,而接纳真实世界的反馈,一是需要我们打开自己的接收器,把信号接纳进来,让反馈进来,这是解码的前提;二是扩展见识,提升自己解码器的效果,更好地理解别人要表达的内容到底是什么。

  • 编解码器算法,也就是怎么协调沟通双方更有效地进行沟通。

  • 通过沟通反馈,不断升级自己的编解码能力。

  • 叫做《程序设计实践》(The Practice of Programming)

  • 计算机科学中只有两大难题:缓存失效和命名。 —— Phil Karlton

  • 名字起得是否够好,一个简单的评判标准是,拿着代码给人讲,你需要额外解释多少东西。

  • 任何人都能写出计算机能够理解的代码,只有好程序员才能写出人能够理解的代码。 —— Martin Fowler

  • 人要负责将业务问题和机器执行连接起来,缺少了业务背景是不可能写出好代码的。

  • Robert Martin 的《代码整洁之道》(Clean Code),

  • 用业务的语言写代码。

  • 开会是为了解决问题,但真实情况却是开了会又没有解决多少问题,这真是一个奇特的矛盾。

  • 凡是效果特别好的会议,基本上都是用来做信息同步的。

  • 改善会议的第一个行动项是,减少参与讨论的人数。

  • 所以,我们的第二个行动项是,如果你要讨论,找人面对面沟通。

  • 在有限的时间内,你能说什么呢?我建议你只说三件事: 我昨天做了什么? 我今天打算做什么? 我在过程中遇到了什么问题,需要请求帮助。

  • 多面对面沟通,少开会。

  • Amazon 的开会方式值得借鉴。https://www.36kr.com/p/203274

  • 事件风暴(Event Storming)放到了“采用”中,如果你还不了解 事件风暴 是什么,强烈建议你点击链接了解一下。

  • 雷达图是一种很好的将知识分类组织的形式,它可以让你一目了然地看到并了解所有知识点,并根据自己的需要,决定是否深入了解。

  • 多尝试用可视化的方式进行沟通。

  • 想要做好持续集成,就需要顺应持续集成的本质:尽快得到工作反馈。

  • 执行同样的操作,本地环境会快于 CI 服务器环境。

  • 如果你对心流的概念感兴趣,可以去读米哈里·契克森米哈赖的著作《心流》,这位作者就是心流概念的提出者。

  • 只有 CI 服务器处于绿色的状态才能提交代码。有检查

  • 想做好持续集成的一个关键点是,用好本地构建脚本(build script),保证各种各样的检查都可以在本地环境执行。

  • 持续集成是软件开发中的重要实践,做好持续集成的关键在于,快速反馈。

  • 做好持续集成的关键在于,快速反馈。

  • 这种把过程还原,进行研讨与分析的方式,就是复盘。

  • 用别人的视角看问题,这就是客体化。

  • 作为组织者,我会先在白板上给出一个主题分类。我常用的是分成三类:“做得好的、做得欠佳的、问题或建议”。 还有不同的主题分类方式,比如海星图,分成了五大类:“继续保持、开始做、停止做、多做一些、少做一些”五类。

  • 一个是写事实,不要写感受。

  • 每张便签只写一条,因为后面我要对便签归类。

  • 所有给出的行动项应该都是可检查的,而不是一些无法验证的内容。

  • 定期复盘,找准问题根因,不断改善。

  • 首先,先对比实际结果和期初所定目标之间有什么差距。其次,情景再现,回顾项目的几个阶段。然后,对每个阶段进行得失分析,找出问题原因。最后,总结规律,化作自己的技能沉淀,再次遇到时可以规避。我再补充一点,复盘资料应该记录到知识库,无论新来的或是接手的人,都能从中获益,从而提升组织的能力。

  • 由听产品经理的话,扩大成倾听用户的声音。

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

  • 多走近用户。

  • 能用尽可能小的时间颗粒度来安排自己的工作。

  • 你的思维方式是否合适,由此产生的执行方式是否到位,检验方式是否科学,理论修正是否能产生更好的思维方式。

  • 不是所有的问题,都是值得解决的技术难题。

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

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

  • 事情往前做,有问题尽早暴露。

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

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

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

  • 输出的过程,本质上就是把知识连接起来的过程。

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

  • 多输出,让知识更有结构。

  • 持续集成的价值在于,它是一条主线,可以将诸多实践贯穿起来。

  • 国内程序员真正落后的不是信息,而是观念。

  • 看板 一种来自精益生产的可视化实践。 按阶段将任务放置其中。 可以帮助我们发现问题。 持续集成 做好持续集成的关键是,快速反馈。 本地检查通过之后再提交。 找到有效的反馈方式,比如:CI 监视器。 持续集成的纪律。 只有 CI 服务器处于绿色的状态才能提交代码。 CI 服务器一旦检查出错,要立即修复。 回顾会议 软件团队复盘的一种实践。 枚举关注点,选出重点,深入讨论,列出行动项,找到负责人。 5 个为什么 又一个来自丰田的实践。 沿着一条主线追问多个问题。

  • 用信息论理解沟通反馈 写代码的进阶路径 编写可以运行的代码。 编写符合代码规范的代码。 编写人可以理解的代码。 用业务语言写代码。 会议是一种重量级的沟通方式 减少参会人数。 找人面对面沟通。 聆听用户声音 能做自己用户,做自己的用户。 能接近用户,接近用户。 没有用户,创造用户。 Fail Fast 一种编写代码的原则。 出现问题尽早报错。 金字塔原理 从中心论点,到分论点,再到论据。

  • 金字塔原理的四个基本原则:“结论先行”(一次表达只支持一个思想,且出现在开头)、“以上统下”(任一层次上的思想都必须是其下一层思想的总结概括)、“归类分组”(每组中的思想都必须属于同一范畴)和“逻辑递进”(每组中的思想都必须按照逻辑顺序排列)。 前面两个特点是纵向结构之间的特点,后面两个特点则是横向结构之间的特点。以上内容收集整理自李忠秋老师的《结构思考力》,

  • 重构,本质上就是一个“微操作”的实践。

  • 你需要把做的代码调整分解成若干可以单独进行的“重构”小动作,然后,一步一步完成它。

  • 在这个分解出来的步骤里,每一步都可以很快完成,而且,每做完一步都是可以停下来的,这才是微操作真正的含义。

  • 重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。 重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。

  • 重构成模式(Refactoring to Patterns)。

  • 锤炼你的重构技能。

  • 朋友。 精选留言: 非鱼 2019-03-15 13:47:24 函数式编程有什么推荐书籍吗? [4 赞] 作者回复 2019-03-16 17:48:01 有几本可以了解一下,《计算

  • 作者回复 2019-03-16 17:48:01 有几本可以了解一下,《

  • 一下,《计算机程序的解释与构造》(Structure and Interpretation of Computer Programs,SICP),还有《Haskell 趣学指南》(Learn You a Haskell for Great Good!),《函数式编程思维》(Functional Thinking)。

  • 一下,《计算机

  • 计算机程序的解释与构造》(Structure and Interpretation of Computer Programs,SICP),还有《Haskell 趣学指南》(Learn You a Haskell for Great Good!),《函数式编程思维》(Functional Thinking)。

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

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

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

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

  • 请谨慎地将工作自动化。

  • 将你的工作过程自动化。

  • 《敏捷软件开发:原则、实践与模式》、《架构整洁之道》

  • 有体系地学习运维知识。

  • https://infoq.cn/article/detail-analysis-of-devops 《DevOps 知识体系与标准化的构建》也不错,下载地址: https://yq.aliyun.com/download/778 运维知识体系: https://www.unixhot.com/page/ops Web 缓存知识体系: https://www.unixhot.com/page/cache

  • https://chaifeng.com/devops-tech-stack

  • 按照不同阶段组织构建的方式,称之为构建流水线(Build Pipeline)。

  • 持续交付,是一种让软件随时处于可以部署到生产环境的能力。让软件具备部署到生产环境的能力,这里面有两个关键点:验证发布包和部署。

  • 基础设施即代码(Infrastructure as code)

  • 将部署纳入开发的考量。

  • 验收测试(Acceptance Testing),是确认应用是否满足设计规范的测试。这种测试往往是站在用户的角度,看整个应用能否满足业务需求。

  • 行为驱动开发中的行为,指的是业务行为。BDD 希望促进业务人员与开发团队之间的协作,换句话说,如果你想做 BDD,就应该用业务语言进行描述。

  • Given 对应前置条件,When 对应执行,Then 则对应着断言。

  • 想写好 BDD 的测试用例,关键点在用业务视角描述。

  • 编写 BDD 测试用例的最佳实践:用业务的视角描述测试用例。在编写步骤定义时,还要考虑设计自己的业务测试模型。

  • 验收测试的方法不止 BDD 一种,像实例化需求(Specification by Example,SbE)也是一种常见的方法。

  • 将验收测试自动化。

  • 一般说集成测试,还是站在内部的角度,也就是技术的角度在说,而验收测试应该是站在业务的角度,

  • 就是 Robert Martin 提出的面向对象设计原则:SOLID,这其实是五个设计原则的缩写,分别是 单一职责原则(Single responsibility principle,SRP) 开放封闭原则(Open–closed principle,OCP) Liskov 替换原则(Liskov substitution principle,LSP) 接口隔离原则(Interface segregation principle,ISP) 依赖倒置原则(Dependency inversion principle,DIP)

  • Robert Martin 的《敏捷软件开发:原则、实践与模式》。

  • 把函数写短。

  • 构建好你的领域模型。

  • 不同量级的系统根本就不是一个系统。

  • 淘宝的工程师之所以要改进系统,真实的驱动力不是技术,而是不断攀升的业务量带来的问题复杂度。

  • 用简单技术解决问题,直到问题变复杂。

  • 怎么划分微服务,也就是一个庞大的系统按照什么样的方式分解。

  • 领域驱动设计(Domain Driven Design,DDD)是 Eric Evans 提出的从系统分析到软件建模的一套方法论。它要解决什么问题呢?就是将业务概念和业务规则转换成软件系统中概念和规则,从而降低或隐藏业务复杂性,使系统具有更好的扩展性,以应对复杂多变的现实业务问题。

  • DDD 分为战略设计(Strategic Design)和战术设计(Tactical Design)。

  • 战略设计是高层设计,它帮我们将系统切分成不同的领域,并处理不同领域的关系。

  • 不同的领域,并处理不同领域的关系。我在

  • 战术设计,通常是指在一个领域内,在技术层面上如何组织好不同的领域对象。

  • 它限定了通用语言自由使用的边界,一旦出界,含义便无法保证。

  • Vaughn Vernon 又出手写了一本精华本《领域驱动设计精粹》,

  • 学习领域驱动设计。

  • 2017 年 Domain-Driven Design Distilled 出了 Vaughn Vernon 讲解的视频版,现在积极补课中,上一个链接: https://learning.oreilly.com/videos/domain-driven-design-distilled/9780134593449

  • 精益创业实际上是一种持续验证,验证想法的有效性,获得经过验证的认知(Validated Learning)。

  • 持续交付 将生产部署纳入了开发的考量。 持续交付的基础设施通常包含持续集成环境、测试环境、预生产环境和生产环境。 构建流水线保证到了下游的交付物一定是通过上游验证的。 随着 Docker 的诞生,交付由发布包变成了 Docker 镜像。 DevOps 将开发和运维结合到一起。 环境配置工具上的进步,让基础设施即代码成了行业共识。 验收测试 验收测试要站在业务的角度编写。 BDD 是一种编写验收测试的方式。 Given…When…Then… 的描述给了一个描述业务的统一方式。 写好验收测试,需要构建测试模型。 SOLID 原则 设计模式背后的道理。 单一职责原则(Single responsibility principle,SRP)。 开放封闭原则(Open–closed principle,OCP)。 Liskov 替换原则(Liskov substitution principle,LSP)。 接口隔离原则(Interface segregation principle,ISP)。 依赖倒置原则(Dependency inversion principle,DIP)。 用好单一职责原则,前提条件是看待问题颗粒度要小。 DDD 它将思考的起点拉到了业务上。 DDD 分为战略设计和战术设计。 微服务 做好微服务的前提是划分好限界上下文。 微服务的第一步,不要划分微服务。

  • 程序员的三大美德:懒惰、急躁和傲慢(Laziness, Impatience and hubris)。 小心 NIH 综合症(Not Invented Here Syndrome)。 写好构建脚本,做好项目自动化。 参照 Java 知识体系,学习运维知识。 软件设计最基础的原则是“高内聚、低耦合”。 分层架构是一种设计上的分解。 不同业务量的系统本质上不是一个系统。 采用简单技术解决问题,直到问题变复杂。

  • 持续集成的延伸。 持续集成完成系统集成。 持续交付完成可部署上线。 “持续验证”完成产品想法验证。 AB 测试,用一个软件的多个版本验证想法。 Selenium 用以完成浏览器的自动化。 熟练使用快捷键。

  • 技术解决的是“怎么做”的问题,而我们第一个应该了解的问题是“做什么”。一个软件到底在做什么,能够回答这个问题的就是业务。所以,我们排在第一优先级的事情应该是业务。

  • 对于一个普通的程序员来说,业务就是这个大图景。

  • 我会选择从外向内的顺序了解起。首先是外部,这里的外部包括两个部分: 这个系统对外提供哪些接口,这对应着系统提供的能力; 这个系统需要集成哪些外部系统,对应着它需要哪些支持。

  • 了解内部系统也要从业务入手,对应起来就是,这个系统由哪些模块组成,每个模块承担怎样的职责。

  • 了解一个项目,从大图景开始。

  • Michael Feathers 的《修改代码的艺术》(Working Effectively with Legacy Code),

  • 一方面,建立好领域模型,另一方面,寻找行业对于系统构建的最新理解。

  • 改造遗留系统,一个关键点就是,不要回到老路上。

  • 构建测试防护网,保证新老模块功能一致; 分成小块,逐步替换; 构建好领域模型; 寻找行业中关于系统构建的最新理解。

  • 小步改造遗留系统,不要回到老路上。

  • 重构 作者: Martin Fowler https://book.douban.com/subject/1229923/

  • 我们的焦虑来自于对未来的不确定性,而这种不确定性是一个特定时代加上特定行业的产物。

  • 诸如《C 程序设计语言》《程序设计实践》、《Unix 编程环境》等,还有一些像 Eric Raymond 这样沉浸编程几十年的人写出的作品,诸如《Unix 编程艺术》,

  • 在学习区工作和成长。

  • 找到愿意和你一起改变的人,做一件具体的事。

  • 关于外部系统的测试,你可以先通过接口隔离开来,然后,通过模拟服务或本地可控的方式进行测试。

  • “学习区”学习模型 舒适区,舒适而缺乏成长。 恐慌区,超出能力范围。 学习区,有难度而可以达成。 在学习区练习才能得到足够的成长。 T 型人才,一专多能 知识的广度。 专业技能的深度。 有“一专”,“多能”才是有意义的。

  • 进入新工作,从全面了解了解开始 业务:做什么。 技术:怎么做。 团队运作:怎么与人协作。 从大到小,由外及内地了解工作。 面对遗留系统,稳扎稳打,小步前行 基础理念 烂代码只是现象,要了解根因。 能重构,先重构,大规模改造是迫不得已的选择。 小步前行。 实际操作 构建测试防护网。 将大系统分解成小模块,逐步替换。 新旧模块并存,由分发模块调度。 建立好领域模型。 寻找行业对于系统构建的最新理解。 程序员的职业发展 程序员的焦虑来自于对未来的不确定性,这种不确定性是一个特定时代加上特定行业的产物。 快速发展的中国经济。 程序员在中国是一个新兴职业。 成为行业专家,制定高目标。 向大师学习,开拓视野。 找到好的问题,和高水平的人一起工作。

  • 推行新观念,找愿意改变的人,做具体的事。 Lead by Example. 外部系统应该用接口隔离,这种做法体现了接口隔离原则(ISP),也是防腐层概念的体现。 外部系统的测试,能模拟的就模拟,能本地的就本地。

  • https://web.archive.org/web/20150924210902/http://dreamhead.blogbus.com/

  • 2.郑老师微博:https://www.weibo.com/dreamhead 3.郑老师 GitHub:https://github.com/dreamhead

  • https://www.douban.com/people/dreamhead/

  • 其实就是尽可能利用已知的信息,少做不必要的事。

  • 我在这个专栏真正探讨的主题是,有效工作。 有效工作,需要我们把力量聚焦到正确的地方,做本质复杂度(Essential Complexity)的事情,少做无意义的事情。