解决方法
找别人的代码来读一读。从你日常使用的应用和工具开始。作为学徒,有一种想法会支持你阅读代码的信念:那些构建了你所用工具的人多少会有点与众不同,或有些特别,或比你更厉害。阅读他们的代码,你可以学会像他们那样写程序,而更重要的是,你将开始理解创造了你所用工具基础架构的那些思考过程。
在研究一个开源项目时,要养成下载最新版代码的习惯(最好从它们的源码控制系统下载),这样你可以查阅它的历史,跟踪未来的发展。看一下代码库的结构,想一想为什么代码是那样组织的。看一看开发者组织代码模块的方式是否有一定的道理,拿它跟自己可能使用的方式比较一下。
试着重构代码,从而理解为什么它的编码者做了那样的决定,同时想想如果你是那个编码的人,写出的代码将是什么样子。这不仅能让你更好地理解这些项目;还确保你能构建这些项目。如果你发现了做一件事的更好方法,你就完全可以为这个项目贡献代码了。
在研究代码的过程中,你会不可避免地看到一些自己完全不同意的决策。问问自己,是否项目的开发者可能知道一些你不知道的东西,或者相反。考虑一下有没有可能这是一个历史遗留设计,需要重构一下;并考虑:为相关特性做个玩具实现是否有助于澄清问题。
除了阅读他人的代码(并在别人需要时提供反馈),也试着找找周围有没有人有兴趣阅读你写的源码。若能拥抱他们的反馈,并从中滤除纯个人的偏好,你将成为更好的程序员。还要记住:要成为熟练工,你必须帮助其他人成长,因此你也应非常开放地阅读他人的源码。
在我们访谈过的程序员中,有种常见的做法是加入一个实施“代码复查”(code review)或者“结对编程”(pair programming)实践的团队或项目中。这类实践创造了一种环境,使得程序员可以很自然地花时间阅读其他人的代码,让其他人阅读自己的代码,并相互学习。这样的团队更容易造就水平极高的程序员。其他一些环境,比如多数高校的计算机科学系,容易忽视实际工作中的程序员在阅读代码上花的时间比撰写代码更多这一事实。他们之所以这样,是因为让每个学生重新发明轮子能造出一些更容易评分的作业。然而,训练自己使自己更善于那些占用更多日常工作时间的任务(阅读代码)是对个人效益的优化,从长期来看能获得更高的回报。即使管理这种工作环境的非程序员们不欣赏这类实践,也改变不了这一事实。
通过阅读其他人编写的各种好的、坏的以及无关紧要的代码,你会慢慢学会特定语言社区中的各种惯用法和精妙细节。久而久之,这会开发你从别人编写的代码中推测其意图的能力,还会让你学会如何应付代码和意图不一致的情况。这些技能会使你成为团队中更有价值的部分,因为你将能够直接维护别人的代码,而不必因为看不出代码的用途而不得不每次重写它。
最终你将获得一个工具盒,里面都是从其他人的代码中收集来的各种奇技。这会磨炼你更迅速、更快捷地解决小问题的能力。你将能处理别人认为不可能解决的问题,因为他们接触不到你的工具盒。
看一看Linus Torvalds编写的Git分布式源码控制系统的代码,或者任何Daniel J.Bernstein(众所周知的djb)编写的代码。像Linus和djb这样的程序员偶尔会用到我们大多数人甚至从未听说过的数据结构和算法。他们并不是魔术师——跟大多数人相比,他们不过是花时间构造了更大更好的工具盒。开源的优势就在于你可以随意观看他们的工具盒,而且可以把他们的工具变成你自己的。
软件开发领域的问题之一是缺少教师。不过多亏了诸如sourceforge.net和GitHub这些站点上开源项目的繁荣,你可以从全世界程序员社区中那些相对有代表性的代码范例中学习。跟传统的教学不同,它们并不是为演示一个技术点而设计的玩具项目,其中不会有各类捷径,以及当问题变得困难时的所谓“留给读者的练习”。它们都是解决实际问题,而且不断演变的真正项目。你可以在项目的开发者不断学习并适应新需要的过程中跟踪项目的进展。通过研究实际代码的演进方式,你可以不必亲手构建那成百上千的软件项目也能更好地理解某些设计决策的作用。这提供了从别人的错误中学习知识的机会,以及获得比简单的代码阅读更关键的技能——无师自通能力——的机会。
在《Programmers at Work》一书中,Bill Gates说:“对编程能力最精细的测试就是给程序员大约30页的代码,看他能多快地通读并理解它。”他意识到了一种很重要的东西。那些能直接从源码中快速汲取知识的人很快就能成为更好的程序员,因为他们的老师就是世界上的每一位程序员写下的一行行代码。
要学习模式、惯用法和最佳实践,最好的方法就是阅读开源代码。看看其他人是如何写代码的。这是一种保持自己不落伍的优秀方法,而且是免费的。
——Chris Wanstrath在2008 Ruby大会上的主讲内容[1]
[1]2008 Ruby大会主讲。视频:http://rubyhoedown2008.confreaks.com/08-chris-wanstrath-keynote.html。手稿:http://gist.github.com/6443。