第10章 开源这条路

10 开源这条路

10.1 这是一个美好时代

回望过去,在冷兵器时代,在奴隶社会,生活在罗马帝国之下,恐怕是一种惶恐、毫无安全感的体验,到处是杀戮,动不动就掠杀。战争不断,还有饥荒、瘟疫和各种自然灾害。别说自己辛辛苦苦积累的财富难以保持,就连生存、甚至保存生命都是一个大问题。那是一个野蛮的时代。

在我国古代的农耕时代,相对来说,老百姓过的是安详的生活,有过“太平盛世”。但那时是封闭的,作为一户寻常人家,一年到头,根据不同的气节,适时劳作,如此反复数十载。而活动的范围通常都只局限于在本村、本县或本洲内,受交通工具限制,再远的地方就去不了了。

随着历史的车轮滚动到今天,我们已进入了文明的时代,并且进入了信息化时代。自从第一台计算机问世以来,到现在软件开发这一领域也已经历了数十载。今天花很少的钱就能拥有一台几乎要以满足日常开发的电脑,不再需要受限于内存、硬盘空间等硬件设备,也不再需要忍受汇编代码的痛楚。更为重要的是,我们拥有了可以和世界交流的网络和互联网。在世界和平这一大背景下,同时在计算机领域和软件开发领域日益成熟这一前提下,我觉得对于我们技术类人员来说,是一个美好的时代。

既然这是一个美好的时代,那么我们应该好好珍惜,做一些有趣的事情。比如,通过我们的开源框架,用代码跟世界说一声:Hello Wolrd。

10.2 为什么要开源?

在开源这么多年以来,有不少同学问过我,为什么当初选择开源?

我觉得这个问题,挺有意思。因为我曾经也考虑过,也想过,但当时还没想到答案。现在依稀也仿佛想明白了为什么要开源。对于这个问题,可以换一种方式继续追加到底。比如,为什么要决定选择从事软件开发?为什么当初要学习编程写代码?

10.2.1 因为兴趣

就我而言,在我初中启蒙时期,初次接触电脑和编程时,就爱上了写代码。可以说,当初乃至现在要学编程都是出于个人的兴趣爱好。为此,这是最大的动力,无论是自己研究某些技术,还是在开源社区,最好的自我驱动力就是兴趣。代码就像是一颗神秘的魔法石,通过它,你可以自己设定规则,创造一些有趣的东西,甚至可以打造一个强大的“小王国”。所以,始于编程,是因为我的兴趣。

10.2.2 因为担当

选择从事软件开发,则是由感性向理性的转变。当一个人完成学业之时,就应该是开始回报于社会之时。除了要把自己在公司的工作做好之外,还应关心一下软件开发领域的成长,同时积极投入到开源社区里为编程世界贡献自己的一份力量。尤其是我国的软件开发和开源社区,为什么那么多经典的计算机书籍都出自国外,为什么那么多术语都是国外定的,为什么那么多主流开源框架都是国外的?作为龙的传人,我们也要不甘落后。

抛开大的方面不说,通过软件开发,研发出来的系统可以帮助提高人们工作效率,提升人民生活,甚至是成为日常生活中不可或缺的一部分。这是令人振奋的。因为作为技术人员,我们可以帮助到别人,创建价值。而通过开源,我们可以更好地帮助广大技术开发人员间接地快速交付有价值的项目和产品。难道这不是一件更让人振奋的事情吗?

这是一个开放的世界,历史走到今天,开源是件自然而然,并且值得去尝试的事情。

10.3 离不开的Linux

Linux是一个出色、令人振奋的操作系统。它不仅每时每刻都在运行着全球各地数不胜数的系统、服务和网站,为人们的衣、行、住、行提供帮助;还散发着古老计算机传统的味道,通过命令行式的操作,为一个个热爱编程的新手打开启蒙之门。

作为现时代的人,我们,尤其是作为技术人员,越发地发现已经不能直接或间接地离开Linux这一操作系统。

10.3.1 开源

如果回顾开源这段历史,在促进源代码开放,让开源成为现实这一过程中,Linux有着重要的影响力。可以说,当提到开源,一个不得不同时提及的词语就是:Linux。而Linux对开源的影响,或者说,对进行开源来讲,是非常深远且不容忽视。

总而言这,作为一名专业的技术开发人员,特别是一位想正式投入到开源社区的技术人员,不得不学Linux。Linux有着太多我们需要学习的东西,这些知识里不仅仅局限于理解和如何使用Linux系统本身。更重要的还有,它对开源的态度、立场和文化,以及它是如何高效地实现分布式协同开发的。

Linux本身就是一个卓越的开源系统,在它之上,又有着如春笋般的开源框架和类库,这些都是非常值得学习和参考的对象。它们的机制、它们的社区、它们的原则,都是人类宝贵的知识财富。

例如Linux系统中的最小立异原则、机制与策略分离、正效性和透明性等。

10.3.2 技术

毫无疑问,现在绝大部分的网站都运行在Linux操作系统之上,当然也不排除还有其他操作系统,如Windows。但至少在中国,很多创业团队、发展中公司,甚至大公司使用的都是免费的、有社区保障、经过时间验证的Linux系统,而不是臃肿、到处有漏洞、还要收取高昂费用的Windows系统。

当选择了Linux系统后,那么还要安装很多与之配套的软件、服务和工具。例如数据库、网站服务器、编程语言、源代码版本控制、开发环境等等。可以这样逆推来理解,最终我们的网站或者系统服务,很可能是运行在Linux系统之上,而且配套使用的软件也是运行在Linux系统上的,包括我们即要编写的代码、开发的程序和研发的系统也是运行在Linux系统上。

所以,我们的开发环境也应该是基于Linux的,在进行PHP开发时,应该尽量使用Linux环境来运行编写的代码。虽然,很多软件,特别是开源的软件也可以安装在Windows系统上,甚至还有集成环境的一键安装包。但根据经验法则,应该尽量保持开发环境和最终线上环境一致。不要线上用的是Linux,而本地开发却是Windows。因为这两者,众所周知,是存在一些微妙的差异的。例如,Windows的文件路径不区分大小写,而Linux严格区分,这会导致明明在Windows上能找到的文件到了Linux却不行了。而这些,通常都是新手会遇到或者经常会犯的错。

小结一下就是,技术上,我们依赖于Linux,并且应尽量保持开发环境也是Linux,避免一些因系统差异性和兼容性问题而产生困惑。

10.3.3 文化

由始至终,可以说,Windows面向的都是大众市场,针对的是不懂任何技术的普通用户,甚至是上了年纪的大妈也能懂得如何在Windows里打开浏览器上网看广场舞的视频。另一方面,Linux偏向的是技术人员,提供的是只有专业人士才能看得懂的终端界面,甚至连读过大学却非计算机专业的人都望而却步。

但我们和普通的用户不一样,至少我们和上了年纪的大妈不一样,我们是专业的技术开发人员,应该比别人更加懂得Linux,更何况我们每天都需要用到它。

如果细细算来,很有可能,在我们职业生涯里的几十年,都会与Linux为伍,与其打交道。如果不能很好地了解它,我们将很难与这位不爱说话的“同伴”更愉快地一起工作。但更为重要的是,Linux对我们的影响是深远的,它的文化耐人寻味,通过了解它的文化,能给我们一定的启发。

在一家沙县小吃店里吃饭,你不会期待服务有多周到,环境有多优美,或者菜式有多可口,并且旁边坐着的很多是赶时间、杂谈的其他顾客。而在一家高档的西餐厅里,你会希望有安静优雅的氛围、礼貌体贴的服务员,以及色香味俱全的菜式,,同时坐在旁边的更多是同样是注重自我形象的顾客。为什么在不同的场景下,你所期望的,以及身边的人会有着不同的反应?这是因为环境、氛围不同,由此产生的文化也就不同。

Windows是商业性的,它要以盈利为主,它要走进千家万户,甚至垄断市场。为此,它需要的是更多炫酷的可视化界面,满足更多傻瓜式的功能操作。相比于注意高效、简约,Windows更注重的是怎么让人们明白、接受并愿意掏钱去买它的系统。而使用Windows的人,则愿意忍受它的慢,它的卡,明明一个很简单的操作,却非得要等上好几秒、有时好几分钟才能处理完毕。例如,对于Git的代码提交,在Linux下,直接输入两行命令就可以:

$ git commit -a -m "演示提交"
$ git push

而在Windows下,如果要通过界面化来实现同样的效果,则步骤更为繁锁。以TortoiseGit为例,分别在先到对应的文件目录位置,右键,提交,输入“演示提交”,点击提交,最后再Push。整个过程,需要多次变化界面,移动鼠标和切换到键盘。这些重复性的手动操作是效率低下且烦人的,对于普通用户来说,他们不懂得编程,不了解算法有最短路径,也不懂得专业技术和电脑,一直忍受是可以理解的。但我们不一样,我们是专业的技术人员,应该懂得如何更高效地提高自己使用电脑的技能。

另一方面,也是最不为人察觉的,长期使用Windows系统进行开发,会造成我们在潜意识认为开发就是这样的,一直停留在Windows这个为普通用户构造的世界中,渐渐习惯于这种缓慢和冗余的步骤,而从来不想着如何从中释放出来,去创造更多的价值。

如果说Windows程序员是缓慢、思想固执的话,那么Linux程序员则是注意实效、不断优化和充满创造性的。这些差异,不是你分别看了Windows系统入门指南和《鸟哥的私房菜》后就能马上获得,而是在对应的系统上长期开发和工作后所得到的特质。而这些特质,而通过你的大脑,通过你的双手,慢慢地融入并体现在你所开发的框架上,最后传递给众人。

可视化手工操作,还是脚本自动化?

不同的工具,不同的使用方式,会潜移默化地影响我们的思维。对于非技术人员,如果长期依赖于可视化的手工操作,影响的只是他本人。但对于我们作为技术开发人员而言,如果我们所开发的框架,也是同样倾向于可视化手工操作,那么间接影响的是更多的其他开发人员。

回想一下,在Windowns上使用IDE编辑器,如Zend Studio运行单元测试时,开发人员是怎么操作的?如果你还有印象的话,肯定还记得,要点击这点击那,还要等上好一会,IDE反应过来后才能通过界面再给你反馈。再来对比一下,在Linux上是如何执行单元测试的。噢!其实只消一行代码即可。也就是路人皆知的:

$ phpunit

使用可视化进行界面操作并等上一会输出结果,和直接敲命令行立即得到输出,哪个更快速、更便捷?脚本能力还意味着可以实现自动化。当需要通过其他方式,让计算机来帮我们自动运行单元测试时,命令行的方式可轻松放在Jenkins构建任务内,又或者通过crontab的方式来定时执行。这难道不是一种提高效率,节省我们宝贵时间的方式吗?

再来考虑另外一个常见的场景。当需要为数据库分表生成创建表结构的SQL语句时,你的第一反应是怎么实现?数据库分表的SQL语句就是一堆重复类似的语句,只是表名不一样,例如10张分表:

CREATE TABLE `pa_meta_0` ( ... ... )
CREATE TABLE `pa_meta_1` ( ... ... )
CREATE TABLE `pa_meta_2` ( ... ... )
... ...
CREATE TABLE `pa_meta_9` ( ... ... )

如果习惯了使用Windowns可视化操作的话,你很可能在编辑器中进行“复制-粘贴”,然后手动一个个替换不同的数字下标。接下来呢?准备好建表的SQL语句之后呢?你又怎么导入到数据库呢?“哦,这个简单,等我打开个软件,连接一下数据为先……”。瞧,又是手工的操作。手工的操作,意味着重复性,容易出错,并且不能被很好的纪录,从而自动重现此过程。

再来对比一下,习惯Linux命令行以及脚本化的程序员,看下他们是怎么做的。一看到准备这类重复性的SQL语句,他们第一时间想到的是:编写一个脚本。这正是他们编程的乐趣,通过编程,创造一些东西,并且提高效率。最终这个脚本,可能类似这样使用:

$ phalapi-buildsqls ./Config/dbs.php meta

CREATE TABLE `pa_meta_0` ( ... ... )
CREATE TABLE `pa_meta_1` ( ... ... )
CREATE TABLE `pa_meta_2` ( ... ... )
... ...
CREATE TABLE `pa_meta_9` ( ... ... )

执行一下这个脚本,输入一些动态的参数,我们就可以自动生成所需要的SQL语句了!那么,Linux程序员又是怎么将这些SQL语句导入到数据库的呢?还是通过脚本命令。

$ phalapi-buildsqls ./Config/dbs.php meta > pa_meta.sql
$ mysql -uroot -p
mysql> source > ./pa_meta.sql

生活总是希望得到的更多。如果还需要将此数据库变更,同步到开发环境,测试环境,回归环境,预发布一次,以及线上环境,怎么办呢?把上面的命名保存到一个脚本,然后各自执行一次即可。多方便啊!

再来看一个例子。开源框架,通常情况下,而且必须提供一份优质的开发文档,以帮助开发人员进行项目开发。使用markdown格式编写源文档,然后根据不同的需要,生成HTML页面,PDF等格式是个不错的方案。那怎么把编写好的markdown文档,更新到网站给开发者查阅呢?

就PhalApi框架的开发文档而言,其生成流程如下:

图10-1 PhalApi框架的开发文档生成流程

概括来说,我需要做的事主要有:

  • 1、在本地编辑并保存markdown文件
  • 2、将markdown文件生成HTML页面
  • 3、把更新的HTML页面提交并push到Git仓库
  • 4、将Git仓库的最新代码同步更新到文档托管服务器

最后,读者就可以访问浏览更新后的HTML页面了。看起来,需要操作的步骤有点多,惯用Windows的开发者,可能会很自然地这样做:在可视化的编辑器内修改markdown文件,然后使用某个软件将刚才修改的markdown文件转换成HTMl页面,可能每次还要重复地在生成好的HTML页面手动加上网站的公共头部和尾部的代码。本地的工作暂高一段落后,再通过前面所说的步骤,又是通过“美观“的GUI工具提交到Git仓库。好了,到了这一步,快接近胜利了。但还要更新到文档托管的服务器。怎么办呢?很简单,打开某个FTP软件,将刚才的HTML页面上传到服务器即可。但是……即使不精挑刚才增量更新的内容而是全量上传HTML页面,也还是要找到本地和服务器保存HTML页面的路径。听起来就已经很复杂了。

那么,有没更简单,更傻瓜式,更自动化的方式呢?答案肯定是有的。例如我的操作流程是这样的:本地编辑保存好markdown文件后,只捎执行一个神奇的脚本,就可以帮我完成剩下全部的事情了。是不是很简单?

因为根据markdown生成html,已经有一些开源的类库可以使用,简单编写个脚本便可完成。至于同步最新HTML代码到服务器,就更简单了,只需要在服务器上配置一个crontab任务即可每隔一分钟自动同步一次。别担心计算机会讨厌这些重复性的工作,因为这正是它们最擅长的,但人类就不一定擅长,更谈不上喜欢了。有时我不禁在想,为什么那么优秀的开源框架都源中外国,很可能我们开发人员还意识到在Linux上开发的真谛。

不同的解决方案,带来的效益和影响是不同的。在沙县小吃能吃到七分熟的牛扒吗?在高档的西餐厅会看到满是油污的桌子吗? 文化,在当你走得更长远时,会发现它就是一切的基础。它不仅影响了你,还塑造了你的框架。只是你尚未察觉。

10.4 领域再细分

前面,我们简单地讲述了一些大背景,即当下这个时代,开源社区,以及Linux操作系统。这三者可以说是从属包含关系,即我们这个时代里有开源社区,开源社区里有Linux系统。但谈论这些,对于我们这些普通开发人员来说,难免比较疏远、空洞。与我们更加息息相关的,是更为细分的领域。即——

10.4.1 编程语言

编程语言的演变过程,就像“太极生两仪,两仪生四象,四象生八卦,八卦化万物”。从最开始由0和1组成的机器代码,到汇编语言,再到高级编程语言,慢慢发展到第四代编程语言,截至今天已经出现了很多各种各样的编程语言。按语言本身的特点划分,可以分为编译型语言、解释性语言和脚本语言;按应用领域划分,可以用于网站开发、大型机开发、应用程序开发、嵌入式开发等;还可以按编程范式、是否跨平台等维度进行划分。

在这么多领域,这么多编程语言中,如何选择自己的编程语言,可以说是重要的。一旦选定一门编程语言,至少会对你的工作以及参与开源社区,有着好几年的影响。

就我个人而言,编程语言没有好坏之分,只有适用与否。在Linux上,进行网站开发,如果力求快速,并且追求轻量级,可以考虑PHP。

10.4.2 开源框架

在编程语言之上,除了语言本身提供的官方函数、标准类库外,很明显让人第一时间想到的就是开源框架,当然还有其他第三方与之共生配套的工具和系统。特别对于PHP,小到有工具类、插件、微型类型,再到开发框架、应用框架、产品系统。基于PHP语言的框架、系统、平台、工具可以说数不胜数,还不算每天都在尝试造轮子的开发者正在研发中的东西。

既然选择参与开源社区,有两个好的选择,一个是提供给其他开发人员用于开发任何产品的开源框架,另一个则是提供给开发人员直接使用的应用框架,如博客、论坛、商城等。

而在这里,PhalApi选择的方向是提供一个开源框架,可用于开发任何产品系统。

10.4.3 接口框架

最后,领域细分到了框架这一层面。那么框架还可以再细分吗?明显是可以的。只要还没到达原子级别,都还可以再细分(实际上,原子也还可以再分)。PHP的开源框架,通常是运行在服务端,那么除了传统常见的网站开发,还有什么呢?

在一开始时,流行网站搭建,我们接触得最多的是怎么制作一个静态的HTML页面,并显示在电脑上。慢慢地,我们学会了使用动态语言来构建更具交互性、功能更复杂的系统,并为了提升用户体验,使用了AJAX。这时已经看到了接口的身影,但还不够明朗或者被社区所重视。直到智能手机的普及,产生了对移动App开发的巨大需求后,远程接口就变得非常有需要了。

与输出一个HTML页面不同的时,接口通常只需要返回数据即可,不需要CSS样式、Javascript脚本和HTML标签。这些数据可以是二进制流格式,也可以是JSON、XML这样的文本格式。

领域细分到这,你也许会发现,在PHP开源社区里,还没能找到一个专注于接口框架这一领域的开源框架,这是一个空白的“市场”,这是一个尚未被很好满足的荒地。

所以,我们选择了从这里开始——

10.5 PhalApi开源回顾

PhalApi自2015年正式开源以来,至今已走过了近64个时节。虽然还是一个跌跌撞撞的小孩,但秉持着对开源社区负责的态度,一直在不断演进,保持生气。作为本书的尾声,让我们再一次简单回顾一下这段有趣的历史。

10.5.1 初为人知

在开源的第一年里,PhalApi在码云平台上的关注人数,就从0增长到330多人。这源自大家对PhalApi的信任和认可,同时也离不开PhalApi开发团队每时每刻投入的时间和精力。

图10-2 PhalApi第一年的开源总结

我还记得第一个开发用户过来使用PhalApi框架时,我跟他说,”欢迎你,第一位开发者用户!“同时我也告诉他,请放心使用,因为我们会一直持续维护,并且很快就会有其他开发同学参与进来使用。事实证明,我们做到了。

在火热的开发升级过程中,我们还连忙的开发并推出了PhalApi的官网。这等于告诉世界,开源,我们是认真的。同时通过留意官网的访问情况,还可以更直接地知道有多少人对PhalApi感兴趣。最为重要的是,可以让百度和谷歌等搜索引擎收录,从而被世界各地的人都能搜索到。不知从何时开始,也许是得到了同是技术人员的认可,很早的时候,当你搜索”PHP接口框架“时,第一个跳出来的就是我们的PhalApi框架。有些开发者还打趣说,我是不是”投资“了几十万才拿到这个排名。

从那一刻开始,渐渐地,越来越多的开发人员间接或直接地知道了PhalApi开源框架。随着用户越多,我们也遇到了随之而来的问题——太多问题需要回答,并等待解决。

于是,搭建一个社区,用于沉淀知识并共享信息就日益迫切了。

10.5.2 自建社区

一开始,由于缺少服务器资源,也没有自己的域名,就打算通过现在的一些热门论坛、平台来建立一个模块,专门用于交流PhalApi的问题。但结果是可想而知的,PhalApi刚刚出来,还鲜为人知,很多大型的平台都不愿意为我们在首页建立这样的一个专区。

到后来,我们意识到,要想建立一个强大、深厚的开源社区,就必须要拥有一个属于自己的问答社区。这样的一个社区,是完全由我们自己维护、管理和控制的。它不会有任何商业的广告,也不会有太多无谓的回复,如单纯为了下载附件而需要回复“楼主辛苦了”、”写得真棒!“。从一开始,我们就希望能营造一个高质量的问答社区,用于解决开发人员、新用户的问题,同时分享知识。

最终,我们摒弃了论坛这古老的东西。因为,如今一提到论坛就让人第一时间想到的是灌水、发布小广告的地方。经过身边的同学推荐,我选择使用了WeCenter来构建自主的问答社区。截至编写本书时,问答社区外来了近400位技术用户,问题总数188个,为开发用户提供了很好的离线交流平台。

此外,问答社区还可以用于发布官方公告,如版本升级、社区活动和重要的信息内容。

10.5.3 文档,博客,视频

当使用PhalApi框架的开发用户从0到300,再翻一倍到700多人时,已经是PhalApi开源的第二个年头了。这时,用户更为多元化,并且需求也是多元化的。这些需求不仅仅体现在对框架本身的功能特性上,还体现在对通过何种途径学习PhalApi框架上。

虽然我们提供了开发文档,不断更新,调整章节结构、补充代码示例、附以贴切的图片,喵了个咪还编写了大量的博客介绍如何从新用户的角度使用PhalApi,但文档这一载体对于很多用户来说,难免过于呆板。于是乎,社区对视频教程的呼声越来越强烈。

但视频的制作成本是巨大的,不仅要录制,还要编制,还要后期处理。幸好,我们的社区也涌现了很多积极的同学,然后组建了视频录制兴趣小组。几经努力,终于在大概花费了半年时间后,我们出台了完整的视频教程,并在百度网盘、优酷、土豆等平台同步上映。在此,再一次感谢以下录制小组的同学:A西瓜妹子、听风不语、彩色的雨、Catch、喵了个咪,是你们让世界看到PhalApi的视频教程!

10.5.4 迈向2.x 全新版本

参与开源社区是件很有起的事情,但只有当你真正全身心投入其中才能感受到它的美妙。

在这短短的几年时间里,我们PhalApi开源社区做了很多事情,开始数都数不清了,如:建立实时交流的QQ群,研发走向国际的英文版并将文档翻译成英文,发起三周年文化衫派发活动,与部分开发者进行线下的交流,同步文档到W3school、看云、慕课网等平台……

在编写到这里时,也就是2017年9月2号这天,我们发布了准备了近半年的PhalApi 2.x 全新版本。PhalApi 2.x 是全新版本系列,移植自PhalApi 1.x,主要采用composer,遵循PSR-4,并支持命名空间。正如你所想的那样,这不是一个终点,而是一个起点。

PhalApi开源,依然在路上。

尾声

行文到这,已到尾声。感谢你的阅读,希望通过PhalApi以及这本电子书,可以:

一来,支撑轻量级接口项目的快速开发;
二来,阐明如何更好地进行接口开发、设计和维护;
三来,分享优秀的编程思想、实用的工具和精益求精的技艺。

以上,此致。