10x程序员工作法
以终为始
💡面对
- 不明确的需求是否合理:精益创业思维
- 做任务之前:先推演一番
- 明确的需求是否完成:验收标准
- 上级的任务是否完成:DoD
- 难以解决的问题:不妨跳出程序员思维
- 一个新的项目:迭代0准备 </aside>
概念
💡以终为始,就是在做事情之前,先想想结果是什么样子的?然后根据结果来确定要做的事情。
这个结果就是:
- 别人会怎么用我做的东西?
- 东西做好后,上线流程是怎样的?
以始为终的实践:
- 测试驱动开发
- 持续集成
“终”到底在哪里?
💡做任何事之前,先定义完成的标准。
完成什么程度才能算终?
如何弥补双方理解的差异?
最佳实践:DoD(Define of done),开始工作前,先制定DoD
比如:“开发完成”,表示开发人员编写好功能代码,编写好单元测试代码,编写好集成测试代码,测试可以通过,代码通过了代码风格检查、测试覆盖率检查。
如何制定DoD:
一个个实际可检查的检查项
- 编写代码
- 编写测试代码
- 通过测试人员验收
- ……
扩展DoD思维:
💡DoD是种思维模式,是一种尽可能消除不确定性,达成共识的方式。
- 某个功能的 DoD,比如:这个功能特性已经开发完成,经过产品负责人的验收,处于一个可部署的状态。
- 一个迭代的DOD,比如:这个迭代规划的所有功能己经完成。
- 一次发布的DOD,比如:整个软件处于可发布的状态,上线计划已经明确。
- 一个接口的定义。比如,返回值是否相同,使用方是否可以配合使用
- ……
验收标准
一个合理需求完成的DoD就是“验收标准”。
💡验收标准,可以清晰定义出需求的边界。
采用用户故事之后,我经常在写完了主要流程之后,再去看一下验收标准,为自己的开发查缺补漏。因为我知道,那是标准,达不成就不算任务完成。
当我们说自己开发完成,可以交给测试人员测试时,我们需要照着验收标准给测试人员演示一遍,证明我们的系统确实能够跑通。这之后,测试人员才会把系统接手过去,做更系统测试。
💡或许你会有这样的疑问,如果产品经理通过用户故事的方式,将需求实现细节都描绘得清清楚楚,那我们程序员的发挥空间在哪里?请注意,验收标准所给出实现细节应该是业务上的,程序员在这种问题上思考才是真正意义上的浪费时间,我们的发挥空间应该是在技术实现上。
持续集成
现在假设“验收标准”已经制定清楚,是不是按照验收标准写完代码,工作就算完成了?或者这样说,“代码是技术团队的交付物吗?”
写代码是程序员的职责,但我们更有义务交付一个可运行的软件。
💡尽早提交代码去集成。
怎样尽早呢?你需要懂得任务分解,这是我们在之后的“任务分解”主题下会讲到。
面对不确定的需求?如何需求探索
(比如敏捷开发中的探索周)
最佳实践:精益创业 ,尽可能少浪费的前提下,面向不确定性创造新事物。
既然是新事物,就要尝试,但是要用最小的成本去试,也就是:少花钱,多办事。
有了框架结构,我们的生活就简单了,当产品经理要做一个新产品或是产品的一个新特性,我们就可以用精益创业的这几个概念来检验一下产品经理是否想清楚了。
比如,你要做这个新的产品特性,
- 你要验证的东西是什么呢?
- 他要验证的目标是否有数据可以度量呢?
- 要解决的这个问题是不是当前最重要的事情,
- 是否还有其他更重要的问题呢?
如果上面的问题都得到肯定的答复,那么
- 验证这个目标是否有更简单的解决方案?
- 是不是定要通过开发一个产品特性来实现呢?
项目负责人的“降维打击”
对比组长来说,你在项目里打杂,你只能关注到一个具体的任务,而项目主力心目中是整个系统。虽然写的代码都一样,但你看到的是树木,人家看到的是森林,他更能从全局思考。
不同角色工作上真正的差异是上下文的不同。
跳出程序员的角色思维,扩大自己的工作上下文。
- 虽然我不是项目主力,但不妨碍我去更深入地了解系统全貌;
- 虽然我不是项目负责人,但不妨碍我去了解系统与其他组的接口;
- 同样,虽然我不是项目经理,但我可以去了解一下项目经理是怎样管理项目的;
- 虽然我不是产品经理,但了解一个产品的设计方法对我来说也是有帮助的。
当你对软件开发的全生命周期都有了认识之后,你看到的就不再是一个点了,而是一条线。与别人讨论问题的时候,你就会有更多的底气,与那些只在一个点上思考的人相比,你就拥有了降维攻击的能力。
现在你知道为什么你的工作总能让老板挑出毛病了吧!没错,工作的上下文不同,看到的维度差异很大。单一维度的思考,在多维度思考者的眼里几乎就是漏洞百出的。
动手之前,先推演一番
这一章是李淼之前说好的问题,做一项任务,要考虑到后期兼容性,可能会出现的问题,以及应对措施。
不要只想着功能实现,还要考虑上线可能出现的问题。比如,和第三方配合可能出现什么问题?
执行过程:
- 先从结果的角度入手,看看最终上线要考虑哪些因素。
- 推演出一个可以一步一步执行的上线方案,用前面考虑到的因素作为衡量指标。
- 根据推演出来的上线方案,总结要做的任务
思维拓展:
- 在做一个产品之前,先来推演一下这个产品如何推广,通过什么途径推广给什么样的人;
- 在做技术改进之前,先来考虑一下上线是怎样一个过程,为可能出现的问题准备预案;
- 在设计一个产品特性之前,先来考虑数据由谁提供,完整的流程是什么样的。
给个数字看看
你的工作是否可以用数字衡量?
产品中是否可以加入一些监控指标?
迭代0
清单:
- 需求方面
- 迭代1需求列表
- 用户界面和交互逻辑
- 技术方面
- 技术选型,技术架构,框架,数据库等
- 持续集成
- 编译打包
- 代码风格检查
- 测试覆盖率
- 单元测试
- 集成测试
- 继承失败的提示
- ……
- 发布准备
- 数据库迁移
- 自动化部署或者发布
任务分解
💡开发任务分解
- 先梳理好任务优先级。
- 然后,开发应该写测试,保证自己代码质量,也就是TDD理念。
- 而做好TDD需要做好任务分解。
- 而任务分解的关键,是每个任务你是否清晰的知道该做什么,而且做完就可以提交
- 那么,测试怎么写?
💡需求的分解
- 原则:粒度越小越好。
💡不确定需求的分解:
- 最佳实践:MVP最小可行产品
概念
分而治之的理念。
要点:
💡任务分解的粒度
- 需要你清楚每一步需要做什么,应该怎么做了。
- 每做完一个任务,代码都是可以提交的
程序员应该做测试吗?
💡尽早发现问题。能从需求上解决的问题,就不要到开发阶段。同样,在开发阶段能解决的问题,就不要留到测试阶段。
自动化测试
- 单元测试
- 集成测试
- 系统测试
随着人们对于测试理解的加深,各种各样的测试都出现了,也开始有了测试的分类:单元测试、集成测试、系统测试等等。越在底层测试,成本越低,执行越快;越在高层测试,成本越高,执行越慢。
所以,多写单元测试。
测试驱动开发TDD
先写测试,后写代码。代码通过后进行重构。
也就是“红——绿——重构”的过程,重构就是消除代码怪味道的过程。
如何做?
需要编写具有可测试性的代码。
任务分解足够小
为什么任务分解对于 TDD 如此重要呢?
因为只有当任务拆解得足够小了,你才能知道怎么写测试。
测试怎么写?
💡测试要足够简单,简单到这个测试本身不会出错。
测试的基本结构:前置准备、执行、断言和清理
一些常见的测试“坏味道”:做了太多事的测试,没有断言的测试,还有一种看一眼就知道有问题的“坏味道”测试里有判断语句。
“砍”需求
有时候一个需求产品说一定要做的话,可以把分解需求后再“砍”。比如登录需求,就可以把手机验证码需求砍掉。
💡需求分解的原则:粒度越小越好。
分解后的需求标准:
- 独立的
- 可协商的
- 有价值的
- 可估算的
- 小:需求估算
- 可测试的
任务优先级
- 默认所有需求都不做,直到弄清楚为什么要做这件事
- 四象限法则
最小可行产品MVP
最小的代价:
能不做的事情就不做,能简化的就简化。因为我们只是为了验证一个想法可行性,并不是为了开发一个软件。
可行的路径
可行的路径,是一条完整的用户体验路径,至少在用户眼中是这样的。我们常常会想给客户一个完整的系统,但在时间有限的情況下,我们必须学会分解。