0%

高效程序员的45个习惯

态度决定一切

关于代码

直面代码问题,解决问题,而非寻根问底。勇于承认自己不知道答案,这会让人感觉放心。一个重大的错误应该被当做是一次学习而不是指责他人的机会。团队成员们在一起工作,应相互帮助,而不是互相指责。

使用代码复审,单元测试等方法。看到更小、更易于理解的代码模块。

建议:不要坠入快速的简单修复之中,要投入时间和精力保持代码整洁

关于会议

会议的目标也是一样的,聚焦于如何解决问题上。“你不需要很出色才能起步,但是你必须起步才能变得出色。”

团队决策可用的技术:设定最终期限,避免陷入无止境套路,没有最好,只有更适合;逆向思维,先认识优点再认识缺点,相对优的方案;设立仲裁人,让每个人都有发言机会,专注调停;一旦做出决定,全力支持做出的决定。

做法:

  • 尽力贡献自己的好想法
  • 只有更好,没有最好
  • 用合适的词和理由解释你为何不赞同,并提出明确的问题
  • 做正确的事,要诚实有勇气说出实情

学无止境

迭代和增量式的学习:每天计划一段时间学习新技术,记下那些你想学习的东西或者术语,以后有时间深入研究它。

了解新行情,参加本地的用户组活动,参加研讨会议,如饥似渴地阅读。了解新技术试图解决什么问题。有规律的午餐会议。

技术变化:计算设备昂贵转向人力成本,加快开发效率很重要。完全转入新的开发环境,相关集成的工具链,养成新的习惯。如饥似渴地阅读。不停地问为什么。

像减肥一样,一点点的成功也是很大的激励。小而可达的目标让每个人全速前进。庆祝每一次难忘的成功:共享美食和啤酒以及团队聚餐。

交付用户想要的

拥抱变化,及时让客户做决定,让设计指导,引入合适技术指导开发。

敏捷开发强调提早集成,频繁集成,实现自动化部署,使用演示获得频繁反馈,使用短迭代增量发布来经常发布新功能。

开发者能做最重要的决定是:判断哪些是自己决定不了的,应该让企业主做决定。

提前准备几个选择方案:从业务角度介绍每种方案的优缺点以及潜在成本和收益。具体到每个选择对时间和预算的影响,如何权衡。让你的客户做决定。

CRC(类-职责-协作)卡片设计,包括类名,职责(应该做什么)以及协作者(要完成工作,要与什么对象一起工作);好的设计是一张地图,它也会跟着进度进化。

最后合理地使用技术,考虑这个技术真能解决遇到的问题吗,你会被它栓柱吗,维护的成本是多少。你的代码写得越少,需要维护的东西越少。根据需要选择技术。

随时保持可发布的系统代码:1.在本地运行测试,通过所有单元测试和系统测试 2.检出最新代码,再编译运行测试 3.提交代码 (小步伐迭代集成测试)

版本管理可以阅读《版本控制之道-CVS》,一般需要每天集成几次,而非2~3天才集成一次。且考虑生产环境上的移植部署。

缩减演示会议的次数,只有做完一些东西可以演示的时候,大家才碰面。演示是用来让客户提出反馈的,有助于驾驭项目方向。如果缺少功能或者稳定性的时候,不应该拿来演示,那只能让人生气。可以及早说明期望的功能:让客户知道,他们看到的是一个正在开发中的应用,而不是一个最终已经完成的产品。

使用短迭代,增量式发布的解决方案:分析、设计、实现、测试以及获得反馈的整个过程,小步频繁前进是敏捷方法的核心。

确定使用户可用的核心功能,然后把它们放到生产环境中,越早交到用户手里越好。如果打算1~2年再交付,则应该分解成一块块有用的小系统-再进行增量开发。

有一堆理由值得尽快将软件交到用户手里:1.交到手里就有了收入,有更好的理由继续为产品投资; 2.从用户得到反馈,进一步理解什么是用户真正想要的。 3.及时了解市场真实的变化

使用短迭代和增量式开发让开发者更专注于自己的工作,本地构建->演示活动->内部发布->交付用户。增量开发:发布带有最小可用功能块的产品,每天增量开发中,使用1~4周左右迭代周期。

具体操作:

  • 每4周迭代开发中,加入一周的维护任务
  • 迭代时间不够可能是任务量大,也可能是迭代周期短,要把握好自己的节奏
  • 如果功能背离了用户需求:多半是迭代周期太长
  • 提供的价值是什么:这必须去询问用户

业务安排上:提议先构建系统最小、可用、核心的功能;下一个迭代时,用户选择新功能开发还是取消;

敏捷反馈

守护天使:自动化单元测试;在日常工作检查输出的过程更上了一层楼,保留了相关值并持续化可自动执行,每个语言均有对应的单元测试框架。

1.有了单元测试,就可以每次编译或者构建代码的时候运行测试,测试的结果和编译器一样,如果测试没有通过,那就跟编译没有通过一样糟糕。

2.接下来构建机器,不断获得最新版本的代码,然后编译代码并运行单元测试,如果有错误及时让你知道。这样一来,你就有了守护天使,这也是最容易修复错误,成本最低的时候。

拥有了回归测试,你就可以随意重构代码,根据需要进行实验、重新设计甚至重写代码;从而无须如履薄冰。《单元测试之道》《项目自动化之道》

自动化测试的理由:

  • 及时提供反馈
  • 提高代码健壮性
  • 有用的设计
  • 自信的后台
  • 解决问题的探测器
  • 可信的文档
  • 学习的工具,加深API认知
    单元测试就像高空作业的安全带:单元测试只有达到一定覆盖率才发挥作用,测试并非越多越好,只有有效才有质量

测试驱动设计时从代码用户的角度思考,有助于设计出更有用和更一致的接口,消除过度复杂的设计,专注于真正需要完成的工作。先用再实现。

判断工作进度最好是看实际花费的时间,而非估计的时间。可以使用待办事项,可以物理上从列表中划掉或者标识它是已完成的状态。当加入新任务,先排列它们的优先级,然后加入待办事项中;类似地,你可以有个人的待办事项,当前迭代的待办事项或者整个项目的待办事项。

实际操作:

  • 找一个合适的时间粒度分割事项,比如说3~4小时。
  • 关注功能的完成,而不是日程安排
  • 注意花足够的时间工作,少量的时间管理自我
  • 一周40小时,得准确计算思考编程的时间是减去会议、电话、电子邮件及相关活动时间之后的。

面对用户的反馈:每一个抱怨背后都隐藏一个事实。找出真相,修复真正的问题。
实际操作:

  • 没有愚蠢的用户,只有自大的开发人员
  • “它就是这样”不是好的答案
  • 如果代码解决不了,考虑通过修改文档或者培训弥补
  • 你的用户可能会阅读所有文档,记住所有内容,但也可能不会。

敏捷编码

代码清晰表达意图,增量式编程。
“可以工作且易于理解的代码当然好,但是让人觉得聪明更重要。别人给你钱是因为你脑子好使,如何让自己变得聪明。”
代码阅读次数远远超过编写的次数,所以让读起来尽量简单。代码清晰度应该排在执行效率前。

要在性能、生产力、优雅、成本以及上市时间中权衡考虑,使每一项都能达到最理想的状态。

没有适宜所有状况的最佳解决方案,你必须对手上的问题进行评估,选出最合适的解决方案。

实际操作:

  • 现在投入资源和精力,要确保未来会得到好处,会获得回报
  • 真正的高性能系统,从开始设计时就往这个方向努力
  • 过早优化乃万恶之源
  • 过去的解决方案对新问题可能适用,也可能不适,确认好当前的状况

开发可以工作的、最简单的解决方案。当你觉得所编写的代码中没有一行是多与的,并且仍能交付全部功能时,这种感觉就对了。这样的代码容易理解和修正。

让类的功能尽量集中,让组件尽量小。避免创建很大的类或组件,也不要带无所不包的大杂烩。相对于继承,委托更灵活;如果你不确定一个接口做出什么承诺,或是有什么需求,那就很难提供一个对其有意义的实现。

敏捷调试

不害怕问题,遇到问题时,保留以前的问题解决方案,以及提供发生问题时更多有用的细节。解决问题并建立记录问题解决日志,假定编译器警告就是错误,致力于解决它们。最后发生错误时,考虑用户的感受并提供有用的错误信息。

可以维护保存一个曾遇到的问题以及对应解决方案的日志,称为每日日志:

  • 问题发生日期
  • 问题简述
  • 解决方案详细描述
  • 引用文章或网址提供更多细节和相关信息
  • 任何代码片段截屏等
  • 最后要将日志保存为可供计算机搜索的格式

实际操作时:记录问题不能超过解决问题花费的时间,保持轻量级和简单;使用足够的关键词,以便查找;要记录发生问题的环境及特定版本,因为不同环境表现不一;记录团队的重要决策原因。

解决警告问题:

  • 尽可能提高编译器检查级别,消除所有警告
  • 指示编译器忽略无法避免的警告以找出真正的错误和警告
  • 尽量不使用弃用方法

将代码从运行环境分离出来,构建单元测试,有助于代码解耦以及隔离问题。
当发生问题时,让应用详细记录错误的相关数据。,最起码以文本文件的形式维护。提供调试试用的完整详细信息。

区分主要错误类型:

  • 程序缺陷:真正bug,用户或系统管理员对此束手无策
  • 环境问题:数据库、service链接、磁盘空间满、权限等问题,可有系统管理员解决
  • 用户错误:告知用户操作问题,重新执行

实际操作:

  • “无法找到文件”的错误信息无助于解决问题,“无法打开/project/main.yaml”更有效
  • 没必要等待抛出异常才解决问题,在代码关键点执行断言以保证一切正常
  • 提供更多信息同时,不要泄漏安全信息、个人隐私及商业秘密等
  • 提供用户信息可包含一个主键,以便在日志文件或者审核记录定位相关内容

敏捷协作

我不仅发挥了自己全部的能力,还将我所仰仗的人的能力发挥到极致 --威尔逊

项目的成功与否,依赖于团队中成员如何一起有效工作,如何互动,如何管理它们的活动。全员行动必须与项目相关,反过来每个人行为又会影响项目环境。

实际操作:

  • 定期安排会面时间
  • 架构师必须写代码
  • 实行代码集体所有制,以免成员缺席对项目造成影响
  • 修改个人编码习惯,准备好再共享代码
  • 一起代码复查及时通报进展与问题

举行站立会议,着重三个问题,人均2Min,到司后半个到一个小时内:

  • 昨天有什么收获
  • 今天计划做哪些工作
  • 面临哪些障碍

立会的好处:

  • 让大家尽快投入一天的工作中
  • 让某人某点上的问题可以公开,积极寻求帮助
  • 帮助管理层了解哪些领域需要更多帮助,重新分配人手
  • 让团队成员知道项目其他部分的进展
  • 帮助团队识别是否再某些东西上重复劳动浪费精力或者某个问题是否有人已有现成的解决方案
  • 促进代码和思路共享,提升开发速度
  • 鼓励向前的动力:看到别人报告的进度都在前进,会彼此形成鼓励

实际操作:

  • 10-15分钟比较理想,可预约1个小时,然后立会后可紧接一个小会
  • 迅速开始保证会议短小,不必浪费时间等着会议开始
  • 如果觉得立会在浪费时间,那可能是大家还没形成真正的团队意识,可以持续改进

优秀的设计从积极优秀的程序员那里开始演化:不愿意编程的架构师也不知道系统的真实情况,则无从展开设计。

架构、设计、编码和测试其实是同一类型活动,它们之间应该是不可分割的。

一方面如果一个开发者专门应对某领域的任务,他可以精通该领域并让后续开发任务高效;但另一方面多双眼睛盯着某段代码一定可以带来好处:可以提升代码的整体质量,使之易于维护理解并且降低出错率。

实际操作中:

  • 不要无意间丧失团队的专家技能,若某开发在某领域极其精通,不妨让他作为这方面的驻留专家
  • 大型项目中,如果每个人都可以随便改动任何代码,一定会弄得一团糟
  • 开发不必了解项目每一部分的每个细节,但也不能因为要处理某个模块的代码而惊恐
  • 有些场合不能采用代码集体所有制。也许需要特定的知识或者特定问题域的了解,比如高难度的实时控制系统
  • 如果不向整个团队分享知识,反而增加了丧失知识的风险

成为指导者:通过分享自己的知识,让身边的人变得更好。可以开设个人博客,贴一些代码和技术在上面。即使是一小段代码和解释,对别人也可能是有帮助的。

成为指导者意味着要分享,意味着对别人的所学和工作感兴趣,同时愿意为团队增加价值。一切都为了提高队友和你的能力与水平,而不是为了毁掉团队。付出的同时便有收获,还可以激励别人获得更好的成果,而且提升整个团队的实力。

实际生活中:

  • 如果就同一个主题对不同人反复阐述,可以考虑写篇文章甚至书本
  • 成为指导者是对团队进行投资的极佳方式
  • 结对编程是一种进行高效指导很自然的环境
  • 为团队成员寻求帮助前陷入某个问题,设置一小时的最大时限

用问题回答问题,只提示一下的好处:

  • 帮助他们学会如何解决问题
  • 除了答案可以学到更多
  • 不会就类似问题反复问
  • 帮助他们在你不能回答时自己想办法
  • 他们可能想出你没考虑过的方法主意,从而你也学到新东西

做好准备再共享代码:绝不提交尚未完成的代码。故意签入check in编译未通过或是没有通过单元测试的代码,对项目来说,这应被视作玩忽职守的犯罪行为。要明了整个团队就在源代码控制系统的另一端盯着你,一旦提交代码,别人就都可以访问了。

代码复查什么:

  • 代码能否被读懂和理解
  • 是否有任何明显的错误
  • 代码是否对应用的其他部分产生不良影响
  • 是否存在重复的代码
  • 是否存在可以改进或重构的部分

实际操作:

  • 代码复查必须进行阅读思考
  • 复查需要积极评估代码的设计和清晰程度
  • 除非你能让某段代码明确变得更好,否则don’t judge code
  • 及时跟进讨论给出的建议
  • 让每个人知道复查完所采取的行动

及时通报进展与问题:发布进展状况、新的想法和目前正在关注的主题,不要等者别人来问项目状态如何。

实际操作:

  • 每日立会可以让每个人明确最新的进展和形势
  • 展示进展状况要照顾受众的关注细节程度,如CEO等不会关注代码方面
  • 别花费太多时间在通报上,应该保证开发任务的顺利完成
  • 经常抬头看看四周,而非埋头于自己的工作

开始引入敏捷

入门级习惯:

  • 版本控制
  • 单元测试
  • 自动构建
    从日常,工作,生活中引入敏捷的思想和习惯,逐步产生更多更大的价值。