Rain-driven Development

雨驱动开发

《程序员的职业素养》读书笔记

一本“方法论”的书,把程序员作为自己的工作确实需要一些态度,以及一些指导。看了之后了解到不少,做了摘录。希望可以对自己起到一些帮助。目标是,成为“专业人士”以及更好的自己。

引言

请你把这本书看成我的错误大全,它记录了我干过的所有蠢事;也请你把这本书当成一份指引,让它带你绕开我曾经走过的弯路。

第一章 专业主义

1.1 清楚你要什么

“专业主义”有很深的含义,它不但象征着荣誉与骄傲,而且明确意味着责任与义务。

实际上,专业主义的精髓就在于将公司利益视同个人利益。

1.2 担当责任

1.3 首先,不行损害之事

“希波克拉底誓言”

“敬禀醫神阿波羅、阿斯克勒庇俄斯、許癸厄亞、帕那刻亞,及天地諸神聖鑒之,鄙人敬謹宣誓:

余願盡己之能力與判斷力之所及,矢守此約。凡授余藝者:余敬如父母,為終身同甘共苦之侶;倘有急需余必接濟。視彼兒女,猶余手足,如欲受業,余無償、無條件傳授之。凡余之所知,無論口授、書傳俱傳之吾子、吾師之子、及立誓守此約之生徒,此外不傳他人。

余願盡己之能力與判斷力之所及,恪守為病家謀福之信條,並避免一切墮落害人之敗行,余必不以毒物藥品與他人,並不作此項之指導,雖人請求亦必不與之,尤不為婦人施墮胎之術。余願以此純潔神聖之心,終身執行余之職務。至於手術,另待高明,余不施之,遇結石患者亦然,惟使專匠為之。

無論何適何遇,逢男或女,民人奴隸,余之唯一目的,為病家謀福,並檢點吾身,不為種種墮落害人之敗行,尤不為誘姦之事。凡余所見所聞,不論有無業務之牽連,余以為不應洩漏者,願守口如瓶。

倘余嚴守上述之誓詞,願神僅僅使余之生命及醫術,得無上之光榮;余苟違誓,天地鬼神共殛之!” Wikipedia

1.3.1 不要破坏软件的功能

所谓专业人士,就是能对自己犯下的错误负责的人,哪怕那些错误实际上在所难免。所以,雄心勃勃的专业人士们,你们要练习的第一件事就是“道歉”。道歉是必要的,但还不够。你不能一而再、再而三地犯相同的错误。

失误率永远不可能等于零,但你有责任让它无限接近零。

1.让QA找不出任何问题

什么样的代码是有缺陷的呢?那些你没把握的代码都是!

2.要确信代码正常运行

你怎么知道代码能否常运行呢?很简单,测试!

实行自动化测试。

你写的每一行代码都要测试。

但是有些代码不是很难测试吗?是的,但之所以很难测试,是因为设计时就没考虑如何测试。唯一的解决办法就是要设计易于测试的代码,最好是先写测试,再写要测的代码。

3.自动化QA

你的自动化测试至少要能够让你知道,你的系统很有可能通过QA的测试。

1.3.2 不要破坏结构

结构良好的代码更灵活。

所有软件项目的根本指导原则是,软件要易于修改。

如果你希望自己的软件灵活可变,那就应该时常修改它!

“无情重构”,我把它叫作“童子军训练守则”:对每个模块,每检入一次代码,就要让它比上次检出时变得更为简洁。每次读代码,都别忘了进行点滴的改善。

测试就是帮助你检查每次改动是否会与开始时的需求相违背。

1.4 职业道德

职业发展是你自己的事。雇主没有义务确保你在职场能够立于不败之地,也没义务培训你,送你参加各种会议或给你买各种书籍充电。这些都是你自己的事。将自己的职业发展寄希望于雇主的软件开发人员将会很惨。

雇主出了钱,你必须付出时间和精力。

不能赞同更多。

1.4.1 了解你的领域

近50年来,各种观点、实践、技术、工具与术语在我们这一领域层出不穷。你对这些了解多少呢?如果想成为一名专业开发者,那你就得对其中的相当一大部分有所了解,而且要不断扩展这一知识面。

  • 设计模式。必须能描述GOF书中的全部24种模式,同时还要有POSA书中的多数模式的实战经验。

  • 设计原则。必须了解SOLID原则,而且要深刻理解组件设计原则。

  • 方法。必须理解XP、Scrum、精益、看板、瀑布、结构化分析及结构化设计等。

  • 实践。必须掌握测试驱动开发、面向对象设计、结构化编程、持续集成和结对编程。

  • 工件。必须了解如何使用UML图、DFD图、结构图、Petri网络图、状态迁移图表、流程图和决策图。

1.4.2 坚持学习

读书,看相关文章,关注博客和微博,参加技术大会,访问用户群,多参与读书与学习小组。不懂就学,不要畏难。

1.4.3 练习

业精于勤。

练习,指的是在日常工作之余专门练习技能,以期自我提升。

1.4.4 合作

学习的第二个最佳方法是与他人合作。

1.4.5 辅导

想迅速牢固地掌握某些事实和观念,最好的方法就是与由你负责的人交流这些内容。

分享知识时也是这样,自己事先需要好好备课。

1.4.6 了解业务领域

每位专业软件开发人员都有义务了解自己开发的解决方案所对应的业务领域。

1.4.7 与雇主/客户保持一致

每次开发系统,都应该站在雇主的角度来思考,确保开发的功能真正能满足雇主的需要。

1.4.8 谦逊

他从不会嘲讽别人,自作自受时他会接受别人的嘲讽。反之,他则会一笑了之。

第二章 说“不”

专业人士敢于说明真相而不屈从于权势。

2.1 对抗角色

我的个人经验告诉自己,要做出艰难决定的时候,存在对抗角色间的冲突于此是最为有利的。

2.2 高风险时刻

最要说“不”的是那些高风险的关键时刻。越是关键时刻,“不”字就越具价值。

2.3 要有团队精神

2.3.1 试试看

没有“试试看”这回事。

许诺“尝试”,就意味着你承认自己之前未尽全力,承认自己还有余力可施。

如果你此前并未有所保留,如果你没有新方案,如果你不会改变你的行为,如果你对自己原先的估计有充分的自信,那么,从本质上讲,承诺“尝试”就是一种不诚实的表现。

很多时候也许是避免冲突,大家习惯上说“试试看”,如果对自己自信,而且有着负责任的态度,更应该对一些很难做到的需求说“不”。

2.3.2 消极对抗

如果一列载货列车向大家冲过来,而只有你一人有所察觉,你可以轻轻抽身退到轨道外,眼看其他人被车碾过,也可以大喊:“车!车来了!快离开!”

2.4 说“是”的成本

有时候,获取正确决策的唯一途径,便是勇敢无畏地说出“不”字。

2.5 如何写出好代码

成为英雄及“解决问题”的诱惑诚然巨大,只是我们要明白,委屈专业原则以求全,并非问题的解决之道。舍弃这些原则,只会制造出更多的麻烦。

第三章 说“是”

3.1 承诺用语

口头上说。心里认真。付诸行动。

做出承诺,包含三个步骤。

(1) 口头上说自己将会去做。

(2) 心里认真对待做出的承诺。

(3) 真正付诸行动。

3.1.1 识别“缺乏承诺”的征兆

在承诺做某事时,应当留意自己的用词,因为这些用词透露了我们对待承诺的认真程度。

3.1.2 真正的承诺听起来是怎样的

你对自己将会做某件事做了清晰的事实陈述,而且还明确说明了完成期限。

3.2 学习如何说“是”

3.2.1 “试试”的另一面

“试试”,则是“可能做得到,也可能做不到”的意思。

3.2.2 坚守原则

如果是专业开发人员,就不会放弃底线。

多年经验告诉我们,打破这些纪律和原则,必然会拖慢进度。

身为专业开发人员,有责任根据标准规范自身工作。

专业人士对自己的能力极限了如指掌。他们十分清楚自己还能保持效率加班多长时间,也非常明白要付出的代价。

第四章 编码

具备“出错感知能力”,说明你已经能够非常迅速地获得反馈,能够更为快速地从错误中学习。

要精熟掌握每项技艺,关键都是要具备“信心”和“出错感知”能力。

4.1 做好准备

相比其他类型的活动,编码要求更加聚精会神。因为在编码时你必须平衡互相牵制的多种因素。

(1) 首先,代码必须能够正常工作。必须理解当前要解决的是什么问题以及该如何解决。必须确保编写的代码忠实遵循解决方案。必须管理好解决方案的每一处细节,并且使语言、平台、现有架构以及当前系统的所有问题和平共处。

(2) 代码必须能够帮你解决客户提出的问题。

(3) 代码必须要能和现有系统结合的天衣无缝。

(4) 其他程序员必须能读懂你的代码。

如果感到疲劳或者心烦意乱,千万不要编码。

4.1.1 凌晨3点写出的代码

疲劳的时候,千万不要写代码。奉献精神和职业素养,更多意义上指要遵循纪律原则而非成为长时间工作的工作狂。要确保自己已经将睡眠、健康和生活方式调整到最佳状况,这样才能做到在每天的8小时工作时间内全力以赴。

4.1.2 焦虑时写下的代码

理想情况下,应该使用个人时间去解决个人问题。

专业开发人员善于合理分配个人时间,以确保工作时间段中尽可能富有成效。

4.2 流态区

这是程序员在编写代码时会进入的一种意识高度专注但思维视野却会收拢到狭窄的状态。

避免进入流态区。这种意识状态并非真的极为高效,也绝非毫无错误。这其实只是一种“浅层冥想”状态,在这种状态下,为了追求所谓的速度,理性思考的能力会下降。

结对编程最大的一个好处在于,结对中的任一方都不可能进入流态区。流态区是一种隔绝沟通的状态,而结对则要求激励持续地进行沟通。

4.2.1 音乐

在听音乐时无法写好代码。

4.2.2 中断

结对是用以应对中断的一种好方法。

另一种很有帮助的方法便是采用TDD。

4.3 阻塞

有一个很简单的好办法可以解决这个问题。这个方法便是:找一个搭档结对编程。

结对带来的主要好处是它能够帮我重新激活思维。

还有其他一些事物可以让我免于陷入阻塞状态。“创造性输出”依赖于“创造性输入”。

4.4 调试

不管是否采纳TDD或其他一些同等效果的实践,衡量你是否是一名专业人士的一个重要方面,便是看你是否能将调试时间尽量降到最低。绝对的零调试时间是一个理想化的目标,无法达到,但要将之作为努力方向。

4.5 保持节奏

软件开发是一场马拉松,而不是短跑冲刺。

4.5.1 知道何时应该离开一会

4.5.2 开车回家路上

4.5.1 洗澡

4.6 进度延迟

管理延迟的诀窍,便是早期检测和保持透明。

根据目标定期衡量进度,使用三个考虑到多种因素的期限:乐观预估、标称预估、悲观预估。尽量严守这三个时间点。

4.6.1 期望

期望会破坏项目进度表。

4.6.2 盲目冲刺

不要经受不住诱惑盲目冲刺。

4.6.3 加班加点

不应该采用额外加班加点工作的方案,除非以下三个条件都能满足:(1)你个人能挤出这些时间;(2)短期加班,最多加班两周;(3)你的老板要有后备预案,以防万一加班措施失败。

4.6.4 交付失误

在程序员所能表现的各种不专业行为中,最糟糕的是明知道还没有完成任务却宣称已经完成。

4.6.5 定义完成

可以通过创建一个确切定义的“完成”标准来避免交付失误。最好的方法是让业务分析师和测试人员创建一个自动化的验收测试,只有完全通过这些验收测试,开发任务才能算已经完成。

4.7 帮助

即使你的技能格外高超,也肯定能从另外一名程序员的思考与想法中获益。

4.7.1 帮助他人

4.7.2 接受他人的帮助

4.7.3 辅导

辅导缺乏经验的程序员是那些经验丰富的程序员的职责。

同样道理,向资深导师寻求辅导也是年轻程序员的专业职责。

第五章 测试驱动开发

5.1 此时已有定论

5.2 TDD的三项法则

(1)在编好失败单元测试之前,不要编写任何产品代码。

(2)只要有一个单元测试失败了,就不要再写测试代码;无法通过编译也是一种失败情况。

(3)产品代码恰好能够让当前失败的单元测试成功通过即可,不要多写。

5.3 TDD的优势

5.3.1 确定性

5.3.2 缺陷注入率

有不少报告和研究称TDD能够显著降低缺陷。

5.3.3 勇气

拥有一套值得信赖的测试,便可完全打消对修改代码的全部恐惧。

5.3.4 文档

单元测试即是文档。

5.3.5 设计

测试代码的一个问题是必须隔离出待测试的代码。

因此,遵循三项法则并且测试先行,便能够产生一种驱动力,促使你做出松耦合的设计。

5.3.6 专业人士的选择

TDD是专业人士的选择。

5.4 TDD的局限

TDD大法好。在学写代码的开始,就是想着怎么实现怎么写,写出来的代码很糟糕。后来在别人的帮助下系统的学习敏捷的一套流程,发现TDD确实很实用。持续集成的局限可能是你要多一台机子去跑CI,TDD的局限我目前还没有注意到,这也是自己功力尚浅的原因。会在后面一直实践下去。

第六章 练习

6.1 引子

6.1.1 10的22次方

6.1.2 转变

无论是搏斗还是编程,速度都来源于练习。

6.2 编程柔道场

The Coding Dojo

就像习武的人那样,有时候一群程序员聚在一起练习,也有些时候是独自练习。

6.2.1 卡塔

Kata

编程卡塔也是一整套敲击键盘和鼠标的动作,用来模拟编程问题的解决过程。

编程卡塔的最终目标,也是逐步练习以达到纯熟。反复的练习会训练大脑和手指如何动作和反应。

要学习热键和导航操作,以及测试驱动开发、持续集成之类的方法,找整套的卡塔来练习都是相当有效的。更重要的是,它特别有利于在潜意识中构筑通用的问题与解决方案间的联系。

6.2.2 瓦萨

Wasa

瓦萨基本可以说是两个人的卡塔。

两个人选择一个卡塔,或者一个简单问题,一个人写单元测试,另一个人写程序通过单元测试,然后交换角色。

6.2.3 自由练习

Randori

在自由练习中,屏幕被投影到墙上,一个人写测试,然后坐下来,另一个人写程序通过测试,再写下一个测试。桌子边的人一个个轮流接下去,或者有兴趣的人可以自己排队参加。

6.3 自身经验的扩展

6.3.1 开源

保持不落伍的一种方法是为开源项目贡献代码。

6.3.2 关于练习的职业道德

职业程序员用自己的时间来练习。

之前在TWU把三种Dojo的方式都练习过,但是当时读书少,不知道它们的名字,只是觉得很有意思,也了解到不同人的思考问题的方式。现在看来茅塞顿开。喜欢书里面提到的一句话,“老板的职责不包括避免你的技术落伍,也不包括为你打造一份好看的履历”。嗯,更多的练习,让自己进步。

第七章 验收测试

7.1 需求的沟通

开发方与业务方之间最常见的沟通是关于需求的。

7.1.1 过早精细化

做业务的人和写程序的人都容易陷入一个陷阱,即过早进行精细化。

7.1.2 迟来的模糊性

避免过早精细化的方法是尽可能地推迟精细化。

但是,这可能造成另一个问题:迟来的模糊性。

“需求文档中的每一点模糊之处,都对应着业务方的一点分歧。”

7.2 验收测试

业务方与开发方合作编写的测试,其目的在于确定需求已经完成。

7.2.1 “完成”的定义

完成意味着所有的代码都写完了,所有的测试都通过了,QA和需求方已经认可。

专业开发人员会根据自动化的验收测试来定义需求。

7.2.2 沟通

验收测试的目的是沟通、澄清、精确化。

7.2.3 自动化

验收测试都应当自动进行。

接触过Cucumber的测试,但是没有实现过,应该尝试一下,写写自动化的验收测试。

7.2.4 额外工作

不要把它们(测试)看作额外的工作,而应当看成节省时间和金钱的办法。这些测试可以避免你的开发误入歧途,也可以帮你确认自己已经完工。

7.2.5 验收测试什么时候写,由谁来写

通常,业务分析员测试“正确路径”,以证明功能的业务价值;QA则测试“错误路径”、边界条件、异常、例外情况。

在敏捷项目中,只有在选定了下一轮迭代(Iteration)或当前冲刺(Sprint)所需要的功能之后,才编写测试。

迭代开始的第一天,就应当准备好最初的几项验收测试。然后每天都应当完成一些验收测试,到迭代的中间点,所有的测试都应当准备完毕。

7.2.6 开发人员的角色

实现某项功能的代码,应该在对应的验收测试完成后开始。开发人员运行这些验收测试,观察失败的原因,将验收测试与系统联系起来,然后实现需要的功能,让测试通过。

7.2.7 测试的协商与被动推进

身为专业开发人员,与编写测试的人协商并改进测试是你的职责。

7.2.8 验收测试和单元测试

验收测试不是单元测试。单元测试是程序员写给程序员的,它是正式的设计文档,描述了底层结构及代码的行为。

验收测试是业务方写给业务方的。它们是正式的需求文档,描述了业务方认为系统应该如何运行。

它们的主要功能其实不是测试,测试只是它们的附属职能。单元测试和验收测试首先是文档,然后才是测试。

7.2.9 图形界面及其他复杂因素

通过GUI背后的API来测试业务逻辑。

有些验收测试规定了GUI自身的行为。这些测试必须通过GUI。但是,这些测试并不是测试业务逻辑的,所以不需要业务规则关联到GUI。最好把GUI和业务规则解耦合,在测试GUI时,用测试桩替代业务规则。

应当尽可能地减少GUI测试。

7.2.10 持续集成

保持持续集成系统的时刻运行是非常重要的。

在持续集成系统里,失败的集成应该视为紧急情况,也就是“立刻中止”型事件。

我们最怕的就是在周五下午提交代码,挂的死去活来的CI是每个人的噩梦。

7.3 结论

要解决开发方和业务方沟通问题,我所知道的唯一有效的办法就是编写自动化的验收测试。

第八章 测试策略

每个专业的开发团队都需要一套好的测试策略。

8.1 QA应该找不到任何错误

对QA找到的每一个问题,开发团队都应该高度重视、认真对待。应该反思为什么会出现这种错误,并采取措施避免今后重犯。

8.1.1 QA也是团队的一部分

QA在团队中要扮演的便是需求规约定义着(specifier)和特性描述者(characterizer)。

8.1.2 需求规约定义者

QA的任务便是和业务人员一起创建自动化验收测试,作为系统真正的需求规约文档。每轮迭代中,他们都可以从业务人员那里收集需求,将之翻译为向开发人员描述系统行为的测试。通常,业务人员编写针对正常路径的测试(happy-pathtest),而由QA编写针对极端情况(corner)、边界状态(boundary)和异常路径(unhappy-pathtest)的测试。

8.1.3 特性描述者

QA的另一项任务是遵循探索式测试的原则,描述系统运行中的真实情况,将之反馈给开发人员和业务人员。

8.2 自动化测试金字塔

8.2.1 单元测试

Unit tests

在金字塔底部是单元测试,这些测试由程序员使用与系统开发相同的语言来编写,供程序员自己使用。

8.2.2 组件测试

Component tests

组件测试是验收测试的一种。通常,它们是针对系统的各个组件而编写的。系统的组件封装了业务规则,因此,对这些组件的测试便是对其中业务规则的验收测试。

在组件测试中,需要使用合适的模拟(mocking)或测试辅助(test-doubling)技术,解开与系统的其他组件的耦合。

组件测试由QA和业务人员编写,开发人员提供辅助。它们需要在FitNesse、JBehave或Cucumber等组件测试环境下编写。其目的是让不具备编写测试能力的业务人员也能理解这些测试。

它们更主要测试的是成功路径的情况,以及一些明显的极端情况、边界状态和可选路径。大多数的异常路径是由单元测试来覆盖测试的。

8.2.3 集成测试

Integration tests

这些测试将组件装配成组,测试它们彼此之间是否能正常通信。

集成测试是编排性(choreography)测试。它们并不会测试业务规则,而是主要测试组件装配在一起是否协调。

在这个层次上,也许已经可以进行性能测试和吞吐率测试了。

8.2.4 系统测试

System tests

这些测试是针对整个集成完毕的系统来运行的自动化测试,是最终的集成测试。它们不会直接测试业务规则,而是测试系统是否已正确组装完毕,以及系统各个组成部件之间是否能正确交互。在这个层次的测试集中,应该包含吞吐率测试和性能测试。

8.2.5 人工探索性测试

这是需要人工介入、敲击键盘、盯牢屏幕的测试。

探索式测试不是要证明每条业务规则、每条运行路径都正确,而是要确保系统在人工操作下表现良好,同时富有创造性地找出尽可能多的“古怪之处”。

8.3 结论

这下更清楚不同测试的目的了。觉得有时间要把Kent BeckTest Driven Development: By Example好好地读一下。作者由Kent手把手教TDD,羡慕。

这里有必要说一句,之前用TDD更多的是写Unit tests,所以对TDD的使用可能有些混淆了概念。TDD测试的是Features, 不是“Units”,有时候Features和Units有关,但更多的时候是无关的。

第九章 时间管理

9.1 会议

关于会议,有两条真理:

  • (1)会议是必需的;

  • (2)会议浪费了大量的时间。

9.1.1 拒绝

受到邀请的会议没有必要全部参加。

9.1.2 离席

如果会议让人厌烦,就离席。

9.1.3 确定议程与目标

为了合理使用与会者的时间,会议应当有清晰的议程,确定每个议题所花的时间,以及明确的目标。

9.1.4 立会

到场的人依次回答以下3个问题:

  • (1)我昨天干了什么?

  • (2)我今天打算干什么?

  • (3)我遇到了什么问题?

站会对团队了解彼此的工作进度很有帮助,还能帮助自己整理思路。要是前一天的产出很低,会不好意思的。

9.1.5 迭代计划会议

迭代计划会议用来选择在下一轮迭代中实现的开发任务。在会议召开前必须完成两项任务:评估可选择任务的开发时间,确定这些任务的业务价值。

9.1.6 迭代回顾和DEMO展示

9.1.7 争论/反对

“凡是不能在5分钟内解决的争论,都不能靠辩说解决。”

唯一的出路是,用数据说话。

9.2 注意力点数

职业开发人员会学习安排时间,妥善使用自己的注意力点数。

9.2.1 睡眠

9.2.2 咖啡因

9.2.3 恢复

9.2.4 肌肉注意力

肌肉注意力有助于改善心智注意力,而且不仅仅是简单的恢复。

9.2.5 输入与输出

关于注意力,我知道的另一重点是平衡输入与输出。

9.3 时间拆分和番茄工作法

番茄工作法的真正好处在于,在25分钟的高效工作时间段里,你有底气拒绝任何干扰。

看来要好好实践一下番茄工作法。之前一直使用的是此刻,看来要继续下去。

9.4 要避免的行为

优先级错乱——提高某个任务的优先级,之后就有借口推迟真正急迫的任务。

专业开发人员会评估每个任务的优先级,排除个人的喜好和需要,按照真实的紧急程度来执行任务。

9.5 死胡同

在走入死胡同时可以迅速意识到,并有足够的勇气走回头路。这就是所谓的坑法则(The Rule of Holes):如果你掉进了坑里,别挖。

9.6 泥潭

比死胡同更糟的是泥潭。

走回头路看起来代价很高,因为要把已有代码推翻重来,但是走回头路绝对是最简单的方法。

9.7 结论

专业开发人员会用心管理自己的时间和注意力。他们知道优先级错乱的诱惑,他们也珍视自己的声誉,所以会抵制优先级错乱。他们永远有多种选择,永远敞开心扉听取其他解决方案,他们从来不会执拗于某个无法放弃的解决方案。他们也时刻警惕着正在显露的泥潭,一旦看清楚,就会避开。

第十章 预估

10.1 什么是预估

业务方觉得预估就是承诺。开发方认为预估就是猜测。

10.1.1 承诺

承诺是必须做到的。

承诺是关于确定性的。

10.1.2 预估

预估是一种猜测。

预估不是个定数,预估的结果是一种概率分布。

墨菲定律:如果可能出错,那么就一定会出错。所以对什么不要抱侥幸心理。

10.1.3 暗示性承诺

专业开发人员能够清楚区分预估和承诺。只有在确切知道可以完成的前提下,他们才会给出承诺。此外,他们也会小心避免给出暗示性的承诺。他们会尽可能清楚地说明预估的概率分布,这样主管就可以做出合适的计划。

10.2 PERT

计划评审技术(PERT,Program Evaluation and Review Technique)。

10.3 预估任务

“德尔菲法”(wideband delphi)。

共识。

一组人集合起来,讨论某项任务,预估完成时间,然后重复“讨论-预估”的过程,直到意见统一。

  • 1.亮手指

  • 2.规划扑克

之前用斐波那契数列实践过,预估过卡片的点数。

  • 3.关联预估

将卡片打乱铺开,按照任务的复杂度排序。最后,静默的排序终止。开始讨论取得共识。在实践的过程中,从有分歧到达成一致,还挺有意思的。

  • 4.三元预估

10.4 大数定理

控制错误的办法之一是使用大数定律。该定律的意思是:把大任务分成许多小任务,分开预估再加总,结果会比单独评估大任务要准确很多。

预估实践的比较少,个人觉得主要还是需要经验的积累。

第十一章 压力

即使有压力,专业开发人员也会冷静果断。

11.1 避免压力

在压力下保持冷静的最好方式,便是规避会导致压力的处境。

11.1.1 承诺

应当避免对没有把握能够达成的最后期限作出承诺,这一点很重要。

11.1.2 保持整洁

快速前进确保最后期限的方法,便是保持整洁。

让系统、代码和设计尽可能整洁,就可以避免压力。

混乱会降低速度,导致工期延误,承诺失信。因此,要尽力保持输出成果整洁干净。

11.1.3 危机中的纪律

观察自己在危急时刻中的反应,就可以了解自己的信念。

选择那些你在危急时刻依然会遵循的纪律原则,并且在所有工作中都遵守这些纪律。

11.2 应对压力

11.2.1 不要惊慌失措

11.2.2 沟通

让你的团队和主管知道你正身陷困境之中。告诉他们你所制定的走出困境的最佳计划。请求他们的支援和指引。避免制造意外之外的诧异。

11.2.3 依靠你的纪律原则

战胜压力煎熬的唯一方法,便是依靠那些你已经知道切实有效的东西——你平时遵守的纪律。

11.2.4 寻求帮助

结对!

第十二章 协作

12.1 程序员与人

编程用的机器则整洁,行为也可预见。

“我的Mac就是我的女朋友。”

12.1.1 程序员与雇主

专业程序员的首要职责是满足雇主的需求。

深刻理解业务目标。

12.1.2 程序员与程序员

团队中每位成员都能签出任何模块的代码,做出任何他们认为合适的修改。

专业人士会结对工作。

因为至少对有些问题而言,结对是最有效的解决方法。

专业人士结对工作,因为这是分享知识的最好途径。

专业人士之所以结对,是因为结对是复查代码最好的方式。

12.2 小脑

有些时候,单独工作是正确的。

但是一般来说,和其他人紧密协作、在大部分时间段中结对工作,是最好的做法。

12.3 结论

编程就意味着与人协作。

第十三章 团队与项目

13.1 只是简单混合吗?

让一个程序员把一半的时间投入在项目A中,把其余时间投入在项目B中,这并不可行,尤其是当这两个项目的项目经理不同、业务分析师不同、程序员不同、测试人员不同时,更不可行。

13.1.1 有凝聚力的团队

这个团队应该配有程序员、测试人员和分析师,同时还要有一名项目经理。

其中有一名团队成员可能会拿出部分时间充任团队教练或Master的角色,负责确保项目进展,监督成员遵守纪律。

类似Scrum敏捷项目管理框架中的Scrum Master。Scrum敏捷实践有接触过,有时间这里的知识要再巩固一下。

专业的开发组织会把项目分配给已形成凝聚力的团队,而不会围绕着项目来组建团队。

13.1.2 如何管理有凝聚力的团队

每个团队都有自己的速度。团队的速度,即是指在一定时间段内团队能够完成的工作量。有些团队使用每周点数来衡量自己的速度,其中“点数”是一种关于复杂度的单位。

管理人员可以对分配给团队的项目设置一个目标值。

13.1.3 项目承包人的困境

项目承包人的职责所在,便是清晰地定义和陈述项目的价值和意义,让项目得到公司管理层的认可和支持。

第十四章 辅导、学徒期与技艺

14.1 失败的学位教育

那些符合要求的毕业生有个共同点:他们几乎都在进入大学之前就已经自学编程,并且在大学里依然保持自学的习惯。

自学很重要,所以更要学会如何自学

14.2 辅导

14.3 学徒期

14.3.1 软件学徒期

  • 1.大师

  • 2.熟练工

  • 3.学徒/实习生

14.3.2 现实情况

我们今天的做法和我所提倡的理想化的学徒制程序,这两者之间的主要差异在于技术方面的传授、培训、督导和检查。

14.4 技艺

成熟工匠是一名专业人士。

技艺是工匠所持的精神状态。

附录 工具

A.2 源代码控制

开源工具通常是最好的选择。

A.2.2 悲观锁与乐观锁

永远不要签入没有通过全部测试的代码。永远不要。

A.2.3 CVS/SVN

Git大法好!强烈建议未曾接触过Git的人开始使用Git对自己的软件版本进行管理。你会发现你打开了美好新世界的大门。

A.3 集成开发环境/编辑器

A.3.1 vi

使用过一段时间的VIM,个人觉得不求精通,但求掌握,毕竟在一些时候,用它可以快速编辑一些代码。如果花时间精通它之后,你会发现它和IDE工具一样好用。

A.3.3 Eclipse/IntelliJ

我现在用的是IntelliJ。你可以更方便地编辑代码,效率当然可以得到很大的提高。对于个人来说,如果不想购买License的话,有社区版可供使用。

A.4 问题跟踪

有时候,最好用的问题跟踪系统可能是一打卡片和一个公告板。

在工作中使用的是LeanKit,个人使用更多的是Trello。创建多栏,在合适的时候把卡片从一栏移到下一栏。

A.5 持续构建

我的持续构建哲学很简单:把它和源代码控制系统对接起来。不管什么时候,只要有人签入代码,就要能自动进行构建,并把结果状态报告给团队。

团队必须一直确保构建成功。

我目前接触过的是Bamboo

A.6 单元测试工具

不论选择什么样的单元测试工具,这些工具都要支持如下一些基本的特性。

  • (1)必须能够快速便捷的运行测试。

  • (2)对于测试是通过还是失败了,这些工具应该给出清楚的视觉提示。

  • (3)对于测试进度,这些工具也应该给出清楚的视觉提示。

  • (4)这些工具应该避免测试用例之间彼此通信。

  • (5)这些工具应该使编写测试变得十分容易。

现在我用的更多的是写Java时的JUnit

A.7 组件测试工具

这些工具用于在API层对组件进行测试。它们的任务是要确保组件行为是以业务人员和QA能够理解的语言来描述的。

我目前接触过的是cucumber,有时间需要好好实践一下。

A.9 UML/MDA

A.9.1 细节

程序员负责管理各种细节,这是我们的职责。我们通过管理各种最微小的细节来规范系统的行为。

整本书读下来,收获不小。之前很多在工作中接触过的方法或实践,并不是很清楚它们的理论或原理。读着读着很多时候发现,原来之前实践的方法叫这个名字。可以方便以后对实践进行更新或是更好的进一步思考。方法论的书,常读常新,把自己的实践和理论结合起来,防止走弯路的同时,也构建起了自己的理论体系。本书提到的很多实践,发现在ThoughtWorks的工作中都接触到了。感谢在TW的成长。

程序员的职业素养 - Robert C. Martin

Comments