标签归档:开发

要写易删除,而不易扩展的代码

英文来源:Write code that is easy to delete, not easy to extend
作者:tef,拥有着犀利的演讲风格,简介请详见他在http://programmingisterrible.com/about上的自我介绍。

译者简介:张咏枫,硅谷创业公司 BloomSky Inc. 软件工程师,加州大学圣克鲁兹分校计算机科学硕士,方向为机器学习。硕士期间曾在 Palo Alto Networks 实习,从事平台开发。在目前的公司做全栈开发,包括后端 API 开发、分布式计算平台的架构、与其它应用平台的整合、数据库架构,以及前端网页应用的开发。涉及到的技术包括:Django、Celery、Nginx、Node.js、React.js、Rethinkdb 等。个人博客:http://blog.yongfengzhang.com/cn/

感谢译者张咏枫对本篇文章的翻译以及授权。

译者序


本文托管在 GitHub 上: https://github.com/freedombird9/code-easy-to-delete,欢迎 Star 或纠错。


好的文章总是见解独到,功底深厚而逻辑清晰。这是一篇关于如何设计、架构代码的文章。文章的观点新颖而有力。作者的观点是,我们所做的一切 —— 重构、模块化、分层,等等,都是为了让我们的代码易于被删改,都是为了让遗留代码不成为我们的负担,而不是为了代码复用。

作者认为,经过七个不同的开发阶段,最终便可以提炼出这样的代码。每个阶段都有详细的介绍和例子。

初读文章,可能会有抽象、晦涩之感。但多读几遍之后,其主旨就会变的清晰。

一个晚上的彻夜不眠,有了这篇中文翻译,与大家分享,希望对读者有所助益。

本文托管在 GitHub 上,水平有限,还望大家多多指点。

感谢

谢谢秋兄将这篇文章分享给我。

中文翻译如下

编程是一件很糟糕的事 —— 在荒废了自己的一生之后所学到的东西

要写容易删除,而不容易扩展的代码。


没有一行代码产生于理性、有很强的可维护性,且不会被偶然地删除掉 Jean-Paul Sartre’s Programming in ANSI C.


每写一行代码,都会有一个代价:维护。为了不在代码上花费太多,我们有了可复用的软件。但是代码复用有一个问题:当你以后想要修改的时候它就会成为一个障碍。

一个 API 的用户越多,为了引入修改而需要重写的代码就越多。相似的,你依赖第三方 API 越多,当其有任何改变时你的麻烦就越多。管理代码之间的兼容性,或者模块之间的依赖关系在大型系统中是一个很重要的问题。而且随着项目越来越久,这个问题就会变得越复杂。


今天我的观点是,如果我们要去计算一个程序有多少行代码,我们不应该将其看成是「产生了多少行」,而应该看成「耗费了多少行。」 EWD 1036


如果我们将「有多少行代码」看成是「耗费了多少行代码」的话,那么当我们删除这些代码的时候,我们就降低了维护成本。我们应该努力开发可丢弃的(disposable)软件,而不是可复用的软件。

我不需要告诉你删除代码比写代码更有趣吧。

为了写易于删除的代码:重复你自己以避免产生模块依赖性,但是不要重复管理这些代码。同时将你的代码分层:在易于实现但不易于使用的模块的基础上构建易于使用的 API。拆分你的代码:将很难于实现且很可能会改变的模块互相隔离,并同时和其他的模块隔离。不要将每一个选项都写死,容许在运行时做改变。不要试图同时去做上述所有的事情,或许你在一开始就不要写这么多代码。

阶段0:不写代码

代码有多少行本身并不能告诉我们什么,但是代码行数的数量级可以:50,500,5000,10000,25000等等。一个一百万行的庞然大物显然会比一个一万行的程序更折磨人。替代它也会显著花费更多的时间、金钱和努力。

虽然代码越多,摒弃起来就越困难,但是少写一行代码本身并不能省掉任何事情。

即使如此,最容易删除的代码是你一开始就避免写出来的代码。

阶段1:复制粘贴代码

写可复用的代码是一件在事后有了代码库中的使用示例后更容易做的事情,而不是在事前就能预料好的。往好的看,仅仅是利用文件系统你或许就已经在复用很多代码了,所以何必这么担心呢?一点点冗余是健康的。

复制粘贴代码若干次,而不是仅仅为了给这个用法取一个名字就去写一个库函数,是完全没有问题的。一旦把一个东西变成共享的 API,改变起来就会更困难。

调用你的函数的那段代码会依赖于其实现背后有意或无意的行为。使用你的函数的程序员不会根据你的文档去调用,而会根据他们观察到的函数行为去调用。

删除函数内的代码比删除一个函数更简单。

阶段2:不要复制粘贴代码

当你已经复制粘贴足够多次数时,或许就是该提炼出一个函数的时候了。这是「把我从标准库中拯救出来」的东西:「打开一个配置文件并返回一个哈希表」,「删除这个文件夹」。这些例子包括了无状态函数,或者有一些全局信息,如环境变量的函数。这些是最终会出现在一个叫做 “util” 文件中的东西。

旁白:建一个 util 文件夹,把不同的功用放在不同的文件里。单个 util 文件总是会不断变大直到大得来无法拆分。使用单个 util 文件是不简洁的做法。

对于应用或者项目而言通用性越强的代码,就越容易复用,被改变或者删除的可能性就越低。它们包括日志记录,第三方 API,文件柄(handle)或者进程相关的库。其他你不会删除掉的代码有列表、哈希表,以及其他集合。这不是因为它们的接口通常都很简单,而是因为它们的作用域不会随着时间的增长而变大。

我们要努力将代码中难以删除的部分与易于删除的部分分隔得尽可能开,而不是使所有代码都变得易于删除。

阶段3:写更多的模版

虽然我们通过库来避免复制粘贴,但是我们常常会需要复制粘贴来使用这些库,最后导致写了更多的代码。不过我们给这些代码另外一个名字:模版(boilerplate)。模版和复制粘贴在很大程度上很像,除了每次使用模版的时候都会在不同的地方做一些改变,而不是一次次重复完全一样的东西。

就像复制粘贴一样,我们会重复部分代码以避免引入依赖性,以获得灵活度,代价则是冗余。

需要模版的库通常有网络协议、有线格式(wire formats)、解析套件,或者很难将策略(一个程序应该做的)和协议(一个程序能做的)交织起来而又不限制可选项的东西。这种代码是很难被删除的:与其他的电脑通信或者处理不同的文件通常是一种必需,而我们永远不想让业务逻辑充斥其中。

写模版不是在练习代码复用:我们尽可能将变化频繁的部分和相对更稳定的部分分隔开。应最小化库的依赖性或责任,即使我们必须通过模版来使用它们。

你会写更多的代码,但是这些多出来的代码都是在易于删除的部分。

阶段4:不要写模版

当库需要迎合所有要求的时候,模版的作用最为明显。但是有时候重复的东西太多了。是时候将一个弹性很大的库用一个考虑到了策略、流程和状态的库打包起来了。开发易用的 API 就是将模版转换成一个库。

这比你想象中的要普遍:最为流行和倍受喜爱的 Python http 客户端模块 requests 就是一个很成功的例子,它将一个使用起来更为繁琐的库 urllib3 打包,为用户提供了一套更加简单的接口。当使用 http 的时候, requests 照顾到普遍的工作流,而对用户隐藏了许多实际的细节。相比而言, urllib3 处理流水线和连接管理,不对用户隐藏任何细节。

当把一个库包进另一个库的时候,与其说是为了隐藏细节,倒不如说是为了将不同的关切分开: requests 是关于http的冒险,urllib3 则是给你工具让你自己选择你自己的冒险。

我并不是主张让你去建一个 /protocol/ 和 /policy/ 文件夹,但是你确实应该尝试使 util 不受业务逻辑的干扰,并且在易于实现的库的基础上开发易于使用的库。你并不需要将一个库全部写完之后再在上面写另一个库。

将一个第三方库打包起来通常也是很好的实践,即使它们不是协议类的库。你可以写一个适合你的代码的库,而不是在整个项目中都锁定一个选择。开发一个好用的 API 和开发一个具有扩展性的 API 通常是互相冲突的。

像这样将不同的关切分开,能让我们在使一些用户很高兴的同时不会让其他用户想做的事情变得不可能。当你从一开始就有一个好的 API 的时候,分层是最简单的。但是在一个写得不好的 API 上开发出一个好的 API 则会很困难。好的 API 在设计之时就会站在使用者的位置上考虑问题,而分层则是我们意识到我们不能同时让所有人都高兴。

分层更多的是为了使那些很难删除的代码易于使用(在不让业务逻辑污染它们的情况下),而不仅仅是关于写以后可以删除的代码。

阶段5:写一大段代码

你已经复制粘贴了,你已经重构了,你已经分层了,你已经构建了,但是代码在最后还是需要做一些事情的。有时候最好的做法是放弃,然后写一大段垃圾代码将剩余部分弄在一起。

业务逻辑是那种有着无尽的边界情况和快速而肮脏的hack的代码。这是没问题的,我对此并不反对。其他的风格,如「游戏代码」,或者「创始人代码」,也是同一个东西:采用捷径来节省大量的时间。

原因?有时候删掉一个大的错误比删掉18个小的交错在一起的错误更为容易。大量的编程都是探索性的,犯几次错误然后去迭代比想着一开始就做对更快速。

这个对于更有趣味或者更有创造性的尝试来说更为正确。如果你正在写你的第一个游戏:不要写成一个游戏引擎。类似的,不要在写好一个应用之前就去写一个框架。第一次的时候尽管大胆的去写一堆乱七八糟的代码。你是不会知道怎样拆分成模块的,除非你是先知。

单一库有类似的取舍:你事先不会知道怎样拆分你的代码,而一个大的错误显然比20个紧密关联的错误更容易处理。

当你知道哪些代码将会被舍弃、删除,或者替换的时候,你就可以采用更多的捷径。特别是当你要写一个一次性的客户端网站,或关于一个活动的网页的时候。或者任何一个有模版、要删除复本、要填补框架所留下的缺口的地方。

我不是说你应该重复同一件事情十次来纠正错误。引用 Perlis 的话:「所有东西都应该从上到下建立,除了第一次的时候。」你应该在每一次尝试时都去犯新的错误,接纳新的风险,然后通过迭代慢慢的来完善。

成为一个专业的软件开发者的过程就是不断积累后悔和错误清单的过程。你从成功身上学不到任何东西。并不是你能知道好的代码是什么样的,而是你对坏的代码记忆犹新。

项目不管怎样最终都会失败或者成为遗留代码。失败比成功更频繁。写十个大的泥球,看它们能将你带向哪比尝试去给一个粪球抛光更快速。

一次行删掉所有的代码比一段一段的去删更容易。

阶段6:把你的代码拆分成小块

大段的代码是最容易写的,但同时维护起来也最为昂贵。一个看起来很简单的修改就会以特定的方式影响代码库的几乎每个部分。本来作为一个整体删除起来很简单的东西,现在变得不可能去一段一段地删除了。

就像我们根据相互独立的任务来将我们的代码分层一样,从特定平台的代码到特定领域的代码,我们同样需要找到一种方法来梳理出顶层逻辑。


从一系列很困难的或者很容易变的设计决定开始。然后去设计一个个模块,让每一个模块都能隐藏一个设计上的决定,使其对其他决定不可见。 D. Parnas


我们根据代码之间没有共享的部分来拆分代码,而不是将其拆分成有共同功能的模块。我们把写起来、维护起来,或者删除起来最让人沮丧的部分互相隔离开。

我们构建模块不是为了复用,而是为了易于修改。

不幸的是,有些问题相比其他的问题而言分割起来更加困难和复杂。虽然单一责任原则说「每一个模块都应该只去解决一个难题」,但更重要的是「每一个难题都只应该由一个模块去解决」。

当一个模块做两件事情的时候,通常都是因为改变一部分需要另外一部分的改变。一个写得很糟糕但是有着简单接口的组件,通常比需要互相协调的两个组件更容易使用。


我如今再也不会尝试用「松耦合」这种速记一样的描述来定义那种应该被认可与接受的材料了,或许我永远不可能以清晰易懂的方式来定义它。但是当我看到它的时候我能够认出来,而当前的代码不属于那种。 SCOTUS Justice Stewart


你如果可以在一个系统中删除某一模块而不用因此去重写其他模块的话,这个系统就通常被称为是松耦合的。但是解释松耦合是什么样的比在一开始就建立一个这样的系统要容易多了。

甚至于写死一个变量 一次,或者使用命令行标记一个变量都可以叫松耦合。松耦合能让你在改变想法的同时不需要改写太多的代码。

比如,微软 Windows 的内部 API 和外部 API 就是因为这个目的而存在的。外部 API 与桌面程序的生命周期捆绑在一起,内部 API 则和内核捆绑在一起。隐藏这些 API 在给了微软灵活性的同时又不会挂掉过多的软件。

HTTP 中也有松耦合的例子:在你的 HTTP 服务器前设置一个缓存。将图片移到 CDN 上,仅改变一下到它们的链接。这两者都不会挂掉你的浏览器。

HTTP 的错误码是另外一个关于松耦合的例子:服务器之间常见的问题都有自己独特的错误码。当你收到400的时候,再尝试一次还是会得到同样的结果。如果是500则可能会变。结果是,HTTP客户端可以替代程序员处理许多的错误。

当把一个软件分解成更小的部分时,必须要考虑到如何去处理错误。这件事说比做容易。


我勉强决定去使用LATEX。在有错误存在的情况下去实现可靠的分布式系统。 Armstrong, 2003


Erlang/OTP 在处理错误方面有独到之处:监督树(supervision trees)。大致来说,每一个 Erlang 进程都由一个监督进程发起并监视。当一个进程遇到了问题的时候,它就会退出。当进程退出的时候,其监督进程会将其重启。

(这些监督进程由一个引导进程(bootstrap process)发起,当监督进程遇到错误的时候,引导进程会将其重启)

其思想是,快速的失败然后重启比去处理错误要快。像这样的错误处理看起来跟直觉相反 —— 当错误发生的时候通过放弃处理来获得可靠性。但是重启是解决暂时性错误的灵丹妙药。

错误处理和恢复最好是在代码的外层进行。这被称为端对端(end-to-end)原则。端对端原则说在一个连接的远端处理错误比在中间处理要更容易。即使在中间层进行处理,最终顶层的检查也无法被省去。如果不管怎样都需要在顶层来处理错误,那么为什么还要在里层去处理它们呢?

错误处理是一个系统可以紧密结合在一起的方式之一。除此之外还有许多其他紧耦合(tight coupling)的例子,但是要找一个糟糕的设计出来有一点不公平。除了 IMAP。

IMAP 中的每一个操作都像雪花一样,都有自己独特的选择和处理。错误处理相当痛苦:错误可能因为其他操作产生的结果而半路杀出。

IMAP 使用独特的令牌,而不是 UUID,来识别每一条信息。这些令牌也可能因为一个操作而中途被改变。许多操作都不是原子操作。找到一种可靠的方式将一封email从一个文件夹移动到另一个文件夹花费了25年时间。它还采用了一种特别的 UTF-7 编码,和一种独特的 base64 编码。

以上这些都不是我编的。

相比而言,文件系统和数据库是远程储存中好得多的例子。在文件系统中,操作的种类是固定的,但是却有很多可操作的对象。

虽然 SQL 像是一个比文件系统要广得多的接口,它仍然遵循相同的模式。若干对 set 的操作,许许多多对行的操作。虽然不能总是用一个数据库去替换出另一个数据库,但是找到可以和 SQL 一起使用的东西比找到任何一种自制的查询语言都更容易。

其他松耦合的例子有具备中间件、过滤器(filter)和管道(pipeline)的系统。例如,Twitter Finagle 的服务都是使用共同的 API,这使得泛型的超时处理、重试机制,和身份验证都能被毫不费力的加进客户端和服务器端的代码中。

(我很确定如果我不在这提UNIX管道的话,肯定会有人向我抱怨)

首先我们将我们的代码分层,但现在其中的一些层要共享一个接口:一系列有着不同实现的相同行为和操作。好的松耦合通常就意味着一致的接口。

一个健康的代码库不一定要完美的呈现出模块化。模块化的部分使写代码变得很有趣,就像乐高玩具的趣味来自于它所有的零件都可以被拼在一起一样。一个健康的代码库会有一些赘言和冗余,但它们使得可移植的组件间的距离恰到好处,因此你不会把自己套在里面。

松耦合的代码不一定就是易于删除的代码,但是它们替代和修改起来都会容易得多。

阶段7:持续的写代码

如果在写新代码的时候不需要去考虑旧有的代码,那么测试新的想法就要容易很多。并不是说一定要写小的模块,避免庞大的程序,而是说你的系统在你正常开发的同时还需要能够支持一两个试验。

功能发布控制(feature flag)是能让你在以后改变主意的一种方法。虽然 feature flag 被视作一种测试不同功能的方法,但同时它能让你在不重新部署的情况下就应用修改。

Google Chrome 是一个很好的例子,能说明其带来的好处。他们发现维持固定发布周期最困难的就是要合并一个长期存在的功能分支的时候。

能够在不需要重新编译的情况下激活和关闭新的代码,大的修改就可以在不影响现存代码的情况下被分解为更小的合并。如果新功能在代码库中更早出现的话,当一个长期的功能开发影响到其他部分的时候就会表现得更加明显。

Feature flag 并不是命令行开关,它是一种分离功能发布与合并分支,分离功能发布与代码部署的方式。当软件更新需要花费数小时、数天、甚至数周的时候,能够在运行中改变功能就变得越来越重要了。随便问一个运维人员,你就会知道任何一个可能在半夜把你叫起来的系统都值得在运行时去控制。

你更多的是要有一个反馈回路,而不是不停的迭代。模块更多的是用来隔离不同组件以应对改变的,而不仅是用来做代码复用的。处理代码的更改不仅仅是开发新的功能,同时也是抛弃掉旧的功能。写具有扩展性的代码是寄希望于三个月后你能把所有事情都做对。写可以被删除的代码则是基于相反的假设。

我在上文中谈到的策略 —— 分层、隔离、共同的接口、构造 —— 并不是有关写出优秀的软件的,而是关于怎样开发一个可以随着时间而改变的软件。


因此,管理上的问题不是要不要建一个试验性的系统然后把它抛弃掉。你会这么做的。[……]所以做好抛弃它的打算吧;无论如何你都会的。 Fred Brooks


你不必要将它全部抛弃,但是你需要删除某些部分。好的代码并不是要第一次就做对一件事。好的代码是那些不会造成障碍的遗留代码(legacy code)。

好的代码总是易于删除的代码。

用来简化开发任务的20个JavaScript类库

摘要:所谓JS库就是预先写好的JS程序库,用于简化以JS为基础的开发程序,尤其是对AJAX和其他以Web为中心技术的JS代码集。文章搜集了20个JS库,帮你处理与开发相关的问题,让你的网站在竞争中领先一步。

所谓JS库就是预先写好的JS程序库,用于简化以JS为基础的开发程序,尤其是对AJAX和其他以Web为中心技术的JS代码集。JS的首要用途是将编写的功能内嵌在HTML页面,并与页面的对象模型(DOM)进行互动。

很多JS库很容易和其他Web开发技术进行整合,例如CSS、 PHP、Ruby、和Java。许多程序库可以检测运行环境之间的差异,删除一些应用程序,以满足整合需求。文章搜集了20个JS库,帮你处理与开发相关的问题,让你的网站在竞争中领先一步。

1. Tracking.js

Tracking.js是一个独立的JS库,可以跟踪照相机实时收到的数据。跟踪对象既可以是色彩也可以是人物,当检测到某个特定的颜色时或人物/脸庞/身体出现移动的时候,我们可以触发JS事件。

2. Aristochart

Aristochart是一个不依赖于其它库的JS库,它能够使用Canvas创建静态的2D线形图表。这个库专注于打造客户化设计,提供多种选项用于更改设计、标签等等。

3. Hitch

Hitch是一个轻量级的JS库,能够向CSS文件添加表现能力。同时具备CSS预处理程序能力,比如添加前缀或变量,还有一些其他的功能。这个程序库有多个随时可用的表达方式,如“any of,all of,has…”,并允许我们定义任何一种方式(称为hitches)。

4. Cesium

Cesium是基于WebGL的JS绘图库,支持3种不同的视图:3D globe、2D map、2.5D Columbus View,相互转换只要一行代码而已!绘画各种形状,突出显示特定区域以及使用鼠标或触摸板与地图进行互动是非常简单的。Cesium作为一个独立的JS文件可以在所有主流浏览器上运行,包括手机上。

5. Two.js

它是一个2D的绘图API,一个优秀的JS库,用于较新的Web浏览器,可基于不同上下文绘制,包括svg、canvas和webgl。 这个库目前只支持形状(非文本或图片),允许导入SVG数据。当需要一起转变的时候,Two.js可以聚合多个有用的元素。其中还有一个内置动画循环方法来绘制各种图形,还具有使之个性化的多个选项。

6. Sequel.js

Sequel.js是一个轻量级JS库,有助于通过一个面向对象的API来构建SQL查询字符串,既可以在浏览器上运行,也可以在所有标准的SQL查询上运行。

7. Draggabilly

这是一个可以让页面元素可拖动的独立JS库,Draggabilly能够帮你轻松实现网页上各种元素的拖放操作。可以在一个限制的容器范围内拖动页面元素,对于每一个事件(start,move,end)都有回调,可以返回当前元素的位置。它可用于大部分浏览器(IE8+)并内置支持触摸事件。

8. Zebra

此JS库带有一串富用户界面组件,可以创建类似于桌面效果布局。UI元素由HTML5 canvas构建,由CSS着色,预期在所有浏览器中渲染出相同的效果。拥有30多个UI元素,包括grid、tabs、menu、form elements、menu等等。

9. Formula.js

这个JS库为Web开发者带来了大多数公式,公式列举了多重分类——日期/时间,文本,逻辑,金融等等。此外,除了在客户端运行,还在服务端(即将发布)上运行。

10. Chart.js

这是一个给人印象深刻的JS独立图表库,大小不足5kb的程序包,建立在HTML5 canvas之上。目前支持6种图表类型:直线图、条形图、雷达图、饼状图、柱状图和地区区域图。颜色、字体、边框、大小都可以根据用户需求自定义。

11. Flippant.js

这是一个迷你JS和CSS库,允许自动翻转桌面上的东西。不依赖任何其它类库,便于自定义,翻转功能效果好。

12. React

React是一个用来构建用户界面的JS库,可以高效灵活地与你之前使用的类库和框架结合使用。

13. PathFinding.js

PathFinding.js是JS里一个综合路径寻找类库,其目的是提供一个可以方便结合到网络游戏里的路径寻找类库。它可以在服务端运行,也可以在浏览器上运行。提供在线演示算法是怎样执行的。当具体使用路径寻找器时,你可以通过其它的参数来指示该用哪一个策略。

14. Reactor.js

这是一个用于响应式编程的轻量级类库。它提供的反应变量,当它们所依赖的的事物发生改变的时候可以实现自动更新。这和电子数据表的运作方式有点相似,当一个单元格的数值有所变化的时候,与其有联系的其他单元格数值也会变化。

15. Bootbox.js

Bootbox.js是一个很小的JS库,允许使用Twitter的Bootstrap模式创建程序对话窗口,不需要担心创建、管理或删除任何任何需要的DOM元素或JS事件处理程序。

16. Parallel.js

Parallel.js在JS里是一个用于多核处理的微型库,它的创建充分发挥了成熟的Web-workers API,JS的确是很快,但由于它的单线程计算模式,它缺乏了与其对等语言的平行计算功能。

17. SVG.js

SVG.js可以通过SVG进行操作和手动绘画,此库轻便独立,功能丰富,有内置方法可以创建各种形状——三角形、圆形、多边形,或自定义图形。

18. Packery

这是一个使用“装箱算法”的JS布局库,这是“补漏”的体面说法。Packery的布局可以是井然有序的,也可以是错乱无序的。元素可以被固定在相应的位置,也可以随意拖放。

19. FPS Meter

FPS Meter是一个简单的JS库,用来制作迷人的、快速的、可主题化的FPS仪表。他可以测量出每秒的帧数,帧之间的毫秒数,以及使用.tickStart()方法时,渲染一帧所需要的毫秒数。

20. Howler.js

Howler.js一个是JS库,通过默认方式运行在网页音频API上,当浏览器不支持时退回到HTML5音频。为了保证跨浏览器的兼容性,它允许接收多种文件格式。该库能同时缓存和播放多个声音,还有循环播放功能,淡入淡出效果和标准的多媒体控制功能。

原文:CodeGeekz

 

http://www.csdn.net/article/2013-07-09/2816111-javascript-libraries

代码审查——提高代码质量的终极武器

摘要:SmartBear公司发起一项调查研究2013年代码审查的使用情况并从超过650名专业开发人士那收集了“实践经验”,结果非常有趣。90%的受访者表示代码审查提高软件质量;74%表示代码审查还有助于跨团队之间知识共享。

如果糟糕的软件是我们的克星,那么优秀的代码就是解药。

软件无法工作是件非常恼人的事!而这种情况往往是由于糟糕的代码所致。在一个项目中,如果开发者孤军奋战,这种情况出现的几率就会增大。

幸运的是,团队中的一些成员愿意贡献自己的空闲时间来改善软件质量。通常,这些人就是我们常说的QA测试者——他们坚持不懈地寻找bug。这里有一个最佳实践方式能够更有效地识别软件代码中的缺陷——同行代码审查(peer code review)。

研究表明,同行代码审查是寻找代码缺陷最高效的方法。有分析称超过12000软件代码使用同行代码审查可以完成60%的效率,而使用单元测试只有25%。每隔一小时使用同行代码审查,可以为开发团队的QA测试节省20个小时,这个听起来不错吧。

近日,SmartBear公司发起一项调查研究2013年代码审查的使用情况。超过650名专业开发人士回答了如何使用代码审查以及对性能影响的相关问题并从中收集了“实践经验”,结果非常有趣。

在此次调查中超过70%的受访者参与了不同程度的协同审查,结果发现,那些做代码审查的比不做代码审查的软件整体质量满意度高达2倍。

我们从中抽取了一个问题,一起来看下代码审查能带来哪些好处。

Q:你认为代码审查最大的好处是什么?

如图所示,显而易见,代码审查最大好处莫过于提高软件质量;74%的受访者表示,代码审查还有助于跨团队之间知识共享;有60%的受访者还发现,代码审查有助于团队之间相互指导及提升协作。

由此可以看出:

 

  1. 代码审查是提高开发团队技能以及保持团队迭代更新最有效的最佳实践方法。
  2. 代码审查工具辅助文档过程本身允许大家互相学习和更正评论。
  3. 假如做代码审查的开发者碰巧没坐在你边上或者开发团队遍布全球或者某个疯狂的同事从凌晨1点工作到5点,那么代码审查工具可追踪任何一条评论以方便你在空闲的时候查看。

 

代码审查不仅能帮助你确保评审、改进代码,还能为开发人员节省大量的时间,帮助你拯救因糟糕软件无法正常运行而带来的压力。

英文出自:Smartbear

http://www.csdn.net/article/2013-06-03/2815518-code-review