最近在图灵社区上翻译了一篇mercurial架构的文章,顺便看了一下mercurial的代码和内部实现:http://www.ituring.com.cn/article/details/11708
我还没看AOSA这本书的git这一章。虽然平时git用的比较多,但是对git的内部实现还是认识的很模糊,没法和mercurial进行对比。就mercurial本身而言,除了在分支的实现上不如git之外,其他都非常好。mercurial一开始只能clone,这对于大型项目来说很坑爹。比如Firefox,开始克隆代码库之后程序员就可以去泡杯咖啡了。为了解决这个问题,mercurial后来加上了branch命令,可以原地切换分支。但是mercurial为了保持对svn和cvs用户的友好性,设计上还是希望在每个changeset之内记录分支名,不像git那么奔放,分支名就是个指针。
Mercurial的另一个特别之处在于每个changeset除了有一个hashid之外还有一个整数版本号。 虽然分布式版本控制系统中的版本历史是非线性的,但是这个整数版本号在任何一个mercurial版本库中都是线性的,只是顺序可能不同。这个数字版本号不仅使得mercurial对svn用户更友好,而且对于mercurial的内部实现很重要,它是mercurial快速读取版本历史的关键。
从社区的角度来说,Github完胜Bitbucket。我不知道为啥,可能是因为git比mercurial性能更好?或者Github更友好?我用python最多,所以也更偏爱mercurial。
Mercurial项目也有自己的性格,比如类名都是小写,变量名的单词之间不要下划线而是直接连起来写(比如loaddoc或者disabledext这样的函数名)。mercurial的代码中的注释真的多啊,不过注释多也不见得一定就是好事。给mercurial提交patch也是要带测试的,但是mecurial现在的测试已经太多了,跑起来要好久。我跑了一遍需要十多分钟。于是大家约定新的patch不再接受新的测试文件,但测试还是要,只是要塞在已有的某个测试脚本之中。囧!另外,虽然有个bugzilla来记录bug,但是所有的patch都要发到邮件列表里,有机器人会扫描新邮件,并根据邮件中的某些字样自动的在相应的bug中添加reference或者修改bug的状态。哎,真是奇怪的工作流程。
2012年9月27日星期四
2012年3月9日星期五
自己实现 Interview Zen
偶尔遇到了www.interviewzen.com这个网站,一开始我觉得太神奇了,而且太酷了,这真是面试的神器!随即我就开始思考它是怎么实现的。
我并没有第一时间查看它的源代码。在考虑了几个小时之后,我感觉它可能是通过记录
2012年3月2日星期五
计算机编程语言的掌握程度
在简历上,“精通”这两个字基本上起到的都是嘲讽和增加仇恨的效果。一旦你自称“精通”某一门技术或者编程语言,面试官如果不是直接在心里给你打一个不靠谱的标签,那就会努力的证明你是不靠谱的——“精通”这两个字一般都会引来最最困难的提问。所以我一直在想,到底应该怎么形容自己的掌握程度呢?某种技术我说不好。但今天偶尔的一次谈话让我觉得对一门计算机编程语言的掌握程度,是可以有以下四个层次的:
1、知道
在这个层次,你已经了解了这门语言的基本语法。虽然这很微不足道,但也足够你阅读这门语言的程序了。不同语言在语法层面还是有一些区别的,比如语言的类型是编译还是解释、强类型还是弱类型、代码段是用begin/end还是{}表示、声明一个函数是用function还是def等等。
2、熟悉
在这个层次,你已经学会使用了这门语言的基本类库。只有语法没有类库的语言是没有意义的,熟悉这些类库是正确运用语言的基础。熟练使用操作文件系统、socket、日志、并发等等的类库,知道什么时候该用链表什么时候该用哈希,你才能算“熟悉”了这门语言。
3、掌握
在这个层次,你已经使用这门语言写出了一些能够解决实际问题的程序了。在前面的层次,你的代码解决的可能都是一些toy problem,但是只有你的程序经受了实践和时间的考验,你才能够有机会去解决一些书本上永远不可能出现的问题,并且更加深入的了解这门语言的细节。
4、精通
在这个层次,你已经阅读了这门语言的源代码。你应该已经了解它的内部实现,并且有了恍然大悟的感觉。
用这个角度检视自己,我对于各种语言的认知程度又有几分呢?
A类:最接近于精通的
Python:感谢《Python源代码剖析》这本书,给了我一个很好的入门。不过一来这本书我也没看完,二来Python本身的代码也在快速变化着,完全理解Python的实现仍然是一个很艰难的任务。
B类:掌握
C语言: 把C语言列在这里有点勉强,因为我上大学之后就基本没有写过C的代码了,不过C给我的影响仍然是巨大的,它塑造了我对计算机和程序的认识。
Javascript:Javascript是我很喜欢的一门语言,更不必说在这个浏览器的时代,它简直就是世界的未来。Douglas Crockford的那本《Javascript: The good part》是每个js程序员都必读的一本书,而Coffeescript则可以看作是这本书的实现。
C类:熟悉
C++、Java: 把这两门重量级的语言放在这一类实在是让我脸红,不过面向对象程序设计的确仍然是我最弱的地方。类、继承、多态、虚函数、接口——这些都不是问题,我似乎只是不知道怎么把这些螺丝刀派上用场。
PHP:玩具语言。
VB:感谢这门语言陪我度过了紧张的高中时光。
D类:知道
这一类就多了,不一一列举。
显然,随着时间的推移,这些分类也总是在变化的。有的语言因为你不再使用而变得生疏,有些则越来越熟悉。门户之见最没有意义,最重要的是把它们运用在正确的地方。
1、知道
在这个层次,你已经了解了这门语言的基本语法。虽然这很微不足道,但也足够你阅读这门语言的程序了。不同语言在语法层面还是有一些区别的,比如语言的类型是编译还是解释、强类型还是弱类型、代码段是用begin/end还是{}表示、声明一个函数是用function还是def等等。
2、熟悉
在这个层次,你已经学会使用了这门语言的基本类库。只有语法没有类库的语言是没有意义的,熟悉这些类库是正确运用语言的基础。熟练使用操作文件系统、socket、日志、并发等等的类库,知道什么时候该用链表什么时候该用哈希,你才能算“熟悉”了这门语言。
3、掌握
在这个层次,你已经使用这门语言写出了一些能够解决实际问题的程序了。在前面的层次,你的代码解决的可能都是一些toy problem,但是只有你的程序经受了实践和时间的考验,你才能够有机会去解决一些书本上永远不可能出现的问题,并且更加深入的了解这门语言的细节。
4、精通
在这个层次,你已经阅读了这门语言的源代码。你应该已经了解它的内部实现,并且有了恍然大悟的感觉。
用这个角度检视自己,我对于各种语言的认知程度又有几分呢?
A类:最接近于精通的
Python:感谢《Python源代码剖析》这本书,给了我一个很好的入门。不过一来这本书我也没看完,二来Python本身的代码也在快速变化着,完全理解Python的实现仍然是一个很艰难的任务。
B类:掌握
C语言: 把C语言列在这里有点勉强,因为我上大学之后就基本没有写过C的代码了,不过C给我的影响仍然是巨大的,它塑造了我对计算机和程序的认识。
Javascript:Javascript是我很喜欢的一门语言,更不必说在这个浏览器的时代,它简直就是世界的未来。Douglas Crockford的那本《Javascript: The good part》是每个js程序员都必读的一本书,而Coffeescript则可以看作是这本书的实现。
C类:熟悉
C++、Java: 把这两门重量级的语言放在这一类实在是让我脸红,不过面向对象程序设计的确仍然是我最弱的地方。类、继承、多态、虚函数、接口——这些都不是问题,我似乎只是不知道怎么把这些螺丝刀派上用场。
PHP:玩具语言。
VB:感谢这门语言陪我度过了紧张的高中时光。
D类:知道
这一类就多了,不一一列举。
显然,随着时间的推移,这些分类也总是在变化的。有的语言因为你不再使用而变得生疏,有些则越来越熟悉。门户之见最没有意义,最重要的是把它们运用在正确的地方。
2011年1月7日星期五
为什么Latex的宋体可以加粗但不能倾斜?
这的确有点奇怪。不过,稍微做一下关于中文出版业的功课就可以知道了。英文中,斜体用在需要强调的地方,在Latex中对应为\emph{}。但在出版上,中文是没有“斜体”这一说的。需要强调的文字不应该用宋体,而应该用楷体。这也就是为什么Latex的CJK包就安装了宋体和楷体两种简体中文字体。
2010年12月17日星期五
此daemon非彼daemon
跳槽之后被各种琐事缠绕,好久都没有写文章了,今天匆匆记一笔
最近被daemon折磨了很久。原来一个程序要成为一个合格的daemon也是很不容易的,不光要进行两次fork,还有一大堆注意事项(PEP-3143):
偏偏我碰到的情况更特殊一点。这段代码的作者肯定是没看过上面这些条条框框的,把自己fork了两次就变身daemon了,然后在某些时候还用multiprocessing模块把自己再复制了几份来异步的做一些事情。在调试一个bug的时候,我注意到了multiprocessing 模块里讲 Process.daemon 属性时是这么说的:
这实在是一段很难懂的话。就像伞兵生来就是要被包围的,守护进程daemon生来就是要被父进程抛弃的,然后再被init进程收养,沉默的完成自己的任务。但这段话却明确的说,当进程退出的时候,它会把自己的子daemon进程都干掉……那daemon还守护个毛啊?而且这里还说守护进程是不能创建子进程的,这更离奇了,太不公平了吧?这是赤果果的歧视啊。
后来我发现自己有点先入为主了。daemon只是一个概念而已,而非一个实际的标签,系统中的进程实际都是一样的。multiprocess模块的 Process.daemon 只是 Process 对象的一个属性而已,是需要开发者自己设置的而非linux帮你产生啊。理解了这一点,上面的这段说明就完全可以理解了。daemonic 类型的 Process 对象就是具有这些属性而已。这里的 daemon 和我们平常理解的 daemon 虽然有联系,但确是不同的了。
有个和我有相同困惑的人09年在python-list发了一封邮件问这个问题,后来又自己理解了,我也是看到他的邮件才领悟的。
* http://www.python.org/dev/peps/pep-3143/#correct-daemon-behaviour
* http://mail.python.org/pipermail/python-list/2009-May/1203871.html
最近被daemon折磨了很久。原来一个程序要成为一个合格的daemon也是很不容易的,不光要进行两次fork,还有一大堆注意事项(PEP-3143):
- Close all open file descriptors.
- Change current working directory.
- Reset the file access creation mask.
- Run in the background.
- Disassociate from process group.
- Ignore terminal I/O signals.
- Disassociate from control terminal.
- Don't reacquire a control terminal.
- Correctly handle the following circumstances:
- Started by System V init process.
- Daemon termination by SIGTERM signal.
- Children generate SIGCLD signal.
偏偏我碰到的情况更特殊一点。这段代码的作者肯定是没看过上面这些条条框框的,把自己fork了两次就变身daemon了,然后在某些时候还用multiprocessing模块把自己再复制了几份来异步的做一些事情。在调试一个bug的时候,我注意到了multiprocessing 模块里讲 Process.daemon 属性时是这么说的:
The process’s daemon flag, a Boolean value. This must be set before start() is called.
The initial value is inherited from the creating process.
When a process exits, it attempts to terminate all of its daemonic child processes.
Note that a daemonic process is not allowed to create child processes. Otherwise a daemonic process would leave its children orphaned if it gets terminated when its parent process exits. Additionally, these are not Unix daemons or services, they are normal processes that will be terminated (and not joined) if non-daemonic processes have exited.
这实在是一段很难懂的话。就像伞兵生来就是要被包围的,守护进程daemon生来就是要被父进程抛弃的,然后再被init进程收养,沉默的完成自己的任务。但这段话却明确的说,当进程退出的时候,它会把自己的子daemon进程都干掉……那daemon还守护个毛啊?而且这里还说守护进程是不能创建子进程的,这更离奇了,太不公平了吧?这是赤果果的歧视啊。
后来我发现自己有点先入为主了。daemon只是一个概念而已,而非一个实际的标签,系统中的进程实际都是一样的。multiprocess模块的 Process.daemon 只是 Process 对象的一个属性而已,是需要开发者自己设置的而非linux帮你产生啊。理解了这一点,上面的这段说明就完全可以理解了。daemonic 类型的 Process 对象就是具有这些属性而已。这里的 daemon 和我们平常理解的 daemon 虽然有联系,但确是不同的了。
有个和我有相同困惑的人09年在python-list发了一封邮件问这个问题,后来又自己理解了,我也是看到他的邮件才领悟的。
* http://www.python.org/dev/peps/pep-3143/#correct-daemon-behaviour
* http://mail.python.org/pipermail/python-list/2009-May/1203871.html
2010年8月2日星期一
介绍一个Vim的插件:Slime.vim
http://technotales.wordpress.com/2007/10/03/like-slime-for-vim/
Slime不是Vim的原生插件,它的创意来自于玩Emacs的阶级兄弟。它的功能很简单,就是将Vim的一个寄存器中的内容传送到screen的一个window中去执行。
这东西有什么用呢?最有用的地方在于简化REPL(read-eval-print loop)这个循环,降低程序员调试代码的时间成本。对于Python这个问题其实不是那么突出,因为Python的命令行程序对于以文件形式作为输入的 python代码很友好。但是其他语言的命令行程序似乎不是这样。Slime的动力就是Ruby和Lisp这样的语言。开一个Clojure的命令行交互界面麻烦的很,而且它的功能和Python命令行没得比,更不用说ipython了。所以Slime看起来就非常好用了。
Slime不是Vim的原生插件,它的创意来自于玩Emacs的阶级兄弟。它的功能很简单,就是将Vim的一个寄存器中的内容传送到screen的一个window中去执行。
这东西有什么用呢?最有用的地方在于简化REPL(read-eval-print loop)这个循环,降低程序员调试代码的时间成本。对于Python这个问题其实不是那么突出,因为Python的命令行程序对于以文件形式作为输入的 python代码很友好。但是其他语言的命令行程序似乎不是这样。Slime的动力就是Ruby和Lisp这样的语言。开一个Clojure的命令行交互界面麻烦的很,而且它的功能和Python命令行没得比,更不用说ipython了。所以Slime看起来就非常好用了。
2010年7月6日星期二
读《Coders At Work》前三章
我水平比较低,看了前几章就感觉学到了许多,不由得想写一写,为自己总结一下。
人在不同的时间、环境和机遇下所渴望得到的知识是不同的,这些只是现在的我所体味到的好东西。但书中还讲了很多,但也许我以后再读才能品出其 中的滋味,也许你现在就能品出来。这也就是一本好书的魅力所在吧。
第一章出场的大牛是Jamie Zawinski。对他的采访给我印象最深刻的地方是他的成长。他高中接触计算机之后通过参加地方性的 User Group聚会认识了卡耐基梅陇大学(CMU)的老师,然后屁颠屁颠的跑去“实习”。Jamie在CMU读了本科,然后仍然是依靠这位老师找到 了自己的第一份工作。之后他又遇到了Peter Norvig,并跑到Berkerly去了。他的学会的第一门计算机语言是Lisp,他写出了 XEmacs,他从不信任gdb,他是Netscape的主要开发者之一,我们每天看到的XScreenSaver也是他的习作。这需要怎样的天分、机遇 和努力,才能成就这一切呢?现在的Jamie是一家夜店的老板,已经不再写程序了。这似乎真的有一丝“哥已不在江湖,而江湖上还流传着哥的传说”的意味啊。
第二位出场的大牛是Brad Fitzpatrick。对他的采访给我印象最深刻的地方是他的创业历程。LiveJournal从无到有,从小到大,都是他努力的成果。他可以今天写 Javascript,第二天却考虑Linux内核的网络算法。Things are always on fire! 今天经验不足的程序员时常会犯过 度设计的毛病,而那时的他却没有任何可以参考的东西。他也提到如果知道自己的网站能有这么大的发展和负载,肯定会好好的考虑架构啊算法啊之类的东西。但是 世界是没有如果的,他的网站很幸运的生存了下来。这就是一个产品是如何进化的。
第三位出场的大牛是Douglas Crockford。对他的采访给我音像最深刻的地方是他对代码阅读的强调。什么是好代码?在他看来,好 代码的第一要义就是可读性(readability),其次是正确性(currectness),最后才是效率(efficiency)。当然,这可能和 Javascript的特性有关,毕竟这的确是一门非常难以驾驭的语言。他谈到了他和他的同事们是如何进行code reading的,也谈到了他在面试 时对面试者有怎样的偏好。我在看这本书之前由于Javascript的缘故就看过几部Douglas的演讲,他是一个非常可爱的白胡子老头。即使你没有时间,至少也应该看看他的《The JSON Saga》 的分享,非常有意思。
这三篇采访都提到了一些共有的话题,其中一个是问你是如何设计一个系统的,是top-down,还是bottom-up,抑或是 middle-out?不同的人有不同的习惯。我对这么问题的印象这么深是因为在我注意到它之前,有人问过我一个类似的问题,而我的回答很悲剧。回头再读 此书看到这个问题,不由的生出“从前有一份答案摆在我的面前,而我没有珍惜……”的哀叹啊。
人在不同的时间、环境和机遇下所渴望得到的知识是不同的,这些只是现在的我所体味到的好东西。但书中还讲了很多,但也许我以后再读才能品出其 中的滋味,也许你现在就能品出来。这也就是一本好书的魅力所在吧。
第一章出场的大牛是Jamie Zawinski。对他的采访给我印象最深刻的地方是他的成长。他高中接触计算机之后通过参加地方性的 User Group聚会认识了卡耐基梅陇大学(CMU)的老师,然后屁颠屁颠的跑去“实习”。Jamie在CMU读了本科,然后仍然是依靠这位老师找到 了自己的第一份工作。之后他又遇到了Peter Norvig,并跑到Berkerly去了。他的学会的第一门计算机语言是Lisp,他写出了 XEmacs,他从不信任gdb,他是Netscape的主要开发者之一,我们每天看到的XScreenSaver也是他的习作。这需要怎样的天分、机遇 和努力,才能成就这一切呢?现在的Jamie是一家夜店的老板,已经不再写程序了。这似乎真的有一丝“哥已不在江湖,而江湖上还流传着哥的传说”的意味啊。
第二位出场的大牛是Brad Fitzpatrick。对他的采访给我印象最深刻的地方是他的创业历程。LiveJournal从无到有,从小到大,都是他努力的成果。他可以今天写 Javascript,第二天却考虑Linux内核的网络算法。Things are always on fire! 今天经验不足的程序员时常会犯过 度设计的毛病,而那时的他却没有任何可以参考的东西。他也提到如果知道自己的网站能有这么大的发展和负载,肯定会好好的考虑架构啊算法啊之类的东西。但是 世界是没有如果的,他的网站很幸运的生存了下来。这就是一个产品是如何进化的。
第三位出场的大牛是Douglas Crockford。对他的采访给我音像最深刻的地方是他对代码阅读的强调。什么是好代码?在他看来,好 代码的第一要义就是可读性(readability),其次是正确性(currectness),最后才是效率(efficiency)。当然,这可能和 Javascript的特性有关,毕竟这的确是一门非常难以驾驭的语言。他谈到了他和他的同事们是如何进行code reading的,也谈到了他在面试 时对面试者有怎样的偏好。我在看这本书之前由于Javascript的缘故就看过几部Douglas的演讲,他是一个非常可爱的白胡子老头。即使你没有时间,至少也应该看看他的《The JSON Saga》 的分享,非常有意思。
这三篇采访都提到了一些共有的话题,其中一个是问你是如何设计一个系统的,是top-down,还是bottom-up,抑或是 middle-out?不同的人有不同的习惯。我对这么问题的印象这么深是因为在我注意到它之前,有人问过我一个类似的问题,而我的回答很悲剧。回头再读 此书看到这个问题,不由的生出“从前有一份答案摆在我的面前,而我没有珍惜……”的哀叹啊。
订阅:
博文 (Atom)