“传统是什么?传统是一种气质,一种性格。这种气质和性格往往是这支部队创建时,首任军事首长的性格和气质决定的 ,他给这支部队注入了灵魂。从此,不管岁月流逝,人员更迭,这支部队灵魂永在。”
——《亮剑》
我决定对自己过去五年来的人生经历做一次简单的总结。一方面,是为了通过回忆过去,重新审视自己过去做的好与不好的地方;另一方面也是为了通过总结经验教训,重新展望未来,给未来的自己定一个努力的方向。这篇文章会按照时间顺序,从工作、学习和锻炼三个主题徐徐展开,以从三个不同的角度去回顾属于我个人的精神成长史。通过回忆,搞清楚什么是应该坚持的?什么是应该摒弃的?什么是做的好的?什么是做的不好的?留下一些思考,让自己不迷茫。不忘初心,方能继续前行。
一. 勤奋工作
1.1 成为游戏程序员
时钟拨回到2014年,那年我在YY已经工作了差不多两年了。我是2013年年初参加工作的,研究生毕业后费了一些功夫,拿到了YY的offer,只身一人来到了美丽的大广州,开始我从事C++后台开发的程序员工作。印象深刻的是我作为后端程序员第一次和公司其他同事联调接口,遇到一个问题搞了两天才解决。对方认为问题出在我这边,我自己也认为作为新手,肯定是我有什么地方写的不对,但最后发现是对方有个小地方写错了。工作流程一般来说就是定协议、写接口、写各种增删改查最后联调。几个月之后我就发现自己在这方面已经成了熟练工了,也接触了公司几个项目,但感觉在技术上进步不大,总觉得哪里不对,但又说不上来有什么不对。第二年我转去部门内部的数据组,专门给公司的产品运营做各种报表数据的清洗和整理工作,供产品运营的同事做各种各样有关直播数据的营收分析和指标分析,统计各种各样的日数据、周数据和月数据等等。当时因为对SQL不熟练,很多复杂的数据分析需求自己还写不出来,特别是表的连接操作搞的我一头雾水,要不断的请教其他同事,但自己始终没有深入的掌握相关技术。有一次因为帮公司一位同事处理贵州地区的行业通信备案书,一来二去就算是认识了,又通过她认识了另外一些同事,其中有一位也在YY工作的同事 ,她是我贵阳一中的学姐。通过和她沟通 我了解到要练技术,还是要去开发一些“强实时交互”的应用,比如到游戏公司工作,处理一些复杂的业务场景,自己的技术才有可能有所突破。于是我在那一年有了跳槽的想法,又通过猎头的介绍和面试,找到了一家在杭州的游戏公司,叫电魂网络,就离职跳槽到杭州去工作了。
其实回过头来看自己当初的迷茫,天天写业务代码,并不是不能得到技术上的进步。关键是自己有没有深入理解自己所从事的业务,有没有利用工作机会深入钻研公司的代码。比如支付系统是如何工作的?业务数据分析的指标有哪些?怎样用SQL写出复杂的数据分析代码?有没有跳出自己那一亩三分地,去下功夫研究和了解别的同事负责的部分,了解整个业务的全貌,主动承担更多工作?可惜的是当时自己并没有意识到这些问题,把这样一些宝贵的机会白白浪费了,这是我做的不好的地方。做的好的地方,是我那个时候已经意识到学习的重要性了。刚去广州的时候,我还下了班买菜做饭,然后边吃饭边玩电脑,懒懒散散,丝毫没有觉得这有什么不对。但心里总有一丝不安,觉得自己应该做点什么,而不是仅满足于工作上接触的那些东西。于是猛然警醒,下班回家和周末不太忙的时候,我都会抽时间看书,学习Coursera上吴恩达的机器学习课程,自学Python语言和Go语言,并偷偷的用在工作中,帮自己解决了一些小问题。对算法进行研究,我将所有的排序算法梳理了一遍,总结了一篇《排序算法》的文章,然后用Go语言实现了go_rng的伪随机数生成器的库,可以用来生成满足各种概率分布的伪随机数,这个小项目我放到了Github上,后来被一个美国程序员发现并对代码结构进行整理,另一位日本程序员也参与了开发,为这个小项目增加了生成“狄利克雷分布”随机数的功能。我还把过去自己写的一篇研究红黑树的文章用Go重写了一遍,并写出了《Go语言与红黑树》一文。那个时候Go语言还是个小众语言,但我从那个时候开始就对它非常有好感了。
2014年告别了广州,2015年我飞到了杭州,开始我的第二份工作:做梦三国手游的Java服务端开发。从喧嚣热闹的广州,来到杭州比较“安静”的滨江区,又是一次谁都不认识的重新开始。刚去的那几天人生地不熟,很不适应,心里很难受,觉得很孤独。公司提供免费住三个月的集体宿舍,但屋里没人的时候静的连一根针掉在地上都能听见。几天之后我果断在钱塘江边租了一个隔成很多个小单间的房子搬了出去。在窗边就能看到钱塘江大桥,算是“江景房”吧。奇妙的是这里居然是我爸当年当兵驻守过的地方,他们空军高炮八师就是负责守卫这座桥的。刚到公司的第一天,项目主程序员(我们都叫他“大哥”)就扔给我一套手游服务器的后端代码,让我一个星期内看懂每行代码的作用。第一周上班,我没有什么别的工作,就是读代码,遇到不懂的地方就去找大哥请教问题。一周的时间我就把代码基本看懂了,特别是看懂TCP网络编程与并发多线程是怎样有机结合在一起构成整个长连接服务的底层引擎的。读代码期间还发现了几个bug报告给了大哥,大哥感觉我学习能力还不错,就陆陆续续安排了几个子系统的开发工作让我做。一开始我参与的是登录服务器的业务逻辑开发,后来又负责开发游戏中的扭蛋系统,用金币或者元宝等虚拟货币抽游戏装备。再后来则是负责PVP服务器的战场匹配,用的是微软的TrueSkill算法——用“平均值+方差”二元组代表每个用户的技战术水平,然后尽量将相同水平的用户匹配到一个房间中进行对战。
在杭州从事游戏开发,第一个感觉就是辛苦!印象最深的是那个时候整个公司都分为不同的游戏开发小组,开始公司内的内部创业,谁的游戏卖座,谁就能获得更多的公司资源。别的小组有些游戏还没上线项目就倒下了,全员遣散;有的游戏上线了但不挣钱,就裁掉了大部分成员,只保留几个人维持游戏的运营,竞争相当激烈。我只记得那段时间大家经常通宵加班,情绪都很差,经常互相发脾气。好几次我躺在椅子上睡着了,到了后半夜测试测出了bug,我又被叫醒起来改代码,改完测试继续测,我又躺在椅子上睡觉,一直到大哥过来拍拍我的肩膀,跟我说没事了可以撤了,我才下班,这个时候一般都是早上五六点了。走在路上正好赶上早上五点包子店开张了,买个包子回去睡一觉到下午又过来上班,然后又是一个通宵。晚上能十点下班都算早的了,一般都要到凌晨一两点,周六一般也是要加班的,遇到急着发版本的时候周日也要加班。我后来统计过,我们组奋战了8个月,这8个月的时间内通宵加班就有26次,有3次连续通宵了3天,有2次连续通宵了2天。
虽然很累,但在杭州的那一年却是我技术上突飞猛进的一年。有一次晚上八点大哥给我打电话说摊上大事了,我写的匹配算法才上线半小时玩家们就全都卡死了,我急急忙忙打车赶回去,大哥早就在公司等我了。和大哥两个人在公司枯坐了一夜。大哥一行一行的检查我的代码,每发现一个问题就说我一次,一直持续到第二天早上,修复了“一吨”的bug,把代码更新上线,才把问题全部修复完。这是我参加工作以来被“批”的最惨的一次,但我很感谢他。在大哥严厉“批评”下,我几乎是一夜之间彻底明白了并发多线程的原理,这是我学生时代看了无数遍的书都没看懂的。看来亲身经历一次,之前看的无数遍书才能融会贯通。
大哥几乎是手把手的教我各种各样的操作,把Java玩出花来了。手游为了防止用户昵称出现关键字,会用被称为AC自动机的算法过滤敏感词。大哥扔了一个库给我让我实现游戏的昵称过滤功能,但我吸取了过去的教训,并没有止步于此,我在完成工作后花了一番功夫研究AC自动机的原理,然后研究了别人的Python实现,自己又用Go语言写了一个简单的版本。后来,一次偶然的机会我发现这个库有bug,有些敏感词中间加个标点符号就能成功绕过检查,没有成功过滤。于是我研究大哥给我的代码,成功地从中发现了bug并修复,后来我问他这个库是谁写的,大哥不好意思的说是他自己写的。但是过了几天临近上线做测试的时候大哥发现我修复的代码又引入了另一个bug,导致线上故障,他又把我的代码又修复了一遍,这个问题才算最终解决。我就是在这样与大哥“相爱相杀”的过程中弥补了很多技术上的不足。
什么样的Leader是好Leader?我觉得包含两个基本要素,一是自己本身“技术超群”;二是能够对下属“耐心指导”。我在认识大哥之前就曾经遇到过一些故作高深但实际上胸无点墨的领导,你请教他问题,他只会用“花钱请你来是让你解决问题的”这样的话来吓唬你,这种人就是那种爱刷存在感的“装逼犯”,没有多少真材实料。不要被这种人吓倒,对其敬而远之就好了。如果自己有一天成为了Leader,也绝不要做这样的人。该怎么做,大哥给了我很好的榜样示范作用。我非常感激他对我的指导,虽然我在这家公司干的时间不长,但我后来我所有的努力学习和刻苦钻研,都是在向他致敬。
1.2 走遍杭州的山山水水
“天堂有雨无翠色,神仙披蓑泛苏州”。因为研究生在苏州度过了一段让人难忘的时光,所以我爱屋及乌的喜欢上了杭州。杭州是个美丽的城市,我见过凌晨四五点时她的样子,也把杭州四季的景色深深的印在了脑海里。不忙的时候,我会跑到钱塘江边跑步,看别人在江里钓鱼,和开着环卫车的司机师傅打招呼问好。周末我会一大早起来,吃一碗加了鸡蛋的葱油面,挎个小挎包,带上公司加班发的饼干和一瓶水,出发去徒步,用脚丈量杭州。冬天我会趁着下大雪出去踏雪赏雪景。杭州有点堵车,我就索性不坐车,全程徒步,早上七八点从住的地方出来,晚上七八点再走回家。沿着钱塘江走到钱江一桥,一边欣赏江景,一边往桥的另一边走,遇到下雨天还要带一把伞,免得被桥上疾驰而过的车辆溅一脸,不过好些个看到我路过的司机都会放慢车速。六和塔就在江边上,“六合听涛”的雅名就是这么来的,我去过两次。过了桥一直走,可以到灵隐寺和飞来峰,可以爬北高峰和五云山,还可以到龙井村一游,那里漫山遍野都是茶田,家家户户都是两层小洋楼,生活很富足。虎跑寺就在杭州动物园旁边,寺内有一尊惟妙惟肖的老虎雕像,我爸20世纪70年代在杭州当兵时曾经拍过一张照片,40年后我也学着他的样子拍了一张一模一样的照片,很有意思。
爬山爬累了,就去西湖边上逛逛,走走苏堤。断桥残雪、花港观鱼、柳浪闻莺和雷峰塔我都去了好几次,晚上的景色尤其优美,可以去湖边的集贤亭坐坐。玉皇山据说是杭州赏月最好的地方,山下有一块田是按照八卦的样子布局的,叫八卦田,我那次爬玉皇山到了饭点就在山脚下随便找了一家馆子吃饭,正好遇到饭馆老板娘过生日,人家还送了我一块蛋糕。杭州有个地方叫满觉陇村,是西湖边上著名的赏桂胜地,别称“满陇桂雨”,每年到了八月满村桂花香,清代张云敖有绝句《品桂》云:
西湖八月足清游,
何处香通鼻观幽?
满觉陇旁金粟遍,
天风吹堕万山秋。
除了这些景色,岳王庙和于谦祠也是我经常去瞻仰的地方。岳王庙人气要旺一些,于谦祠就少有游人去了,可能只有读过《明朝那些事儿》知道北京保卫战这段历史故事的,才会去拜访吧。后来与岳少保、于少保并称“西湖三杰”的张苍水先生,也曾提笔写下“日月双悬于氏墓,乾坤半壁岳家祠”的诗篇,我的人生座右铭“热血千秋”就是在于谦祠看到的。他们都是历史上的民族英雄,都值得后人记住。
我几乎每个周末都要这样出去徒步一次,每次都要走20多公里,最长的一次走了40公里,那段时间经常霸榜微信运动排行榜。晚上回到住处吃了就睡着了,很累但是很爽,很锻炼身体,加班那么严重我也没生过什么病。虽然在杭州呆的时间不满一年,但是我还是很怀念那里的山山水水的,虽然有点不舍,但我还是离开了,这么加班身体扛不住。最后要离开的那几天,当我最后一次走过钱江桥,回头一看,一轮明月孤悬天空,银色的月光洒在了江面上,很好看,我想这是杭州这座美丽的城市在向我告别吧。
1.3 建设家乡
选择回到家乡,其初心一定是建立在“建设家乡”这个精神基础上的,而不是别的什么东西,否则就是在浮沙之上筑高台。匆匆作别杭州,我在2016年初回到了贵阳。在华尚高新公司做我的老本行:服务端开发。刚来公司我接手的第一个任务是负责公司业务系统的维护,它是用Python开发的,用来上传智能锁的设备信息以及用户信息到CouchDB数据库。刚接手的时候,第一版裸写了大量通过HTTP请求访问数据库的代码,重复的代码比较多,有新的功能又要重复写一遍,效率不高。我调研了Github上的一些开源的实现,发现couchdb-python少了一些我需要的功能,联系作者问明原因,这位芬兰小哥答复我说他觉得“这个功能他用不到,所以没写”。于是我准备自己动手,我在他的基础上自己动手实现了缺失的功能,然后给他提交了PR,然后被他打回,说我没有增加测试代码,代码风格也不对。于是我又修改再次提交,跟他反复折腾了几轮后,代码终于被他接受了,于是我将couchdb-python存了一份副本放到本地代码库,然后基于它重构了业务代码,精简了很多重复的代码量。
接手的第二个任务,是智能锁的长连接服务的开发和维护。公司的智能锁产品是需要与服务器保持长连接并以心跳的方式保活的。这样手机App可以通过网络远程遥控智能锁打开。原来的服务器是用C语言开发的,存在着一些并发问题,一段时间后服务器就卡死或者崩溃了,不太稳定。在这种情况下,我想起了之前在杭州读过的服务器端代码,正好也是基于TCP的长连接服务。趁自己对它还有点印象,我果断跟同事提出来要对它进行重构。考虑到我们是一个小团队,技术实力并不是很强,我提出用Go语言来实现,用Go语言一个人可以干三个人的活,效率很高。经过一段时间的研究和摸索后,我找到了一个比较简单的开源项目,在阅读其源码并弄懂原理后,我开始了对网络编程库的构思。花了几天时间画了个思维导图,然后我就根据整理好的思路用Go编写了tao网络编程库,还专门写了一篇文章《Tao - Go语言实现的TCP网络编程框架》来详细描述整个网络库的设计。那两个月的时间内我基本上没干别的,也没有被其他的事情打扰,就专心致志地开发tao,两个月后,网络库的第一版基本成型了,我又将原来的长连接服务用tao网络库重写了一遍,正式上线后,我不断思考如何改进,并通过服务器日志观察长连接服务是否正常。我还为此写了专门为tao网络库准备的holmes日志库和性能分析工具pangolin。随着对Go语言认识的深入,我又在原来的基础上对tao网络库进行了重构,删掉了上千行不必要的代码,使之成为一个Go语言风格的网络库。我开源了这套网络库,发布到了Github上,一开始只有零零星星的关注,后来有一次《码农周刊》推荐了它,于是那几天给我STAR点赞的开发人员越来越多,这个开源项目目前已收到600多颗小星星,后来它还获得了“北极勋章”——Github会将她以胶片的形式存储到北极,时间长达几千年。
为了便于日后使用Go语言访问CouchDB服务器,我还利用一部分工作时间开发了CouchDB-Golang的库,我利用Go的标准库开发了一个小功能,用来把Go语言格式的条件语句解析成复杂的JSON表达式,用来支撑数据库查询,其原理就是对解析好的抽象语法树进行解析和翻译。后来这套服务器一直在稳定工作,还用到了智能电表上。一直到公司因为经营不善在2017年底裁员。
2018年3月6日,我通过面试进入大数据国家工程实验室,在系统平台研究室从事大数据软件开发工程师工作,这个部门几经调整,现在已经改名为创新应用研究中心了。进入新的环境带来了新的挑战,原来作为工程师我只要做好手头的工作就可以了。到了新单位,我则需要以技术负责人的身份去带团队做项目,因为缺乏经验且没有转变思维,不知道如何指导团队,还是用过去的方式去处理工作问题,经历了一些痛苦和挫折。这同时也使我深刻的认识到了,很多时候并不是单纯靠技术就能解决一切问题的。如果说战争是政治的延续,那么技术就是业务的支撑。原来的工作成绩靠的是个人产出,现在的工作成绩则来自于团队的产出,要学习如何建立流程并与团队沟通,指导团队和依靠团队,充分的相信团队,在团队遇到问题时协调各方面资源去解决,及时处理风险。这些都是我从来没遇到过的新情况和新问题。
二. 刻苦学习
刚回家工作的时候,我还是一个服务器后端开发,且从参加工作以来接触的都是基于TCP的长连接服务,没有做过Web开发,对前端等其他细分领域的知识也知之甚少。贵州大数据的发展,无论是硬件条件还是软件条件,与一线城市都相差很远,那个时候也才是刚刚起步。最大的问题还是人才储备上,高端人才很少,很难能指望身边出现某个我杭州的大哥那样的大牛来带你。遇到什么问题都得自己想办法解决。
这样的现实环境让我从内心深处产生了一种强烈的危机感。主观上,我的技术水平比较单一,一旦失业很容易找不到工作;客观上,贵州的就业环境并不像大城市那样品类丰富,分工明确,有萝卜就有坑。而软件行业最大的职业风险就是被不断更新的新技术所淘汰。看来要想一条路走到黑,先得解决“生存问题”,降低失业风险,于是我做出了一个决定:通过工作之余不断学习来点亮更多的技能树,提高自己的竞争力和抗风险能力。
我调研了一些在线学习平台,也试用了一段时间,总的来说,免费的课程大多讲的不够深入,有点蜻蜓点水,关键是没有人带容易走弯路,耽误时间;付费的课程讲的要深入些,有实战项目,有的还有一对一的指导,但是价格不菲,相当于是用钱换时间。有一个更大的问题是,回到家乡之后我的收入水平是大不如前了,工资被腰斩一半,没进大数据院之前甚至连公积金都没有。是节约成本还是节约时间?是采取被动防御的策略,先存钱再说,还是采取主动进攻的策略,把本来就不太多的存款转化成脑子里的知识?我思考权衡再三,还是决定采取后者,做个只会算账的账房先生是不会有大出息的,“打得一拳开,免得百拳来”。我决定利用Udacity这个平台来学习。
2.1 成为Udacity学员
我启动的第一个学习任务是Udacity的数据分析师纳米学位,正好碰上那个时候平台正在试点优等生班,我就报名了。每个优等生班采取小班教学的模式,由一位班主任带领,大家来比赛,以闯关的方式完成一个又一个的实战项目,看谁最后第一个修完纳米学位。通过学习和完成一个又一个的实战项目,我复习了抽象分布和假设检验等统计学知识;学习了如何使用Jupyter Notebook结合Python编程语言的numpy和pandas库,沿着一维、二维和多维对数据进行探索性数据分析(EDA)并对数据进行可视化,尝试发现数据中的关联关系;然后又学习了数据可视化的叙事结构,并用D3.js创建自己的前端数据可视化项目,对数据进行解读。我的班主任名叫李华阳,是一位很热心的朋友,他会在每个周末不定时的和班上学员沟通,也会及时解答学习中的困惑,我记得那个时候我对各种各样的统计图表要怎么用很困惑,曾经就这个问题专门请教过他,得到了他的积极回应,他在查资料解答我的问题时,我们都有了不小的收获。我是第二个冲到终点线的,班上最厉害的同学是同济大学的学霸李亚男,她向我们分享了她自己的学习方法:
“先看要解决的任务/问题/项目的需求,然后有目的地学习,需要啥学啥,需要哪儿看哪儿,不需要的就先过一遍。但先完成了项目,心里踏实了,之后再回过头来系统的再补一遍。”
后来我们三个人成了很好的朋友,我们拉了一个“精进打卡”群,组成三人学习小组,不定期打卡自己目前正在学习的知识,分享一些好的学习资料或者经验,互相勉励。Udacity在上海组织了线下见面会,华阳和亚男见了一面;我和爸妈去广州旅游,我又和恰好在广州IBM实习的亚男吃了一顿饭。2017年6月1日,我顺利完成了“数据分析(入门)”,然后我乘胜追击,又在2017年9月14日完成了“数据分析(进阶)”。
点亮“数据分析”技能树并不能满足我,在那之后,我又趁热打铁开始点”前端开发“技能树。因为和华阳关系很好,他又走在了我的前面,我就找他借来账号,先提前看要学习的内容。Udacity采取的是报名制,每一期有固定的开班时间,我在等待开班的时间内也没闲着,拿了华阳的账号提前“发育”,在还没开班之前就开始着手学习并做通关项目了,这加快了我的学习进度。刚开班我就已经完成了一半的学习任务,这就争取了主动,避免了被动,还为自己积累了心理上的先发优势,打出了快速进攻的节奏感。于是2017年10月10日我完成了“前端开发(入门)”的学习,然后2017年11月28日又完成了“前端开发(进阶)”的学习,又在2017年12月21日完成了“React开发”的学习,点亮”前端开发“技能树。最后受Udacity工作人员之托,我把学过的知识总结整理了一遍,形成了一系列的学习笔记:
《HTML基础语法总结》
《CSS基础语法总结》
《前端页面设计的基础思维:盒子模型》
《CSS布局与响应式设计》
《响应式布局框架基本原理》
《JavaScript编程基础》
《JavaScript中的面向对象编程》
《现代JavaScript语言》
点完了前端开发技能,我又开始点”人工智能“。我在结束了对前端开发的学习后,开始关注”机器学习“和”深度学习“。我投了大把的时间和精力在里面,然而这个领域对从业者的要求非常高,尤其是数学要求很高。大学时学的高等数学、线性代数和概率统计只是入门必备技能,你必须把三者结合起来,要能看懂各种复杂的矩阵微积分公式推导,才能掌握精髓。我虽然分别在2018年4月24日和2018年5月8日完成了“深度学习”和“机器学习(进阶)”的课程学习,但是我的能力离真正能落地进行实际应用的能力还相差甚远。大量涉及数学的内容只能理解基本概念,严谨的公式推导却看不懂,我为此苦恼过,也买来各种书籍复习数学基础,比如系统地学习了一遍《线性代数及其应用》,然而最终并没有坚持对这个领域的深入研究,因为我摊子铺的有点大了,学习的速度跟不上知识遗忘的速度。
这又一次引起了我的反思。人的精力和时间是有限的,要完全穷尽某个领域的所有知识,并做的非常深入那是不可能的。这就好比打仗,如果每一个领地你都认为重要,要分兵去“占领”,最后导致的结果必然是“无不备者无不寡”,每一个领地上的“兵”都很少,就容易被各个击破。有一种动物叫鼯鼠,《荀子-劝学》有“鼯鼠五技而穷”的说法,它“能飞不能上屋,能缘不能穷木,能游不能渡谷,能穴不能掩身,能走不能先人”,谓多能而不精一技。什么都懂什么又都不精,就成了“万精油”,做万精油是要不得的。正确的做法,应该是把自己往“π”型人才这个方向去发展:精通一两个领域,其他方面则略懂皮毛。读书学习切忌平均用力,什么都想搞好,最后换来一个累死累活却无比平庸的自己。
2.2 成为Udacity教员
因为对学习充满热情又热心帮助别人,很快我就认识了很多志同道合的朋友。有一次有一个学员在“机器学习”通关群里抱怨课程内容太难学不到东西,然后又和群里的一位助教起了冲突,我忍不住在群里发话了,我说在这里学习的没有谁觉得学习是轻松容易的,课程只能拿来入门,关键还是要靠自己的努力,有什么问题大家可以互相帮助,算是为助教解了围。就这样,我逐渐认识了“柠檬橙”、“淑雯”、“Daisy”和“香老师”等一众工作人员。然后又经淑雯介绍成为了一名助教(mentor),开始了我在Udacity的教员生涯,后来还获得优秀mentor称号,成为101优秀助教团成员,接受过Udacity的采访,为其编写采访稿。一开始我只是在通关群中解答学员提出的问题,一段时间以后通过淑雯认识了”芒果兔“,她们建议我做内容审阅,于是我成为淑雯和兔总负责的审阅者(reviewer)成员之一。我的工作是负责审阅实战项目,为学员提供一对一的指导。通过给学员审阅实战项目作业,指出他们做的不错的地方,指导他们做的不好的地方,并及时提供一些课外参考资料供深入学习。做这些工作是有一定报酬的,我也通过帮助别人,把自己投资在学习上的钱都给赚回来了。但我的初心并不是为了赚钱,而是为了服务那些和我一样热爱学习的同学,因此我在当教员期间还做了一些其他的贡献,比如一个视频一个视频的核对字幕并将修改意见反馈给官方,修正了“人工智能编程基础”课程的中文翻译错误。比如为了更好的指导学员学习和审阅他们的作业,我又学习了“商业数据分析课程”,并为此制作了一些PPT,写了一些学习笔记,作为提供给学员的课外资料:
- 《数据处理学习笔记》
- 《数据分析解决商业问题学习笔记》
- 《数据分析与SQL学习笔记》
- 《数据工程师成长指南》
- 《一图胜千言:数据可视化不完全总结》
做教员期间,我于2018年9月4日完成了“人工智能编程基础”的学习,于2019年1月6日完成“商业数据分析”的学习。我在Udacity学完的最后一个课程,是2019年11月22日完成的“数据工程师”,学习了AWS云平台和一些基本的数据工程技能,想着自己在大数据国家工程实验室从事的是大数据软件工程师的工作,不能对它一窍不通。此后Udacity因为其他的一些原因退出了中国市场,回到了美国硅谷,我的教员生涯也就慢慢结束了。
“谈笑敢言非胜算,梦中常忆跨征鞍”。在那一千多个奋战的日日夜夜里,因为白天要上班,我就把能利用的时间几乎都利用上了,哪怕牺牲一些休息时间。每天上班前、中午休息的时候见缝插针看一两小节课程视频;下班回到家经常干到深夜才休息,如果是遇到周末,有时候一直会持续到凌晨,然后第二天睡到自然醒又接着干。除了课程介绍的内容,自己下来又查了一些资料,读了一些书加深印象。什么时候提交的项目有问题被审阅打回,什么时候放下手上正在忙的事情立马查看老师的审阅意见,然后重新修改并提交,有时候会被打回好几次又提交了好几次才通关。我很享受这种被“逼”的焦头烂额然后冥思苦想,最后恍然大悟后成功解决问题的快乐,俗称“花钱买罪受”。通过解决大大小小的问题,我学会了各种各样的知识,进一步丰富了自己的知识技能。建立了数据分析和前端开发的知识体系,虽然对人工智能知识的掌握并没有特别深入,但起码对其很多内容有了较为深入的了解。
在做教员的时候,印象最深刻的是有一年Udacity因为双十一大促销,涌进来了大量学员。兔总提醒我接下来的几天可能会很忙,让大家都做好准备。果然,那个周末学员提交的作业排山倒海一般飞来,我和其他几位审阅者没日没夜的审阅。我周末早上7点过就爬起来坐在电脑面前开始审阅,一直审阅到深夜困得不行了才爬上床,刚觉得自己快要睡着了手机又开始不断震动提示有学员提交了作业,就又爬起来接着改,一直到确认不会再有提交了,才去睡觉。然后第二天又赶紧起床接着改作业。通过积极为大家答疑解惑,我也在帮助别人鼓励别人的同时得到了进步。大家也愿意和我交朋友,我微信朋友圈中有327位好友都是通过Udacity认识的,他们来自天南地北,从事IT领域各种各样的工作,我也通过他们了解到了现在各大一线城市IT圈子里的情况,知道各种各样的奇闻轶事,也时常与行业目前的发展现状保持同步。我们相互激励,互相影响,这种热烈的气氛一直持续到了今天。
三. 坚持锻炼
我从小就是一个胖子。翻翻自己以前的照片,大部分时候都是以“两个下巴”的形象出现的。不爱运动,中学时代甚至经常逃体育课回教室里写作业,或者跑到图书馆找书看。小的时候被老爸强迫早起锻炼,跑不了几步就脸色发青。读本科的时候是体重的巅峰,达到了将近180斤,胖的眼睛都看不见了,以致于被老师误以为上课睡觉,还差点因为体能测试不及格影响毕业。后来读研究生之后受了一些刺激,开始拼命减肥,减了30多斤。从那以后就慢慢培养了自己锻炼身体多运动的习惯。
3.1 胖子回头金不换
这五年中,我一直有通过坚持长跑来锻炼身体,每年还积极参加贵阳马拉松比赛。从2017年开始,我给自己制定了年度的体能训练目标,每年要完成1000公里的跑量,其完成情况如下:
- 2015年:341.34公里
- 2016年:809.79公里
- 2017年:763.30公里
- 2018年:1005.04公里
- 2019年:690.47KM
我还通过高中同学学习了一种不伤膝盖的“姿势跑法”,是俄罗斯人发明的,具体来说就是身体适当前倾并以前脚掌着地,刚开始跑的时候身体不适应,小腿疼痛,一段时间后习惯了就好多了。家里还买了跑步机和跳绳,有时候不想出门夜跑,就在家里锻炼。不想跑了就跳绳或者去游泳。现在我的身体状况已经很好了,以前老爱感冒,现在一年就感冒个一两次。以前一感冒就病来如山倒,现在不用吃药,多喝水多睡觉,1-2天就好的差不多了,抵抗力大大增强。每天都思维敏捷,精力充沛,不觉得累。然而“锻炼身体,控制体重”,从来不是东风压倒西风,就是西风压倒东风的。稍有懈怠,体重就蹭蹭蹭的往上涨了,并不是一件容易的事。表面上看是减肥,实际上是自己与自己心中的懒惰作斗争,与欲望作斗争。“破山中之贼易,破心中之贼难”,这并不轻松。
3.2 锻炼身体的重要意义
锻炼身体有非常重要的意义,因为欲文明之精神,必野蛮之体魄。物质决定意识,意识反作用于物质,良好的精神面貌是建立在强大的身体素质之上的。身体和心理是会相互影响的,身体很差的人精神世界也强大不到哪里去。要应对人生大大小小的挑战,没得个好的身体是扛不住的。且人到中年之后,要避免各种脂肪肝、腰椎间盘突出、高血压和糖尿病的折磨,在年轻的时候及时培养起锻炼身体的习惯,是极有必要的。作为一个长期主义者,锻炼身体这件事,还要努力坚持下去。
四. 战斗下去,成为一名百炼成钢的战士
回过头来看,我在过去五年中采取的人生策略,是一种广度优先的策略。这种策略在一定的现实情况和历史条件下有着它存在的必然性。它为我打下了较为广泛的技术基础,使我了解IT领域各端的工作原理,提升了我职业抗风险能力,也为着自己在大数据院承担技术负责人工作,指导技术团队完成项目开发,起了一定的作用,有着一定的历史意义。“翰音登天,何可长也”,如果技术不好,经常开黄腔,搞外行指导内行那一套,还要来指导技术团队工作,是不可能的,是难以服众的,工作也根本无法开展。
一个严峻的现实是,要在贵阳从事IT工作,不像在其他的一线城市那么容易,个人要付出更多的更艰辛的努力。例如,会因为缺乏在一线互联网公司实践高并发、高可用和高性能应用场景的条件,而导致个人的技术成长与行业发展严重脱节。会因为不会管理团队,而无法发挥自己的最大价值,无法实现再一次的自我成长,也无法帮助团队成员成长,把团队带入万劫不复的深渊。会因为没有掌握系统思考的思维方式,而陷入各种主观主义的泥潭中,要么认为读书无用,全凭经验,沦为经验主义者;要么干脆尽信图书,照本宣科,沦为教条主义者。会因为放弃了自己的技术理想,丢弃了自己想成为架构师的信念,而自废武功,彻底沦为咸鱼。
这样的一些危机是客观存在的。重新审视现实情况并及时调整策略,是很有必要的,因为“了解情况和掌握政策两件大事,前一件事就是所谓认识世界,后一件事就是所谓改造世界”。作为先锋队,一定要对未来有一定的预见性,要根据自己的情况和未来的发展,对未来的战略进行调整,既有政策如果不适应发展的需要了,就必修部分的或者全部的改变。否则走一步看一步就容易栽大跟头,犯战略性的大错误。
4.1 变广度优先为深度优先
有了过去五年的积累,我在技术成长的策略上首先要变“广度优先”策略为“深度优先”策略。要集中主要精力去突破“服务器后端”和“大规模数据处理”两大领域,往纵深方向发展,形成自己独特的竞争优势。前者属于OLTP业务系统;后者属于OLAP分析系统。要深入到这个两个领域中的最底层去学习和掌握其背后的基本原理和客观规律,包括(但不限于)以下几个方面:
- 操作系统内核
- 关系型和非关系型数据库
- 分布式系统
- 计算机组成原理
- 计算机网络
- 系统架构设计
不可再采取过去那种遍地开花式的学习方式。从学习的目标上说,一切学习的中心任务,都只为着一个目的,那就是建立技术自信,突破技术转折点。从学习的手段上说,在大的方向上要把一切学习拆分为三个阶段,分步骤实施。
在阶段一,重点掌握领域特定知识,也就是要搞清楚要学习的目标所包含的大量的信息和具体的概念等。一旦掌握了如何完成具体任务,各组成部分如何构成整体的大致框架就变的显而易见了。并且随着时间的推移,学习者自己会摸索出一些固定模式,一开始让人觉得困扰的陌生概念就慢慢习以为常了。在这个阶段主要要关注的是各种细节,特别是关注教程或者文档中的各种细节。有时候你认为它应该是这么运作的,但其实并不是,学会处理报错和问题是必经之路,也是“主观符合客观”这一哲学原则在技术学习上的具体体现。处理的经验越丰富,对其认识就越深刻,花费在修复错误上的时间就越少,最后从遇到的每个错误中吸取教训。当见识过了足够多的错误信息并且不会被难倒,且熟练掌握如何通过搜索找到解决方案,并能够参考写过的代码,遵循它里面的一些代码模式来完成任务,而不是按部就班的跟着教程做的时候,就可以认为学习者已经达到了阶段一的要求,可以过渡到阶段二了。
阶段二是转折点阶段,重点要掌握过程性知识。学习技术,不光要学习领域特定知识,还要学习过程性知识。过程性知识是一种在学习的过程中通过探索来自学未知的东西的能力。这种知识往往是语言无法表达的,只能靠亲身实践。你要想知道梨子的有多甜,无论我怎么描述,都不如你亲自尝尝;你要想学会骑单车,无论我再怎么教你,都不如你亲自骑一骑摔几跤学得快。关键是要学着自己从黑暗中摸索,要能够通过自学解决碰到的问题。这个阶段是学习技术过程中最容易感到沮丧的。它是一个逐步停止学习别人制作的教程,开始着手解决那些自己遇到的实际问题的转折点,就好比婴儿扔掉学步车开始自己学走路。在转折阶段学习技术,速度会比前一个阶段慢10到20倍。这个阶段会伴随着各种不安全感和自我怀疑。尽管十分“缓慢”,但这个阶段是积累过程性知识的关键时期。要树立正确的认识,必须认识到,人永远都不会等到所有的一切都准备充分后才开始解决问题。学习是一种终身的经验。解决那些还未解决的问题是一种学习更多知识的机会。
对于后端工程师而言,要突破的转折点有两个,一个是开发的转折点,一个是算法和数据结构的转折点。跨过这两个转折点就进入了被称为“自由王国”的第三个阶段,就能掌握如何操作数据并能够理解所做的决策对性能的影响,这也是成为高级工程师必经历的一道坎。高级开发每天所从事的工作其实就是解决那些两个领域都有涉及到的挑战:在开发中构建所需的复杂算法。
采用深度优先的学习策略。学习技术唯一的目标就是找到转折点并彻底征服之。对此我也是曾经有过切身体会的。当年读高中的时候,我曾把我哥的那本给高三毕业班准备的《英语试题研究》拿过来,尝试做上面的高考英语模拟题,走在其他同学前面。刚开始的时候也是做错很多题,阅读理解十题九错,英语写作也只能拿个几分或者十几分,好几次对完答案发现自己都不及格。我抱着灰心丧气的心情,挂着愁容满面的表情坚持了两个多学期,然后不知道什么时候突然就“开窍”了,正确率开始突然飞升,也找到了英语写作的那种“手感”,真到了自己高三的时候,英语成绩从来没低过,题目越难分越高,这种苦练之后得到的题感我自己都没意识到是什么时候获得的。一直持续到我考研的时候,英语都没怎么复习,就考过线了。我想这就是突破转折点之后的感受吧。
以上就是我对如何通过深度优先策略保持技术成长的一点点思考。
4.2 学习如何管理团队
学习如何管理团队,是成为系统架构师必备的基本素质,是时候进一步提升自己的软技能了。我的目标不是成为“兄弟们给我上”那样的团队Leader,而是要成为“同志们跟我上”那样的团队Leader。要转变思维方式,在遇到事情时,不是自己事必躬亲去做,而是放手发动团队,充实团队力量,驱动团队成员把事情做好,自己则做好资源的协调、任务的计划和风险的管理,并在关键时候做技术决策。管理团队时,既要把问题说清楚,让人知道要做且有动力做,又要培养团队成员,使之有能力去做。要带领团队明确目标,建立良性运转的机制。团队的整体产出好了,效能提高了,才是自己的成绩。最后,要提高自己的沟通能力,在掌握如何与机器打交道的同时掌握与人打交道的能力。
在管理团队方面,会面临一些新问题,如何应对?我想这得通过不断学习和亲身实践才能掌握,我现在对此问题还缺乏深入研究。也许再过几年我能对这个主题进行总结概括,目前就先提一些关键点,重要的是要虚心学习。
4.3 建立系统性思考的思维框架
系统性思考是一种科学理性地认识世界并改造世界的思维方式。要做到系统性思考,首先要以实事求是的精神多搞调查研究,了解情况,然后才能使制定出来的方针计划与实际情况相符合,做到主客观相统一。实践是更加不容易的事,拿着书本尽管讲得头头是道,但实践起来却有做成没做成之分。关键在哪里呢?关键在于熟识问题各方面的情况,多做调查研究,找出其规律,并且把规律付诸于行动上。
“指挥员的正确的部署来源于正确的决心,正确的决心来源于正确的判断,正确的判断来源于周到的和必要的侦察,和对于各种侦察材料的联贯起来的思索。指挥员使用一切可能的和必要的侦察手段,将侦察得来的敌方情况的各种材料加以去粗取精、去伪存真、由此及彼、由表及里的思索,然后将自己方面的情况加上去,研究双方的对比和相互的关系,因而构成判断,定下决心,作出计划,——这是军事家在作出每一个战略、战役或战斗的计划之前的一个整个的认识情况的过程。粗心大意的军事家,不去这样做,把军事计划建立在一相情愿的基础之上,这种计划是空想的,不符合于实际的。鲁莽的专凭热情的军事家之所以不免于受敌人的欺骗,受敌人表面的或片面的情况的引诱,受自己部下不负责任的无真知灼见的建议的鼓动,因而不免于碰壁,就是因为他们不知道或不愿意知道任何军事计划,是应该建立于必要的侦察和敌我情况及其相互关系的周密思索的基础之上的缘故。”
认识情况的过程会贯穿始终。不但存在于制定计划之前,而且存在于制定计划之后。执行计划的过程中原来的东西是否符合实际情况,需要重新加以检查。如果计划和情况不符合,或者不完全符合,就必须根据新的认识,构成新的判断,定下新的决心,修改原有的计划使之适合于新的情况。不知变通,或不愿改变,只知道蛮干傻干,则又要出问题。一切事物的规律是客观实际在头脑中的反映。要做到“知彼知己,百战不殆”。
要做到系统性思考,关键在于变不确定性的东西为相对确定的东西,变笼统的目标为清晰的行动路线。有一种被称为“四步法”的方法是值得参考的。它将一个大的问题拆分为四步来分步骤解决:界定问题、拆解问题、执行解决和总结复盘。
解决问题的第一步就是要搞清楚要解决的问题是什么。如果不熟悉专业术语,就要用“what-else”循环法熟悉各类专业术语内涵和外延,做各类案头或访谈类调查研究。在充分了解的基础上,用“3W-2S-1R”对问题干系人、问题背景、迫切程度、成功解决的标准、问题范围和风险与挑战进行分析,形成问题分析表。根据重要程度、紧急程度和工作量画出问题价值矩阵,评估问题价值。最后利用SMART原则清晰地陈述问题的关键点、解决的目标、解决的方向、与问题密切相关的要素以及时间限制。
解决问题的第二步是复杂的大问题拆解成相对简单的小问题,降低问题的解决难度,规划清楚问题的解决步骤和先后顺序。满足“MECE(相互独立,完全穷尽)”原则和“同一层面”原则的议题树就是拆解问题的有力工具。其中第一层级是基本问题;第二层级是关键议题;第三层级是三级议题;后续层级是细节议题。对于熟悉的领域,可以采用自上而下的方式拆解问题;对于不熟悉的领域,则可以通过自下而上的方式进行总结提炼;在没有头绪的时候,可以“大胆假设,小心求证”,通过先假设后检验的方式进行分解,慢慢就有思路了。
解决问题的第三步是执行解决。可以先通过一个总体工作流程表总览几个大的关键里程碑,然后把拆解好的议题树转化成工作计划表,定好负责人,规划好工期,画出甘特图,推动工作的并行执行。然后开始执行工作计划,动手解决一个又一个的问题。
解决问题的第四步是总结复盘。解决问题过程中每告一个段落就要进行一次简单的事中复盘,工作完成后还要再进行一次事后复盘。复盘是对工作目标的再一次回顾,对工作结果的再一次评估。对做的好的和做的不好的地方进行根因分析并优化改善。
4.4 坚持理想,坚定信念
“就令如萤火一般,也可以在黑暗中发一点光,此后如竟没有炬火,我便是唯一的光。”
我并不是一个天赋异禀的人,从小到大参加各种数学或者信息学竞赛从来没拿过什么奖。甚至那本信息学竞赛的教材还被我扔到了沙发底下。直到有一天晚上我独自一人坐在沙发上洗脚,无意间瞥见了沙发底下那本书,捡起来翻了一下,在看懂了什么是写程序的那一刻,我的兴趣就瞬间被点燃了。从此编程就变成了我一生的热爱,这种热爱持续了20年,而且还将持续下去。唯有热爱才能抵御人生的枯燥和孤独;有所追求,才能不被迷茫和堕落带入万丈深渊。
总结过去五年自己人生经历上的得与失,一方面是在总结经验教训,另一方面也是在告诉自己:不要忘记当初的誓言。要继续发扬过去做的好的方面,努力改正做的不好的方面。不断地否定之否定,在持续否定旧的自己的同时发展出一个新的自己。让我们继续发扬不怕辛苦连续作战的革命传统和优良作风,做百炼成钢的战士!我的总结就到这里,与诸君共勉。
“无常逐一升起和熄灭,我对你的赤子之心永存。”
有疑问加站长微信联系(非本文作者)