艾莉亚的猫 Time is limited, To be a better man

使用开源项目的正确姿势

导读:开源精神是技术发展的源动力之一,受到工程师们的热烈欢迎。但是开源项目如此之多,哪一个最适合自己?如何更好利用开源项目,甚至做二次开发?今天,阿里资深无线开发专家李运华,总结多年与开源项目打交道的经验,讲述如何正确利用开源项目,希望对大家有所启发。

软件开发领域有一个流行的原则:DRY,Don’t repeat yourself,我们翻译过来更形象通俗:不要重复造轮子。开源项目主要目的是共享,其实就是为了让大家不要重复造轮子,尤其是在互联网这样一个快速发展的领域,速度就是生命,引入开源项目,可以节省大量的人力和时间,大大加快业务的发展速度,何乐而不为呢?

然而现实往往没有那么美好,开源项目虽然节省了大量的人力和时间,但带来的问题也不少,相信绝大部分同学都踩过开源软件的坑,小的影响可能是宕机半小时,大的问题可能是丢失几十万数据,甚至灾难性的事故是全部数据都丢失。

除此以外,虽然DRY原则摆在那里,但实际上开源项目反而是最不遵守DRY原则的,重复的轮子好多,尤其是歪果仁,一看哪个开源方案不爽,自己就吭哧吭哧搞一个差不多的:你有MySQL,我有PostgreSQL;你有MongoDB,我有Cassandra;你有memcached,我有redis;你有Gson,我有Jackson;你有Angular,我有React。总之放眼望去,其实相似的轮子很多!相似轮子太多,选择就是让人头疼的问题了。

怎么办?完全不用开源项目几乎是不可能的,我们需要更加聪明的去选择和使用开源项目。形象点说:不要重复发明轮子,但要找到合适的轮子!你开的是保时捷,可别找个拖拉机的轮子。

接下来我将根据加入UC,5年与开源项目有关的经历,总结出一些“如何正确使用开源项目”的经验和教训。有的项目是我亲身经历,有的是我接触到的,有的是我观察的,其中部分描述细节可能并不完全准确,大家可以结合自己的经历一起探讨。

以下内容主要分3个部分进行描述,分别是“选”、“用”、“改”。

选:如何选择一个开源项目?

聚焦是否满足业务

我们在选择开源项目的时候,一个头疼的问题就是相似的开源方案较多,而且后面的总是要宣称比前面的更加牛逼。我们在选择的时候有点无所适从,总是会担心选择了A方案而错过了B方案,或者反过来。这里我们的经验是聚焦于是否满足业务,而不需要过于关注开源方案是否牛逼。

案例:当时尝试一个社交类业务时,我们发现了TT(Tokyo Tyrant)这个开源方案,觉得既能够做缓存取代Memcached,又有持久化存储功能,可以取代MySQL,很牛逼,很高大上,于是就在业务里面大量使用了。但后来的使用过程让人很蛋疼,主要表现为:

1、不能完全取代MySQL,因此有两份存储,设计的时候每次都要讨论和决策

2、功能上看起来很高大上,但相应的bug也不少,而且有的bug是致命的,例如所有数据不可读,后来是自己研究源码写了一个工具才恢复了部分数据。

3、功能确实牛逼,但需要花费较长时间熟悉各种细节

后来我们反思和总结,其实当时的业务Memcached + MySQL完全能够满足,且大家都熟悉,当时的业务完全不需要引入TT。

简单来说:如果你的业务要求1000 TPS,那么一个20000 TPS 和50000 TPS的方案是没有区别的。有的人可能会担心我TPS不断上涨怎么办?其实不用担心,我们的架构会不断演进的,等到真的需要这么高的时候我们再来架构重构,记住:不要过早优化,过早优化是万恶之源 —— 《UNIX编程哲学》

观点一二

阮一峰博客看到的一些观点,如下

康威定律

1968年,计算机学家梅尔文·E·康威发表了一篇著名论文,后来被称为康威定律(Conway’s law)。

  • “软件系统的架构,反映了公司的组织结构。”

这个定律说,公司的行政组织架构,会反映在软件产品之中。举例来说,如果四个小组一起写编译器,那么这个编译器内部一定会分成四个环节。很多实证研究,都证实了这个定律。 为什么这样?原因是大公司里面,主管的地位主要取决于他的团队规模和预算。团队越大、预算越多,主管在公司里面的地位就越高,这就是为什么主管都会争取尽可能大的团队和预算。问题在于,团队变得越来越大时,你不得不做出安排,让每个成员有事可做。因此,当团队的所有人都在做一个项目时,随着组织结构的膨胀,软件的架构不得不跟着膨胀,以容纳所有的人手。 根据康威定律,大公司的大型项目一定会有复杂架构,哪怕这种架构可能是不必要的。另一方面,许多程序员崇拜复杂性,认为软件越复杂,表示作者的能力越高。这导致了这样一种状况:大公司(比如阿里腾讯)由于组织架构复杂,会做出复杂软件,然后大家认定,软件必须那么复杂,为了向业内前进水平看齐,自己的软件也必须模仿他们的复杂性。这种想法是不对的,仅仅因为阿里腾讯那样做,并不意味着你也应该那样做,他们无法摆脱复杂性,并不意味着你也需要那种复杂性。

工作

Basecamp 是 IT 行业很有名的一家公司,提供团队协作工具,同时也是 Rails on Ruby 框架的创造者。这家公司的特别之处在于,它不仅写软件,还写畅销书! 它的两位老板喜欢写书,已经出版了三本—-《Rework》、《Getting Real》和《Remote》—-每一本都卖得很好。最近,他们又出版了第四本《工作何必疯狂》(It Doesn’t Have to Be Crazy at Work,见上图)。

这本新书的主要观点是,IT 行业的员工加班(或者说投入工作的程度),已经超过了合理标准,接近于疯狂,应该得到遏制。很多软件工程师每周的工作时间已经达到了60小时,甚至70、80小时。除了工作和睡眠,生活几乎没有其他内容。作者认为,这是错误的。 加班真的是 IT 行业的日常。国内有过一个《2016 年 IT 公司加班时间排行榜》,排名前三位的分别是华为、腾讯和阿里,平均每天的加班时间分别为3.96小时、3.92小时和3.89小时。 是不是一定要那么多加班?这本书说,也不是。加班多的一个因素是,公司没有好好珍惜员工的时间,打断工作的事情特别多,最典型的举措就是开放式办公室,使得人们互相干扰。员工因此不得不加班,因为在正常时间内无法完成工作。作者认为,公司应该创造条件,让员工全身心投入工作,不要拖到夜深人静时才能没有打扰。 许多公司似乎都很擅长浪费:浪费时间、注意力、金钱、精力。每周60、70、80的工作小时中,有多少是真正用于工作本身的?又有多少时间是在会议中浪费掉的,或被各种琐事打断的?大部分吧。 答案不是更多的时间投入,而是减少浪费,减少员工的注意力分散,减少那些引起焦虑和压力的事情。

同时,这本书也指出,IT 公司的工作任务也确实过多:无休止的需求、不断的营销活动、精确到小时的排期,都给工程师带来了焦虑和压力。普通的行业,用户一年增长一倍,绝对是值得庆祝的,但是 IT 行业不行。这个行业渴望的是一年增长十倍,甚至百倍,要的是从0变成独角兽的那种速度。 作者说,我们要一定要这样吗?IT 行业对高速增长有一种不健康的痴迷。正是这种痴迷,使得人们产生不切实际的期望,导致从业者精疲力尽。 这本书的主张是,软件行业也可以是一个平静的行业,而不一定像现在这样,是一个加速再加速的行业。平静才是长期可持续发展的关键。(注意,这里不是指公司,公司只要不断雇佣新人,就可以让工作永远加速运行。但是员工不行,人的生理和心理都不是可以长期透支的。)

过去的18年里,我们一直致力于让 Basecamp 成为一家平静的公司。我们不提出不可能的承诺,不追求高额的营业额,不设置最后期限,不人为制造繁忙的工作和系统性的焦虑。有些项目似乎永远不会结束,我们觉得也 OK。

努力

漫画家蔡志忠有一个演讲,题目叫做《努力是没有用的》。读完这份演讲稿,我觉得他说的有道理。

有些人非常勤奋,别人休息和娱乐的时候,都在工作学习。但是努力了一辈子,人生也没有显著的提升,就像报道里经常说的:”某某在平凡的岗位上,勤勤恳恳工作了一辈子”。

另一方面,很多成功者似乎也没有特别努力,就取得了许多成就,过上了好日子。蔡志忠以自己为例,他从小就喜欢画画,然后一直画,不知不觉就成了大漫画家,名利双收,从没有觉得过得很辛苦。 老师或父母老是说,努力就会走到巅峰—-才怪。如果这样,不是所有人都走上巅峰了吗?没有人开始不努力,为什么后来不努力,因为努力没有效果。”

人生不是走斜坡,你持续走就可以走到巅峰;人生像走阶梯,每一阶有每一阶的难点,学物理有物理的难点,学漫画有漫画的难点,你没有克服难点,再怎么努力都是原地跳。所以当你克服难点,你跳上去就不会下来了。 蔡志忠的核心观点就是黑体的那句话,成功的人生是台阶式向上,而不是一条水平线。努力只是说明你拼命在走,跟你能不能向上走,关系不大。那些努力却没有结果的人,根本原因就在于,他一直走在平面上,没有走到更高的台阶。 也就是说,垂直方向的努力更有意义,水平方向的努力意义不大。你把同一件事情勤奋地做上十遍,还是只会做这一件事;你做完这件事后,再去挑战更难的事情,就有机会学会做两件事。

死海效应

公司发展到一定阶段,能力强的员工容易离职,因为他们对公司内愚蠢的行为的容忍度不高,他们也容易找到好工作,能力差的员工倾向于留着不走,他们也不太好找工作,年头久了,他们就变中高层了。这种现象叫”死海效应”;好员工像死海的水一样蒸发掉,然后死海盐度就变得很高,正常生物不容易存活。(周鸿祎)

如何高效学习github开源项目

这一篇整理本来是为组内分享准备的(十分钟分享),后来换了一个话题来说,这部分内容就一直放在了MRU文件,重新梳理出来

写代码 VS 读代码

提高编码能力,主要是靠写代码和读代码,读代码能力在一定程度上还要重要于写代码

github上值得关注的公司和个人

Facebook google alibaba tencent douban qiniu etc

云风 陈皓 陶叔度 庄晓丹 司徒正美 etc

整理认识开源项目

开源项目整个目录架构,大体上是 src test doc include lib tests perf build 其核心实现一般都是在src下面需要主看

工程构建工具大致上有几种: bazel cmake makefile libtool shell

编译安装过程大致: ./configure && make && make install

如何阅读项目代码

README文件一般都是整个项目的总结归纳,包含了基础的编译安装使用的说明信息,是首先需要看的内容

从main函数看起,熟悉大的框架,再入手自己感兴趣的点,不断深入学习

利用版本控制系统,可以从项目最开始提交的简单实现看起,还可以结合branch tag来看

著名的项目一般都有书籍和文档总结,结合docs学习

让代码跑起来,结合日志学习

开源可以学到的东西

源码之下 了无秘密(看别人如何制造轮子)

学习别人细节上的优秀的点,不断提高完善自己细节处理能力

把握技术潮流和趋势(docker travis)

开源项目多框架少业务,代码实现多是优美,设计模式学习

大阪游记

是不是要补一篇大阪游记了?

1

不要删除数据

Oren Eini(又名Ayende Rahien)建议开发者尽量避免数据库的软删除操作,读者可能因此认为硬删除是合理的选择。作为对Ayende文章的回应,Udi Dahan强烈建议完全避免数据删除。

所谓软删除主张在表中增加一个IsDeleted列以保持数据完整。如果某一行设置了IsDeleted标志列,那么这一行就被认为是已删除的。Ayende觉得这种方法“简单、容易理解、容易实现、容易沟通”,但“往往是错的”。问题在于:

删除一行或一个实体几乎总不是简单的事件。它不仅影响模型中的数据,还会影响模型的外观。所以我们才要有外键去确保不会出现“订单行”没有对应的父“订单”的情况。而这个例子只能算是最简单的情况。……

当采用软删除的时候,不管我们是否情愿,都很容易出现数据受损,比如谁都不在意的一个小调整,就可能使“客户”的“最新订单”指向一条已经软删除的订单。

如果开发者接到的要求就是从数据库中删除数据,要是不建议用软删除,那就只能硬删除了。为了保证数据一致性,开发者除了删除直接有关的数据行,还应该级联地删除相关数据。可Udi Dahan提醒读者注意,真实的世界并不是级联的:

假设市场部决定从商品目录中删除一样商品,那是不是说所有包含了该商品的旧订单都要一并消失?再级联下去,这些订单对应的所有发票是不是也该删除?这么一步步删下去,我们公司的损益报表是不是应该重做了?

没天理了。

问题似乎出在对“删除”这词的解读上。Dahan给出了这样的例子:

我说的“删除”其实是指这产品“停售”了。我们以后不再卖这种产品,清掉库存以后不再进货。以后顾客搜索商品或者翻阅目录的时候不会再看见这种商品,但管仓库的人暂时还得继续管理它们。“删除”是个贪方便的说法。

他接着举了一些站在用户角度的正确解读:

订单不是被删除的,是被“取消”的。订单取消得太晚,还会产生花费。

员工不是被删除的,是被“解雇”的(也可能是退休了)。还有相应的补偿金要处理。

职位不是被删除的,是被“填补”的(或者招聘申请被撤回)。

在上面这些例子中,我们的着眼点应该放在用户希望完成的任务上,而非发生在某个 实体身上的技术动作。几乎在所有的情况下,需要考虑的实体总不止一个。

为了代替IsDeleted标志,Dahan建议用一个代表相关数据状态的字段:有效、停用、取消、弃置等等。用户可以借助这样一个状态字段回顾过去的数据,作为决策的依据。

删除数据除了破坏数据一致性,还有其它负面的后果。Dahan建议把所有数据都留在数据库里:“别删除。就是别 删除。”