一次优秀的代码提交应该包含什么?

标签: 代码 包含 | 发表时间:2013-11-19 22:27 | 作者:
出处:http://kb.cnblogs.com/

  英文原文: What's in a Good Commit? 译者: @neevek

  首先我们来听一个令人恶心的例子。

  你看到 问题 F00-123 被解决了。这是关于一个你自己很熟悉的子系统的 Bug,所以直觉告诉你造成这个 Bug 最可能的原因。为了证实你的怀疑,你决定看看这个 bug 是怎么被解决的。你花了很长时间搜索了整个版本历史,直到把这个 bugfix 的范围缩小到了 4 个连续的提交,它们分别的提交信息是: dao 小调整(dao tweaks)moarFixes, 还有 删除一些调试信息(remove debug stuff)。每个提交的修改集看起来都很大,多达十几个文件的几百处修改。“我艹尼@#$%%^&”,你准备骂娘但还是停住了,没有骂出你脑中那句最难听的粗口。“这个 bugfix 不应该超过三行代码!”。

  上面的例子听起来是不是很熟悉咧?很多开发者仅仅只把版本控制系统当成是一堆文件的备份。这些历史备份除了可以让你取回某个时间点上的文件内容之外,没有任何其他用处。下面这些建议可以帮你把你的版本控制系统从一个备份系统,变成用于沟通和文档编写的一个宝贵的工具。

   1. 每次提交只做一个修改

  如果你在一次提交中修复了 F00-123F00-233、重构了一个类、界面上添加了一两个按钮、还有把整个项目文件中的 tab 改成空格,那么基本上没有人能 review  F00-123 的 bugfix,只有你自己才知道哪些修改属于那个 bugfix 的一部分,但是一周以后很可能你自己都忘了。

  要是一周以后你发现原来的那个 bugfix 导致了另外一个更严重的问题那你就完蛋了,你不能使用 hg backout或者 git revert来撤销你的修改,因为那样会把除了那个 bugfix 之外的所有修改都撤销掉,也意味着你一周的努力白费了。

  上面这种问题的解决办法就是“每次提交只做一个修改”,对于怎么样才算是“一个修改”没有任何硬性或者既定的规则,但如果你能够用一个句子并且不用用到“和”这个字来描述你所做的所有事情,那么你算是做到了。

  分布式版本控制系统其中一个很好的功能就是,如果你的工作目录中有很多相互之间没有关联的修改,你可以用它来帮你 收拾好你的烂摊子(clean up the mess you’ve made),但是最好别在一开始就搞出一个烂摊子。在你开始修改代码之前,先确定你想干什么和你想怎么做,然后再认真把关注点放在你想修改的那个点上。

  在没有想出怎么改进某块代码之前,貌似不太可能去修改那块代码。你发现了 bug、看到了一些糟糕的代码、还有一些你很好奇想进一步了解的东西。无论你多么想去做,千万别被转移了注意力。这些发现非常有价值,用一个笔记本或者一个 TODO 文件把他们 写下来(jot them down),在完成当前任务之前不要想去解决那些问题。

  这个不仅仅是关于更好地提交。当你沉浸在解决某个编程问题里面的时候,你的头脑充满着关于这个问题的一堆细节,如果这个时候你跳去想一些其他问题,那么你会忘了原来那个问题的细节,再回到原来那个问题需要花一些时间。你需要 减少任务切换(minimize task switches)来提高你的工作效率。

  当然有些时候你会发现在没有解决某些其他问题之前,你很难完成当前的任务。这个时候最简单的方式就是使用 hg shelve或者 git stash把你当前还没有完成的修改暂存起来,把两个问题的修改分开,提交那个被依赖的修改,再回到你原来的任务上面去。

   2. 每次提交要包含完整修改

  如果一个修改分布到了几个提交里面,那么这个修改也是很难 review 的。通常这是因为在同一时间解决太多问题导致的,如果你吃不了那么多,却啃了那么多,那么在你想保存其中的某些修改的时候,你会发现大部分的修改都是未完成的。同一时间关注太多问题会导致最后需要很长时间才能够提交完整的修改。(原文是:Focusing on one task at a time takes you a long way towards committing complete changes. 但我觉得作者的原意应该是:Focusing on too many tasks at a time takes you a long way towards committing complete changes.)

  有些修改需要花很长时间,所以如果中间在某个点上你搞错了,重头再来你肯定折腾不起,所以你需要在过程中保存一些中间版本。幸好分布式版本控制系统都允许你保存很多中间版本但是最后只提交一次修改到中心版本库(central repository),你可以提交任意多次的中间版本,在最后使用 hg histedit或者 git rebase把多次的中间版本合并成一个修改集。

  另外一种,也是我个人比较喜欢的方法,因为它把中间版本和永久性的修改版本分开了,这种方法使用 Git 的 index,或者 Mercurial Queues 中的一个 patch 来保存最近一次正确的(没有 bug 的)中间版本,每次你做了新的修改你都更新这个 index/patch,如果你犯了个错误,你就可以使用他们恢复你的工作目录了。I like to think of it as a one-slot quicksave for version control.(译注:这句只可意会,我不知道怎么翻。)

   3. 写好注释,说明你修改了什么

  像“修复(Fixes)”、“提交(Commit)”这样的提交信息没包含任何有用的信息。如果别人想看看版本历史,像这样的提交信息只会逼他们去看完所有的代码修改,看代码是很费时费力的。写这样一个简短但表达不清晰的提交信息,可能是省了你一分钟时间,但是却浪费了其他人几个小时。

  一个好的提交信息可以让看的人清楚代码的哪一部分被修改了,是怎么被修改的,他们也不需要去看你的代码:

SomeClass: use bleh instead of xyzzy in someMethod (fixes FOO-123)

   4. 注释说明为什么做这个修改

  假设每次修改代码都有一个很好的理由/原因,但如果这个理由/原因被没有记录下来,那么整个代码库(codebase)将面临以下风险:

  • 其他开发者不明白为什么原代码是那样写的。当他们修改代码的时候,他们可能会引入一些原作者已经发现或者避免的问题。
  • 其他开发者认为原代码那样写肯定是有(好的)原因的,所以最好别动它。他们把这些代码看成是一个黑盒,然后加各种复杂的 workaround,避免修改原代码。最后导致这个代码库变得臃肿,代码变得难以看懂。

  如果你有足够的理由有必要破坏一个项目的规范或者约定,那一定要把这个理由作为注释写在你的代码里面:

- xyzzy (bars); + // Our bars are already sorted, so bleh is much faster than xyzzy + bleh (bars);  

  如果你的代码遵守了规范,并且你的代码没有什么微妙(subtleties)的点需要注意,那就没有必要把你的文档注释写在代码里面。但仍然有必要让人知道为什么新代码优于旧代码(尤其是当新代码引入了一个新问题),所以还是要把原因写在提交信息里面的:

SomeClass: Don't flush caches in someMethod The caches are flushed automatically at the end of each request.

  如果一个修改解决了一个已知问题,确保在提交信息里面带上 ticket 号(bug 追踪系统中的 ticket),以便其他开发者在看版本历史的时候能够清楚地知道是在什么情况下做出的这个修改。

   5. 不要提交被注释掉的代码

  我没有办法理解提交被注释掉的代码背后的理论依据,我假设这是为了保存旧代码,以防新代码不能正常工作,但这种做法很莫名其妙,最开始我们使用版本控制系统不就是为了保存旧版本吗?!

  为什么要注释掉这些代码?这些代码能运行吗?会正常运行吗?曾正常运行过吗?注释代码是我们应该支持还是摒弃的呢?被注释掉的代码毫无用处,因为每当开发者读到这些被注释的代码,总会冒出一些没有答案的问题,它只会混淆开发者视听,让开发者分心而无法更好专注于有用的代码。

  对于提交被注释掉的代码这件事情,只有一个原则,那就是:

相关 [代码 包含] 推荐:

一次优秀的代码提交应该包含什么?

- - 博客园_知识库
  英文原文: What's in a Good Commit.   首先我们来听一个令人恶心的例子.   你看到 问题 F00-123 被解决了. 这是关于一个你自己很熟悉的子系统的 Bug,所以直觉告诉你造成这个 Bug 最可能的原因. 为了证实你的怀疑,你决定看看这个 bug 是怎么被解决的.

测试Jsp 静态包含和动态包含

- - CSDN博客Web前端推荐文章
静态包含是在请求包含页面时去编译包含页面,编译时遇到静态页面包含伪码将被包含页面的内容复制到被包含页面中进行编译. 动态包含是指在请求包含页面的时候遇到动态包含指令将请求转到被包含页面,这时去编译被包含页面. 但两者生成的class文件缺不同:. 通过以上说明可知,动态包含在请求到来时编译包含页面和被包含页面,如果都是jsp页面,那么将生成两个个页面对应的class文件和java文件.

Safari 5.0.1到来 包含扩展中心

- tom - cnBeta.COM
带有扩展的Safari浏览器终于来了,这意味着Firefox和Chrome终于迎来了新对手. 这就是苹果最新发布的带有5.0.1版本,新版不但带来了HTML5和CSS3以及JavaScript新标准支持,最重要的是Safari Extensions Gallery特性,首批为苹果制作扩展的厂商有MLB.com, The New York Times和Twitter、eBay等大户人家,扩展中心也可以通过访问extensions.apple.com抵达.

代码重构

- - ITeye博客
随着程序的演化,我们有必要重新思考早先的决策,并重写部分代码. 代码需要演化;它不是静态的事物. 重写、重做和重新架构代码合起来,称为重构.    当你遇到绊脚石  ---  代码不在合适,你注意到有两样东西其实应该合并或是其他任何对你来说是"错误"的东西  -------- . 如果代码具备以下特征,你都应该考虑重构代码:.

包含西方文化的英语短句

- 晓江 - 每日英语
  有些句子我们在电影里面经常听到,但对于它们的确切意思可能并不是很了解,下面我们一起来看几个这样的句子吧.   如果外国夫妇请你到家里吃饭,看着一桌丰盛的酒席,你问他们可以开始吃了吗,他们通常会说“Sure. 当两个小孩子在相互追逐玩乐,互相打斗的时候,一个通常会主动碰了一下另一个,然后说“哈哈,打到你了.

BUILD: Windows 8 包含手机呼叫和短信功能

- Lionheart - LiveSino - LiveSide 中文版
Long Zheng 在 BUILD Session 中注意到了一张幻灯片显示的“未接来电”瓷片,这暗示了 Windows 8 将内置手机电话呼叫功能,同时也使得 Windows Phone OS 的未来更加难以琢磨. 其次,我们也可以在 Windows Live 应用演示中看到,人脉(即 People)应用中明确显示了可以发送短信和拨打手机,而且支持 Threads 功能:.

[图]Windows8依然包含“经典模式”的蓝屏

- Darth Noctis - cnBeta.COM
Win8再一次蓝屏了,本次蓝屏出现在启动过程中,可爱的笑脸不知道哪里去了,那个标志性的Windows又回来了…….

Windows 8 首批下载将包含中文等5种语言

- Tolay - cnBeta.COM
微软的Windows 8版本保密机制无疑是做的最好的,有史以来也是泄漏版本最少的. 现在,随着9月13日Build Windows大会的临近,一切都意味着微软Windows 8的公开下载即将开始. 除了针对开发者(编程人员)的Windows Developer Preview(开发者预览版本),Windows 8 Beta公测版本也将在随后的几天内放开下载.

《质量效应3》将包含多人合作模式

- lin - Solidot
BioWare宣布,将于明年三月发布的《质量效应3》将包含一个多人合作游戏模式. 根据官方论坛的介绍,在《质量效应3》中,BioWare引入了Galaxy at War系统去管理和体验多人模式,多人模式由四人参与. 玩家无法扮演单人游戏中的指挥官Shepard,Garrus、Ashley和Liara等,但可以扮演Turians、Krogans和Asari,玩家可以定制角色、种族和特殊能力,可以通过多人游戏提升等级和武器.

CyanogenMod 7.1正式版发布 包含最新Android系统2.3.7

- kxxoling - cnBeta.COM
知名的第三方Android定制系统开发团队CM今日发布了最新的作品,CyanogenMod 7.1版. 此次更新的内容非常庞大,主要工作围绕Bug修复和外观改变上展开. 但这一版本最重要也是最引人注意的是,CM7.1现在提供的系统为最新的Android 2.3.7.