上周受到一位 CppJieba 用户的邮件咨询所启发 (我也很好奇为什么那么多人还是偏向于邮件咨询,而不是通过issue发问。), 重构了CppJieba的代码,高度集成了一下各个api, 对于用户来说使用起来更加简单,更容易上手了。 然后趁机把 CppJieba v3.0.0 和 NodeJieba 1.0.0 都发布了。
这两者是我在GitHub上面star数最多的两个项目, 维护到现在也快两年的时间了, 除了能让自己的GitHub更好看之外, 收获还是非常大的。 GitHub是整个IT界的知识宝藏, 这几年让我学到最多知识的,几乎都是在GitHub上面的开源项目。
经常会有同学问我如何去学习开源项目, 所以刚好写篇博文来谈谈学习开源项目的一些方法。
那天我发了一个微博关于Node.js代码考古:
软件考古真的很有意思,checkout到很旧以前的版本, 看到node最开始时候的Makefile, 突然感觉好像打开了游戏的简单模式。
当时有股很贱的兴奋感,因为我发现Node.js的一开始也是非常的简陋。 但是简陋往往代表着简单,就比如说,一开始的Node.js是使用Makefile管理。 所有可编译文件都一清二楚。而不是现在的node-gyp,一大坨一大坨的源码, 光看明白这些文件相互之间的关系就要看很久。
这些和我刚开始写CppJieba的时候一样, 因为C++这门语言标准库的缺陷,C++11普及的不咋地, 然后很多常见功能的库,大家都是使用boost之类的库。 不知道有没有很多人和我有同样的感受, 就是每次使用一个C++的代码,最恶心的就是需要安装各种依赖代码, 而且还经常因为依赖的代码的版本问题,导致安装失败。 这种情况在Linux上面特别严重,以至于vczh还讽刺过在linux安装软件:“看的不是使用说明,而是使用攻略。”
所以我一开始就决定不依赖任何第三方库, 遇到需要用的函数都自己写, 所以因此也诞生了我自己常用的一个C++库limonp。 虽然一开始代码写的很简陋, 但是起码,我的程序可以直接在不需要安装任何依赖库的情况下运行,超轻量。 当然单元测试依赖了gtest,不过是将gtest的源码归并进自己的项目代码中。
事实证明,这个非常重要。 还是那句话:没有依赖,就没有伤害。 而且后来我看到的ideawu的SSDB也是如此。 这样的开源项目,才是重视用户体验的开源项目。
我有一个项目叫practice, 用来积累自己的代码片段, 当我在接触一些新的技术的时候, 我需要写一些小练习代码, 我就会将练习代码放入这个仓库。 其实有时候,这些小片段就是大项目的种子, 就好像Node.js代码考古中其实就可以看出来, 刚开始的Node.js也是作者的实验性的代码, 就是一种使用JavaScript编写异步IO服务的实验性代码。 (刚开始代码只实现了当服务接收到请求的时候,就读取js源码文件,然后将执行结果返回,这样而已。)
比如我自己写的一个简单HTTP服务器, 也是从一些小实验性代码拼凑起来,比如socket的收发, HTTP包头的解析,使用BlockingQueue构造线程池等。 这些都是常见代码,但是组装起来,就是一个项目。 而且写这些代码片段,对自己学习新技术,非常有帮助。 事后还可以回头翻看,现在有GitHub这个好社区真的比以前学习编程的时候方便太多了。
这个很好理解,就是善于借助别人的分析文档。 就好比如果要深入阅读Redis源码的话, 不妨先看一遍《Redis设计与实现》再去看源码。 就好像在走迷宫的时候,别人给了你一幅地图, 就轻松多了,还能沿途欣赏风景。
但是不理解的是不太明白为什么很多人喜欢硬啃, 我除非遇到很新的开源项目,搜不到相关前人的文档, 才不得不硬啃。 但是现在其实开源项目的作者都很重视文档了, 一般都很自觉写了一些源码文档。
开源项目不是star数越多越好,而是对你来说越容易读懂越好。 一般和你当前所做工作越相近的就越容易读懂。 和你所做工作相近的时候,阅读源码能带来一些开发或者是重构的灵感。 甚至光看看一些文件名、类名、源码注释, 就可以知道使用了什么技术, 然后去搜相关技术的文章论文等来详细研究。 这些都是非常有帮助的。
如果阅读的源码和自己工作内容牛头不对马嘴, 理解的也不透彻,然后没几天就忘了。 基本上只剩下装逼时候吹牛用了。
一味追求看高性能的代码其实并不好, “代码是写给人看的,顺便能在机器上运行而已。” 但是很多明星开源项目因为性能太重要了, 有时候不得不略微牺牲一点可读性来实现高性能。 而且star数量大的明星项目,考虑的东西多, 兼容性,易运维性等都是不小的代码量。 而这些其实并不是项目的核心。 阅读源码,应该是越容易读懂核心越好。
感觉最近开源项目作者越来越受热捧, 让开源项目变得越来越功利了。
希望不要忘了开源项目的初衷, 是为了知识更好的分享和传播。