带你撸出一手好代码
程序员的江湖

小D是一名九零后程序员, 身高超过一米九, 是程序员中的长人,每一个新接触到他的同事都会为他的身高所惊骇:长这么高,当什么程序员啊,应该去打篮球

 

小D在大学里学的是C++开发,立志毕业以后做一名优秀的C++服务器程序员。 然而, 一个偶然的机会, 他接触到了PHP,他深深的被这门号称“世界上最好的编程语言”的优雅特性所吸引,那种简洁、方便与高效不是复杂到令人望而生畏的C++可以比拟的。

 

小D叛变了, 在即将毕业的当口, 全身心的投入到PHP的学习中,连毕业设计也从原定的C++项目换成了PHP项目。

 

毕业后小D如愿以偿的应聘到了一个PHP Web开发岗位,在一家游戏公司。游戏公司除了开发游戏以外, 还需要各类Web系统支撑,如官网、支付系统、游戏运营支持系统等, 小D主要开发的就是这类系统。

 

小D第一天到公司上班, 就被公司的环境和氛围吸引。 顶配电脑、高端座椅、吃不完的零食,公司业务蒸蒸日上,各种福利不错, 还开给了小D不低于大部分同学的工资。最重要的是,部门里有一班志同道合的同事,他们同样深爱着PHP,每次和同事们聊到技术相关的内容, 如各种PHP框架的优缺点、高并发应对方案、PHP在领域内的优势等话题时,就如同他乡遇故知般,有说不完的话茬。

 

小D觉得自己进入了一个新的世界,在这里,比在学校要富足很多, 精神和肉体两个层面的。 小D发誓,要为公司和PHP代码付出自己的一切,尤其是PHP,因为写PHP代码能为他实现人生意义提供源源不绝的动力。

 

小D在公司中尽自己所能发挥PHP的威力。 针对小型的简单项目,他使用简洁、轻量的CI框架实现;针对规模较大的框架他使用YII框架进行实现,因为YII框架对于面向对象的支持、功能、代码组织方面的能力要远胜过CI框架。

 

然而,小D最爱却不是它们。 小D非常痴迷高性能程序的编写, 喜欢处理高并发相关的技术问题, 因此他对Swoole框架情有独钟。

 

Swoole和传统的PHP有所不同, 传统的PHP纯粹是用来做Web程序的,程序的运行依赖于如apache、php fpm之类的Web服务器,脱离了它们的支持PHP就什么也做不了了,因此那样的PHP功能着实有限,尤其是处理高并发问题,束手束脚。

 

而Swoole却不一样,它是以PHP扩展的方式通过C语言实现的,以编写高并发PHP程序为目标被实现,它填补了PHP高并发处理能力不足的痛点。 

 

正因为这个优秀的特性, Swoole获得了小D的青睐, 小D花了很长时间去研究它,并且将传统的CI框架移植到了Swoole上面,使CI框架也有了应对高并发访问的能力。

 

通过对Swoole的研究, 小D意识到,PHP的应用终究是有终点了,只有以C语言实现PHP扩展的方式去使用PHP, 才能在服务器开发的海洋中任意的遨游。

 

小D的技术追求不知不觉的发生了变化,他决定学习C语言服务器开发,把开发出来的C程序做成PHP扩展,再通过PHP去调用自己写的C程序,这样才能真正意义上的开发出自己的高并发程序, 才有底气拍胸膛对别人说自己真正拥有处理高并发问题的能力。

 

小D把自己的想法告诉自己的上级老Z。 老Z是部门主管,因为对公司多年的贡献, 加上表现突出,已经由一名加班加到爹妈都不认识的码农跃升为管理层,告别了底层的编码生涯,负责指挥整个技术团队的运行。

 

老Z听了小D的想法后说到:“一直以来都有大量用户反馈我们做的一些Web项目存在响应速度慢的问题, 你提出用C写高性能PHP扩展的方法的却能解决这个问题。但是, 不是已经有Swoole框架能解决这类问题了吗, 我们为什么还要重复造轮子?”

 

小D听了老Z提出的质疑, 解释道:“Swoole或许是能解决我们的问题, 但是Swoole总归是别人写的框架,用起来不免会遇到一些坑,况且Swoole过于复杂,里面很多功能我们更本用不到。我想设计一套完全针对我们公司业务小而美的高性能扩展,这样遇到问题后可以自己优化而不必受制于人。 另外, 有这样一套框架不也是我们公司的财富吗?”

 

老Z听了小D的解释, 觉的有点道理, 思索了一下继续道:“嗯,那好, 你放手去做这件事情吧, 我尽量给你少安排一些工作,让你多抽点时间去设计这套框架。 如果你的想法能实现且成功应用那你对公司的贡献可就大了,到时部门副主管的位置非你莫属。”

 

得到了老Z的肯定, 小D心满意足的去规划他的PHP扩展项目了。 

 

小D在大学主修的就是C++,C语言是C++的子集,因此小D对C语言没有任何门槛。 于是小D磨刀霍霍的开始着手实现他的伟大的想法,在PHP界青史留名。

 

由于小D将大部分精力放在了PHP扩展的设计上,加上原本就人手不足,需求已经快要堆积到爆炸,运营和产品部门各种抱怨催促,研发部扩充人力已经迫在眉睫。

 

经过人事和研发经过几轮筛选,大X加入了团队,和小Z以及其他同事一同完成工作。

 

大X八五后程序员,比小D大几岁,是根在软件开发行业摸爬滚打好多年的老油条。  大X其貌不扬,浓眉大眼,一副人畜无害、忠厚老实的模样。

 

大X的技术栈非常的庞杂,PHP、Java、.Net各领域都有涉及,老Z面试他时也是看中他有很强的学习能力和对技术有着无与伦比的兴趣这两点才把他招进来的, 这是好事,因为团队找到了一个工作能力强的人,但也为原本纯净的PHP技术氛围注入了一丝的杂质,给团队起到的作用是福是祸也未可知。

 

 

大X来上班以后,很快和大家一起投入到堆积如山需求的开发中,任劳任怨, 总是冲在工作的前线。也难怪,工作积极是所有新人的共同特点, 新人的工作态度很重要,如果刚入职就很懒散,那干久了变成老油条后还了得。 所以新人工作不认真,试用期能不能过都是个问题。

 

随着工作的逐步深入,加上较强的工作能力, 大X接触到的项目也渐渐变多, 很多运行好的年的项目开始由他维护。 大X在部门的项目中发现了一个很普遍的问题, 项目的代码杂乱无章,难以维护;而且BUG百出,没有一套系统是平安无事的,每天都会有用户反馈问题, 不是数据不对就是页面报错, 很多时候还找不到问题所在,一个BUG就能折腾大半天,改完以后说不定还会带出其他的BUG,接着就是修东补西。 总而言之, 大侠每天的工作感觉最多的一种体验就是“蛋疼”

 

痛定思痛, 大X决定想办法改善这个问题。他觉得, 项目的代码难以维护很重要的一个原因是由于代码是由PHP写成的缘故。

 

PHP是动态的弱类型语言,写的时候可以各种走捷径,简洁方便到屌炸天,实现同样的功能,用Java要十行代码, 用PHP可能只需要一半都不到。 维护的时候却能要了程序员的老命, 就像大X的几个项目,很多代码静静的躺在那里,却不知道是不是除了扰人视线以外根本没有任何作用的死代码。 有句形容PHP之类动态语言的话说的很贴切:动态类型一时爽,代码重构火葬场

 

因此, 大X想使用静态类型语言开发新的项目,毕竟大多数项目不是一次性了事,项目的维护成本远要大于开发的成本,况且, PHP在性能层面也是输于主流的静态类型语言的。此外, 部门所有同事一直使用PHP,技术面接触有点窄,大X想改变这个现状。

 

大X想使用windows下的.net平台作为部门的第二技术体系, 毕竟visual studio 和 C#的组合不管在开发体验、开发效率、简介易用性等各方面都要胜过其它与之平行的技术, 这点是毋庸置疑的。

 

大X决定在部门进行推广, 他相信好东西人人都会喜欢

 

大X精心总结了.net的优势、与其它技术体系的对比、能解决部门中项目存在的问题等相关内容,还制作了一个精美的PPT, 打算在部门周会上跟大家做一次分享, 看看同事们的意见。

 

会上, 大X演示了PPT,表述了自己内心的想法,满心希望同事们能认同他的想法,并在部门中应用.net技术。 然而, 大家的反应很淡漠,似乎对大X的这个想法一点也不感兴趣。

 

小D听了大X说的内容后,觉得非常的不靠谱, 于是提出了质疑

 

“我不认同你说的这些 观点,你说的这些存在于PHP身上的问题根本不是问题,假如PHP真有这么多毛病,为什么还有这么多网站跑着PHP代码,而且这些网站中不乏一些非常知名的网站,如Facebook、新浪微博”

 

“但是我们部门的项目代码质量差PHP的却有不可推卸的责任”大X答道

 

“我认为代码质量的好差和编程语言是不相关的,反而跟写代码的人的技术水平关系非常的大”

 

“但是我们不能要求所有的程序员都能有Facebook和新浪微博的程序员的水平呀”

 

“用PHP写不出容易维护的代码, 难道用其它语言就能写的出来吗?”

 

“话虽如此,然而我觉得用同样水平的程序员,写出来的C#代码在可读性和可维护性方面觉对要胜过PHP代码。我并不是说PHP不好,我认为驾驭PHP需要更高的水平。就像开车一样,开自动挡明显在各方面要胜过开手动档,手动档更难开, 体验也更差, 这跟使用PHP和C#是一样的道理。”

 

“这个问题我想再争下去也不会有答案。我现在再问你,我们这边所有的人都不懂.Net平台技术, 假如你用.Net技术开发项目,那么这些.Net代码只有你能维护,这显然是现实的”

 

“所以我这次在会议上提议这件事情的目的就是想看看大家的想法”大X把眼光从小D身上转向其他人,继续说道:“大家对.Net技术有兴趣吗?有的话我定期分享,我家里还有很多.Net技术的书籍也可以带过来供大家翻阅、 学习”

 

说完后大X望着大家,看着每个人的反应, 然而, 良久过后也没有一个人发言或者反馈,他们玩手机的玩手机,发呆的发呆 ,既没有表示反对, 也没有表示认同。 大X知道,不认同即是反对,大家不说话只不过是不想打击自己的积极性而已。

 

大X感到一丝失望,自己的这个酝酿良久的美好愿望是没法达成了。虽然人人都知道.Net技术的优秀,可对于微软却存在根深蒂固的负面刻板印象, 尤其是在互联网公司中,这种现象更加严重。大X知道进退, 知道同事们心中的想法后, 就不打算再提这个事情,他不想成为大家眼中的异教徒,然后被拖出去祭天。

 

大X想引入新技术的想法就这么被搁置了。 所有的项目所有的需求, 依旧使用PHP开发。

 

而小D,对大X不知不觉生出了反感,大X工作和为人都没问题,但是却大肆编排小D钟爱和为之疯狂的PHP语言。 这也难怪,说自己觉得好的东西不好,那不是间接的说自己是傻逼吗,换成谁都不会乐意的。

 

然而,大X说的部门项目的问题是客观存在的,这些问题如同滚雪球般的积累,直到有一天终于爆发了。


因为公司业务的发展, 有一个网站被重点推广,网站的访问量持续增加。 而运维部门反应,这个网站非常占用服务器支援,导致该服务器持续报警,服务器百分之九十五的CPU资源都被这个网站占用,虽然这个网站访问量不小,但远没有达到占用高配服务器这么多资源的地步,这是一个不正常的现象, 网站程序肯定存在问题。 另外, 居公司运营部门反馈,有大量用户向他们吐槽,网站经常性的无法访问, 这让他们很抓狂,已经到达忍无可忍的地步,他们迫切需要技术部门解决这个问题。

 

因为这个问题, 老Z召集相关开发人员,一起讨论这个问题的解决方案, 其中小D和大X也在内。

 

 

这个网站最初的开发人员已经离职, 现在由大X负责这套系统的维护, 老Z望向大X

问道:“这个网站现在主要由你负责维护,现在网站持续出现占用服务器资源不释放和间接性无法响应问题, 你认为应该如何解决”

 

大X答道:“这跟网站是由PHP实现由很大的关系,PHP不支持多线程, 不善于处理高并发问题。我觉得应该把这个网站的核心模块用性能高的语言重写,比如说Java”,因为知道.Net不为大家所接受,大X决定改变战略,尝试推广口碑较好的Java技术。

 

大X的回答遭到了小D的强烈反对, 小D说道:“这个我不认同。诚然, PHP在性能上相对于Java的确略有不及。然而, 这个出问题的网站还有很大的优化余地,远没有达到需要Java来重写的地步。我觉得应该找出使网站占用服务器资源和无法响应的根本原因, 解决之, 而不是一言不和就重写,这是以一己喜好浪费公司资源的做法, 是最末流的解决问题的方案”

 

大X感觉除了小D话里有刺, 他不想和小D争辩, 因为在平时工作中,这样的场景出现的太多了,他不想把这种技术偏好的争辩带到这个紧要的关口, 于是他一眼不发,望向老X, 等待他来做决定。

 

老Z是部门的第一个员工,也是程序员出生, 现在部门深刻的PHP基因就是他流传下来的,虽然他现在已经不写代码了,用什么语言实现功能已经跟他半毛钱关系没有, 只要能把问题解决就可以了。 然而,使用PHP作为部门唯一开发语言的规矩毕竟是自己定下的,如果让大X用Java去重写系统, 那不是意味着承认自己当初决策失误吗。 虽然, 即便是如此, 也没有人会在意, 但是老Z还是不想看到发生这样的事情。 因此, 老X大心底里赞同小D的说法。

 

“我比较赞同小D的意见,重写系统成本太大了, 而现在这个问题需要尽快解决。所以, 还是需要如小D所说的, 把网站运行时存在的问题找出来, 解决之, 才是正确的做法。”老Z说道“小D,既然是你提出来的方案,那么这件事情就由你去做,这周把这个问题解决, 下周运营部门大推跟这个网站相关的业务,到时候网站访问量会成倍增长,你要做好准备, 别出漏子”

 

讨论结束后,小D开始着手去优化这个网站。

 

小D从运维那里了解到,服务器的资源是被运行网站的Apache进程所占,针对并发处理请求, Apache会fork出子进程来进行处理, 所以,网站的请求量一大,子进程的数量也随之增多,服务器资源就这么被无情的消耗。

 

小D决定先对Apache进行开刀,Apache是全能型Web服务器,既能处理静态资源又能执行动态程序,遗憾的是Apache做好了功能全面性的支持却忽视了性能上的问题, 在静态资源处理上nginx显然更胜一筹,在动态程序执行上也做的不如phpfpm。  于是, 小D决定使用nginx和php fpm的组合,取代原本运行网站的Apache。

 

小D制定了一系列方案,由运维去实施, 迁移网站的运行环境。 小D有很大的把握能解决这个问题,因为类似的问题不知道在技术论坛上看过多少遍, 这个解决方案屡试不爽。

 

运维装服务器软件、改配置、设置nginx反向代理等一系列工作完成之后, 网站从旧的apache下切换至新环境, 一瞬间, 服务器的资源占用迅速恢复正常,让老D抓耳挠腮多时的牛皮藓就这么痊愈了。

 

小D欢呼雀跃的把这个好消息告诉老Z,老Z狠狠的拍了拍小D的肩膀,对小D的这次解决问题的表现表示嘉许,并透露不久后就给小D加工资。 小D很开心, 这种开心不是来自于自己的收入即将增长,而是来自于解决重要问题后的那种成就感, 是一种无与伦比的高峰体验。 小D回自己工位经过大X身边时, 向大X瞄了一眼, 眼神仿佛在说:“看到没有, 这才时真正解决问题的能力”

 

很显然, 在这个问题上, 大X被打脸了, 不用重写代码,问题也能很好的被解决。但是大X并不是那种死要面子的人, 虽然在这次竞争中输给了小D,但他也么有感觉到任何不舒服,甚至隐约还感受到了一丝轻松,首先他是这个网站的主要技术负责人,网站出问题, 他的责任首当其冲, 现在问题解决了, 自然是皆大欢喜。 其次, 这个网站的代码逻辑实在太复杂, 如果真让自己去重写,他完全没有把握,使重写后网站的功能和旧网站功能保持一致并且不出BUG。 所以对于小D能解决这个问题,大X还是打心底里接受的。

 

在告知运营部门这个问题已经解决后,运营部门的同事表示非常的不可思议,这是一个反常的现象, 平时让开发处理这种大BUG, 没有十天半个月是搞不定的。

 

得知系统已经能健康运转了, 作为公司接下来重头项目的其中一环, 运营同事开始大力对网站进行营销推广,通过各种渠道打广告。

 

开始推广第一天的晚上, 小D打着哈欠,合上笔记本电脑,准备休息, 因为已经是凌晨2点了。他的PHP C扩展开发已经接近尾声,合上电脑之前他刚写完了最后一行核心代码,接下来就是测试运行, 找出程序的缺陷并改进,应该说程序最艰难的部分已经开发完成,胜利的目标已经在不远处,只需稍微努力下,就能到达目的地了。

 

然而, 小D刚关灯躺下,电话的铃声突兀的想起, 以前这点个点, 小D的电话从未响过。 小D诧异的拿起手机, 接通电话,并且礼貌的说了声你好。 然而, 电话那头却响起了一个愤怒的声音:“你他吗快给我来公司, 立刻, 马上”,  小D辨认出是老Z的声音, 他意识到可能是自己写的程序出BUG了,而且很严重。

 

“出了什么事情吗?”小D问

 

“你先来公司再说”说完, 老Z啪的一声挂掉电话。

 

小D对这电话那头呜呜的电话挂断后的响声, 一脸懵逼,但是他意识到, 自己肯定捅了大漏子了。

 

小D匆忙的穿好衣服,用滴滴叫了taxi, 打车来到公司。办公室灯火通明, 几个同事三三两两坐在工位上, 其中包括老Z和大X。

 

老Z黑着脸, 看到小D到了, 没好气的说道:“你不是信誓旦旦的跟我说那个网站已经优化成功了吗? 怎么先在又出问题了”

 

“出什么问题了? ”小D不解的问道, 因为小D觉得,优化的工作已经做的很好的, 网站又出问题了实在是出乎自己的意料

 

“今天运营部大推,花重金在许多知名平台投放了广告,但是有大量用户反馈, 通过点击广告跳道我们的网站时, 网站出现无法访问的现象,而且是大面积的 ”老Z愤怒答道“你知道这意味着什么吗? 这意味着公司这次的项目大推失败了, 这不但扰乱的公司的运营计划, 砸出去的钱还都打了水漂, 这都是因为你说网站已经优化好了, 但事实根本没有。 现在按照公司的损失来看,整个部门都需要背锅了,接下来所有人都没有好日子过, 这都是你的责任”

 

小D被老Z的话噎的呆在原地说不出话来, 小D意识到原来出的问题比自己想象中的严重太多。

 

老Z继续说道:“现在大家有什么方法能迅速解决这个问题的”

 

然而,办公室力一片鸦雀无声,似乎谁也没有办法。 老Z这个时候快要抓狂了,刚才运营总监脸色非常难看的来找他,嘴里还骂着娘,勒令他快速修复这个问题, 如果修复不了, 也要明确通知他们,他们需要及时调整运营方案。

 

这时候坐在角落力的大X说话了:“我刚才查看了服务器日志, 出现性能的瓶颈在数据库访问上,因为访问量大, 数据库访问堵塞, 许多数据库连接无法响应。刚才DBA还质问我,为什么我们的程序把他的数据库搞死了”

 

“那怎么解决?”老Z急切的问道

 

“短时间内肯定没有办法解决, 现在我们的程序并没有使用数据库连接池机制,创建和销毁连接太频繁才把数据库拖死的” 大X说道

 

“那赶紧让程序支持连接池机制啊”

 

“这个没有办法, 因为PHP本身的机制不支持”

 

老Z下意识的明白过来, 自己怎么问出这么不专业的问题, 真的是急的智商都下降了。 当项目写下第一行代码时,底层的机制就定死了, 除非大规模改动代码。现在这个项目的代码已经杂乱无章了, 底层的机制哪能所改就改。

 

“那现在最有效果的解决方案是什么?” 老Z继续说到

 

“先让运营部门停止推广, 降低公司损失。 至于问题的修复, 得从根本着手, 我得意见是, 用Java重写核心模块, 至于其他不那么重要得功能, 让它自生自灭,不管了。这个过程大约需要三天左右时间, 三天后, 问题可以解决, 运营可以再一次开始推广” 大X贼心不死, 铁了心的要用非PHP技术

 

听了大X的方案, 小D说话了:“为什么你非要重写重写的,你就不能想象办法优化现有的代码吗? PHP没有这么不堪,人家Facebook、微博这个规模的访问量都支持的住, 何况是我们”

 

听了小D的话, 大X没什么反应,老Z却发火了:“你给我闭嘴,你这么有本事,为什么还会出这么大漏子, 现在你去干好自己的事情,不要再插手这件事了, 一切都让大X去负责”

 

听了老Z的话, 小D气呼呼的走向自己的工位

 

其实吧, 小D这次是挺冤的, 他其实并不是没有能力解决好这件事情, 只是被这个网站的妖孽的问题给蒙蔽了判断力。 之前网站存在两个问题, 第一是占用大量服务器资源, 第二是间接性抽风无法访问。 通常情况下,程序员都会把这两个问题关联到一起, 认为是服务器资源占用太高才导致网站无法访问的, 所以, 只要解决服务器资源占用问题, 网站偶尔无法响应的问题也就迎刃而解了。 然而,事实上这两个问题没有因果关系, 应该分开来处理他们。 小D就是因此而掉坑里的。

 

现在这么一档子问题一出, 不但之前解决问题后的成就感瞬间全无, 说好的加薪也没有希望了, 小D沮丧之极, 一脚踢向自己的椅子, 嘴里顺势骂出一句:他妈的。

办公室里谁都看出来了, 小D很不开心

 

而老Z采纳了大X的方案, 用Java重写程序核心模块。 发生这中不幸的事故, 已经令他无法顾及当初自己为部门制定使用PHP技术栈而现在却承认自己选择有误不得不使用非PHP的技术来解决问题而产生的没面子的感觉, 只要能把问题解决,其他什么都不重要了。

 

确定方案后,老Z就去和公司高层汇报情况, 并处理一些善后的事宜。

 

大X开始优化重写网站, 虽然只是部分模块,但是三天时间还是很紧张。 但是既然已经下了军令状,那就只能提着脑袋上了。

 

大X从三个层面进行优化, 第一, 使用数据库连接池机制, 复用数据库连接,减少网络开销; 第二, 使用多线程机制并行查询数据库,因为之前的数据库查询都是串行的,这会增加响应时间;第三,优化代码逻辑,降低算法最坏时间复杂度,减少代码执行时间, 并使用缓存技术,保存重复查询的数据。

 

三天时间, 大X吃住全在办公室,累了趴在桌上睡会, 醒了对着电脑敲代码, 饿了叫外卖, 不分昼夜的工作。 有同事看着实在不忍心,怕他身体撑不住, 毕竟干IT的猝死也是常有的事情 ,所以劝大X回家好好睡一觉。大X只是淡然一笑,感谢同事的好意,三天嘛,撑一撑就过去了, 大X最守的就是诺言, 他讨厌说话不算话的人。

 

三天过后, 大X如约的完成了任务。  他将新的Java项目部署上线,并使用nginx将旧的链接反向代理到新的服务上。 测试一切正常后, 上线。 大X对于这次优化很有信心,他最大限度的优化了代码的各方各面,还起了好多的相同的服务,做了负载均衡。对于这次优化, 大X可以很有自信的说:我以自己的职业生涯担保,假如网站继续出问题, 他就退出互联网行业, 从此不写一行代码。

 

大X没有让公司所有同事失望, 优化有的网站上线后,没有再出现过问题, 包括再运营部门再一次大推的时候。

 

大X通过了自己的表现,证明部门引入Java技术是有充分理由的, 至少能处理一些极端问题,如不久前面对到的让所有人焦头烂额的问题。

 

当大X再一次表示要引入Java技术作为部门的除PHP以外的开发语言并且希望其他同事一起学习使用时, 老Z首先表示出支持的态度

 

老Z说道:“我们大家活在自己世界里太久了, 让我们跟不上技术发展的趋势,导致了出现令公司损失惨重的严重问题。通过这次教训, 我们应该认识道自身问题的所在,不能学了PHP就一招鲜吃遍天, 我们要突破自身的舒适区, 去学习接触一些陌生的知识与技术,以应对将来公司更加复杂的业务。此外, 这对自身的职业发展也是一件非常有意义的事,我们要加油、努力、更上一层楼,。 谢谢大家,我说完了”

 

老Z一番慷慨激昂的讲话,狠狠地击中了在场每个人的心, 场下掌声经久不息。 大X感叹:“不愧是老大, 说话就是有感染力”

 

然而, 大X内心却有一种鄙视自己的感觉, 觉得自己太卑鄙了。其实,想使用Java完全是因为自己的一己之好, 能为部门带来好处, 那只是附加的价值而已。大X非常讨厌PHP, 至于为什么讨厌, 他自己也说不上来, 就像喜欢一个女孩,问为什么喜欢, 估计也很少有人说的上来。 那个网站的优化, 其实用PHP也可以,使用Java是大X想推广Java的策略而已。

 

经过老Z的助力, 大X推广Java很顺利, 很多同事开始使用Java写项目,虽然Java和PHP是两种不同的语言, 但是编程技能殊途同归, 经验丰富的程序员, 从一种编程语言过渡到另一种编程语并不是一件艰难的事情。

 

渐渐的, 部门所有的项目都开始用Java实现, 甚至一些旧的PHP项目也开始用Java重写, 这预示着部门的技术栈已经由PHP向Java过度了。

 

然而, 有一个人却坚持着使用PHP, 他就是小D。小D的PHP 高性能C扩展已经完全实现,测试数据显示, 在性能方面完胜Java。 可这个扩展对于部门已经没有意义, 因为现在部门使用的技术已经是Java主导了。 虽然这个扩展性能强劲, 但是,那又怎么样呢,Java性能足够好了, 这个扩展充其量也只是锦上添花。

 

小D觉得现在部门的基因已经变了, 变的让自己觉得陌生,甚至于所有的同事都很陌生, 大家都在写Java, 只有自己写PHP ,这让小D觉得自己很另类,小D无法忍受这种,和团队其他同事格格不入的感觉,他觉得自己已经不属于这个团队

 

于是, 小D决定辞职, 他把毕业以后的所有青春奉献给了公司, 放弃了外面的花花世界。 但是, 现在,小D累了。 累,小D并不怕,再苦再累, 只要能做自己喜欢是事, 那又算的了什么呢。 小D要走,是因为痛,痛到无法呼吸, 因为公司的一切, 让小D觉得陌生,这个世界上最可怕的一种感觉就是, 从熟悉变为陌生的感觉。小D确定, 是时候该跟公司诀别了。

 

对于小D的离职, 老Z没有挽留,因为小D有更好的发展, 老Z还是支持的。 为了公司的利益, 老Z应该挽留小D,然而, 老Z往往会把同事的利益至于公司的利益之上, 因此,老Z支持小D去外面发展, 这对小D有好处。

 

提出离职后交接工作的日子很轻松,这让小D有点无所适从,小D不想让自己闲下来浪费青春, 于是开始深入研究C语言服务器技术。

 

正当小D以两耳不闻窗外事一心只读圣贤书的状态研究技术准备撤退时,大X那边的项目却出了大问题。

 

最近, 大X负责开发一个即时对战游戏的服务器,这个游戏是公司的重点项目, 大X和其他同事花了无数精力在上面。现在, 游戏的第一个版本上线了,在测试阶段却出现了一个令所有人琢磨不透的BUG。对战游戏开始后,没隔一段时间就会出现卡顿。 起初, 大X以为是网络不畅问题引起的,重点排查网络问题,然而从开发到运维, 所以技术人员费劲九牛二虎之力没有找到是网络出现问题的证据。 于是,他们把游戏在内网也部署了一套,然后大家开始组队测试。 然而, 令人意外的是, 在内网,卡顿现象依旧, 所以,是网络作怪的嫌疑被排除了。

 

之后, 大X和同事们开始排查程序问题,但是, 翻来覆去的看代码,打断点调试,也没有发现程序代码上有问题。

 

为了这个BUG, 一帮人加班加点好几天, 可是却一点进展也没有, 所有人都被这个BUG击败了,他们的情绪已经处于崩溃的边缘。然而, 如果是其它BUG也就算了, 这个BUG却必须解决之。 这个游戏的核心就是对战,但是玩游戏的时候打着打着卡一下,打着打着卡一下,谁受的了,玩家玩两盘直接就把游戏给卸了。

 

所以, 大X只要还有最后一口气在也要把这个BUG给揪出来。

 

正当大写被这个问题折磨的精疲力竭葛优躺在椅子上休息的时候, 突然一串单词在大X的脑海里闪过

 

stop the world

 

这是Java虚拟机的一个特性, 在Java虚拟机进行垃圾收集的时候,所有在运行中的进程都会被迫挂起, 当垃圾收集结束时才恢复。 这个过程可以是几毫秒、几秒甚至几十秒, 视Java堆的大小而定。

 

大X确定, 就是这个机制导致游戏卡顿的。 游戏在运行的时候,Java冷不丁就来一次STW, 然后所有代码停止运行, 不卡才怪呢。 而游戏, 最忌讳的就是卡顿。

 

怎么办, 大X懵逼了。 这他妈根本不是个BUG, 而是Java虚拟机的特性, 如何修复? 这简直就是无解啊。

 

大X从来没有感觉到如此无助和丧气过。

 

大X天赋异禀, 自学成才,出道以后, 没有碰到过自己搞不定的问题,然而这一次,大X绝望了, 对于这个问题它束手无策。 唯一的办法就是不使用Java虚拟机, 但是, 不使用Java虚拟机, 程序又怎么运行呢? 这是个悖论。

 

究其原因, 当初开发程序使, 大X就选错了技术栈, 这类对实时性要求极高的程序根本就不能使用Java开发, 然而大X当初没有意识到, 等到意识到了, 已经为时已晚, 程序已经病入膏肓,药石难医。

 

大X把这个噩耗告诉了老Z,老Z不抽烟, 这个时候也点了一根, 皱着眉头思索着。 突然, 老Z脑中灵感一闪, 想到了即将离职的小D。小D在开发PHP扩展的时候,积累了丰富的C语言经验, 让它把用C语言重写游戏的战斗服务器, 问题不久迎刃而解了。

 

 C语言是老古董级别的语言, 没有垃圾回收机制, 必须手动释放内存。 对于安全性和开发效率而言, 这是个大问题,但是对于开发实时性非常高的程序, 这是必不可缺的特性。 因此, C语言经常被应用于高性能程序开发的场景。 即时对战游戏的战斗服务器, 也最适和用C编写, 可是之前大X却不知道。

 

想到点子后, 老Z从椅子上蹦了起来, 飞奔向小D的工位。 小D正在坐位上调试自己的C程序,看到老Z风风火火的站在自己面前,小D的眼神透露着疑问。

 

老Z把来龙去脉跟小D讲说了一遍,希望小D能帮忙完成这个事关生死的重要任务。

 

面对老Z恳切的眼神, 小D说道:“我三天后就要去新公司上班了,怎么可能有时间帮你们写完这个程序, 这可是三个月的工作量啊”

 

老Z眼泪都流了下来,就差跪在了小D面前, 抓住小D的手说道:“你一定要帮帮我们,一定要帮帮我们,这里可是你曾经的家啊, 现在你的家人有难, 你难到忍心袖手旁观吗? 要不你别离职了, 好不好, 我要求人事给你加工资”

 

“那不行, 我已经答应新公司,三天后去上班了,我不能放人家鸽子的” 小D急忙说道, “要不你们去招个C程序员来帮你们解决这个问题吧”

 

“临时抱佛脚招人肯定不行的, 这个项目是急着上的, 记者发布会都开了, 箭已经到了弦上,不得不发了呀” 老Z痛心疾首的说到

 

此时, 小D陷入了两难的境地, 一遍涉及诚信问题, 而另一边有是有着知遇之恩的旧领导的恳求, “这可如何是好啊” 小D纠结了

 

突然间, 小D脑海中出现一个疯狂的想法,“也许我有办法在三天内完成这个程序” 小D自言自语说到

 

本来这只是小D无意识间说的一句话,在老Z听来却向一根救命稻一样,死命要抓住, 老Z两眼泛光,那种眼神犹如色狼见美女一般, 恨不得一口吞了。 

 

听到小D的话,老Z急切的说:“真的吗? 你说的是真的吗? 哦, 这真是太好了,你不要骗我, 我最近被检查出了高血压,受不得刺激的”

 

这下小D真的是骑虎难下了, 老Z是出了名的死缠烂打, 被他抓住把柄,非说脱你一层皮不可。于是就答应了老Z的要求,尝试着用三天时间去写这个程序。 小D答应老Z的请求是有原因的, 一来, 他不想在和老Z做口舌之争, 小D知道自己不是他的对手; 二来, 小D想挑战一下自己, 看看能不能完全这个常人眼中难于登天的任务。

 

至于老Z他也知道小D不可能在三天内完成任务的,但是管他呢,只要现在能答应, 到时候通过自己的三寸不烂之舌, 肯定有办法让他留下来,这叫做登门槛现象, 那些个只会写代码的屌丝不会懂,我能做他们老大是有原因的。

 

小D的方案很奇特, 他压根就没打算重写战斗服务器的Java代码, 花三天时间完成别人做了三个月的任务,这简直就是开国际玩笑。他决定使用另外一种非常冷门的技巧。

 

小D曾经写过一个PHP代码转C代码的编译器, 如果实现一个Java代码转C代码的编译器,那这个问题不就迎刃而解了吗。这三天时间他要做的就是这个事情。

 

但要在三天时间开发一个Java转C的编译器,  跟天方夜谭没有差别。 然而,小D可以复用PHP转C的编译器的一部分代码。

 

小D的编译器的实现有以下几个步骤组成。 词法分析、语法分析、语义分析、C代码生成、C代码优化

 

其中前三步是编译器前端,后两步是编译器后端,从技术的角度来看, 前端很简单, 后端非常复杂。 小D的PHP转C编译器已经实现了所有的功能。他现在有做的只需要实现一棵抽象语法树, 挂到之前的PHP编译器上,C代码就自动会生成了。 换言之, 小D只需要完成上面五步中的前两步词法分析、语法分析即可。

 

只实现Java代码的词法分析和语法分析, 这就比较轻松了, 小D一秒钟也不想浪费,老Z一走就开始编写程序。

 

小D其实是懂Java的, 而且还学的不错。 但他就是喜欢用PHP, 就算部门其他同事用Java, 他明明会Java也不跟随, 问为什么,没人知道, 牛B的程序员总有那么些常人难以琢磨的个性, 不然怎么配得上牛B二字。

 

小D没有打算手写Parser(语法分析器), Java语法元素太庞杂了,  为每一个元素手写递归下降分析, 三天不一定完的成。他打算用第三方的Parser生成工具做这件事情,如Yacc。

 

小D开始整理各种Java语法元素, 并转换成相应的Parser生成器配置, 供生成器生成抽象语法树。

 

小D不眠不休的开始工作, 吃住都在公司, 如同之前大X解决那个让小D产生了心理阴影的BUG一样。

 

老Z时不时的来慰问一下小D, 带点吃的,嘘寒问暖, 顺便了解以下进度。 但是,小D知道,老Z主要还是来了解进度的, 其他的都是附带。

 

在实现Parser的过程中, 小D在心里把大X骂了个狗血淋头,大X使用的Java8的语法特性编写程序, 这给小D实现Parser 带来很多无谓的工作量,这些时间小D原本可以多休息一会的。

 

两天后, Java代码的抽象语法树制作完成,小D把语法树挂到之前的PHP编译器上,编译、运行, 通过, Java转C代码编译器顺利完成。

 

接下来的工作相对轻松,小D从大X那里拿来游戏战斗服务器的代码,运行编译器进行转换, 只花了十秒钟, 就把大X写了三个月的Java程序统统转成了C程序代码。

 

转换完成后,小D开始调试运行C代码,处理一些编译器处理的不完善的代码。 两天不到的时间, 小D神奇的完成这项不可思议的工作。当小D宣布他已经实现了所有功能以后, 整个办公司的人都惊呆了,他们不敢相信这个事实, 难道小D真的图灵祖师爷附体了吗

 

老Z得到这个消息以后, 激动到无以复加,他单腿跪在小D面前, 保住小D一米九身材独有的粗壮大腿, 一把鼻涕一把泪,感动到热泪盈眶。

 

在测试环境下模拟了几轮比赛确定程序没有问题以后, 就开始正式替换正式环境下的原来由Java写成的战斗服务器程序了。

 

运维、开发、测试、策划、美术、运营、事业部总经理统统到场, 一起见证这神圣的时刻。

 

正式切换开始前十分钟, 他们杀掉了一个程序员祭天, 鲜血染红了运维的键盘。

 

运维在血淋林的键盘烧敲下执行替换脚本的命令, 一条条白色的命令执行结果在黑色的屏幕上滚动,几秒钟之后,  屏幕上跳出了, Program started successfully, 0 error 的字样以后,现场一片欢呼雀跃。

 

此时, 办公室窗外天边已经微微泛白,还有三小时, 小D就要去新公司报到了。

 

小D满脸胡渣,双眼挂着两个浓浓的黑眼圈, 憔悴到令人心痛。 

 

一帮人送小D到办公司大楼门口,和小D拥抱诀别后, 目送着小D高大的背影, 消失在苍茫的夜色之中。 每个人脸上都刮着一丝伤感,内心感受着浓烈的凄凉,他们都默默的为小D许愿, 希望他在新的环境不断成长,最终成为他心中那个理想的自己:拍黄片的程序员


注:小D是我的同事,大X即作者本人,老Z是我和小D的上级

作者:陈大侠
日期:2017-10-20

留言(0条)

我要发表留言

您的大名 选填
电子邮箱 选填

欢迎关注微信公众号 「带你撸出一手好代码」

首页    GitHub 知乎 豆瓣 博客园