如何成为优秀开发人员

内容纲要

这篇博文是看的编程随想的系列文章后整理而来的,此博客的文章质量还是非常高的,不过看的话需要自备梯子去翻墙。

0.怎样算是优秀的

对于大部分的软件开发团队都有这样的一个现象,那就是团队中的少数(一般来说,小于总人数的20%)开发人员具有更快的开发效率、更好的程序设计、更好的代码质量、更善于 debug、更能够解决技术难题......(总之就是让 team leader 事事省心)。而且这一小撮开发人员的贡献总和可能与另外那一大撮人(大于总人数的80%)的贡献总和不相上下(甚至可能超过)。那么,这一小撮开发人员,就是我所谓的优秀开发人员。

1.关于兴趣

因为物理学超级大牛爱因斯坦曾说过:兴趣是最好的老师。俺对此深以为然。所以咱们先从兴趣这个话题聊起。兴趣这玩意是心理学层面的东西,据说人在本能上有一种“构建”的快感(例如小朋友喜欢搭积木就是)。有些人天生喜欢写程序,就是因为能够从中体会到构建的快感。有兴趣的开发人员和没兴趣的开发人员,差别怎么就这么大捏?这主要是因为有兴趣的人,比较有动力去学习新东西、碰到新鲜玩意喜欢去刨根问底、碰到开发过程中的困难(比如一些难调试的bug)也显得比较有耐心、......久而久之,两种人的差别就渐渐地体现出来鸟。

2.关于自学能力

根据自学的主动性分为以下几种:

  • 抗拒自学者
    这类人不愿意自学(部分人是由于懒惰、另一些是由于抵触新事物)。当工作中要用到某项新技术而需要自学时,他/她就找若干理由推诿
  • 被动自学者
    这类人平时没事不会想到去自学新东西。只有当上司逼着他去学某某技术,他才勉为其难地去学。
  • 需求驱动型自学者
    这类人自学的动机和方向是基于需求驱动。比如因为工作中要用到 XX框架、XX库、XX软件,然后就利用业余时间找资料去看
  • 计划型自学者
    这类人自学的动机和方向是基于自己的规划。定期看看自己的知识结构有什么缺陷、将来自己想朝什么方向发展、最近哪个新东西将来会用得上 ......然后给自己定一个学习计划。

自学的常用招数: 网站,视频,书(可习惯于电子书和英文书),综合的小项目

3.设定个人发展目标和计划

大部分人从来没有【明确】地设定自己的发展目标,每天都是得过且过。等到几年过去了,才发现自己这些年啥也没学会,还是老样子,然后就感叹时光飞逝、岁月如梭。

  • 个人发展目标
    先说说什么是【个人发展目标】。顾名思义,就是和你个人的职业发展有关的目标,包括知识、技能、工作岗位等都可以被设定为个人发展目标。
  • 个人发展目标的三种类型
    我一般会把个人发展目标分为“长、中、短”三种类型,以此来对应不同的时间阶段。不管是哪种类型的目标,都要做到如下:

    1. 要把目标设置得【难易适中】。太容易的目标对自己的成长帮助不够大;而太难的目标则容易中途放弃或者超出时间(导致打乱计划)。
    2. 设定的目标要尽量容易评估(否则到时候连自己也搞不清楚到底目标算不算已达到)。
  • 短期目标
    先说说短期目标。短期目标的时间跨度大约在几个星期到一个季度之间。短期目标要定得比较具体,便于自己评估目标是否达成。
    下面举几个短期目标的例子:“在本月读完《Thinking in C++》”、“在本月熟悉 Spring 框架”、“在这2个月用 C++ 写一个五子棋游戏”......
  • 中期目标
    然后说说中期目标。中期目标的时间跨度大约在几个季度到1-2年。中期目标比短期目标更抽象,且必须是短期目标的有机结合。
    比如有个短期目标是“本周看完《Dive into Python》”,那么对应的中期目标可以是“1年内成为熟练的 Python 程序员”。
  • 长期目标
    最后谈谈长期目标。长期目标同样也必须和中级目标沾边,它的层次当然更高,时间跨度大约在5年以上。
    而且长期目标一般不会关系到具体的XX语言、XX平台等,倒是经常和职业岗位有一定的关联。比如“5-7年内成为技术总监”、“5年内成为公司产品的架构师”等。
  • 个人发展计划
    当你把3种目标都设定好之后,就形成了【个人发展计划】。既然是计划,你就得在每一个阶段结束时自己总结一下,评估一下该目标的完成情况好不好,有什么收获、有什么经验教训。必要的话还需对尚未开始的后续目标进行一下调整。定期回顾还有一个好处,就是能获得一种满足感,从而有利于你坚持完整个计划。

4.做正确的事

优秀的开发人员往往具有较高的效率。俺这里提到的【效率】包括两方面:“做正确的事”和“正确地做事”。并且“做正确的事”比“正确地做事”更加重要。
一些不好的习惯:

  • 先做自己喜欢的事情,再做自己不喜欢的事情
  • 先做紧急的事情,再做不紧急的事情
  • 先做容易做的事情,再做不容易做的事情
  • 先做自己了解、熟悉的事情,再做自己不了解、不熟悉的事情
  • 先做有趣的事情,再做枯燥的事情
  • 先做易于告一段落的事情,再做不易于告一段落的事情
  • 先做自己熟悉的人托付的事情,再做自己不熟悉的人托付的事情

如何克服?

  • 评估权重
    “做正确的事”的关键在于评估你准备做的每件事情的【权重】。权重来源于这件事情对于达成目标是否有帮助?帮助有多大?
    如果某个事情对目标的帮助越大,则此事的权重越大;反之亦然。
  • 严格按照权重执行
    然后,每天醒来,你都要把当天准备做的事情根据权重排好优先级,然后【严格】按照优先级顺序执行。
    如果工作中偶尔碰上看起来紧急的突发事情,也【不要】轻易改变原先安排的计划表,而要先冷静评估一下这个紧急的事情的权重。只有属于紧急且权重高(重要)的突发事件,你才可以调整计划,把这件突发事情加入其中。
    上面说的这些,看起来简单,但是真的操作起来挺难的。能否修炼成功得看各自的造化了。一般来说,【理性】的人比【感性】的人胜算更大。如果你是一个感性的人,那更得多努力了。

5.正确地做事

“正确地做事”主要讨论的是有关工作效率和工作质量的关系(也就是如何“多、快、好、省”地完成工作)。

1.善用工具

  • 编辑器
    字体、颜色、快捷键、还有一些比较琐碎的功能,比如:代码自动缩进、自动补全、动态提示等等。
  • 版本管理软件(简称“RCS”(Revision Control System))

    • 不正确的提交频度
      正确的提交频度应该分两种情况:在编写功能代码时,每完成一个功能点,并且自己经过了自测之后,提交一次;在调试的时候,每修复一个 bug,提交一次。这样能够保证提交到 RCS 的代码都是【能编译通过】的,并且业务逻辑上也是相对完整的(对于每日构建后的测试很重要)。
    • 提交时不写注释
      很多人提交代码时不写注释,将来再想到版本历史里面找代码就犹如大海捞针般困难。
      比如在俺经手的代码中,有些源代码文件历时3年,提交次数上百次,如果提交时不写注释,日后根本没法找。
    • 不做代码基线(Baseline)、不做代码分支(Branch)
      在正规的开发团队,每当有一个版本发布(Release)并交付给用户使用时,都需要在 RCS 中制作一个基线,以便于进行相应的 bug 跟踪和补丁制作。因此,诸如【做基线】之类的事情,属于整个团队的集体行为,需要由 Team Leader 牵头来搞。
      假如一个开发团队从来不做代码基线或者代码分支,仅仅是把 RCS 当成一个源文件的备份工具来用,那至少说明这个团队的 Team Leader 在软件工程管理方面非常失败。
  • 用于调试/测试的运行辅助工具
    运行辅助工具对于开发效率的影响也很大。一般来说,你自己的开发机器上要有尽可能仿真(和用户的环境相似)的运行环境,并且运行辅助工具能够有效地发现运行时的一些不正常的信息。这样有利于让 bug 在交付给用户之前【尽早暴露】出来。
    如果你是 Web 开发人员,那么你自己肯定要安装好常用的浏览器(至少包括 IE、Firefox、Chrome)。对于 IE,还得设置成“显示脚本错误通知”。
    如果你主要开发 Windows 应用程序,你手头肯定要备好诸如:Depends(Visual C++自带)、Process Explorer等工具,便于查看进程、线程、动态库、堆内存等运行时信息。
    如果你是搞手机应用的,那么你至少得有目标系统的模拟器软件(如果能配一个真机当然更好)。
    如果你主要进行跨平台方面的开发,那么诸如“VMware / VirtualBox”之类的虚拟化软件是必不可少滴

2.善用自动化

具体该如何做呢?要实现自动化,首先就要观察你平时做的事情中,有哪些属于【重复】劳动;然后评估一下这些重复劳动是否可以用某些工具来替代;如果有可能替代,你就可以动手把这个工具实现出来,然后就可以让工具来帮你做事情了。
实现“自动化”的例子:

  • 调试程序
    估计看俺 Blog 的同学,大部分都有过调试程序的经验。当程序行为不正常时,经常需要设置断点,然后单步跟踪代码,以便找出程序出错的源头。其实这个过程也有大量的重复劳动。
      俺一般喜欢通过程序断言(以下简称 assert)来简化上述过程。看到这里,有些同学心里犯嘀咕了:程序断言和自动化有毛关系啊?其实每一个 assert 就好比一个【自动的】代码检查点,【每次】程序运行到 assert 处的时候,如果你设置的逻辑条件不成立,它会立即终止程序并打印出相关信息(比如函数调用栈、文件行号等)。
      如果你在写代码的时候,经常在一些【关键点】设置一些【条件恰当】的 assert,可以大量节约调试时间。俺自己写的程序,在自测的时候,有70%-80%的逻辑错误会被 assert 暴露出来,所以改起来非常快;测试人员提交给俺的 Bug,大概也有一半以上可以通过 assert 快速定位出错误的源头
  • 自动化测试
    说完了程序员的例子,再来说一下测试人员(其实我在“每日构建:流程”已经稍微提到了测试的自动化)。俺发现很多公司的测试人员,重复劳动特别严重。他们不断地重复做一些软件功能的验证操作;发现bug后通知程序员改;程序员改完,再次进行验证操作......如此循环往复。N年之后,这些测试人员的个人能力没啥提高,年龄倒大了不少。
    在此,俺强烈建议测试人员:尽量多使用一些自动化测试工具(比如 QTP)和一些测试脚本来完成上述的软件功能验证操作。不光能节约很多时间,提高了效率;而且在自己编写测试脚本的过程中,或许还能学些新东西,提高一下个人能力。比如俺见过一个测试人员,由于经常用Python写一些脚本进行网络和数据库方面的测试,久而久之,写 Python 脚本的水平很熟练,然后就被转去做 Python 开发。
  • 人肉自动化
    上面说的自动化都是技术层面的(都是靠软件实现)。为了给大伙儿扩展一下思路(免得思维定势),最后来说一下非技术的例子。
    比如部门中经常有人出差,每次出差都要都要订机票。订机票就属于重复劳动,而且挺繁琐。得去网上查航班、还得看哪个航班折扣优惠、选好航班还得付钱,然后去机场还得打印行程单,出差回来还得填写报销单(报销单还得找N个人签字),然后拿着报销单与行程单找秘书报销。这些琐事累加起来,少说也得一个小时才能搞好。
    为了提高效率,把上述这些琐事统统都交由秘书搞定。出差的家伙需要做的就是发一个邮件告诉秘书,要订某天某时的飞机到某地,就一切 OK 了。经过这样改革,部门里的人(除了秘书)都皆大欢喜。