程序员的点滴回忆

在ThoughtWorks就要两年了,相比进来之前的自己,现在做事可以抱有更低调的态度了。因为当你和众多聪明的人做事情的时候,你不得不谦虚,逐渐的你就会形成“开放性格”,这是我从ThoughtWorks收获的最有价值的东西。

今天反思一下自己在开发中遇到的一些问题和TW的答案(只是一个Check list,没有逻辑顺序),有如下地方需要考虑:

  1. 做一个需求(对于我们指User Story或Tech Task)的时候要做好评估。评估一般都不准,因为预测本身就不容易准确。有几个方法帮助你让它变得准确,最重要的就是在你工作的团队里面计算Velocity,通过不断的评估Story point(实施工作量的一个概要评估,可以使用1、2、4、8、16这样的大概数字,和人天没有关系)记录实际完成时间,两者相除则为Velocity。有了Velocity就可以作为之后该团队评估需求实现所需时间的参考。Story point使用民主投票的方式,民主要做好就要保护好“异见”,任何高估和低估的情况都要平等的讨论清楚,并达成一致。
    上面说的方法在某个需求有未知技术点的时候会产生严重的评估偏差,甚至完全无法评估。此时一般使用的方法是Spike。Spike的做法是从技术可行性着手,多参考网上的资料和现成代码,使用Quick and Dirty的方式让他们工作,并且在这个过程中评经验得出实现它大概付出的代价,帮助你正确评估一个需求。Spike要尽量覆盖自己所有拿不准的技术点,不要深度,但是要有足够的广度。Spike代码可以不写测试,但是推荐使用测试的方式去实验(因为它更容易组织)。Spike代码一样需要使用源代码控制,并且要多做提交。最后,最重要的一点是Spike代码永远不要进入production code base。李晓曾经说理想的Spike方式是做一个基本满足需求的Spike原型,然后抛弃,重新用TDD的方式实现相同的需求,保证进入code base的代码都是TDD出来(或者起码是有测试保证)的。
  2. 关于些代码是否要测试的问题,Kent beck说我只给会被Break的逻辑写测试。但是实际上不仅如此,在Kent beck总结出的TDD中,测试还是用来明确你的“意图”的代码。做事要有明确的“意图”,一方面它保证你不会迷失目标,另一方面它也是你和你的代码还有你的同事沟通(还包括你自己)的重要手段。但是这里有一个容易让人迷惑的事情,TDD出来的测试到底是测试分类(单元、集成、验收)中的哪一种呢?同事们的答案是它们没有直接关系。TDD是可以表达你对代码行为/结果“期望”的任何一种测试,当然你要尽量保证你的测试是更靠下面的测试(单元测试),因为底层的测试运行快依赖少,所以保证你的红-绿节奏更快。冤有头债有主,每个测试表明一个“意图”,几个“意图”对应一个需求,一个需求对应一些商业价值。如此的映射帮助你从代码的“意图”到“价值”打通经脉。
  3. 一般说User story以“As someone, I want to do something, Then I can achieve some business goal”的形式书写。一般说与之对应的验收条件以“Given some context,When something happened, Then you got the result”的方式去组织,这种书写方式可以保证你的验收条件被映射到一些Specs上面,一些逻辑相关的Specs就组成了对一个Feature的验证。如果你用这种方式组织你的测试,那么你就自然的实践了BDD。BDD是一个很大的概念,组只好测试只是个开始。Ruby里面的Cucumber是一个很好的验收测试工具,它能帮助你更好的从你使用需求及验收特性Driven你的测试,书写有价值的代码。而Rspec这样的BDD测试框架则可以帮助对你的其它测试(如单元测试)进行管理。这些都是形式,但是形式影响你思考的方式,最终可以帮助你提升的代码的“价值”量,减少“无价值”的代码。
  4. 如果你是一个测试驱动狂人,你是否要考虑试验ATDD(验收测试驱动)呢?我们认为ATDD是TDD的一个极致形式(因为它最大程度保证你的商业意图和代码的有效映射)。但是这里还是有很高的门槛。一个是ATDD的难度的确比其它层次的TDD要高,很多时候你都苦恼于不知道如何做Assertion,这种问题会影响效率。因为测试代码本身是没有商业价值的。另一方面即使你是脑力超人,可以很好的写出验收测试级别的测试代码作为驱动,这些代码运行的速度一般也比较令人失望。因为根据测试分组(Category)的理论,越在上层的测试运行速度越慢。所以,如果你用验收测试作为高层驱动可能会拖慢红-绿节奏。这时你需要清除的知道要向下面层次的TDD进行委托,保证节奏效率的同时还能清晰的让自己的测试回溯到“商业价值”上面。
  5. 保持一致的标准。有的时候你会说我们的Code base不允许Quick and Dirty代码的污染,有的时候你又说我们的首要任务是让它Work。Teck lead此时要保证好统一的标准,找到自己团队能够接受的合理平衡。
  6. 站立会议一定要短,昨天作了啥,有什么问题,今天准备做啥这个形式如果哪个方面与团队没什么关系就可以省略。站立会议不是报功会,所以不要说你Fix的bug的编号是什么,那个完全没有价值。
  7. 回顾会议非常重要,如果大家都觉得需要回顾会议的时候就开。时间可以是几个小时一次也可以是几个星期一次。常用的Theme是“Well/Less well/Puzzle”,回顾会议需要Time box,一般半小时以内比较好。长时间跨度的回顾可是使用Timeline的Theme,就是大家不根据资料回忆一个时间段内发生的印象深刻的事情(团队和项目相关的)和记忆中他们发生的时间,然后大家讨论这个事情产生的正向/负向的效果,因为记忆会“骗人”,所以收集到的记忆的偏差实际上都可以和当时团队的情绪变化产生映射(类似精神分析法,可以帮助团队找到很多有意思的东西)。回顾产生的偏差是个很有趣的话题,这是为什么我们办公室有大量的精神病和精神分析相关书籍的原因。其它的Theme还包括Future retrospective,就是回顾“没有发生的未来”的回顾会议,使用“Well/Less well/Puzzle”作为容器,收集你想要得到的和希望避免的事情。出了这些基本形式,我们的Bonna还发明过大字报方式(就是搜集Headline hot news,bad news,流言八卦),用来收集各种客观消息并且集体对齐进行评估。Star fish也是一个Theme,不过因为大家总是忘记它的缩写是什么意思,用的比较少。回顾会议的主持人非常重要!还有回顾会议归档以后所有Action item都需要有负责人,并且要定期验证结果。
  8. 结对的时候两个人产生分歧是正常的,争论也是好的。不过不要争论太久(如超过15分钟)。久的争论大部分的原因就是互相没有聆听,产生了共同障碍。此时解决方法就是暂停争论,按照听起来比较短的路径前行一段实验一下,然后再讨论。此时一般会发现殊路同归,或者发现死胡同以后可以早点掉头。
  9. 只结对解决重点问题和难点问题是可以的,但是大部分的问题是你根本不知道哪里是“难点”和“重点”。所以资源和体力允许的时候尽量结对解决问题。
  10. 评价一段代码的好坏:首先看是否容易读懂,意图是否明确。这个要求需要你无惊讶的设计(使用模式、精心的设计)还有make sense的方法/变量命名。其次代码/方法要短,代码短是硬道理。然后是是否有代码重复。都达到了以后再看效率等问题(效率关键场合除外,但是这种场合很少)。
  11. 做事要尽量自动化,DRY。

困了,下次继续。

One thought on “程序员的点滴回忆”

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.