前 言
那是20世纪90年代中期,我的职业生涯刚刚开始两年,巴西圣保罗有家大型国际公司宣布要一次招纳60名开发者。选拔过程分四个阶段,共需数周时间。第一阶段是三小时技术测试;第二阶段是两周的公司专有技术培训,培训结束后考试;第三阶段是一整天团队互动;第四阶段是最终一轮面试。该公司在一家大报纸上刊登了这一消息,大约有900名开发者应聘。那时我正在一家小软件公司上班,工作非常开心,但我觉得自己已经准备好干一番大事。因为第一阶段安排在周六,所以我决定去试试。不到300名开发者进入第二阶段,我也在其中。我信心满满但略带忧虑。接下来的选拔过程需要很多天,如果我要继续参加剩下的三个阶段,那就必须辞掉现在的工作。当时我经济条件并不好,而且也无法指望家人资助。为了追求理想的工作而放弃现有的工作,是非常艰难的,何况那份工作还未必能够被录用。而且一旦找不到新工作,我也不知道怎么维持生计。然而我还是辞职了。我必须去试一试——我就是想去那样的公司上班,我就是想从事那份工作。
那年我21岁,虽说很年轻,但其实已经有好些年编程经验了。我11岁开始写代码,19岁开始上班。问题在于,像这种年轻而又稍微有点经验的人很容易骄傲。我自然也不例外。我就是一个傲气的年轻开发者。我觉得自己比谁都强。我当时认为自己特别优秀,比学校里的同学强,也比从前共事的大部分同事厉害。
四个阶段都结束后,公司宣布没有招满60名符合要求的员工。他们只招了32个人,我就是其中之一。我当时真是兴高采烈、志得意满。公司的系统中有多个业务模块,第一周上班,我分到了负责交付某个业务模块的开发团队里。头几周时间,我在和负责其他业务模块的开发者聊天时,听他们提到了一个团队,据说那是公司里最好的团队。那就是所谓的“架构”(architecture)团队,他们负责系统核心,并且要提供所有的基础代码(infrastructure code)给各业务团队使用。
架构团队的主管是个了不起的家伙,除了做管理工作之外,他还是个出色的开发者。他是个大忙人,但总能挤出时间去写代码、以自己的身份提交代码,并审校本团队其他成员的代码。我听说那个团队一直在做些有趣的事,而且代码写得超级棒。那正是我想去的地方。我想和最优秀的人在一起。
漫长的几周过去了,我决定和架构团队的经理谈谈,他就是我刚说的那个人。我既不知道该谈些什么,也不知道结果会怎样。我能确信的事只有一件:我没什么可失去的。最坏的结果就是他说他不想把我放到他们团队里。某天我看他一个人在咖啡间,于是哆哆嗦嗦地走了过去。我向他介绍自己:“你好,我是Sandro。”他对我微笑,跟我握手,并且平静而从容地说道:“我是Namur。很高兴认识你。”几秒钟尴尬过后,我紧张地说了一句:“我想加入你们团队。”他稍微有点惊讶,但看上去很高兴。我开始和他聊应聘的过程,聊自己为什么要来这家公司,以及公司对我的要求等。他也问我有没有参加业余兴趣项目,问我对什么技术感兴趣,以及是否在工作时间之外写代码,然后还说了其他一些事,我记不得了。聊了大概30分钟之后,他就问我什么时候可以开始过来上班。我愣住了。我根本没想到他这么快就会答应。我以为还要安排一次面谈,再来一场正规面试什么的。后来我才意识到,其实整个谈话过程中,他都在判断我对软件开发的喜爱程度。他在分析我是不是那种认真负责的人。他并不担心我目前的技术知识水平。我对Namur说:“我去和现在的经理谈谈,希望能快点过来。”几周之后,我就和新队友坐在一起了。
第一天上班是个周一。Namur早上跟我说,要布置一项任务给我。他描述了应用程序的某个部分,以及我需要完成的事项,然后说周五会过来看看我的成果。我太激动了。这正是展示自己能力的好机会!我要叫他看看我自己在团队中的价值。于是,我一直到深夜才离开办公室,只睡了几小时,周二一大早就爬起来上班,到周二下午两点就把任务完成了。只花不到一半时间就做完自己的第一份任务,这感觉妙极了。我一向都认为自己很棒,但这次,在这样一个高水平的团队里,面对这样一份从未参与过的代码库,我能把任务完成,那真是了不起!
我跑到Namur办公室,兴奋地告诉他:“做好了。程序已经写完,而且能够运行。”他当时正在敲键盘,看到我之后停了下来,平静地说:“写出的程序能运行,只是我对员工最起码的要求。你告诉我某个程序已经写完,那本身就意味着它要能正常运行才对。”这话给我泼了盆冷水。我脸上的笑意稍稍收敛了一下,不过我认为这也许只是他的说话习惯而已。可能他今天不太顺吧。我想他绝不至于故意讲难听话。“咱们坐下来看看你写的代码吧。”他继续说着。我坐下看他从源码控制系统里获取一份.pas文件,我写好的所有代码都在这份文件里。他通过命令行,用一种黑绿相间的神奇编辑器打开了这份文件。那是我头一次看到vi。当时我们一般都是用Delphi来开发的,Delphi是一种非常流行的集成开发环境(Integrated Development Environment,IDE),功能特别强大。我看到有人用vi打开Delphi文件,觉得特别怪异(vi是一种UNIX文本编辑器)。“坐过来一点,咱们一起看代码。”他说。我写的代码大概有两百行。他把光标移到第一行,然后一行一行往下看。每五六行,他就停下来,跟我说下面这些话:“你知道分配内存和释放内存的时候会发生什么吗?看看这里,你在一个方法里面分配内存,但却在另一个方法里面释放。这可能会导致内存泄漏。听说过临时耦合(temporal coupling)吗?看看这块代码,你仔细想想就会发现,可以把它从8行精简到2行。你知道在try/catch块中放这么多语句会出现什么问题吗?这个变量和方法的名字起得合适不合适?它们表示什么意思?你是否想过,有些同事可能需要修改这段代码,但他们又不像你那样,拥有足够的信息和明确的语境,他们怎么理解这些名称呢?他们在不了解这段代码的情况下,又该如何维护呢?这个地方怎么会出现硬编码?你有没有想过,现在把固定值写在这里,将来万一要修改,那我们又要打开代码、修改代码、编译代码,而且要重新部署整个应用程序?文件里为什么老是重复出现这几行代码?噢,还有这里,这个方法怎么这么长呀!要是每个方法都写这么复杂的话,我们看代码的时候还能不能理解它了?应该使它们短小精悍,而且要按照功能起个合适的名字。”他就这样一直说下去……
然后,他在一个地方停了下来,开始盯着那几行代码。他在那上面花了几分钟,偶尔把光标移到前一屏或后一屏看看。20世纪90年代那阵,如果某个开发者能写出别人看不懂的代码,那大家就会觉得这个人很强,他们会说:“这个人肯定特别厉害,写出来的代码我们都看不懂喔。”我在那份源文件里也写了一些晦涩难懂的代码,用来炫耀自己很聪明。等Namur看明白那些代码的时候,我在想,他最后总该鼓励我一下吧?但是他却冷冰冰地说:“你知不知道这么写代码很不好?我们在做一个非常大的系统,有很多团队和开发者都要在同一份代码库上面工作。要是每个人都这么炫耀的话,这代码理解起来该有多困难?不要说有几百万行代码,就算只有几千行,这样写也不行。”第二盆冷水又泼了下来。
我写的代码只有两百行,但针对这两百行代码,我却没办法回答他的任何问题,他指出那些缺点时,我也想不到该怎么答复才好。他就这样一行一行看着代码,批评我的写法,然后跟我说应该怎样写才会更好。等他看完整份文件之后,我已经十分羞愧苦恼了,但他依然淡淡地对我说:“你明白我刚说的那些了吗?你觉得我的建议对不对?”他说话时那种口气,就好像写代码的这个人不是我,而是另一个不在场的陌生人一样。我什么都没说,只是点点头。他又问:“你现在觉得自己能把这份代码写得更好一些吗?”我没看他,只是点点头。他还接着问:“你觉得自己以后写代码的时候能不能做到我们刚说的那些?”我还是只点了点头。于是,他按了几个键,把我写好的整份代码文件全删了,然后说:“嗯,那就好。还有三天时间呢,重写吧。”
我又愣住了。我不知该怎么回答。站定之后,我缓步走向门口,一句话也没说。“Sandro,”快走到门口时他叫住我,“方式与结果一样重要。”说完之后,他又回过身,对着那个怪异的绿色编辑器开始打字。
我很沮丧。实际上,我特别愤怒。离开他办公室后,我直接下楼,走出了公司。当时我心想:他以为他是谁呀,居然用这种口气跟我说话,混蛋!我才不给这种人干活呢。真是受够了!我不想留在这家公司了!辞职!抽了几根烟后,我冷静了一点,开始回想刚才的事。Namur毕竟花了一个多小时来看我的代码,而且还跟我解释了怎样才能写得更好。在我偶尔表达自己观点的时候,他也能倾听,并且会认真地指出我的错误,或者告诉我还有另一些更好的写法。我发现,自打开始编程,这是头一次有人肯花工夫告诉我怎么样才能写出好的代码。另外,他水平确实比我高很多,而且经验也远比我丰富,他是真心希望别人能把代码写好的那种人。我想,我发现了一个追求优秀软件和高质量代码的人。这样一个人会花时间来指导我,而且,更重要的是,我找到了自己的第一位导师。
几根烟过后,我重新振作起来,跟变了个人似的。那天我终于明白自己并不如想象中那般优秀;我明白了应该如何保持谦虚的态度;明白了我还有很多东西要学;明白了只把事情做完是不够的,尤其是身处团队之中;明白了怎样做才能受到同事与客户尊重,而不是留下一堆烂代码不管;更明白了一名真正优秀的专业人士一定会在乎自己的作品。
我和导师Namur及其他一些优秀开发者共事了两年半的时间。这段经历不仅使我变得更加专业,而且使我变得更会做人。虽然当时并没有提及“软件工艺”这个词,但十年之后我发现,我第一次接触这个概念正是在那个时候。我从他们身上学到了很多。从技术角度来看,那是一段有益的经历,但最重要的并不是技术本身,而是我在那段时间里从主管和同事那里学到的对待工作的态度。第一次审校完代码时,Namur对我说的那句话彻底改变了我。十年后,我成立了伦敦软件工艺社团(London Software Craftsmanship Community,LSCC,网址是:http://www.meetup.com/london-software-craftsmanship),而Namur的那句话——“方式与结果一样重要”(how it is done is as important as getting it done),成了我建立网站时第一批写上去的文字。后来我给LSCC定制了一些T恤衫,这句话也印在上面。这句话不仅使我成为一名更优秀的开发者,而且也把我变成了一个更好的人。
关于本书
数十年间,众多软件开发方式(methodology)涌现,可是软件项目依然会失败。失败的原因很多,但有几个问题不容忽视:管理者只把软件开发当成一条生产线;公司不知道怎么管理软件项目,不知道怎么招聘优秀开发者;很多开发者仍然不够专业、不够积极,他们向雇主和客户提供非常糟糕的服务。有了敏捷软件开发(Agile)这种方式之后,软件行业确实出现了巨大进步,但软件项目的失败率还是很高。这些项目为什么依旧做不好呢?为什么无法顺利完成软件项目呢?我们到底缺少什么?
尽管“软件工艺”这个词十几年前就出现了,但直到最近它才成为一种可靠的解决方案,能够用来应对软件行业时下面临的许多问题。
软件工艺为开发者和软件公司提供了一套独特的理念。尽管它并不是一种软件开发方式,但却强烈建议我们采用某些技术实践手段及指导原则,这些手段和原则基本上都在极限编程(Extreme Programming)中做了界定。通过与敏捷(Agile)和精益(Lean)原则紧密结合,软件工艺可以大幅提升软件行业的水平。它关注的重点是专业精神、高超技术,以及良好的客户满意度。而其中一个重要方面就是转变态度:不要再把软件开发者看成生产线上的工人,也不要再把管理软件项目当成开工厂。
如何才能变成更好的开发者?如何才能交付更好的软件项目?本书将会讲述真实案例,给开发者和软件公司提出实用的建议,直接参与软件项目的每位开发者和专业人士都适合阅读本书。
目 录
第一部分 理念及态度
第1章 21世纪的软件开发
1.1 何谓资深开发者
1.2 新的挑战
第2章 敏捷软件开发
2.1 面向流程的敏捷软件开发原则
2.2 面向技术的敏捷软件开发原则
2.3 何谓敏捷
2.3.1 转变开发方式
2.3.3 丰富职业技能
2.4 《敏捷软件开发宣言》
2.5 由传统开发方式向敏捷转型
2.6 因转型不佳而表现出的问题
2.6.1 转型不彻底
2.6.2 局部转型的积极意义
2.7 敏捷软件开发与软件工艺的关系
2.8 小结
第3章 软件工艺
3.1 更恰当的比喻
3.2 维基百科对软件工艺的定义
3.3 笔者个人所推崇的定义
3.4 更为简洁的定义
3.5 不要拘泥于定义
3.6 软件开发是手艺、生意、工程、科学,还是艺术
3.7 软件工艺的历史
3.7.1 软件工艺峰会
3.7.2 软件工艺概念走向全球
3.7.3 软件工艺师交换计划
3.7.4 软件工艺社团
3.7.5 《软件工艺宣言》的制定过程
3.7.6 《软件工艺宣言》及讲解
3.8 小结
第4章 软件工艺师的态度
4.1 你的事业由谁掌控
4.2 与时俱进
4.2.1 博览群书
4.2.2 阅读并撰写博客
4.2.3 关注技术网站
4.3 寻找业界高手
4.4 反复练习
4.4.1 kata
4.4.2 兴趣项目
4.4.3 开源项目
4.4.4 结对编程
4.5 参与社交活动
4.6 主动发现问题
4.7 兼顾工作与生活
4.7.1 挤出空闲时间
4.7.2 用“番茄工作法”集中注意力
4.7.3 处理好工作与生活之间的关系
4.8 小结
第5章 争强好胜、满腔热情与专业精神
5.1 学会拒绝
5.1.1 大败局
5.1.2 从这次失败中得到的教训
5.1.3 更加专业地工作
5.2 提出解决办法
5.3 开明的项目经理
5.4 小结
第6章 什么是可行的软件
6.1 只开发出可行的软件是不够的
6.2 软件维护
6.3 潜在的危险
6.3.1 编写高质量的代码
6.3.2 要雇用软件工艺师,而不是平庸的开发者
6.4 错误的时间观念
6.4.1 技术债务的故事
6.4.2 过于忙碌的团队
6.4.3 单元测试任务卡
6.4.4 合理运用时间
6.5 遗留代码
6.5.1 转变态度
6.5.2 既要享受工作,也要令客户满意
6.6 小结
第7章 技术实践
7.1 不仅要做正确的事情,而且要把事情做好
7.2 软件公司的具体情况
7.3 极限编程的历史
7.4 极限编程的做法及其价值
7.5 为自己的决策负责
7.6 注重实效
7.7 小结
第8章 漫漫职场路
8.1 巴西少年成长记
8.2 专注与决心
8.3 把工作当成投资
8.4 自主、精通与目标
8.5 在公司内谋求发展与追求事业成功之间的关系
8.6 小结
第二部分 全 面 转 变
第9章 招纳人才
9.1 普通的职位描述
9.2 因过于忙碌而草率地招聘
9.3 最好别在招聘启事上面写职位描述信息
9.3.1 如果一定要写职位描述,如何写才好
9.3.2 这不仅仅是一份工作
9.4 推荐工作
9.5 参与社团活动
9.6 确定有效的筛选标准
9.7 储备式招聘
9.8 小结
第10章 面试软件工艺师
10.1 把面试当成商业谈判
10.2 如何判断对方是不是良好的合作伙伴
10.2.1 用人公司对良好合作伙伴的理解
10.2.2 开发者对良好合作伙伴的理解
10.3 有效的面试
10.3.1 在面试中关注重点
10.3.2 用思维图促进谈话效果
10.3.3 在面试过程中结对编程
10.3.4 请根据公司的实际要求来设计面试
10.4 大胆录用有潜力的开发者
10.5 如何为现有团队招募新成员;如何招募新团队
10.6 面谈之前先通过代码练习来筛选开发者
10.7 每个人都应该学会面试
10.8 必须由开发者来面试开发者
10.9 小结
第11章 面试中的禁忌
11.1 不要自作聪明
11.2 不要出脑筋急转弯问题
11.3 不要问连自己都不知道答案的问题
11.4 不要看不起开发者
11.5 不要阻止开发者上网
11.6 不要在纸上写代码
11.7 不要用算法来面试开发者
11.8 不要安排电话面试
11.9 小结
第12章 团队士气低落的害处
12.1 公司向敏捷转型之后所表现出的问题:士气低落
12.2 雇用“朝九晚五”式开发者的代价
12.3 缺乏工作动力会阻碍公司的变革
12.4 请软件工艺师来提升团队的工作热情
12.5 小结
第13章 营造学习气氛
13.1 错误的变革动机
13.2 营造一种学习文化
13.2.1 举办读书会
13.2.2 举行午餐研讨会
13.2.3 举行小组讨论
13.2.4 在一个迭代周期内互换项目
13.2.5 小组代码审校
13.2.6 举行编程实验
13.2.7 在公司内部组织实践社团
13.2.8 鼓励大家做兴趣项目
13.2.9 参与公司外的技术社团
13.3 其他人不想参与时该怎么办
13.3.1 自己做个榜样
13.3.2 关注那些乐于改变的人
13.3.3 不要强迫他人参与
13.3.4 不要试着改变每个人
13.3.5 避免出现大家都借故不参加活动的情况
13.3.6 不必征得老板同意
13.3.7 不要化简为繁
13.3.8 建立有规律的聚会制度
13.4 小结
第14章 推动技术变革
14.1 确定自己所面对的质疑者是何类型
14.2 为推进技术变革做好准备
14.3 从何处入手
14.3.1 建立信任
14.3.2 以身作则
14.3.3 逐个解决问题
14.3.4 迭代、回顾、调整
14.4 恐惧与无能
14.5 如何说服主管
14.6 如何说服团队采用TDD
14.7 面对质疑
14.7.1 如何面对“象牙塔里的架构师”
14.7.2 如何面对抱怨公司的人
14.8 你真的要在乎这么多吗
14.9 小结
第15章 务实的软件工艺
15.1 大家总是想要高质量的软件
15.2 打破“开发高品质的软件昂贵而耗时”这一迷思
15.3 重构
15.4 软件开发的方式不止一种
15.5 帮助业务人员
15.6 软件项目并不是围着我们转的
15.7 优秀开发者与平庸开发者之间的区别
15.8 简洁设计四原则
15.8.1 设计模式
15.8.2 从重构到模式
15.9 软件工艺与务实态度
15.10 总结 189
第16章 软件工艺师的职业进化之路
16.1 软件工艺师的品格
16.2 职业发展
16.3 道路与里程碑
16.3.1 选好职业发展过程中的每一份工作
16.3.2 不知道接下来的发展方向怎么办
16.4 接触各种类型的软件开发工作
16.5 使命感