我的十年编程路 2016年篇

时间:2022-03-11 00:43:18

时光匆匆,2016年来了,此时的我已经工作了3年有余。过去的三年,虽有坎坷,但总体顺利,是个逐渐上升的线。

进入2016年后,我不再做那些技术探索方面的App了。部门的拳头产品——加密通信要添加IM即时消息功能,类似微信的样子,这个大功能由我来设计实现。

有了前面几年的技术积累和探索,我们在众多服务提供商中选择了容联云通讯。

就在写作这篇文章的时候,我还去容联的官网逛了一圈,发现他们现在比之前提供的能力更大更强了。站在今天的视角,当时我们用的应该只是 敏捷连接->即时通讯->IM即时通讯 的能力。再加上App本身是信息安全产品,因此并没有采用公共服务器,而是私有化部署方案。关于如何部署Server,我当然并不是很了解,直到今天其实我也不太懂,毕竟没怎么做过服务器产品。

整个2016,我都在忙这个功能模块的开发。当时想法其实特别简单,就仿着微信做就行了。功能尽可能都做出来,实在做不出来的话就算了。另外就是加上阅后即焚模式和传送任意类型的文件功能。没错,当时微信还不允许传送任意类型的文件。

虽然要求用这一两句话就能说完,但实际做起来可就复杂多了。回想那段做开发的时光,有三件事让我印象非常深刻,我慢慢说,您慢慢听。

第一个事,就是深切地感受到编程基础很重要。我记得好像是判断一条消息的状态,然后更新UI显示。就比如正在发送、发送失败、已读/未读等等。这个过程中需要判断两个消息实体是否为同一个。举个例子,比如一条消息是一个Message对象,发送的时候构建了一个这样的对象,名为textMessage,发出去了。然后Server端返回一个发送成功的回执,也是Message对象,名为textMessageReceipt。此时,就需要定位到UI上的若干Message实体中的textMessage,只有它和textMessageReceipt是对应的。相信很多人会想到比对某个或某几个成员变量,只要一致就代表它们二者指的是同一个消息。我想到的是用equals()方法,但是直接用肯定不行。于是我便重写了这个方法的实现,只比对唯一id,从而实现精准定位。类似地,还有方便Log输出的,复写toString()方法等等,我记不清太多,只记得复写了这两个。

得益于我实习期间攻读那两本Java大部头,不然我也不会有这样的思路,不会想到复写对象的方法,很可能会卡在这个需求上很久。

所以如果正在看这篇文章的你,是入行不久的朋友。或许你已经可以通过调用各种API接口实现需求,并成功做成产品,然后上线,甚至还收获了很多用户。但要警惕的是,不要骄傲自满,觉得自己很厉害。一旦这些API需要修改,或者碰到那些看似不可能的Bug,或是要进行性能调优等等,这些才是真正考验技术能力的时候。单纯很熟练地调用接口,只是“很厉害”的假象。

当然,后来这个方案又得到进一步优化。不再直接用两个对象比对,而是更新本地数据库,然后通知界面刷新。

第二个事,就是消息乱序。这个事,我印象极其深刻。不仅不好处理,而且是部门领导陪我一起改的。当时的我固执地认为是容联那边出了问题,因为我是根据时间排序显示,电脑排序的结果总不会错。再加上我存储信息的时候,就是服务器端给了我什么,我就存了什么。于是乎便不认为我有什么错,认为是网络问题,导致后面发的消息比前面发的消息,提前到达对方那里。但是部门领导还是坚持让我检查一下,认为这样的结果不合理。

我抱着十分怀疑和千方百计要证明自己的想法,用容联官方的Demo进行测试,竟然没有问题。随后便怀疑会不会是私有化部署的Server端才存在这个问题?于是还是用人家官方的Demo,设置服务器地址,再次进行测试。还真别说,依然没有问题。

这下子,我就开始迷惑了。同时,心态也变得踏实了。于是,开始脚踏实地从自己的代码中查找原因了。

其实说到底原因特别简单,我记得好像是一条消息实体里面有两个时间字段,一个是消息创建时的,也就是发送时的;另一个是状态改变,或者是其它什么操作后的时间。进行排序时,应该使用消息创建时的时间,而不能是状态改变的时间。

发现了问题,有了修改思路,到改的时候就变得轻松多了,也更有自信了。随便测试,反正再也不会乱序了。

这个事情告诉我,出了问题时,先别管那些“看上去”就是怎样的结论,首先在自己身上找原因。先问自己:“真的考虑了所有情况吗?真的都做到位了吗?真的没有一点问题了吗?”

其实,何止是编程,何止是工作。在生活中,对人对事我觉得也应该有这样的态度。有了矛盾,就算是对方做得不好,也要先在自己身上找原因,激化矛盾只能让事情变得更复杂难解。凡是矛盾,没有一方是无辜的,因为“一个巴掌拍不响”。

第三个事,就是漏收消息和来电。没错,这回不只是IM模块出问题,连之前的通话模块也出问题了。这就很奇怪,因为在之前,通话模块一直是不存在漏接的问题。

当然首先是查原因,无果。然后我们几个人有点绝望,开始回滚代码到旧版本,还是无果。部门领导也来出主意,但是依然无果。

我记得黎明前最后的黑暗,是有一天,大家都熬到很晚,差不多晚上10点,或是11点,反正我到家之后,稍事休息就过12点了。为了测试这个Bug,还把测试机带回家搞。搞到电池都快没电了,于是先跑去冲个澡,顺便给手机充电,继续测试。

但是,神奇事情就发生了,我这边就再也没有漏接过电话,也没有漏收消息。我就开始分析,我好像什么也没做,唯一的变量就是插上了充电器。一开始我无论怎么想,也不会猜到电池是问题的根源。我是抱着死马当活马医的态度,拔了充电器。然后便又开始漏消息了,电话也接不到了。这个时候,其实我就很接近事实真相了。我再次插上充电器,发现一切开始变得正常。

当时,我意识到,这个问题我就要解决了。我赶快到系统设置里,调整智能省电、添加App常驻白名单、黑屏后不自动断开Wifi等等。随后再怎么折腾,也不会漏掉消息和电话了。你看,最后的找到问题的根源,竟然是手机设置……

于是,后面便与手机厂商展开合作,将我们的App添加到默认白名单保活,这个严重的Bug就这样被解决掉了。

现在看来,这个经历告诉我两个道理:一是坚持,就像拔萝卜那样。就是很简单又很经典的一句话:“坚持就是胜利”;二是打开思路,问题的数量终归是有限的,但解决问题的方法是多样的。当局面陷入僵局时,不妨先冷静一下冲个澡,随后换个思路,也许就能找到问题的出口了。

说个题外话,也许是这段经历,让我竟然爱上了洗澡。大部分时候,洗完澡都会精神焕发,疲惫的身心又再次充了下电,比咖啡都好使。

添加IM模块,搞了一年。常规的单聊、群聊都已经实现。消息的类型除了常见的文字、图片、语音外,还支持名片、短视频、文件、定位等等。当然,这些消息内容都是经过加密处理的。

搞完这些,2016年其实就已经结束了。

另一方面,虽然工作渐渐变得饱和起来,但是我依然没有停止探索和写作。在这一年里,我开始使用Markdown写文档,用墨刀设计产品原型,注册了简书账号,开始产出内容。从当年的收件箱中,我发现我的文章不断地被加入某些技术专题,不断有新的人关注我的账号。探索GitHub Page、GitBook、Mapbox等等。也似乎是在这一年,我在CSDN认证了博客专家。

哦,对了,还有前一篇我提到的树莓派。说到树莓派,就不得不提2016年是我开始独自生活的元年。从我上面说的经历上讲,这一年过得算是充实。但很拮据。房贷+车贷,真的有压力。那段时间恰逢Uber和滴滴抢占市场,无论是乘客还是司机,给的补贴都不少。于是我也出去当司机,企图能多有一些生活补贴。

那个时候早上6点多出门,跑早高峰;下午5:30下班后就开始上班,跑晚高峰。到晚上10点后收工,周六日偶尔加班,不加班的时候偶尔也出去当司机。平均算下来,差不多7106的强度,比行业中常见的996稍微再辛苦一点点。直到有一天晚上,我准备收工,行驶在快速路高架桥上。实在太困了,就点了一下头,再回过神来,车已经偏离了一个车道。一下子我就精神了,不困了。也正是有了这一次,我就不再那么辛苦了,毕竟生命更重要。再之后好像经济上就没那么紧张了,我也就不怎么当司机了。

当时我自己住的家里,因为没多少钱置办家具,其实有一点点家徒四壁的感觉。家里只有沙发、衣柜、床是新买的。像音响,是从父母家搬过来的。再也就没有什么其它的东西了。对,电视没有,宽带也没有。我还清晰地记得我在次卧里面打电话,房间里都会有回声。我还担心对方听起来我的声音会奇怪,满屋子找合适的没有回声的地方。

不过,也正是这样的条件,让我养成了独处的习惯。正如《乌合之众》一书说述,陷入集体情绪中的人是不理智的,会盲从,使一个民族的大部分人都处于同一水平。多个个人一旦形成群体,就会出现智力下降、易于冲动和自信倍增的心理特征。所以有些时候,独立+思考往往比待在群体里,更冷静,更清晰。再加上没有短视频、游戏等等消耗我的时间,虽然看上去我做了不少事,但是事情都能安排得很有条理,做起来有条不紊。

那个时候,我主要的娱乐活动就是听音乐、看一些小说。听各种古典音乐,与那些来自几十甚至上百年前的作曲家/演奏家对话。树莓派就是当作DLNA服务器,给音响输出音频信号用的;看《三体》、《解忧杂货店》、《消失的地平线》之类的畅销小说。还特意买了刻章,每本我读过的书,都要印上“文翰藏书”四个字,表示这本书是我完整看过的。如果有一天,它从二手书市场上流转,到了某个有缘人的手里。又在某种机缘巧合下,我和那本书再度相见,那种感受,想来也是极好的吧。

2016这一年,虽然过的拮据了一些,但是精神上我很充实,很富有,养成了独立思考、不盲从、爱读书的好习惯。直到现在,我依然很怀念这一年的时光,它教会了我很多很多……