《十倍工作法,寻找最佳实践》笔记

· ☕ 13 min read · 👀... views
🏷️
  • #manage
  • 以3个思考问题为核心的思考框架

    • Where are we?(我们现在在哪?) 现状
    • Where are we going?(我们要到哪儿去?)目标
    • How can we get there?(我们如何到达那里?)实现路径

    整个工作法以4个思考原则展开讨论

    以终为始,确定好真实目标

    • 遇到事情倒着想,首先描述要做的事情,包括背景和意义,然后先写用户使用文档,最后再写代码。
    • DOD (Definition of Done,完成的定义)-做任何事情,先定义完成标准,可以固化到流程,是一种有效协作方式
    • 检查项清单
    • 梳理依赖,确定边界,用“用户故事”描述需求,定义验收标准(正常流程和异常流程)
    • 交付物不是代码,是可工作的软件,如何做好集成?
    • 最小可行产品 MVP(Minimum Viable Product),默认所有的需求都不做,知道弄清楚为什么这么做。
    • 《精益创业》
      • 精益创业的方法论里,提出“开发(build)-测量(measure)-认知(learn)”这样一个反馈循环。就是说,当你有了一个新的想法(idea)时,就把想法开发成产品(code)投入市场,然后,收集数据(data)获取反馈,看看前面的想法是不是靠谱。
    • 得到的结果无非是两种:好想法继续加强,不靠谱的想法丢掉算了。不管是哪种结果,你都会产生新的想法,再进入到下一个循环里。在这个反馈循环中,你所获得的认知是最重要的,因为它是经过验证的。在精益创业中,这也是一个很重要的概念:经过验证的认知(Validated Learning)。
    • 扩大自己工作的上下文,在更高的维度思考问题。
    • 不同角色工作真正的差异在于上下文的差异。在一个局部上下文难以解决的问题,换到另外一个上下文甚至是可以不解决的。所以说无论单点有多努力也只是局部优化,很难达到最优的效果。
    • 想把工作做好,就需要不断扩大自己工作的上下文,多了解一下别人的工作逻辑是什么样的,认识软件开发的全生命周期。
    • 在动手做一件事之前,先推演一番。
    • 问一下自己,我的工作是不是可以用数字衡量。大数据时代,可视化的价值,定义好测量工作的有效性指标

    迭代考虑项

    decuple-01

    任务分解,找到实施路径

    • 动手做一项工作之前,首先进行任务分解。
    • 最佳实践称之为测试金字塔,它强调的重点是,越底层的测试应该写得越多。只有按照测试金字塔的方式写测试,持续集成才能更好地发挥作用。
    • 多写单元测试。
    decuple-02
    • TDD测试驱动开发已经是行业中的优秀实践,学习测试驱动开发的第一步是,记住测试驱动开发的节奏:红——绿——重构。把测试放在前面,还带来了视角的转变,要编写可测的代码。
    • 将任务拆小,越小越好。
    • 按照完整实现一个需求的顺序去安排分解出来的任务。
    • 测试一定要写断言。
    • 一段旅程(A-TRIP)
      • 怎么样的测试算是好的测试呢?有人做了一个总结 A-TRIP,这是五个单词的缩写,分别是
      • Automatic,自动化;
      • Thorough,全面的;
      • Repeatable,可重复的;
      • Independent,独立的;
      • Professional,专业的。
    • 绝大多数问题都是由于分解的粒度太大造成的,少有因为粒度太小而出问题的。
    • 想要管理好需求,先把需求拆小。
    • 评价用户故事有一个“ INVEST 原则”,这是六个单词的缩写,分别是:
      • Independent,独立的。一个用户故事应该完成一个独立的功能,尽可能不依赖于其它用户故事,因为彼此依赖的用户故事会让管理优先级、预估工作量都变得更加困难。如果真的有依赖,一种好的做法是,将依赖部分拆出来,重新调整。
      • Negotiable,可协商的。有事大家商量是一起工作的前提,我们无法保证所有的细节都能100%落实到用户故事里,这个时候最好的办法是大家商量。它也是满足其它评判标准的前提,就像前面提到的,一个用户故事不独立,需要分解,这也需要大家一起商量的。
      • Valuable,有价值的。一个用户故事都应该有其自身价值,这一项应该最容易理解,没有价值的事不做。但正如我们一直在说的那样,做任何一个事情之前,先问问价值所在。
      • Estimatable,可估算的。我们会利用用户故事估算的结果安排后续的工作计划。不能估算的用户故事,要么是因为有很多不确定的因素,要么是因为需求还是太大,这样的故事还没有到一个能开发的状态,还需要产品经理进一步分析。
      • Small,小。步子大了,不行。不能在一定时间内完成的用户故事只应该有一个结果,拆分。小的用户故事才方便调度,才好安排工作。
      • Testable,可测试的。不能测试谁知道你做得对不对。这个是我们在前面已经强调过的内容,也就是验收标准,你得知道怎样才算是工作完成。
    decuple-03
    • 按照时间管理的理念,重要且紧急的事情要立即做。重要但不紧急的事情应该是我们重点投入精力的地方。紧急但不重要的事情,可以委托别人做。不重要不紧急的事情,尽量少做。
    • 需求分解之后,最重要的是,排列需求的优先级。
    • 需求分解成一个个小块,其实也分解了原本合一的上下文。如果想要有效地管理需求,尤其是确定事情的重要程度,一种方式是找回丢失的上下文。如果我们自己无法判断上下文,一种好的办法是,引入外部更大的上下文。
    • 我们要做的是验证一个想法的可行性,甚至不是为了开发一个软件,开发软件只是一种验证手段。
    • 不是一个模块做得有多完整,而一条用户路径是否通畅。
    • 做好产品开发,最可行的方式是采用 最小可行产品(Minimum Viable Product,MVP)。
    • 最小可行产品就是“刚刚好”满足客户需求的产品。

    沟通反馈,解决与人打交道出现的问题

    • 通过沟通反馈,不断升级自己的编解码能力。
    • 用业务的语言写代码。
    decuple-04
    • 站会。之所以采用站会的方式,就是要控制时间。在站会上每个人说什么,我给了你一个建议的格式:
      • 我昨天做了什么?
      • 我今天打算做什么?
      • 我在过程中遇到了什么问题,需要请求帮助。
    • 多面对面沟通,少开会。
    • 人的大脑更擅长处理图像。
    • 多尝试用可视化的方式进行沟通。
    • 雷达图、流程图、UML 等。
    • 看板。看板把工作分成了几个不同的阶段,在看板上对应不同的列,然后,每个任务作为一张卡贴在上面。每完成一张卡,就把这张卡挪到下一个阶段。
    decuple-05
    • 做好持续集成的关键在于,快速反馈。
    decuple-06
    • 定期复盘,找准问题根因,不断改善。
    • 多走近用户,聆听用户声音,做对用户有价值的产品。
    • 能用尽可能小的时间颗粒度来安排自己的工作。
    • 在工作中要拓展自己的上下文,将自己放在更大的范围、平台上去思考问题,主动发掘问题关键点,在面对不同职能人员间沟通时,多运用“以终为始”模块中的知识尝试解决分歧,达成共识。
    • 一旦有困难,尽早暴露问题,寻求帮助。
    • 多输出,让知识更有结构。
    • 金字塔原理。
    decuple-07
    • 持续集成的价值在于,它是一条主线,可以将诸多实践贯穿起来。
    • 做好持续集成的关键是,快速反馈。
    decuple-08 decuple-09
    • 重构,本质上就是一个“微操作”的实践。你需要把做的代码调整分解成若干可以单独进行的“重构”小动作,然后,一步一步完成它。
    • 函数式编程已然成为时代的主流。

    自动化,解决与机器打交道出现的问题

    • 学习自动化,先要知道哪些东西不要自动化,尽最大的努力不做浪费时间的事。一方面,我们要从需求上规避那些没必要做的事;另一方面,我们也从自身防止 NIH 综合症(Not Invented Here Syndrome),争取做一个懒惰的程序员。
    • NIH 是什么意思?就是有人特别看不上别人做的东西,非要自己做出一套来,原因只是因为那个东西不是我做的,可能存在各种问题。
    • 不懂软件设计,只会被各种层出不穷的工具和框架淘汰。
    • 将你的工作过程自动化。
    • 有体系地学习运维知识。
    decuple-10 decuple-11 decuple-12
    • DevOps 是将开发(Development)和运维(Operations)组合在了一起。
    decuple-13
    • 持续交付,是一种让软件随时处于可以部署到生产环境的能力。让软件具备部署到生产环境的能力,这里面有两个关键点:验证发布包和部署。
    • 验证发布包,不仅是功能上的验证,还包括与环境结合在一起的验证。所以,通常会用几个不同的环境验证,每一个环境都是一个单独的阶段,一个阶段不通过,是不能进入下一阶段的,这种按照不同阶段组织构建的方式,称之为构建流水线(Build Pipeline)。
    • 今天定义交付,不再是一个发布包,而是一个可以部署的镜像。
    • BDD(Behavior Driven Development)用业务的视角描述测试用例。
    • 将验收测试自动化。
    • 按照设计原则而不是设计模式重构代码,先有设计模式,再有设计模式。
    • Robert Martin 提出的面向对象设计原则:SOLID,这其实是五个设计原则的缩写,分别是
      • 单一职责原则(Single responsibility principle,SRP)
      • 开放封闭原则(Open–closed principle,OCP)
      • Liskov 替换原则(Liskov substitution principle,LSP)
      • 接口隔离原则(Interface segregation principle,ISP)
      • 依赖倒置原则(Dependency inversion principle,DIP)
    • 把函数写短。
    • 人们擅长解决的是小问题,大问题怎么办?拆小了就好。
    • 分层架构,实际上,就是一种在设计上的分解。
    • 构建好你的领域模型(Domain Model),指的是服务层。领域模型中一个重要的组成部分:领域对象。领域对象中不应只包含数据访问,也就是常说的 getter 和 setter,还应该有业务逻辑。
    • 你的领域层只依赖于你的领域对象,第三方发过来的内容先做一次转换,转换成你的领域对象。这种做法称为防腐层。
    decuple-14
    • 领域驱动设计(Domain Driven Design,DDD)
    • 领域特定语言(Domain Specific Language,DSL)
    • 用简单技术解决问题,直到问题变复杂。
    • 领域驱动设计(Domain Driven Design,DDD)是 Eric Evans 提出的从系统分析到软件建模的一套方法论。它要解决什么问题呢?就是将业务概念和业务规则转换成软件系统中概念和规则,从而降低或隐藏业务复杂性,使系统具有更好的扩展性,以应对复杂多变的现实业务问题。
    • DDD 到底讲了什么呢?它把你的思考起点,从技术的角度拉到了业务上。
    • DDD 分为战略设计(Strategic Design)和战术设计(Tactical Design)。
    • 战略设计是高层设计,它帮我们将系统切分成不同的领域,并处理不同领域的关系。
    • 战术设计,通常是指在一个领域内,在技术层面上如何组织好不同的领域对象。
    • 学习领域驱动设计。
    • 看到差距之后,我唯一能做的,就是自己下来偷偷练习。幸好,无论是快捷键也好,重构也罢,都是可以单独练习的。花上一段时间就可以提高到一定的水平。
    • 入职新公司,了解的优先级是业务,技术(技术栈,技术架构,功能模块),团队运作(协作方式)。
    • 了解一个项目,从大图景开始。大多数程序员习惯的工作方式,往往是从细节入手,很难建立起一个完整的图景,常常是“只见树木不见森林”,而我的方式则是从大到小、由外而内,将要了解的内容层层分解,有了大图景之后,很容易知道自己做的事情到底在整体上处于什么样的位置。
    decuple-15
    • 先尝试重构你的代码,尽可能在已有代码上做小步调整,不要走到大规模改造的路上,因为重构的成本是最低的。
    • 如果你的“小模块”是一个系统,那就部署新老两套系统,在前面的流量入口做控制,逐步把流量从老系统转到新系统上去;如果“小模块”只在代码层面,那就要有一段分发的代码,根据参数将流程转到不同的代码上去,然后,根据开发的进展,逐步减少对老代码的调用,一直到完全不依赖于老代码。
    decuple-16
    • 要想代码腐化的速度不那么快,一定要在软件设计上多下功夫。一方面,建立好领域模型,另一方面,寻找行业对于系统构建的最新理解。
    • 改造遗留系统,一个关键点就是,不要回到老路上。
    • 只要产品还在发展,系统改造就是不可避免的。改造遗留系统,前提条件是要弄清楚现状,知道系统为什么要改造,是架构有问题,还是领域模型混乱,只有知道根因,才可能有的放矢地进行改造。
    • 改造遗留系统,我给你几个建议:
      • 构建测试防护网,保证新老模块功能一致;
      • 分成小块,逐步替换;
      • 构建好领域模型;
      • 寻找行业中关于系统构建的最新理解。
    • 小步改造遗留系统,不要回到老路上。
    • IT 行业在国内的大发展也就最近20多年的事,行业里很少有走过完整职业生涯的程序员。也正是因为如此,我们经常会产生了各种焦虑:
      • 我刚刚入行时,有人问,程序员能做到30岁吗?
      • 我快30岁时,有人问,35岁还能做程序员吗?
      • 我35岁时,讨论变成了40岁的程序员该怎么办。
    decuple-17
    • 有了“一专”,“多能”才是有意义的,否则,就是低水平重复,而这正是很多人职业生涯不见起色的真正原因。

    • 这里的“专”不是熟练,而是深入。你可能是个有着10年丰富经验的程序员,但实际上只不过是重复了10年解决同样难度的问题而已,这根本就不算深入,也就没有做到真正意义上的“一专”。

    • 当你有了“一专”,拓展“多能”,就会拥有更宽广的职业道路。比如,我拥有了深厚的技术功底,通晓怎么做软件:

      • 如果还能够带着其他人一起做好,就成了技术领导者。
      • 如果能够分享技术的理解,就有机会成为培训师。
      • 如果能够在实战中帮助别人解决问题,就可以成为咨询师。
    • 反过来,当你有了“多能”,也可以拓宽你的视野,帮你认清自己的“一专”怎样更好地发挥价值,而不是狭隘地认为自己有了技术,就已经天下尽在掌握了。视野窄,缺乏大局观,也成为了许多程序员再进一步的阻碍。

    • 既然要朝着行业中的专家方向努力,那你就得知道行业中的专家是什么样。我的一个建议是,向行业中的大师学习。读这些大师写的书的一个好处在于,你的视野会打开,不会把目标放在“用别人已经打造好的工具做一个特定的需求”,虽然这可能是你的必经之路,但那只是沿途的风景,而不是目标。

    • 怎么才能让自己的水平不断提高呢?找一个好问题去解决,解决了一个好的问题能够让你的水平快速得到提升。什么是好问题?就是比你当前能力略高一点的问题,比如:

      • 如果你还什么都不会,那有一份编程的工作就好。
      • 如果你已经能够写好普通的代码,就应该尝试去编写程序库。
      • 如果实现一个具体功能都没问题了,那就去做设计,让程序有更好的组织。
      • 如果你已经能完成一个普通的系统设计,那就应该去设计业务量更大的系统。
    decuple-18
    • 最内层是舒适区(Comfort Zone),置身其中会让人感觉良好,但也会因为没有挑战,成长甚微,你可以把它理解成做你最熟悉的事情。
    • 最外层是恐慌区(Panic Zone),这是压力极大的地方,完全超出了你的能力范围,你在其中只会感到无比的焦虑。
    • 中间的是学习区(Learning Zone),事情有难度,又刚好是你努力一下可以完成的,这才是成长最快的区域。
    • IT 行业依然是一个非常有前景的行业,但想在这条路上走好,需要我们成为 “T ”型人才,也就是“一专多能”。一专多能的前提是“一专”,让自己成为某个方面的专家。这个专家要放在行业的标准去看,这才能降低因为一个公司的波动而造成的影响。
    • 成为行业专家,要向行业的大师学习,给自己定下一个高的目标,然后是脚踏实地,找适合自己的问题去解决,让自己一直在学习区成长。
    • 在学习区工作和成长。
    • 外部系统对你来说,应该只是一个接口。
    • 能模拟的就模拟,能本地的就本地。
    • 关于外部系统的测试,你可以先通过接口隔离开来,然后,通过模拟服务或本地可控的方式进行测试。
    • 所谓的算法优化,其实就是尽可能利用已知的信息,少做不必要的事。
    • 我在这个专栏真正探讨的主题是,有效工作。
    • 有效工作,需要我们把力量聚焦到正确的地方,做本质复杂度(Essential Complexity)的事情,少做无意义的事情。
    • 怎么才能有效工作呢?小结一下就是:
      • 拓展自己的上下文,看到真正的目标,更好地对准靶子,比如,多了解用户,才不至于做错了方向;站在公司的层面上,才知道哪个任务优先级更高;站在行业的角度,而不局限于只在公司内成为高手,等等。
      • 去掉不必要的内容,减少浪费,比如,花时间分析需求,不做非必要的功能;花时间做好领域设计,别围着特定技术打转;花时间做好自动化,把精力集中在编码上,等等。
      • 要想有效工作,有两点非常重要。一方面,意识上要注意自己工作中无效的部分。这就像一个开关,拨过去就好了。另一方面,要构建自己关于软件开发的知识体系,这是要花时间积累的。

    ·End·

    Rudy
    WRITTEN BY
    Rudy