2013年五月月 发布的文章

buildc 0.3.0版本发布

buildc正式在项目中应用以来,我们收到了许多同事针对buildc演进的意见和建议。其中确实有些易用性的问题是在最初设计时未考虑周全的,尤其是.buildc.rc中的配置,同事们对该文件的配置已经“怨声载道”了。

.buildc.rc是用来配置某开发者在开发过程中使用的第三方库所在subversion repository信息的,例如:

a_repository = ('SVN库地址', '本地缓存路径',
              [
                  # 格式:[(“第三方库名称”, “库版本”, “特征库文件”), …]
                  ('libevent', '2.0.10', 'lib/libevent.a'),
                  ('instantclient', '10.2.0.5.0', 'lib/libnnz10.so'),
                  …
              ]
            )
b_repository = ('SVN库地址', '本地缓存路径', [])
c_repository = ('SVN库地址', '本地缓存路径', [])

external_repositories = [
                        a_repository,
                        b_repository,
                        c_repository,
                        …
                   ]

这里面需要维护最多、最频繁的就是各个repository中具备的第三方库名、版本号。开发者所开发的项目所依赖的第三方库信息发生变化,不仅仅需要修 改project下的buildc.cfg文件,还可能要修改.buildc.rc,大家维护起来确实体验不好,会多耗费一些工作量。

针对这个主要问题,我们决定对buildc进行一次较大范围的重构,重构后的版本定为buildc 0.3.0版本。以下是buildc 0.3.0版本的主要改动点:

一、简化.buildc.rc的配置,重新定义cache相关命令的语义

0.3.0及以后版本的.buildc.rc只需配置repository的地址信息以及cache缓存的本地路径信息,无需再提供repository 里面具体的第三方库以及版本号信息了,这样一来,大多数情况下,project依赖的第三方库发生变更,都无需修改.buildc.rc了。

a_repository = ('SVN库地址', '本地缓存路径')
b_repository = ('SVN库地址', '本地缓存路径')
c_repository = ('SVN库地址', '本地缓存路径')

external_repositories = [
                        a_repository,
                        b_repository,
                        c_repository,
                        …
                   ]

随之而变的是buildc cache相关命令的语义,0.3.0中cache相关命令的语义如下:

* buildc cache init - 生成.buildc.repository,该文件是svn库的目录结构文件,相当于一份svn repository内部的地图,repository中存放的各种第三方库以及版本均在该文件中索引;如果该文件已经存在,命令执行的结果为:提示已存在。

* buildc cache upgrade – 根据.buildc.rc的最新更新,重新生成.buildc.repository文件,并将该文件中所有lib本地的 Revision号置为none。该文件并不会执行本地cache的library的真实更新操作。

* buildc cache update  - 
    1. 如果.buildc.rc已经修改,但没有执行buildc cache upgrade,update会对比本地缓存库信息与对应的.repository文件中的同名lib信息,如果不一致,则提醒执行upgrade。
    2. 如果.buildc.repository是新生成的,所有lib本地的Revision号均是none,则提示没有要更新的本地缓存库;
    3. 如果某个项目已经download了自己依赖的库,那update将比对svn库中和本地库的revision差异,并下载最新库版本。并修改.buildc.repository中对应库的本地revision number。

* buildc cache remove – 将.buildc.repository中对应库的本地revision number都置为none,并删除本地缓存的库文件。

二、重新定义config make的语义

前面提到了,在执行buildc cache init时,buildc只是负责生成.repository文件,而并不真实执行库文件的下载和缓存。那何时真正下载呢?答案是在执行buildc config make时。这里颇有些“lazy evaluate”的味道,需要时再“download and cache it"。

* buildc config make

1. 如果.buildc.rc已经修改,但没有执行buildc cache upgrade,config make会对比本地缓存库信息与对应的.repository文件中的同名lib信息,如果不一致,则提醒执行upgrade。
2. 如果.buildc.rc是新生成的,或执行cache upgrade后的,config make会根据project对应的buildc.cfg中配置的第三方库,在.buildc.repository中查找是否存在(包括对应的版本 号),如果存在,则从subversion server端自动下载;否则提示出错。
3. 如果本地缓存中某个库文件不存在,buildc config make会检测到,并自动下载该库,并cache起来。
4. 如果subversion端某个库的svn revision号发生的更新,buildc config make会检测到,并下载最新的版本。

总之一切都是在buildc config make时来完成的,按需下载或更新,这样你甚至无需进行手工的library Cache维护。

三、转向OO范型

实现buildc 0.3.0的小同事(wtz1989227@gmail.com)对OO情有独钟,因此在这个版本中,他将以前的结构化代码做了大幅度调整,并用OO的方 式进行了重构。按照wtz的思路,这次改造比较初级,OOD做得还不够充分,以后慢慢调整。实际代码中反映出来的情况也的确是这样。

四、buildc 0.2.3发布

在将buildc 0.3.0代码merge到trunk之前,我创建了buildc-0.2的maintain branch,虽然理论上buildc 0.3.0在功能和配置方面与buildc 0.2.x版本是兼容的,但毕竟代码调整幅度较大。另外建议大家都转移到0.3.0这个最新版本上来,buildc-0.2分支顶多做一些bugfix, 不会再有新feature添加进去了。

昨天在发布buildc 0.3.0的同时,还发布了buildc-0.2的一个Bugfix版 – buildc 0.2.3,该版本主要做了如下一些fix:

  * 执行cache upgrade时增加对.buildc.rc中repository特征文件存在性的检查;
  * 执行config make时增加对Make.rules文件是否为空的判断;
  * 执行pack source时,添加VERSION文件,记录打包的上下文信息。

五、其它

考虑到github的活跃度远远高于google code,加上google code最近访问十分不稳定,因此之前就将buildc(还有cbehavelcut以及我的实验代码库)fork了一份到github上了,也攒攒 github上人气,因此这次buildc 0.2.3和buildc 0.3.0的代码还要发布到github上一次。git工具平时用的少,尤其是提交代码到github,这次算入门了。

* 代码远程提交
用git remote add一个github的remote repository后,就可以使用git push origin master将本地的commit推送到github上了。

* 打tag,并推送tag

   — 查看Tag的git命令是git tag
   — 本地打tag,用这个命令: git tag -a v0.2.3 -m"0.2.3 released"
   — 推送Tag到remote repository:git push –tags origin master,不加–tags是无法推送tag的。

* branch操作
  — 查看branch:git branch
  — 创建branch:git branch buildc-0.2
  — 推送branch:git push origin buildc-0.2
  — 本地切换branch:git checkout buildc-0.2

也谈Commit log

版本控制工具大行其道的今天,作为程序员,势必要每天与各种版本控制系统(比如SubversionGitMercurial等)打交道, 每天不commit几次代码都不好意思说自己是专业程序员^_^。不过commit代码可不止敲入commit命令这么简单,对于一个专业程序员 来说,我们还要关注每次commit所携带的背景信息,这里暂且称之为“commit context”。在每次commit时,这些上下文信息只能通过commit log来体现。

一、Commit Context

今日的软件复杂度日益增加,软件开发模式也早已从单打独斗的英雄模式变成了团队协作模式了,而在团队模式下,版本控制系统发挥着至关重要的作用, 它让开发过程变得有序,将冲突解决的成本尽可能地降低到最低。但版本控制系统毕竟不是智能的,它只是机械地记录着每次提交前后的内容的raw差 异,至于这个差异究竟代表了什么,版本管理系统是不得而知的,这就需要我们开发者们来提供,这就算是产生commit context的动机吧。即便是一个人开发维护的项目,个人的记忆也是有时效性的,时间久了,以前的代码变更context势必也就淡忘了,良好且规范的 commit context有助于更好的维护项目,追踪历史思路和行为,甚至在查找bug时也是能帮得上大忙的,比如确认bug引入的时段边界、代码范围等。

前面说了,commit context最终是以commit log形式提供的,这才是我在这篇文章中真正要说的内容^_^。评价一个项目的好坏,无论是商业项目,还是开源项目,代码本身质量是一个重要的方面,代码 维护的规范性则是另外不可忽略的一个重要因素,而在代码维护规范性方面,commit log的规范是一项重要内容。做了这么多年Coding工作,到目前为止部门内部还没有哪一个项目在commit log规范方面是让我满意和欣赏的。另外本人在亲为commit log方面也是不能让自己满意的,这也是促使我思考commit log这块内容的一个初衷。

commit log承载着每次commit动作的context。一般来说context中至少要有一项内容,那就是此次代码变更的summary,这是最基本的要 求。如果你的commit log还是空着的,那你真该反思反思了,那是对自己和他人的不负责任。但无论是商业公司内部开发还是开源项目,commit context涉及到的因素往往不止一个,很多情况下commit context还与项目过程、质量保证流程以及项目使用的一些工具系统有 关联。我们来看两个知名开源项目的commit log样例吧。

[example1 - Linux Kernel]

audit: catch possible NULL audit buffers
It's possible for audit_log_start() to return NULL.  Handle it in the
various callers.

Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Eric Paris <eparis@redhat.com>
Cc: Jeff Layton <jlayton@redhat.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Julien Tinnes <jln@google.com>
Cc: Will Drewry <wad@google.com>
Cc: Steve Grubb <sgrubb@redhat.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

这是Linux Kernel项目的一个commit log的内容。从这个log携带的context信息来看,我们能够清楚地了解如下一些内容:

- 修改的内核模块范围audit
- 修改的原因summary: to catch possible NULL audit buffers
- 这个patch从诞生到被merge到trunk过程中涉及到的相关的人员列表
- 这个patch由Who sign-off的。

将mail list放入到commit log中,这是Linux Kernel开发过程规范所要求的,同样也是质量保证的一个方法。在《如何加入Linux内核开发社区》系列文章中你可以了解到一些有关Linux Kernel开发过程的内容。从这个例子中我们主要可以看出commit context与Project过程、质量保证链条方面的相关性。

[example2 - Apache Subversion]

Fix issue #3498 – Subversion password stores freeze Eclipse

* subversion/libsvn_auth_gnome_keyring/gnome_keyring.c
  (simple_gnome_keyring_first_creds, simple_gnome_keyring_save_creds,
   ssl_client_cert_pw_gnome_keyring_first_creds,
   ssl_client_cert_pw_gnome_keyring_save_creds): If the keyring is locked
    and we are in interactive mode but have no unlock prompt function, don't
    throw a "GNOME Keyring is locked and we are non-interactive" error;
    instead, continue without unlocking it, so that the unlocking may be
    handled by the default GNOME Keyring unlock dialog box.

这是Apache Subversion项目的一个commit log的内容。同样从这个log携带的context信息来看,我们能够清楚地了解如下一些内容:

- 修改的代码范围subversion/libsvn_auth_gnome_keyring/gnome_keyring.c,包括括号中的函数名列表, 这个显然更为细致。
- 修改的原因summary: Fix issue #3498 – Subversion password stores freeze Eclipse
- 这个patch与问题跟踪系统的关联性 -issue #3498

通过这个commit log,我们可以快速找到此patch对应的问题跟踪系统中的条目#3498,这样可以查看到一些更为细致的context信息。从这个例子我们主要能够 看出commit context与项目所使用的一些工具系统的关联。

综合以上可以看出良好的commit log是可以清楚全面反映commit context的。这里的“全面”是project-dependent的,是需要能够体现出涉及project的一切必要信息的:过程的、质量的、工具 的。

二、Commit log格式

Commit log没有放之四海而皆准的统一格式,而是project-dependent的。就我个人而言,我会在下面的几个问题上有纠结。

* 语言

不得不承认在创造编程语言方面,西方文化占了主导,语言中的关键字也多取自英语。虽然目前主流的语言以及新兴的语言都号称源码原生支持utf8或 unicode其他字符集格式,但却是很少见到在源文件中使用非英语命名变量或函数的,这也影响了我在commit log中对语言的选择 – 我基本上都是用英文编写commit log的。目前主流的版本控制工具都是支持unicode字符集的,你用中文提交也是没有任何问题的,尤其是在国内商业项目中,使用中文描述起来,理解上快且歧义少。我是不反对用中文写commit log的,但反感的是中英文混合写commit log(有些人用中文,有些人用英文)。每当批量看commit log时,中英文混在一起,一点美感都没有了。

commit log不是给最终用户看的,而是给开发维护人员看的。因此选择语言种类时要看这种语言是否能给开发维护人员的工作带来便利,精确全面地传达context。即便 应用是要发布给非洲人民,但若开发人员都是中国人,一样可以用中文编写commit log。

* 地道

说到“地道”,主要是针对你选择外语(大多数情况是英语)作为你commit log的承载语言时。就像生活在国外要用外国人熟悉的语言习惯与人交流似的,我们在用英语编写commit log时也要学会选用“地道”的词汇,远离Chinglish。当然想立即做到“地道”也不是那么容易,毕竟我们一直以来就按照Chinglish的思维去学 习英语的,一个比较好的方式就是多看看知名开源项目(比如linux kernel)的commit log,看看人家是如何选择词汇和组织句子的。其实Commit log中用到的词汇和句型很少,看多了也就找猫画虎的学会了。

* 规范

“没有规矩,不成方圆”,无论是商业软件项目,还是大型开源项目,莫不如此。如果要想很好的传达commit context,一个设计规范,内容全面的commit log格式是必不可少的。我们无需从头做起,很多开源项目在这方面都已经有一些良好的实践,比如上面提到的linux kernel的commit log convention,再比如这里有Apache Subversion的Commit log要求。TYPO3和FLOW3也有自己详细的Commit log说明

制定规范时总体来说,注意以下几点:
– 格式简明扼要,只保留必要的项;
– 注意与项目过程、质量保证流程的结合,以及与第三方工具的关联(注意序号或ID的唯一性);
– 对于规模较大的系统,可以考虑在log中体现影响的涉及的“子模块”或“子目录”名字或者逻辑功能的名字(比如前面linux kernel例子中的audit),这样便于快速定位本地commit的影响范畴。

三、Commit模板

如果像linux kernel或subversion那样涉及到过程、质量控制以及第三方工具的集成(比如问题跟踪系统、代码评审系统等)时,建议设置Commit log template(模板)以简化开发者commit log编写的工作。

* Subversion命令行客户端支持commit log模板

Subversion在命令行客户端侧暂无对模板的支持。不过可以通过一些trick模拟实现这个功能:

- 创建commit log模板log.tmpl,放在特定目录下,本例中放在用户的$HOME目录下
- 添加并导出环境变量SVN_EDITOR
         export SVN_EDITOR="rm svn-commit.tmp && cp ~/log.tmpl svn-commit.tmp && vi "

svn commit时,svn客户端会在当前路径下会执行类似$SVN_EDITOR svn-commit.tmp的命令,而svn-commit.tmp文件已经被替换为我们的模板文件,开发者只需按模板填写内容,并保存退出即可。如果 commit成功,svn客户端会删除当前目录下的svn-commit.tmp,否则svn-commit.tmp不会被删除,这将导致下次再提交 时,svn客户端检测到svn-commit.tmp的存在,从而新建立一个svn-commit.2.tmp的新文件,导致模板失效,这也是这个方法的 一个瑕疵。

* Git命令行支持commit log模板

Git是目前very hot的分布式版本管理工具,起步晚,但起点高,因此已经内置了对模板的支持,只需将模板文件配置一下即可。
         git config –global commit.template ~/log.tmpl

四、良好格式commit log的实施

即便有了良好格式的commit log的模板定义,但就我经验而言,实施起来也还会遇到诸多问题。commit行为是客户端发起的,要让所有开发者都能很好的使用模板并主动按模板提交需 要一些流程以及工具支持。比如在server段部署pre-commit hook,对提交的log格式进行检查,不符合模板格式的予以拒绝等。

对于与问题跟踪系统有关联的log格式,还要注意保持问题跟踪系统id或序号的唯一性,这显然是管理和过程方面的工作。

对于开源项目,一般merge到trunk需要owner的检查,所以反倒实施起来容易了些,只要有一篇内容丰富的 developer/community guide或convention之类的文档即可,多数知名的opensource project(比如linux kernel、subversion、apache httpd server、python等)都是有这类文档的,为这些project提交patch前是要好好阅读这些文档的,不能坏了规矩^_^。     
 

推动知识管理的这两年

掐指算来,部门知识管理的推广工作已有两年了。两年时间不能算短,但对于知识管理这件事来说,只能算是热身阶段,我们依旧站在起跑线上,或者稍乐 观地讲我们只是刚刚迈出了万米长跑的第一步。

下面是这两年来部门内部知识库建设的一个Timeline:

- 2011年中旬,我所在产品线私下在一台PC上建立了基于MediaWiki的知识库。
- 2011年末产品线在部门内部做了有关知识库与知识管理实践的分享。
- 2012年初,部门在新采购的高性能服务器上建立基于MediaWiki的知识库,并指定专人负责;我们产品线将已经积累的内容迁移到了部门知识库中,这 也标志着部门知识库1.0版本正式上线。知识管理的策划和推广事宜也交由专门的子部门负责。
- 2012年中,设立子部门KM负责人,设立子部门KM定期工作会,设立子部门技术交流汇报会,旨在各子部门之间分享最新信息,减少重复劳动,提高效率。
- 2012年末,启动知识库2.0建设方案。
- 2013年3月末,知识库2.0版本上线。邀请专业设计人员策划和实现了全新主页,提高了UE;重新策划了分类;重新划分了知识版块,专人负责更新;增加 了知识达人等多个激励内部童鞋分享知识的手段和方法;通过piwik统计和分析知识库的最新访问动态;通过一些实用的插件来简化Wiki Page编写工作、更好地展示内容;提炼高质量知识文章,形成知识周刊、月刊,作为内部知识库营销推广手段,吸引大家来到知识库,并尝试留下自己的知识。

两年来,我这个“始作俑者”在知识库建立起来后已经不做什么具体的工作了(骨子里其实是不愿意做重复性、事务性工作),只是充当着“幕后推手”。值得我庆幸的是有那么几位同事都认同知识管理 的重要性,愿意参与进来执行具体的工作。专职负责知识管理的子部门的领导也十分重视此事,这才有了部门知识库的持续演进,才有了目前的2.0版本 上线,他们才是真正的猪角。

这两年来,我在知识管理方面所作的工作主要有如下几方面:

* 找人,形成圈子

知识管理和推广虽然重要,但并非核心业务,不能显式地让大家看到其对部门发展的贡献度,因此多数人对此工作并不感兴趣,找到适合且对此有兴趣和热 情的人也就并非易事。另外还要得到相关子部门领导的长期支持,事情才好持续办下去。在1.0上线后,经过大半年的观察,我们找到了真正合适的人 选。也有两位志同道合的子部门领导十分重视此事,也亲自参与到知识库建设的交流讨论中。这样一个知识管理和推广的小圈子形成了。

* 识别广泛的需求,形成可行性共识

最初之所以在产品线私下建立起Wiki知识库,显然是因为我们遇到了诸多具体问题,诸如知识如何共享、知识的发现、知识更新以及一致性等(那时的 知识局限在项目过程中的各种文档资料等)。我们想通过一个共享的协作平台解决掉遇到的问题,于是有了我们自己的Wiki。这些问题其实是有共性 的,我们遇到了,其他产品线、开发组、子部门也会遇到。也就是说这个Wiki不仅仅能解决我们的问题,还能帮助解决其他人的问题。为此,我们做了 多次公开调查和私下交流,确定了知识库的必要性和大力推广的可行性。

* 保持与知识库的直接负责领导常沟通

我顶多算是一个“推手”,具体的知识库运营是由某子部门领导负责的。因此在用人以及知识库演进方面,还要常与领导沟通,达成一致后,推动执行起来 就方便的多了。

* 元策划

所谓的元策划就是为负责策划的具体执行人提供策划咨询,指导如何策划,仅此而已。当然有时也提供具体策划思路^_^。

* 监督实施

这个很关键。虽然我不直接负责知识管理这块,但我心目中是有一些期望达成的里程碑点的。因此我会不时的与具体的执行人了解进度情况,也算是一种督促和监督了。

知识库2.0上线一月有余,他们弄了个知识月刊首期,居然把我评为月度“知识达人”,还问我是否可以分享些知识积累和总结方面的心得。以前从未系统考虑过这个问题,冷不丁的提起来还真没啥思路。不过花些时间深入想了想,还是有点体会的,也许这个体会比较另类。

我承认我日常喜欢做一些知识积累和总结,只是喜欢并习惯为之而已,谈不上什么擅长,无论是工作中还是业余时间的学习过程中。为什么会这样呢?这么做到底动 机何为?我也仔细想了一下:从心理上来说这可能是源于一种“忧患意识”吧。真的是忧患:担心记性差,导致设计思路等知识和技巧的遗忘,那可真是种浪费和损 失;担心无地儿去回顾/查找(因此要起个好标题,找个好分类,贴上适当标签);担心体验和心得的消失;担心自己每天没有进步(一直追求每天进步一点点,而 积累和总结则是一种显式地进步的体现);担心别人看不到自己最新更新的内容(因此放到Wiki这种载体);担心大脑容量不够,无法装得下那么多内容,所以 持久化到一类“永恒”的介质(blog、wiki)中;担心自己说不清楚,讲不明白,就写下来,并反复揣摩修改,直到自己满意;担心太多的东西放在大脑 中,太沉重,无法轻装前进,因此写出来,腾出一些空间,容纳点新东西等等。

两年了,还是那句话,自己在知识管理方面依旧是野路子+新手!估计自己以后依旧不会直接做知识管理方面的执行工作,但肯定会是一个知识分享者以及一个旁观 参与者。知识库的建立为组织内的每个人、项目、产品线、子部门提供了一个分享的平台,也是一个自我展示的平台。知识库的内部营销才刚刚上路,前途光明,道 路坎坷,猪脚们要有一颗耐心。

最后和大家分享一下我们知识库的slogan:“知识不怕从头积累,就怕从不积累”

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!




这里是Tony Bai的个人Blog,欢迎访问、订阅和留言!订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:


如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:


以太币:


如果您喜欢通过微信App浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:



本站Powered by Digital Ocean VPS。

选择Digital Ocean VPS主机,即可获得10美元现金充值,可免费使用两个月哟!

著名主机提供商Linode 10$优惠码:linode10,在这里注册即可免费获得。

阿里云推荐码:1WFZ0V立享9折!

View Tony Bai's profile on LinkedIn


文章

评论

  • 正在加载...

分类

标签

归档











更多