书名:我是一个程序员
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
本专栏以一个刚踏入职场的互联网从业者的视角出发,讲述了工作四年期间所经历的有关个人职业发展、人际交往真事、领导能力提升等故事。本书力求以朴实的口吻,以发展的方式,还原一个互联网职场新人眼中的真实世界。
途索,真名贾建超,曾就读于北京邮电大学(2008~2012年)和电信科学技术研究院(2012~2015年)。毕业后就职于阿里巴巴(中国)有限公司,工作至今。曾担任嵌入式工程师、后端开发工程师、数据开发工程师,以及算法工程师……用技术的方式解决现实世界的问题,是他多年来所追求并坚持的目标与方法。兢兢业业工作,认真认真搞专利、写论文,是他生活的常态。此外,他还热衷分享知识,不仅进行过数十次关于数据科学的分享与演讲,而且还在不同平台上推出了“Python设计模式”“Python3数据分析与挖掘实战”等多门网络课程。这些是他的过去,也会是他坚持的未来。
写这本书的初衷,是因为我不断地被刚毕业的高中生和大学生问道:当程序员是一种什么样的体验?每当被问到这样的问题,我不禁会想到当年自己求学时,对未来充满迷茫的样子。那个时候我特别想知道自己将来会从事一份什么样的工作、社会上有什么样的工作、工作中会做些什么……但当时并没有多少途径让我了解这些。当我想到每年都有无数和当年的我一样,在试图进行自己的职业选择时,因为缺少对于“工作”的充分认知,连自己要选择的是什么都不知道,就更不要提该怎么选择了。这时候,他们能依靠什么呢?
我决定把我的所见所闻都记录下来。我自认为没有能力把三百六十行都写得真实详尽,但把程序员的与一个大学四年周期同样长的时间经历进行记录,还是能做到不失现实的,并且是力所能及的。
关于这本书的写法,我考虑过以一个过来人的角度,聊聊经验和人生方向,并讲讲怎么样成为一名优秀的工程师。但我想到,介绍这些经验时,自己的主观想法免不了会介入,而自己的主观想法若是太强,就会偏离我写这本书的主要目的。每个人心目中的优秀工程师都有不同的定义,我不应该片面地表述自己定义的优秀,而忽略了更多“优秀”的可能。同时,自己独有的感悟与观点,也容易把话题收得太窄,反而会让自己真正想要说明的意思得不到表达。所以,在进一步构思细节的过程中,我打消了这个想法。
接着,我考虑以我接触与学习技术的经历为主线,以技术人的视野介绍程序员这份工作。但经过思考,我同样放弃了。原因有两个:一是介绍技术这件事,本身就缩小了受众群体,也同样偏离了我的写作目的。这本书,我还是想以接地气的方式,向大多数人阐述当一个程序员的体验,而不是向技术相关从业者介绍技术细节。二是作为技术人,确实不太好抑制自己秀技术的冲动……
思来想去,我打算以事实与一些个人的感受作为本书的主要内容,而把技术细节、观点、论点等专业性较强和主观性较强的东西隐去不写。每个人看到同样的事实,一定会有自己的想法。我觉得,当面对这些想法时,最好的处理方式,就是尊重:让读者自己结合自身的生活与经历,去想这究竟是对是错,这其中是何缘由,有何苦衷。尽可能少地告诉读者该怎么做,而积极去与读者讨论这其中可能的背后逻辑与真实原因。书中涉及的大多数场景,如学习成长,与HR、领导、猎头的交道,晋升、面试、出差等环节,均来源于真实案例。当然,这些案例有的直接发生在我身上;有的是我经过采访后,转换成了书中主人公的经历;有的是我将一些零碎的故事简单重列后,以尽可能不失真的方式重新组织,以提高阅读体验……其中大多数故事来自我自己的见闻,为保险起见,加上了一些“交叉验证”,但即使如此,也难免会有一些疏漏,或是与读者所见所闻有出入的地方。希望大家在阅读本书时海涵,若是能提出宝贵的意见和建议,那就再好不过了。
在我所接触的教育体系中,关于工作、职业的启蒙与教育常常难见踪迹。这也导致许许多多的人,在逐步认识社会这个大协作体的过程中,往往不够系统,只能根据自己有限的视野,结合道听途说的方式来了解三百六十行。有些地方的人,只知道像医生、老师、警察这样的职业,而不知道还有像金融家、精算师、程序员这样的工种;有些高中毕业生,到了选专业的时候,对自己接下来做的选择将如何影响自己的未来几乎一无所知;有的大学毕业生,在他踏入公司之前,对自己这份将要从事的工作是做什么的都一知半解……我们每个人都有权利先认识这个社会的分工,再选择自己干什么。我希望,每行每业的人都能行动起来,记录下自己行业内的真实故事,让更多的人知道律师、健身教练、产品经理、活动运营、兽医、证券分析员、培训讲师、煤炭工人、科学家、人类学家、月嫂、导游、网约车司机、花店老板、外卖小哥……这些职业背后的辛酸与喜悦,让各行各业的人能相互理解的同时,也让祖国的花朵们能以更聪明、更理性的方式,对将陪伴自己一生的职业做出最认真的选择。
“嗨,你好,你就是途索吧。”
“嗯,我是。”
“请跟我来。”
就这样,被行政同事“搭过讪”以后,我第一次以一个正式员工的身份进入了A公司。
几个月前,我是无法想象能通过这家公司的考核的。A公司是一家很大的互联网公司,它的营利能力很强,业务范围也很广,能攻克各种世界性的难题,竞争力在全球也能排到前几名。而那个时候的我,还是一名在一所不知名的研究院见习的研究生,从事着一些与互联网技术毫无关系的技术开发工作。
2008年,高考结束,我如愿来到了北京上大学,学校是我倾心已久的大学,专业也是大家公认比较不错的通信专业。对于一个生活在小城市、没有多少见识的我来讲,这可能是我这辈子遇到的第一件充满了巨大挑战的事情了。在我以前的日子里,我几乎没有离开过家乡。不曾住校,所以我也不曾离开过父母。家境不殷实,基本温饱虽略有压力,但其实也并没有遇到过什么真正的危机性事件。那个时候,我也仅限于知道,外面有一个巨大的世界,还有很多我没有见过的东西和没有见过的人,但那个世界是什么样的,那些人是什么样的,我却并不了解。于是,去一个大城市上大学,成了我中学时代的目标。那年,目标达成。在即时与激烈的兴奋过后,巨大的忧虑一直伴随着我的左右:未来是未知的,可能是美好的,也可能是困难的,到底是什么样子,我一无所知。
现在回想起来,大学四年,过得其实并不算精彩。大一那年,以高三的姿态和节奏一直在读书做题,与其把那一年叫大一,对我来讲,还不如叫高四更适合一些。同时,真正见识了“大城市的孩子”之后,我才意识到,除了在考试成绩单上我会有一些几乎可以忽略不计的优势外,在视野、表达、性格、情商、交流、团队活动等方面,自己几乎全线被碾压。于是,本来性格就比较内向的我,变得更不爱说话了。大二那年,我想寻求些改变,主动把自己置身于各种社团活动中,并积极地去说话、交流、表达。然而,十几年养成的习惯,以及与人打交道的相关经验的缺乏,让这一切都很不成功。这一年,我隐隐约约地听到了很多人对我的评价与印象:不合群、木讷、呆、土……在他们眼里,我的形象可以说是已经被下结论了。雪上加霜的是,这一年,就连之前撑起颜面的考试成绩单,也惨不忍睹。于是,沮丧、失落、挫败感……这一切成了这一年的主题词。大三,调整方向,我回归了自己喜欢的“学习事业”中,开始研究与琢磨技术。当然,受专业影响,钻研比较多的还是通信技术和硬件技术。我参加了一些竞赛,获得了一些小奖,算是找回了些自信,挺过了那段充满悲剧的日子。“还是技术对我比较好。”那时,我决定,以后要从事一份与技术相关的工作,能不跟人打交道,就尽量离他们远一些。大四那年,考研失败,不过还是有一个调剂到某小型电信研究院读研的机会。与此同时,我也拿到了国内最大的通信公司的技术开发的Offer。虽然我更想去工作,不过最终还是听了父母之言,决定去再上两年半学。
后来,我不时地对放弃工作转而选择来读研的这个决定持怀疑态度:那可是国内最大的通信公司的Offer,我放弃了它,而选择了一家在业内并没什么突出业绩的小研究院,为的只是获取一个硕士学历。那时的我,觉得这并不划算。而且,我也觉得,这个决定并不是我做的,而是父母帮我做的。虽然心里怀着各种不舒服,但日子终究要过,最终不得不抛给自己一个能接受的理由:来都来了……
在读研这几年,我的技术方向还是之前自己一直在努力学习与研究的硬件技术。那个时候,我已经开始想很多未来的事了。所以,内心里是特别渴望有一个“过来人”告诉我如果我做了这个工作,我未来的生活是什么样子的。我原以为,我的导师,我的师兄师姐们,都会告诉我这些,事实却扇了我一记响亮的耳光,并轻蔑地告诉我:小伙子,你还是太天真。似乎,不管是导师,还是师兄师姐,都有很多自己的事,已经没有心思去帮一个“愣头青”。在进行学业与研究的过程中,我常常会被分配一些我自己从来没有做过的工作,并且没有人关心我能不能完成这个工作。如果我真想了解些什么,不管是生活上的还是研究中的,不管是当前的问题还是未来的疑惑,只能自己去问,去面对一张张充满了不耐烦的脸……对于一个有“社交恐惧症”,并且情商为负数的我来讲,这又是一件令人十分难受,但为了对得起“来都来了”这四个字而不得不去做的事。自大二的社交尝试失败后,虽然我默认了自己“孤僻”的标签,但有些不得不去面对的“应酬”,我还是会刺激我的脑仁儿,希望能想几句能糊弄过去的台词。就这样,在读研的那几年,我会每天绞尽脑汁去想问题,想该问谁,想什么时候适合问……“可怕的社交”简直成了家常便饭。那时,我想知道是不是所有研究院或者大学的导师、师兄师姐都这样?是不是就不会有一个真正的“导师”,主动来告诉你些经历,告诉你一些你应该知道的东西?好在,后来认识了一个我的大学学姐,她主动帮我解惑,主动教我如何在这儿学习,并告诉了我许许多多我想知道的东西。其实她也没有刻意去讲什么人生哲理,只是讲了讲她的故事,以及她的同学后来都在干什么。这些其实才是我一直渴求的东西。直到现在,我还记得那个学姐的耐心与善良。
经历了这些,我发现,如果我真的想做一个优秀的人,能依靠的只有一个木讷并没什么见识的自己了……
那个时候,我还是力争想基于自己所学到的东西,成为一个优秀的嵌入式工程师。只不过,我开始主动疯狂看书,找资料,去浏览各种技术论坛,甚至花了攒了几个月的“积蓄”,买了一块功能强大的开发板。当时,研究院有着不错的政策,毕业可以留下直接工作,并且直接解决北京户口问题。可这些对于我来讲,似乎一点吸引力也没有,除了每天玩命地学习,我脑子里唯一的想法就是:离开这里。
再后来,到了要找工作的时候,除了比较对口的通信与电子公司,我注意到了互联网公司的存在。其实,互联网一直都是比较热的词,只是我不认为这跟我有多大关系。当初靠着“懒”算法,选了与自己专业最相似的技术方向,虽然是对自己缺乏途径去了解更多技术领域的好东西的一种妥协,但选择了就是选择了……而在经历了这么多之后,我变得有了些想法:听说互联网公司特别人性化,每个人都充满了活力与干劲,团队氛围特别好。而且,互联网的薪酬待遇貌似很诱人的样子……“我可以付出那么多辛苦去搞通信和嵌入式技术,分出来点精力搞搞互联网技术,也不是不可以嘛。少看两眼手机的事儿。”我对自己默默地讲。互联网领域的技术方向虽然和我的专业方向不同,但我发现,这其中貌似没有我想象中的那么大差距。一些算法、数据结构等,大家也都是用同样的思考方式;代码运行平台,也都是Linux和Windows……似乎,我又被以前的自己骗到了……
终于到了求职季!早已蓄势待发的我,一下发出五十多份简历,这其中,有十份简历是投向互联网公司的。几天后,我收到了第一份笔试邀约,看到公司名字,我被吓到了——互联网巨头A公司。当初向这家公司投简历时,我只是抱着试一试的态度,没想到,这家公司居然是我求职路上的第一个挑战。更神奇的是,原以为难度非常大的笔试题目,做起来也没那么难。题目里没有什么很专业的东西,反而是之前看到的算法和数据结构知识比较多。于是,我就还算比较顺利地进入了面试环节。
常年被笼罩在社交恐惧阴影下的我,要面对面试这一环节,是需要更多的勇气的。面试进行了四轮:第一轮面试,我怀着忐忑的心情,十分担心面试官问出我一些深不可测的互联网技术难题,然而,面试官没问一点有关互联网技术的问题,一直在问我关于我自己曾经做过的那些嵌入式工程的项目。在讲解项目时,我突然发现,自己居然可以滔滔不绝地讲半个小时的话!而且,自我感觉十分流畅,都不敢相信,那些话都是我自己说出来的。当一面结束时,刚开始,我是一脸蒙的状态,我被自己吓到了,后来想到自己做到了曾以为自己做不到的事,我还是挺为自己感到高兴的。不管最终能不能去成A公司,但看到自己身上发生的变化,就已经足够让我自己开心好长一段时间了。面试进入第二轮,虽然经历了一面的自我感觉的小成功,但二面我却丝毫没有平静下来,依然紧张兮兮的。除了与一面一样,问了一些项目上的细节以外,二面面试官着重考察了许多算法上的基本概念,像是二叉树、快速排序之类的算法,还让我在纸上写了一段伪代码。大部分题目我都答了出来,一部分题目我明确知道见过问题中的概念,但对太过细节的东西还是没掌握牢靠。总的来说,我感觉发挥得不太好,考点都很基础,但自己思考的时间有些长,还是怪自己基础知识掌握得不太扎实。好在面试官比较宽容,我还是进入了三面。A公司的三面叫作“交叉面”,那个时候,其实我并不明白交叉面是怎么个交叉法,感觉是一个HR,一个技术大拿(后来才知道,这个大拿和之前的面试官必须是不同的部门),一个会问许多关于团队协作的技术问题,另一个则会对一些心理想法多问几句。经过几个回合,当我差不多猜到谁是技术大拿、谁是HR的时候,突然,枪头调转,原先问技术的面试官开始问关于工作的计划和未来的规划,另一个原先“摸心理”的面试官则开始问技术(问得还蛮专业的)……在发蒙的状态中,面对一个个的问题,还是要好好答。有一句话:“如果面试中你不知道该怎么答,那就说实话。”记得我是从一次面试经验交流的讲座中听到的这句话,我也只记住了那次讲座中的这一句话。为什么会只记住这一句话?或许,对于那时的我来讲,我也只愿意把这句话付诸实施。这样,如实交了底,也不知道自己表现如何。不安地等了二十分钟,听到了终面组织者叫到了我的名字,这样,还没来得及松口气,就又迎来了新的一波紧张。最后一面是HR面。越是到了最后一个环节,反而越不需要那么紧张(不是不紧张)。记得HR小姐姐一直面带微笑,关心着我平时都喜欢做些什么,有些什么爱好特长……虽然不知道这些问题有什么用,但也没有什么所谓的“面试技巧”,会的也只有“全招”这一个办法,就坦荡荡地又一次“交了底”……十几分钟的“自白”结束,整个面试流程就这样走完了。能走到终面,对自己的表现已经很满意了。心里是不敢奢求能收到A公司的Offer的,毕竟,人家是大公司,我以前从事的工作也不是互联网相关的工作,它可以有一百个理由不发我Offer。但我也真的特别想拿到这个Offer,我没想过要以此证明自己的实力(因为,确实实力还不咋地……),我的真实想法,是去这个地方,见识下优秀的人、优秀的团队到底应该是什么样的。
之前,我的计划,是要成为一名优秀的嵌入式系统工程师,而接到A公司的面试通过的电话通知后,我觉得,“优秀”应该比“嵌入式系统工程师”更重要。那个求职季,我拿到了四个Offer,其他三个Offer都是通信公司的嵌入式系统工程师的职位,在我投过简历的十家互联网公司中,也只拿到了A公司这一家的Offer。对我来讲,这个Offer是最为特别的一个,为了得到它,我把自己几乎所有能耐都用了一遍。更重要的是,它给了我最需要的东西:真正去见识“什么是优秀”的机会。
回忆这段日子的时候,我始终记不得当时我到底是激动和高兴比较多,自豪与解脱感比较多,还是紧张与不安比较多。如果非要落入俗套,这些情感因素都应该有一些:我应该有拿到了来之不易的Offer的高兴与激动,应该有一种面对过去的自己的自豪感和从一种自己不喜欢的环境中逃脱出来的解脱感,也应该有一些对未来与挑战的紧张与不安。不过,当时有没有这些情绪,真的已经不记得了。我只是隐隐约约记得,要迎来一种新的生活方式了,有一种比较特别的新鲜感。它没有夹杂着从学生要变成一个职场人的踏实,反而饱含了更多类似于升学时成长的滋味:未来的大部分是未知的,已知的是你一定会有不少出人意料的收获。
就这样,A公司,我来了。
刚刚接触互联网,此时心里不知道该说些什么,索性:Hello Internet!
今天是我来入职报到的日子,也可以说是我这辈子第一天上班的日子。
从事行政的女士熟练地把工卡放在感应器上,刷开了一扇很大的玻璃门,我紧紧跟在后面,终于走进了这家费了老大劲才挤进来的公司。初入职场还不知道该关注什么,索性就把大多注意力放在公司的布置上了。在我眼前是一条长长的走道,在明亮的灯光下,可以清楚地分辨出地面青灰色的大瓷板砖结构。墙壁靠近地面的部分是橙色的,这也是这家公司的主色调。橙色部分大约有一米高吧,再往上直到天花板,都是白色的粉刷墙体。长长的走道两旁,白色的墙壁部分每隔一小段,都会挂着一些看着很舒服的“小栏目”:有公司的Logo,有行政办事流程的介绍和公告,有公司日常宣传口号,有团建活动中大家开心模样的照片,还有些不知道是谁设计的刻画日常工作的小漫画……整体上简约直接又不失想法的布局,让人着实喜欢。
“前期手续差不多都帮你办完了,你在这里登记一下,就可以领你的电脑和工牌了。”
“好的,谢谢。”
所有的手续办理结束,终于拿到了作为一个程序员的最主要的办公用具:笔记本电脑。“不愧是大公司,标配的笔记本都是价值上万的高端牌子。”我默默地想。接着我端详了一眼工牌:有了这个,以后我就是一个职场人了。与印象中不同的是,工卡的封面是我的一张生活照,想起前几天,也不知道是人力的小姐姐还是行政的小姐姐,貌似是找我要过一张照片,原来是拿来制作工牌了。互联网公司这种自由随性的风格,让我很喜欢。
“好了,带你去你的工位吧。”
又走过一段长长的走道,拐进另一扇玻璃门,就到了占据了一大片地方的办公区。办公区是开放式的,在同样明亮的灯光下,整齐排列着十几排长桌,每一排长桌都有整齐八个小区域,每个小区域都是一个员工工位,工位与工位间没有什么隔断,工位前是一张据说符合人体工程力学的椅子。我的工位被安排在整个办公区最后一排,靠窗数第二列,工位背后是一个巨大的会议室。我走到了属于自己的工位前,周围的其他同事好像有什么事,不在工位。我趁机坐下感受了一把那高大上的椅子:嘿,这符合人体工程力学的椅子,坐着还真挺舒服。我一边感受着椅面给我带来的贴合感,一边控制着自己的好奇,尽量不把自己的无知显露出来。
“好了,一会你的团队Leader就会来找你了。你先等下,我走了啊。”
“好的,谢谢你。”
我回头看了看那张符合人体工程学的高端椅子,把它摆正,又把电脑放在桌上,与桌沿保持平行,慢慢坐了下来,插上电源,打开电脑。当前的我还什么都干不了,不过,正好有时间看看周围这些马上要相识的同事,都是什么样的人。我所在的部门,是个研发团队,大部分都是技术人员。放眼望去,男女比例感觉很高的样子……或者可以说,看不到几个女同事。大伙穿着都比较朴素,色调主要以深色为主,如各种黑色、深蓝、灰色等。要说都是一种纯色的穿着,也不全是,比如,我马上发现了第二种主流穿着:格子衬衣。红蓝格、红黑格、黄蓝格……配上一条精干的牛仔裤,一双看着有些发旧的运动鞋,这样的穿着甚是常见。仔细想了想,深色为主的色调其实不管在哪儿都算普遍,毕竟,属于男人的衣着打扮就那么几样。不过格子衬衫,尤其是这么大规模的、成片的格子衫,在其他地方还真是罕见。不远处,终于见到了两个女同事。之所以现在才发现她俩,自己近视是一方面,另一方面,貌似这两个少有的女同事也包含着一些“女汉子”的味道,不像刚才带我来的行政同事那样,脸上会涂上些显白的什么粉,嘴上会抹上些在我看来一样颜色却又叫着不同色号的口红。她俩纯素颜的面孔虽然谈不上美,不过看着还是蛮舒服的。她们的穿衣打扮同样十分朴素,甚至连格子衬衫也与广大男同胞保持了一致。“这应该是我们研发部的妹子。”我心里想。看着这些,想想前几天的自己,为了能有良好的形象,花了大价钱搞“形象工程”:配了新的黑框眼镜,买了这辈子最贵的衬衫(是深蓝色的)和卡其裤,还搭了一双擦得锃亮的皮鞋。我感觉自己跟这环境似乎显得有些格格不入……
远处大门那边进来一波人,朝我的方向走过来了,看样子像是刚开完会。为首的同事戴着金属框的眼镜,估摸有个三十五六岁的样子,他看到了我,向我挥了挥手。我猜,他就是我的Leader了。
“途索是吧?”
“嗯,是我是我。”
“你好,欢迎加入我们团队。我是团队的负责人海布。先带你认识认识团队里的同学吧。”
“好的好的。”
早听说A公司的习惯就是把“同事”叫作“同学”。作为一个刚毕业的职场新人,听到“同学”两个字,倒是不觉得自己转换了社会属性,而是如升了学一样。
缓过神我才发现,刚才还比较空的周围,现在已经坐满了人。我小心翼翼跟着海布,他带着我,开始一一介绍团队成员了:“这位是XX。”“你好,我是途索。”我笑着和新同事打招呼——虽然我没听清他叫什么名字。“这位是YY。”“你好,我是途索。”“这位是ZZ。”……到了一个女同事,哦,不,是女同学旁边,我一眼就认了出来:就是我刚才调侃的两个女同学之一。“这位是许楠。”“楠姐你好,我是途索。”忍了半句“刚才我还暗地里吐糟你来着”没说出来……就这样,一路下来,貌似没记住几个同学的名字,不过,混个脸熟,也算是有个开始了。
“你的引导人是这位,还记得他叫啥吗?”海布指了指坐我旁边的一位圆脸、略微发胖的同学,刚刚介绍过,但是我根本就没记住。我尴尬地吐吐舌头,海布笑着说:“他叫立刚。”“好,这下我记住了。”立刚也站起身来:“欢迎你,以后多多切磋。”我不好意思地点点头,像傻子似地笑了笑,啥也没说,其实,是不知道接下来该说啥。
“立刚,新同学就交给你了。”海布说道。
“好的。”立刚答道。
待海布回到了他的位置,立刚非常熟练并且略显程式化地开始介绍起团队的情况和我接下来要做的事情。从立刚口中,我了解到,这个团队是在半年前的组织架构调整后新成立的,不过团队里的成员,大多数都是老员工。团队的主要职责,是做一些数据后台服务的支持和数据挖掘方面的工作。而对于我的安排,立刚说海布想让我先做后台服务。虽然这个时候我还不知道后台服务是什么概念,也不知道相对应的“前台”会不会有好看的小姐姐,不过要做些听上去很有意义的事儿,我还是在紧张之中透露着一些让人跃跃欲试的兴奋感。
至于第一天的任务,简单粗暴——装软件。立刚告诉我了一系列开发可能要用到的软件,我就开始行动了。在D盘新建一个Program文件夹,用内网工具找到软件、下载、双击、一连串的“下一步”、完成,然后就进入了一个比较漫长的等待时间。等待是件好事情,这样我就可以继续刚才的事情:观察这些“大佬”。
在我前排左前方同学的装备首先引起了我的注意:一台Mac本,架在一个笔记本支架上;一个敲起来“啪啦啪啦”响的略大一号的无线键盘有节奏地在他手里响着,这应该就是传说中的“程序员最爱装备之一”——机械键盘了;大体看了下周围的同事们,用Mac的还真不少,几乎和装Windows操作系统的电脑在数量上是差不多的。想起刚领电脑的时候,管理资产的同事问我:用的是Windows操作系统吧?当时没想到他为什么这么问,现在终于明白了,还是可以选Mac的。不过这对我影响不大,如果给我一个Mac,我拿到手要做的第一件事一定是装上虚拟机,然后再装个Windows操作系统……除笔记本外,他在自己右前方还立了一台近30寸的显示器,笔记本上应该是某种IDE(集成开发环境)的界面,显示器布局则是黑底,并且只显示命令行及输出内容,那应该是与服务器的交互界面。虽然笔记本被垫高了,但他还是放低了身子,背部紧靠在那张符合“人体工程学”的椅子上,头微向前伸。我猜测,这是一位身材比较伟岸的大佬。看着这写代码的专业范儿,不禁让我有一种想向他学习的冲动。
在我前排右前方的同学不在工位上,但工位上的多肉还是挺显眼的,在工位橙色与白色的大背景下,这一抹小绿色更是可爱。不过,为什么他的工位上也有个笔记本支架?不禁环顾了一下整个办公区,虽说这种笔记本支架并不是谁都有,但这玩意也不能算少了,估计有两成的工位上都有它。转过头,我不自觉地摸摸自己的脖子。
瞅一眼自己的电脑屏幕,一个软件装完了,接着,执行同样的步骤:用内网工具找到软件、下载、双击、一连串的“下一步”、完成,然后又开始了等待时间。
往前数两排,只见一个女同学指着自己的笔记本电脑屏幕,正对着旁边的男同学讲着什么。我起身去打一杯水,顺道想看清些细节。女同学跟之前海布介绍时见过的女同学不太一样,要说哪里不一样,乍一看还真是指不出来,只能说是给人的感觉不太一样。临近了,看仔细了,我才意识到:她化了淡妆。嗯,这应该是位产品经理。那他们沟通的过程,一定是在对接需求了。只见女同学轻声细语地讲几句,然后看了看旁边的男同学,男同学点了点头,然后女同学继续讲。有的时候,男同学也会回应几句,我听到一句“这个接口确定要返回用户昵称吧”,便自然想到,他应该也在一起配合着明确需求内容了。我回到了座位上,那位女同学的需求好像也对接完了,笑嘻嘻说了声:“辛苦啦!辛苦啦!”那位程序员同学应该听多了这种话,说了声“嗯,没事”,就又面无表情地转过头,继续写代码了。
又一个软件装完了,这个软件装得真快,接下来,我要装个大点的软件。然后,我看了看还没有装的软件,开始安装占磁盘空间最大的那个……
偷偷看了看我左边的立刚,他貌似在百度着什么。仔细瞅了瞅,他居然在百度“python urllib2.open”这个函数……我原以为,这里的程序员写代码都不需要查这些接口和API,都是直接行云流水“一码到底”,就像是电影里演的那样。没想到,像A公司这么大的公司,程序员不光写代码时是一字一顿地写,也会采用一些我本觉得像我这样的新手才会用的手段。顿时感觉,成为一个优秀的程序员,或许并不太难。不过,我马上又看到了他IDE上各种复杂的代码逻辑和注释,又小小一惊:还是别过早下这种骗自己的结论了。
远处海布站着,跟旁边一个高高大大,并且脸上透露着沧桑感的人在聊天,他的衣着相貌和大家相差不大,但直觉告诉我,他不是一个一般的人。我问立刚:“立刚,那个跟海布聊天的人是谁?”立刚回答:“啊,那个是咱们部门的老大如风。海布是咱们小组的老大,他是咱们部门的老大,也是海布的老大。”大Boss,终于见到了。不过,我马上把视线从那里移开了,要是被大Boss发现我在偷窥……啧啧,还是不想后果了……
在办公区最前方,我注意到有一片地方,光线显得尤其明亮一些。趁着装电脑的空闲,我慢慢走过去,原来是一片休息区。这里的布置与装饰显得很休闲:淡黄色纹理的木地板,像酒吧吧台式的大方桌,还有一台巨大的自动售货机。靠着墙有一个细长的白色桌子,桌子上放着些枸杞、冰糖、菊花茶、绿茶等饮料原料;还有一台热饮机,提供咖啡、奶茶等热饮……工作之余,到这儿来一杯饮料解解压,是个不错的选择。“互联网公司还是很棒、很人性化的。”我默默地想。
闲逛一圈,我又偷偷往工位方向撤。咦?我看到了奇怪的东西:我正前方的同学,居然在上淘宝!莫非公司没有上班时间不能上与工作无关网站的规定?当时我疑惑了好一阵,后来想想,那时的自己实在是紧张地有些神经质了。
最大的软件装完后,我又把其他小软件很快速地装上。软件算是都搞定了。
想起之前行政妹子跟我说过,装完电脑,要先打开内部通讯软件钉钉。于是,我打开了钉钉,看到行政妹子给我弹的消息,内容是几个压缩包。我打开压缩包,阅读里面的内容,都是上班和生活的一些流程性事务和小提示,包括班车时间、怎么取寄快递、周围有哪些好吃的、怎么使用内网工具办公等。“大公司想得就是周到。”我想(虽然我并不知道小公司是什么样的)。
因为是下午来报到的,忙完这一阵,已经到了晚上六点半,嗯,差不多该下班了。看看周围,有些同事已经准备要出去了。那应该是可以下班了。我背上了包,跟立刚打了个招呼,立刚颤颤巍巍说了声:“明天见。”当时我还没了解他为什么会显得有些惊讶。走到门口等电梯时,我发现门卫看了我,也露出和立刚同样的惊讶感。嗯?难道我脸上有什么脏东西?那为什么他们都不告诉我?我抹了抹脸,并没发现什么异常。
第一天的工作算是结束了(如果这样的一天也算是工作的话)。总体感觉呢,互联网公司和之前的研究院,或者从同学朋友那里听到的一些公司不太一样。它更有人情味儿,也更加充满活力,至于其他,我还是慢慢发现吧。
但是,最后立刚和门卫脸上露出惊讶的表情,还是不能让我释怀。直到第二天,同样六点半下班的我,见到门卫终于忍不住问了一句,他的回答让我出了一身冷汗:“你是我这几天见过下班最早的人。”“不对啊,其他人不也刚走出去吗?”“他们都没带包,是去吃饭了。你带着包,显然是要下班。”
惊呆!真是个愚蠢的职场新人!
对于一个刚从学校毕业的职场新人来讲,入职后最重要的事儿就是学习了:学习各种在工作中将会用到的技术、各种业务逻辑,还要学习公司章程、员工准则。当然,还需要学习职场中高深莫测的人际关系。
来A公司之前,我一直在做嵌入式技术和通信技术,接触互联网技术的东西甚少,所以,需要学习的东西就多了。立刚是一个职场“老鸟”。对于在工作中用什么工具可以让工作更高效、掌握什么知识可以长期受益,就如同一个资深演讲家一样,说起这些东西滔滔不绝。听海布说过,我安排做互联网后端服务。通过立刚的介绍,我也终于明白了什么是后端服务。
立刚清了清嗓子,抖抖手里的笔,一边在纸上比画着什么,一边开始了他的“演说”:“自打互联网发展起来以后,连接就成了属于互联网最主要、最重要的功能。从技术的角度来说,互联网系统的作用,就是建立连接。设计一套互联网系统,并不是想实现什么功能,就实现什么功能,而是需要通过严密的设计,构造高可复用的框架,形成稳定的架构,才能在功能、效率和稳定性上都可以得到保证。对于这里的框架,我们可以理解成在软件系统中,针对被重复使用次数比较多的功能,剥离出这些共同使用的功能,用一种编程语言实现,就形成了一个框架。一个系统中可能会用到很多框架,也有很多非框架的部分,充分考虑这些技术要素的特点和他们之间的关系,根据要实现的功能,把他们有机地组织起来,就形成了架构。软件架构就如同房屋的架构一样,好的架构能让软件系统更加稳定与牢靠,同时可以减少软件开发周期,提升软件运行的效率,并且方便迭代更新版本,更利于协同作业。在互联网技术领域中,常见的架构就是C/S架构(客户端-服务器架构)和B/S架构(浏览器-服务器架构)了。这里说的C(客户端),包括PC上的软件、手机上的APP等;这里的B(浏览器),包括PC上的浏览器和手机上的浏览器以及手机上相关的浏览器引擎。这些‘端’都与用户直接相‘接触’。服务器端实现互联网应用信息处理与计算服务,但相对来讲,它是远离用户的。我们把与用户直接相连的这一端,叫作前端;把距用户相对较远的服务器端,叫作后端。在发展过程中,后端再次演化,就形成了如今特别常见的‘服务端+数据端’的模式了。”
立刚是一个逻辑性很强的人,讲得行云流水,极具感染力。他全神贯注地讲,我一边听,一边记着笔记。而后我又反复琢磨着他讲的这些话,又查阅了一些资料,算是理解了前后端和数据端的概念,也算是开了一个头。看了看立刚给我罗列的接下来要学习的东西,足足有一页A4纸那么多……这可有的忙了。
常听一些职场老人讲,职场中所谓的学习,都是需要什么就去学什么。这一点在读研的时候是有些体会的。不过,现在对我来说,手里没有什么工程项目,还达不到那样的境界,像上学那样系统地学习基础技术知识,反而是一个更不错的选择。拿起要用到的基于Java的Web教程,搜一些教学视频,一边学习,一边在自己的电脑上鼓捣鼓捣,时间过得也是极其快的。只是有一点我不太明白,我面试时的岗位是C++开发工程师,为什么来了就成了做Java的?好在有这个心理准备:作为一个新人,尽可能大范围地去学习是必须的,既然人家让你去学习Java,就是相信你学得会,这个时候要是还计较什么“没学过,不熟悉”之类,就太禁不住考验了。“噗,或许所谓的‘工作中需要什么,就去学什么’有这个意思?”我心里想。
没过几天,属于我的又一个小考验就到来了:一位同事因为组织调整要换部门,需要交接手里的一个项目,组里貌似就我一个人手里还没有项目,所以海布就把这项任务交给了我。入职以来第一次与项目接触,有可以听大佬讲解代码的机会,我终于可以切身体会到因为技术而带来的既紧张又激动的感觉了。
要交接的项目是一个爬虫项目,并不是一个后端Web服务。这也意味着,我又有新的东西要学习了。要对接项目的同学叫开睿,来A公司有两年,总的工作时间五年有余了。立刚跟我讲,新人还是主动些好,我就在钉钉里联系了开睿:“开睿,你好!我是海布安排的要交接爬虫项目的同学,叫途索。你什么时候方便呢?方便的时候我去找你说说项目吧。”发送完毕,盯着这条消息,心里一阵嘀咕:用“你”是不是不够礼貌,是不是应该用“您”?我用不用说自己的名字?编辑完这条信息,应该问问立刚这样措辞到底合不合适,太沉不住气了,这要是给大佬留下了不好的印象,接下来还怎么在公司混?忐忑了几分钟后,终于收到了回复:“过十分钟,咱们休息区见吧。”看这样子,应该是我多虑了吧。我立刻拿上电脑,带着笔和本,直奔休息区,想着接下来该怎么去交流……不得不说,社交真是我的一个大的软助。过了不久,一个身材魁梧、身穿红黑格衣服的青年,快速迈着大步向我走来。我准备了十几种开场要说的话,还没有选好说哪种,开睿先开了口:
“途索,是吧?”
“嗯,是的。”
“好,那我们开始说。”
就这样,假设了各种场景下的应对方式,用不上了……
开睿打开电脑,把这个项目的文档发给了我,然后开始了他的讲述。
“这个项目的主要模块我在文档里都有介绍,不过文档写得也比较简单,你可以参考一下……”
我粗略地翻了翻文档。这份文档确实不算是“正规”文档:虽然也有总体设计的框图,但图形也仅有方形和圆形两种形状,图形颜色也一律是默认的淡蓝色,图形之间的关系也只用了一种箭头样式来表示。没有规整的排版,区分各子模块介绍的部分,也仅用一行黑体小标题来标示。
“这个项目的目的,是用这个爬虫工具,抓取某网站的基础信息和评论信息。它主要分成这几个模块,这个模块可以理解成第一个运行的入口模块了……”
开睿开始滔滔不绝地讲,想起之前面试时自己讲述项目的经历,再看着开睿流利讲项目的样子,不禁感慨:一个技术人,面对只要是真正用心做过的事,不管他性格是内向还是外向,讲到这件事总会以最通顺、最自然的方式表达出来。
关于爬虫,之前我只是知道它可以用来抓取和捕获网上我们可以看到的大部分信息,不过由于我没有做出过一个完整的爬虫程序,所以,为了能达到与大佬交流的“基本水平”,我提前特意在网上找了很多资料查看。
“这个部分的代码,”开睿指了指自己电脑屏幕上一部分代码,“这个是调用JS渲染引擎进行渲染的部分。”
JS引擎渲染,还是JS渲染引擎?这是什么东西?此时,我特别想打断开睿一下,问问这个JS引擎是什么,但看开睿很自然地接着往下讲,我又想:这会不会是一个特别简单的概念?问出来是不是显得特别傻?算了,还是回去使用那个我能搞懂的引擎——搜索引擎吧……于是,我低下头,很认真地在本子上记下“JS引擎渲染?JS渲染引擎?”然后打了大大的问号。
“这个函数,就是调用URL进行请求数据的函数,函数的这部分,可以指定参数……”
这个我在网上查到过,终于看到了一些眼熟的东西,对于这块理解也比较快,不过,我还是注意到了一个之前没有见到过的参数。正在盯着看,开睿好像也注意到了我的疑惑,问:
“这块有什么问题吗?”
“嗯,这个参数是什么意思?”
“这个啊,是请求数据时需要的cookie信息。”
cookie……之前见到过,是干什么用来着?算了,先记小本本上吧。
“这个模块,作用是把数据整理好,然后存入数据库。比如你看这块代码,直接用这个Java包,解析网页的评论部分信息,然后在这个地方写入数据库……”
看着开睿指给我的代码,我发现一个现象:有些代码,显然是被精心设计过的,用到了各种封装技巧,代码逻辑也是井然有序,比如像数据入库这部分;但有另一些代码,就显得比较乱,连我这样写代码没几年的人都可以看到,这些代码是可以有更好的安排与设计的,比如解析网页到单个具体字段的部分,存在较多的重复代码,完全可以提取出来写一个函数,替代这部分的重复。为什么会存在这种情况?不管这个了,先理解了代码逻辑再说。
“代码的SVN地址我一会发你,还有什么问题没有?”
我看了看小本本上的一小堆问号,脑子里还想着刚刚开睿讲的代码逻辑。还是回去先自己整理整理思路吧,那就先回复“没有问题”。
“暂时没有问题了。”出口之前,加上了“暂时”二字,还是给自己留条后路吧。
“好的,有问题联系我就好了。”
说完,开睿拿起电脑,又以同样大步流星式的方式走出了休息区。我也拿着电脑、本子和笔,一边想着刚才开睿给我讲的东西,一边慢慢回到工位坐下。开睿发来了SVN地址,我申请了权限(填写“申请理由”时又花了三分钟想措辞),就开始学习我的第一个项目了(虽然是交接维护的项目)。
对照着本子上的十几个疑问,我开始用搜索引擎查它们的含义,不过还是遇到了两三个没有查到的概念。“这些应该是可以直接问开睿的。”我打开本子,腾出新的一页,把这几个概念又重新誊写了一遍,准备抽个时间再去问问开睿。
我把代码下载了下来,开始读代码。有句话讲:世界上有两件最难的事,一件是把别人的钱装进自己的口袋,另一件就是把自己的思想装进别人的脑袋。别说把自己的思想装进别人的脑袋了,就算是我主动配合,做好准备,等着被别人灌输他们的思想,也是很难内化和吸收的。这份代码,刚才开睿讲的时候头头是道,一个模块一个模块显得很协调,而现在在我看来,又成了一团乱麻。好不容易找到了入口模块,回想起开睿刚讲的有关入口模块的功能和层次,理顺了七八行代码后,又见到一个不知道的函数调用。于是,我一层一层深挖这个函数的实现逻辑,试图想搞清楚这个函数的作用。没想到,在这个函数的实现细节里,又调用了另外几个不知名的函数。没办法,我就一个一个再继续理顺这些函数的实现逻辑。终于,函数功能理完了,但最早遇到的几个函数貌似已经忘得差不多了……更糟糕的是,我依然不知道这么做的意义是什么……当然,还是更更糟糕的:“我为什么要看这个函数来着?刚才的代码看到哪行了?”于是,我又拿起我的小本本……“一边看,一边记吧。”我对自己讲。
好不容易把代码整体过了一遍,看看小本本上的乱七八糟的笔记,再努力回想一下自己记住的东西,好像也没什么记住的东西,只有一些零零散散的概念和代码段。于是,瞬间感觉这一遍代码算是白看了。“还不如让我自己写代码呢,读别人的代码真是痛苦。”我想。
但是,项目交给我了,还是要硬着头皮上的。第二天早上,我早早地到了公司,喝了一大杯咖啡,打开电脑和小本本,准备跟这个代码接着死磕!
第二遍,第三遍……读着读着,发现之前的代码好像没有白读,每次重读代码,都会读出些新的东西来,而且这些东西都是基于之前读代码记下的内容所衍生出来的。有些代码虽然写在前面,但想知道这块代码的含义,读过后面的几个模块才能理解得更加清晰;有些代码只使用过一次,本可以直接写成大的代码段,但封装成一个接口、函数或者类,就成了一个构件,换个项目也可以使用;有些代码,看起来很不必要地嵌套了好几层封装,但研究起来才发现,在编写或者修改一个函数或者类时,这样的设计可以让我们不用关注其他函数或者类的调用和依赖关系,节约了宝贵的“大脑资源”……把这些一一参透,慢慢也就了解了开睿当时在写这段代码时的一些想法,一方面觉得开睿的技术水平确实了得;另一方面,也因为真正了解了写这些代码时的思想,感到了一丝丝的成就感。想想之前还说“宁愿让我自己去写代码,也不读别人代码”,就觉得自己很傻、很天真。
再后来,我再拿着自己读代码时没有理解的部分去问开睿,底气就显得很足了。与开睿的一问一答,不再是之前“过滤式接收信息”的模式,此时我真正体会到了他在帮我整理思路的感觉。
我把自己这几天的经历和感受跟立刚讲了讲,他对我说:“读代码确实是非常好的学习与进步的方式。”在肯定了我的想法之后,他又问我:“你看过Spring的源码吗?”Spring是一个Java企业开发中常用到的编程框架。虽然之前对着一本编程书使用过这个框架,但对源码还是敬而远之了。于是,我摇了摇头。立刚紧接着说:“你不仅要看同事的代码,还要多看一看优秀的开源代码。优秀的源码汇聚了更多人的智慧,研究这些,会让你学到更多。”我点了点头,紧接着就在IDE里建了Project,下载了一份Spring源码并加到了这个Project里。
就这样,我白天理解开睿的代码,晚上就研究Spring源码。研究Spring遇到了和之前一样的诸如理不清的代码逻辑、不懂上下游关系的问题,甚至还遇到了更多之前没有遇到过的问题。有些调用的接口,甚至逐层往里跳,跳转到已经不能再跳转了,最终还是一个我没有见过的调用(猜测是一个生僻的系统调用)。有了之前的经验,再面对这些问题时,我就淡定了不少。因为我知道,“码读百遍,其义自见”,最终我还是会明白的。立刚跟我讲,常见的系统调用类的东西可以用搜索引擎解决,权威的解释官方文档可以解决。不得不说,立刚真是一个老开发者,给的建议真是帮了我不少忙。
一边与老开发者交流,一边读代码的这段日子,是我个人觉得成长比较快的时候。这段时间,意料之中的事是更加熟悉了Java语言的语法、调用、函数,不过相比这些,更重要的是一些意料之外的收获:我有了自己的架构观,开始用一种“设计”的思想去看待代码,开始主动思考之前接触过的“多态”“封装”“设计模式”等高阶玩法的意义。想起在毕业前,一个从事过多年开发工作的学长讲过:“一个开发人员,应该把七成精力放在代码结构设计上,实际写代码的精力不应该超过三成。”此刻,我才觉得懂得了他的话。
过了几天,开睿带着一个长得还挺好看的女同学找到了我。
“途索,这位是爬虫项目的产品经理,赫雅。咱这个项目有新需求了。”然后,他转身对赫雅说:“这位是这个项目的新的开发同学,途索。以后这个项目的需求直接提给他就好了。”
赫雅对我笑了笑,礼貌地打了个招呼:“你好,以后多多指教。”
我还没开口,开睿马上插了句:“那这个项目就交给你了,要还有什么细节问题,问我就好。我先走了。”
“嗯……”
我还没完全反应过来,开睿又像风一样地离开了。
产品经理和研发人员怎么配合工作,这样的流程我还不是很了解。虽然我认为产品经理与研发人员协同工作的方式也很重要,但我觉得这还不是我现在应该系统性关注的内容。我的脑子里只有一件事儿:怎么把属于我的第一个需求完成好。
赫雅一上来就开始讲这次需求的背景和具体需求项,看来她也是一个追求效率的人。这次的需求主要是要扩充一些数据字段,也就是说,之前在解析网页时,有些内容没有被存入数据库,而现在,这些内容要用起来了。赫雅讲得慢条斯理,声音中带着些严肃,听起来很专业的样子。本来想到这是我大展身手的好机会,在她认真与正经的腔调的影响下,却又显出了几分紧张。
“好了,需求说完了。大约多长时间能完成?”
经过了几天刻苦的学习,这样的需求对我来讲,不算太困难。想到这儿,我回答:“一天吧。”
“一天?那太棒了!”
从她的反应中,可以听出一丝有失严肃的喜悦感,这也让我的紧张感又增加了一分。
说干就干!我又整体捋了一遍代码,找到了解析网页数据的部分。接下来,就是找到需求中的那个字段位置了,怎么找来着?貌似可以在网页上单击右键,直接看源代码。呵,一大堆字符出现在我眼前,这可怎么找?一点一点找吧……找了十分钟,可算找着字段名了。提取这个字段名得厘清这个字段相比于整体网页结构的位置。啊,又得小心翼翼再找一遍?好在立刚看到了我焦急的傻样儿,告诉我浏览器中的“开发者模式”功能可以直接看到网页的树结构,我才知道,这种事情其实一分钟就可以搞定的。“不光后端知识要学,前端知识也要恶补。”我不服气地想。
代码算是改完了。可我还是不踏实:“改动了这块,不会影响到其他模块的正常功能吧?”我来回翻着代码,到头来,还是无法说服自己“肯定没有问题”。于是,我又打开了钉钉,打开了与开睿的对话框,输入“开睿,忙吗?什么时候有空?能帮我看下代码吗?”,发送。可能开睿有些事忙,过了一个小时,他回复我:“我去找你。”而在这一个小时里,我觉得我差不多又把整个代码读了一遍……
“这么改是对的。自信点,没有问题的。上线吧。”开睿没瞅几眼代码,就给出了结论。听了这些,我总算是放心了。
之后开睿告诉我服务器地址,帮我申请了权限,教我上线流程,就离开了。他离开以后,我收到了一封邮件,是赫雅发的需求邮件,抄送了一整行密密麻麻的收件人,我只认识海布和开睿。不过,我已经完成开发了,在收到需求邮件之前就搞定开发工作,这算不算是提前完成任务?想想心里还有些小得意。
终于要上线了,我就像做神圣的祭祀活动一样,每进行一个步骤都像是在操作一件圣器。此时我才发现,SVN没有拉分支,代码写完没有加注释,对应文档也没有做修改……这样,我又把之前的思路清理掉,重新思忖着先干什么,后干什么。
总算是成功地上线了。第一次接需求,总体来说还是很紧张的,虽然整个过程不算是完美,但结果看起来还是不错的。
不一会,收到看上去是下游使用方发来的邮件,确定系统运转正常。此时,我才真正有了一种放松的感觉。
“丁零零……”又是新的一天。
工作差不多一个多月了,我已经习惯早上七点左右起床了。为了节约住宿开支,租住的地方离公司比较远,坐地铁的话,大约需要一个小时,算上“某些不确定因素”耽误的时间,差不多得用一个半钟头去公司。就这样,七点起床,半小时洗漱,再加上一个半钟头的地铁,差不多九点我就可以到公司了。公司并没有要求我们必须几点上班,也不强制打卡,只是建议十点到岗。不过,作为一个新人,我还是想着尽量早到一些,力争能增加几个宝贵的印象分。
在拥挤的北京,地铁可以说是最准时与靠谱的交通工具了。不过,这个大前提是你得先挤得上地铁。我所居住的地方,正好处于住在城郊上班族进入市区的一条主要交通线上,每天上午七点半到八点半,是这条交通线入城方向最拥挤的时候。好不容易挤进了地铁站,排在几米长的队伍的后边,此时看到一辆满载着人的地铁开过来,但基本上没什么人下车,内心多少是带着些崩溃感的。有些排在队伍前边的上班族,会仔细寻找着挤在车里的人与人中间的缝隙,一旦发现了一个手掌宽的缝,或者发现估摸着自己的脚能完全踩在车厢里的机会,就会使把劲,把自己拱进车厢。就这样,看着一个个扭曲的身形被列车送来,又看着一个个更加扭曲的身形被列车送走,内心居然不会觉得怜悯,反而有些小羡慕——至少,他们是上了车的“幸运儿”。要是没有这么多人,我能顺利地挤上地铁,一个小时就可以到达目的地。而由于这骨感的现实,我每天不得不花半个钟头来进行这无谓的等待。
九点左右,到了公司,跟门卫打个招呼之后,我迅速走到自己的工位坐下。环顾一周,只有两三个同事在。然后接一杯水,吃完从楼下小摊买的灌饼,就开始接着读昨天还没有搞明白的代码。
十点左右,同事们陆续就位。有时抬头间与某个同事对视了,就马上说声“早”。立刚也来了,刚坐下,就抱怨了两声:“今天地铁人太多了,全北京的人都出来坐地铁了吧!”我没好意思提醒他透过窗户看看外面水泄不通的马路……
虽然同事们差不多都到了,不过有那么一段时间,是没有上班的氛围的:有同事刷着新闻,有同事看着股票,有同事逛着论坛,还有我右前方那位,在摆弄自己的小多肉……这样过了十几分钟,节奏逐渐紧张起来,才算是进入到工作的节奏了。
一旦进入工作节奏,办公区就会显得特别安静。有时几个产品经理会过来和研发讨论讨论需求,有时几个同事会对某个技术问题有些争论,这才能在办公区听见一些人的嗓音。写代码是我的这些程序员同事的主要工作,但这也不意味着除了写代码他们就没有其他的事要做了,他们还会花更多的时间用在读文档、设计代码结构、进行不断的试验等这些代码以外的附属操作上。此外,参加各种需求评审,或者不断地与产品经理、项目同伴核实实现细节,也会消耗掉他们的“精力值”。这些事情不会带来什么肌体上的疲乏,不过大脑可能会消耗掉比让肌体疲乏多得多的能量。虽然才工作一个月,但我已然感受到了这些。
上午的工作时间很短,不久便到了吃饭时间。我所在的办公楼并非A公司的总部,有些基本设施自然就没有跟得上,比如食堂。所以,一到午饭时间,大家就一窝蜂地往外跑,扫荡公司周围的小馆子。在来A公司入职的前几天,我买了不少厨具食材,几顿折腾,终于学会了做饭。在入职后的一段时间,我都是坚持“带饭”上班的。中午大伙都出去吃了,我就在公司专门开辟的“饮食区”,用微波炉加热一下自己带的两道菜和一份米饭,然后迅速吃掉。之所以选择带饭,除节约成本以外,更重要的,还是对社交有一种比较大的抵触感。一想到中午与同事一起出去吃饭,得想话题沟通交流,就有些内心的不适感。不过,我也知道,这一切是躲不掉的。终于,想通了这必须要走的一步,同时也因为自己的惰性(不想做饭了),我加入了一个饭团。
至于为什么会加入这个饭团,地理位置应该是比较大的影响因素了。立刚是一个有毅力的“带饭”人,其他周围的同事同属于一个饭团,中午出发前有人看我落了单,也常会叫我一起去,我也就顺势加入了这个饭团。
饭团算上我一共八个人,从正式行政层级上来看,大家都是一个组的,但从项目的角度来说,大伙又分散在四个不同的项目中。加入饭团第一天,一个微胖一些、穿着冲锋衣、与我差不多身高的同事主动找到我,问了我好多像“你从哪毕业的”“之前做什么的”“为什么没带饭了”之类的问题,我讲到之前在研究院做的事,他还会顺势追问几句。我呢,人生地不熟,再加上没什么沟通技巧,只是问什么就答什么。他叫冷烨,有五年职场经验,在A公司工作两年了。“那你做饭一定很好吃吧?”“还好还好。”“哦,那挺好。”一问一答的模式,再加上一个不会主动发话题的回答者,几个回合下来,就偃旗息鼓了。蛮尴尬的。虽然对于这样的对话已经习以为常,但感觉总归是一个好现象,开局不太完美,不过算是开始了,慢慢熟悉吧。
饭团里有两个女生,一个是之前我偷偷调侃过的许楠;另一个女生,个子特别小,显得特别可爱,名叫惟爱。她们一起慢悠悠走着,聊着一些生活小技能、周末去哪玩之类的话题。走在最前面的有两个同事,看上去有三十大几,很兴奋地聊着什么,不经意间瞅到了其中一个人手机上的红方块和绿方块,猜着他们应该是在聊股票了。冷烨给我简单地做了介绍,一个叫乎克,另一个叫俊崖,他们都有六七年的工作经历了。还有两位,一个是在侃侃而谈昨天的互联网巨头B公司收购某团购网站的大棋局,另一个则是若有所思,有时接上一句,更多时候,则是一言不发,看起来很认真地听着。冷烨告诉我,这个话比较多的叫问生,这个不怎么说话的叫颂勇,工作都不到三年。
饭点时候,小馆子里很是热闹,不过好在人们吃得也比较快,我们很快就落座了。落座点完饭,只见几个人齐刷刷拿起了手机,本想主动突破一下,找些话题的我,为了不显得不合群,也只好拿起手机。有时,乎克会不禁再与俊崖聊上几句关于某支潜力股的具体走势,许楠也会不经意地讲些她刚看到的段子……我心不在意地瞅着手机,心里想着是不是要学些股票知识,造些话题聊聊。
午饭过后,园区里到处都是遛弯的男男女女,他们七个也是要去小逛一圈的,我决定还是先回去了,这次的理由不是“社交恐惧”了,而是一个从小养成的习惯——午休。那张椅子,躺着还是蛮舒服的。
简短的一段午休以后,是一大段的工作时间。很多同事都会选择在上午的时候设计实现逻辑和模块布局,而把专心写代码的时间放在下午。上午的时间不多,按照最为普遍的情况,最多过两个小时就会进入吃饭时间,如果把写代码放在上午,两小时之内写不完这段代码,就不得不放在下午去写,中间就会有一个间断。据我观察,大多数程序员是比较讨厌在写代码的时候被中断的,不管是什么原因。写代码时,大脑在高速运转,从敲下第一行代码开始,接下来的时间就被分成了几个阶段,在每个阶段里,程序员都会用符合自己思维的方式在脑子里搭下一个个看不到的逻辑模块和结构,这些逻辑模块和结构在下一个时间阶段里会被直接用到,同时,要完成的功能的整体架构,也是会被程序员牢牢记在大脑中。如果此时中断了手里的工作,去吃个饭;或者,被某些人打断,问了个问题……那么,当前这个时间段的东西(很有可能包括之前时间段所建立起的逻辑基础)全都土崩瓦解。要再厘清楚整个脉络,得往前倒好几步,甚至得从头开始。有些程序员在下午这段宝贵的整块时间内,不看钉钉,不看邮件,同时在个性签名里写上“下午X点到X点专心写代码”。也正因如此,或许你什么都没有做错,只是因为多和他们说了一句话,他们就会显得有些不高兴。被打断思路的这种难受,程序员可以说懂得痛彻心扉。有时,你会看到一些程序员,在写代码中间,停顿一会儿,伸个懒腰,或者很闲适地打个水,拨弄两下手机,再或者出去抽根烟,买杯咖啡什么的,那么他很可能是搞定了某个重要的阶段性任务,或是完成了一个模块的开发,或者做好一条琢磨已久的处理流。不过这也只是一个小憩,接下来,还有同样需要集中注意力的时间等着他们。
晚上六点过后,有些同事起身拉帮结伙开始往公司外走。刚来公司前几天闹出的乌龙还历历在目,现在我知道,他们只是去吃晚饭去了。他们中的大多数,还是会回来的。其实有些同事也是会直接下班走人的,不过他们大多数会离开得比较晚一些,反正,不会像我第一天那样,六点多抄起包就走人。
晚上又是一段大块的时间,而且,比下午那段时间更宝贵的是,这段时间几乎没有什么人打扰,可以更专心地写代码。所以,很多人都选择加班。这个“很多人”究竟有多少……嗯,不少……有段时间我特别想知道,是不是所有加班的同事都在写代码,为此还在几个办公区转了好几圈,发现加班做什么的都有:有在写代码的,有开会接着讨论问题的,有在看各种文档的,有利用这段时间学习的。A公司虽说是大公司,不过自己的事情,还是得靠自己。有了之前的教训,我也习惯了所谓的“加班”的节奏。要学习的东西有很多,与其在家过目,不如在公司环境的感染下专注完成。嗯,也显得合群一些……
脑力劳动有时比体力劳动更累。之前想着晚上回家可以拓展些业余爱好,可是真进入了工作的节奏,每天回家就只有疲惫,只想躺着,刷刷无聊的社交APP,或者打打游戏……之前业余生活的宏伟蓝图?呵呵。咦,找到了没有继续带饭的另一个理由了……
有了接手的项目,渐渐习惯了工作的环境与内容,立刚也逐渐放手,让我自己去发展。只是一直以来,我总认为自己是一个学习者,而不是一个能解决问题的开发者。我需要一个机会,来完成一个自我认知身份的转变。好在没等多久,机会就来了。
公司计划要做一套内部使用的数据管理系统,工期特别紧急,只给了一个月的时间。我不太明白一个内部使用的系统为什么会这么紧急,但看样子包括如风在内的技术人员都默许了。这套系统的服务端由海布的团队来做。海布最终选定了三个人来完成这件事:许楠、俊崖和我。我们三个与一位叫作柳蔷的前端同学一起配合来完成整个系统。当然,产品经理也是少不了的。他是一个叫呼哈的蒙古族哥们身担此任。
终于要搞一套全新的系统了!这其实是我所期待的一次锻炼的机会。但冷静下来,想到这是一个从零开始的项目,是一个要从无到有构建的系统,而且,将会有很多的同事使用这个系统,想到这儿,压力就代替了之前短暂的激动。经验是我缺乏的东西,做一个全新的系统充满了不确定性,不过好在身边还有两个有经验的“老师傅”带路,我倒不会怀疑这个系统做不出来。那么,最重要的事,就是怎么在这个系统里,尽量多地注入我自己的知识。
就像大多数项目一样,项目启动第一件事,就是开需求评审会了。内部系统的需求评审还不是很复杂:一个不是很大的会议室,坐着几个业务需求方的代表、产品经理呼哈、一个前端研发人员柳蔷、还有我们三个后端开发员。所有人员差不多都凑齐了。呼哈开始以他职业性的风范,让业务需求方陈述需求。业务需求方一边陈述需求,我们……哦,不,是他们三个研发员一边针对性地问一些理解不是很清楚的问题。我呢,还把握不到要点,最好还是拎起耳朵先仔细听。需求评审结束后,呼哈把所有沟通的内容整理成一份需求文档,以邮件的形式发给我们。接下来,就是我们四个确定技术细节的过程了。
前后端的交互,只需要确定接口即可。“即可”虽然说得轻松,不过确定接口也不是一下子就能拍板的事儿,即使用上几个小时拍了板,落到具体实施时,十有八九,还是要被再次拿起来的。所以,这个时候的交互只需定个大概。然后,就是我们三个人的分工了。如果之前想到有他们两个撑腰,完成这个系统我个人并不感觉到急迫的话,但在我们三个人分完工后,顿时感觉变了天。由于这个系统依赖的数据项比较多,数据融合和计算逻辑也很复杂,所以,最终决定由俊崖和许楠来负责数据处理与计算的模块,后端数据接口由我一个人完成……其实我是想拉他们当中的一个人和我一起做的,但一种“不好意思”加上“不能让人家觉得我能力不行”的想法,让我闭上了嘴。我们几个交流分工的时间不长,也许就20分钟吧。不过这20分钟前和这20分钟后,却截然不同。如果20分钟前可以从我脸上看到些兴奋与干劲的话,20分钟后我的脸上只写着忧虑……他们也就真放心把这么重要的东西交给我?
我们四个开发人员的工位距离比较远,由于项目比较紧急,呼哈为我们申请了封闭会议室。这也就意味着,接下来这接近一个月的时间,我们将会在这间封闭会议室里度过。虽然我本着尽可能多的学习的态度接受着周围的一切挑战,但这样的工作压力还是让我有些措手不及。
要干起来了!
我仔细回忆着这段时间所学到的知识……记得当时在看书、看代码、看各种教程时想着,如果要用这块内容的时候,直接把它拷贝过来就行。而真到了要做事情的时候,一方面是当初想着要拷贝的代码,已忘却七八;另一方面,即便是凭印象记得住的部分,把它们拷贝了过来,对它到底能不能运行成功,依然持有怀疑。为了恢复记忆,就不得不把当时看的内容再翻一翻;为了打消怀疑,就只好一次又一次地编译、尝试,直到确定了没问题,再接着走下一步。
带着惴惴不安的心情尝试了一些基本框架,确定每个要用到的功能都没问题后,我想到了那句“七分在设计,三分在编码”。于是,我开始沉下心思,一边思考着业务功能和数据依赖,一边开始设计模块。这样,我花了两天时间,一直在设计模块。虽然有了几个模块雏形,但到最终的完全成形,还需要比较长的时间。这两天中,我一行代码也没写。看看许楠和俊崖,已经在不断地敲代码了。说不着急,我自己都不会信。可想到自己下定了先构思、再写码的初心,还是劝自己坚持这么做了。
最终改变了这一节奏的,是产品经理呼哈。他注意到我一直在忙,但又不是在忙着写代码,似乎有点急了。呼哈虽然是一个看上去粗犷的蒙古族哥们,但情商水平还是很高的。他提醒我几件事:前端模块的构建要依赖后端数据接口的,后端数据接口没有做好,前端效率无法保证;虽然工期是30天,但过15天得做出一个原型Demo吧……我特别想解释一下我为什么这么做,但想想他说得也没错,最终的系统还是要尽快做出来的,有Bug可以改,但没做出来这个东西,那性质就变味了。并且,这是我的第一个从0到1的项目,想到现在这个时间提出太多困难,会不会是变相认了怂?无奈,我放弃了已经理通了一半的模块设计,开始硬着头皮写代码。
果然,没有清晰的思路,写代码的效率就是提不上来。之前想通的部分,还能抽象一个类,抽象一个函数,到后来,只能是想起啥就写啥,想起什么功能就写什么功能,用到什么变量就声明什么变量,常常一个函数,会写上几百行代码……之前写代码时,如果遇到了被重复用到的部分,我常会把这部分提出来设计成一个函数,或者封装成一个类,而现在,在“贪心算法”的驱使下,在能节省几分钟时间的“诱惑”下,“复制—粘贴”反而成了此时我最常用到的操作。而一旦调试时遇到问题,就要梳理一大片的代码。虽然隐隐感觉到这样是得不偿失的,但看着呼哈那急切的眼神,此时的我也想不出什么更好的理由来为一种不确定性冒险。
这样就可以节约大量时间,就可以按期完成了?才不呢。时间还是不够。怎么才能再争取来更多的时间?解决方法当然就是那老生常谈的两个字——加班。刚开始,我们四个会加班到10点或11点,过了五天,觉得时间还是不够用,就搭进一个周六。然而,还是看不到能如期完成的影子,就把下班时间再推迟到凌晨一点。到了最后那几天,不光搭进了周六日,我们还创造了加班到凌晨四点半的壮举。
封闭开发虽然看上去不如在开放办公区更舒服,不过封闭开发的效率确实是高,有什么疑惑或者不明白的,直接张口就问。我们四个程序员谁有什么想法,直接提出来,就可以同步一下大家的思路。对我来讲,更可贵的是,深入了解了三个资深互联网人的经验和历程。
许楠是一个办事极其踏实与认真的小姐姐。她是一个从农村出来的姑娘,虽然在城市上的大学和研究生,但她还是保持了一个农村姑娘所特有的纯朴和认真。有时,她会在我们忙得焦头烂额的间隙,讲上几句生活轶事,或是说一说她看到把自己都逗乐的段子。不管是在工作中,还是在生活里,在她脸上写着的都是真诚。她有一个非常好的习惯——会把常用的命令、调用等分类记在多个记事本里,同时定期还会加以整理,这样就形成了一个类似于计算机快速缓存的机制:想到什么用得比较多的操作语句,直接打开记事本就可以粘贴,稍微修改一下,就可以执行,大大提高了工作效率。其实之前我也想到过这么做,不过做得比较潦草,很多时候想到“这命令以后不会再用了吧”就没有去记。而许楠非常认真,把一切都整理得井井有条,仔细看看每条命令或者语句,都不是什么“高级用法”,但对于“快速”“高效”的目标来讲,这确实是非常有效的一招。
俊崖有三十大几的样子,不过面庞还是透露着一股挡不住的帅气。他是一个家庭与工作权衡得相当好的人。偶尔听他与他的女儿打电话,语气里透露着作为一个父亲的慈爱,就很能让人感觉到他满满的幸福。俊崖踏实、严谨的工作作风同样感染着我:说到技术,他可以把细节讲得非常精细,而且不用翻阅什么手册;解决同样的问题,他可以列出多种解决方法,着实看得出具有一个优秀技术深厚与扎实的功底。
柳蔷是一个前端程序员。据说,前端程序员多少会带着一些艺术范儿。他来看,确实印证了这一点:时尚的发型、前卫的黑框眼镜、潇洒的行事风格……让人感觉他不是一个程序员。他说话带一些南方口音,不过咬字却是蛮清晰的,应该是在北方生活的时间较长了。有时我会对前端的一些技术产生一些兴趣,会让他给我讲讲写前端是一种什么样的体验。他给我讲过许多遍的MVC,貌似像他们这样的前端程序员,熟练掌握MVC是必需项。因为我一直搞后端接口,他负责前端,我俩一直在校对接口参数问题。他跟我说,后端服务在做出来之前,应该先要有个接口文档,这样他就可以先快速写代码了。这个确实是我之前没想到的,一个科学、完整的工作流程应该是什么样的,我还没有一个完整的概念。不过,即使有这个概念,在呼哈那么急切的目光下,我也不知道那个时候我会不会搞个文档出来。我高中班主任说我性子里透露着一点“急”,可能这也是没有大局观,只知道先做当前看起来似乎更快的事的一种幼稚表现了。
我把因为需求紧急、没有时间整理代码的困惑跟他们讲了讲,他们听后露出一种过来人的笑,轻描淡写说了句:这很正常。原来,有这种困惑的不光是我一个,他们告诉我,很多项目因为工期紧,是没有时间设计得太过精细。即使你用心地设计完成了整个架构,如果需求发生一次较大的变化,很有可能之前的设计方案都要推翻重来。很多程序员都因为需求突然变动,不得不去推翻设计好的架构,而与产品经理“撕”起来。这其中固然有架构设计考虑不周的因素,但这种因需求飘忽不定而存在的风险,是谁都说不准的。“但一点都没有设计,也是不行的。”俊崖如是说。我又看了看自己凌乱的代码,想着自己应该是走了这个极端……不过还好,虽然代码是乱了些,逻辑我还是记得的。和柳蔷调试接口时,我能从一大堆看上去乱七八糟的大片大片代码里找到对应出问题的那一句语句。我默默地想:这代码要是以后交接给别人,我该如何解释当初为什么这么写?历史原因?历史有啥原因,无疑就是自己不是很说得过去的能力了。
离最终上线的时间还有十天,许楠和俊崖的数据都有了比较完整的版本,柳蔷的前端界面设计与开发也完成了,我的接口……也算是完成了……吧。按理说,是需要测试的同学来参与的。呼哈说,现在测试没那么多资源,只能我们自己测试了。呼哈说要自己先演示一遍看看。看着他一边演示,一边若有所思的样子,我一直在默默祈祷不要出什么问题……太天真了,怎么会没有问题?呼哈一口气说了几个“这儿好像不对”,我就一连串绷紧几次神经。虽然说不是所有的问题看似都是我这边的接口问题,但在我看来,每个问题都似乎与自己的部分有关。把代码写成“大片大片”的样子虽然看似写着轻松(其实并不是),要是修改起来,会是一番令人难忘的痛苦体验……幸亏,刚写完不久,还记得住哪块代码代表哪块功能。即使这样,也要十分小心刚刚修改的部分会不会影响其他模块;所有的修改项是不是都照顾到了……想起一个段子,说:程序员刚写完代码时,只有上帝和程序员知道这些代码是什么意思;一个月以后,只有上帝知道这些代码是什么意思。这个程序员,应该说的就是这时候的我了。
离最终上线的时间还有五天,呼哈带来了一个不大不小的问题。说这个问题不大,其实就是需求有些调整;说这个问题不小,是对我自己说的,这意味着,我又要改代码了……好吧,瞪大眼睛,再来一遍吧……一遍又一遍地修改,让那“一大段代码”变成了“更大段的代码”。
离最终上线的时间还有三天,呼哈的演示终于确认了。虽然主体完工,马上就要上线了,但我还是选择加班到12点:一遍又一遍地梳理这看上去乱七八糟的逻辑……
终于要上线了。对我这样头一次从零开始做一个新项目的菜鸟来讲,这一天又是异常神圣的一天。看周围的一切东西,所有的人都像是一尊佛,让我有想立马跪下来拜一拜,保佑上线顺利的冲动。这一天,我甚至在想,用自己的什么东西才可以换正式上线的无bug,不管是啥,我都换……
由于我们做的是一家公司内部使用的系统,部署上线后,呼哈就开始游走于各个该系统的使用方,收集反馈意见。
几个小时过后,呼哈终于回到了我们封闭开发的会议室,说:“功能上没问题了,已经开始使用了,小需求咱们后期再优化吧。”此刻,一种从未体验过的兴奋感与成就感遍布全身。他们几个显得比较平静,为了不显得太不合群,我没有把自己内心里的这种热烈的感觉表现出来,但上升的体温、急促的呼吸,还是部分地出卖了我自己。
第一个项目虽然同样充满了不完美,但看到同事们都在使用有我参与开发的系统,一下子就感觉自己已经不是一个新人,而是一个可以和他们一样,创造价值的互联网工作者了。回想这种自我认知的身份的转变,就是在一瞬间发生的,仿佛前几分钟还有一种微微的青涩,而几分钟过后,就感觉自己是一个堂堂正正的互联网人了。体验过了这种身份上的转变,再去想想那些加过的班、熬过的夜,真的就不算是什么了。
海布说我“干得不错”,同事也送来“这工具挺好用”的赞扬。此时,我有了两个想法:一个是千万不能让他们看我的代码;另一个是我终于有了自己的资本,可以去了解互联网更丰富、更绝妙的东西了。
经历的第一个项目是个“急活儿”,很多流程化的东西都被简化掉了。接下来的第二个项目,就显得非常完整了。
大概进入A公司半年的时候,我被安排做一个公网服务的后端开发。有了第一个项目的洗礼,本来想着做一个新项目其实已经没有当初的那种紧张感了,但一听是个公网项目,还是小小地被吓了一跳:公网服务,意味着要用到这个系统的会是广大的互联网用户。不过,再怎么紧张,也没有接手第一个项目之前那么手足无措了:当初做事前不知道遇到问题该怎么办,而现在已经很清楚,遇到问题可能会麻烦点,但总是会解决的。
这个项目由产品经理赫雅牵头。之前在交接开睿的项目时与赫雅有过合作,也给这个项目带来了一些亲切感。
首先还是开需求评审会。这次的需求评审会,规模比之前大了很多:一个大约可以坐十人的会议室坐满了人,此外还有人拿了小凳子加了座。而在座各位的职位名称也丰富了很多:一个运营、两个产品经理、一个交互设计、两个前端工程师、两个应用端工程师、一个数据端工程师、三个测试、一个数据库管理员(DBA)、一个运维、一个数据分析师、一个安全顾问。看上去这是一个大项目,几乎所有工种都为这个项目配齐了。在这个项目里,我被分配担任数据端工程师一职,不直接负责与前端的接口设计,主要负责项目所需要的基础数据准备和数据接口开发。想到不用直接与前端打交道,略微松了一口气。
赫雅是一个做事很有条理的人,从她开始阐述需求的时候就不难得出这一结论。关于先做什么,后做什么,哪些议题可以放在一起讲,哪些议题需要分开讲,哪些议题需要深度交流,哪些议题可以先带过、留着以后补充细节……一切都在她的掌控之中。除了赫雅之外,在场的还有另外一个产品经理,她似乎负责前端逻辑和界面,而赫雅负责后端、数据逻辑和前后端交互。
赫雅在大屏幕上投出一张特别大的几个点相互连接形成的图(Graph),图的节点都是一张张简单设计过的用户界面,节点与节点间的边代表了各个界面的切换关系。赫雅清了清嗓子,开始顺着代表初始界面的示意图节点讲述需求的细节。出席的工种多了,意见也就多了起来,几乎讲到每个地方,都会有不同的同学出来说一些他们关注的问题:有时是设计同学会问配色细节问题,有时是前端同学会问绝对布局和相对布局问题,有时是应用端同学问交互逻辑问题,有时是数据端同学(也就是我)问某个页面是否需要提供些额外的数据,有时是测试同学提一些特殊的情况,询问这些特殊情况要如何处理……各种问题和意见还是比较杂。好在赫雅是一个比较专业的产品经理,对得起“经理”这两个字儿,把即时可以解决的问题都解决,需要长时间去解决的问题记录下来,以待会后整理解决。
基本沟通结束以后,就是排期了。各个部分之间其实是有依赖关系的,比如前端部分要依赖应用端接口,应用端要依赖数据端提供的数据支持,排期基本也是根据依赖关系进行前后布排。前后布排并不是首尾相接,大多是有一段重合。很多时候,为了方便流程后面的同学可以早点开发,流程靠前的同学会先做一份假数据或者假接口,或者直接以文档的形式将数据格式或者接口样式固定下来,这样虽然让流程靠前的同学有了一些额外的工作,但可以有效减少整体的工期。对我来讲,比较兴奋的一点是,我终于可以自己给自己排期,有了可以按照自己想法去设计模块、写代码的机会。由于我负责的是数据端,在整个项目流程里比较靠前,所以排期也不能排得太任性。不过有了之前的项目经验,不太充裕的排期倒也不是什么事儿。毕竟,时间不够,可以用加班来凑。
根据我们每个人报的排期计划,赫雅把这些整理到一张甘特图上,排期就算是基本定下来了。
需求评审结束后,按照一个比较正规且流程化项目的角度来讲,就要进行具体的架构设计和交互设计了。拿我在A公司的经历来看,这个阶段最常见的有两种模式。其中一种我把它叫作集中式项目管理模式,在这种模式下会有一个总负责人,我们把他叫作架构师或者项目经理或者系统工程师……总归,要有这么一个人。这个人负责整个项目的需求控制、总体设计、进度控制、风险控制等。这个人虽然不用写一行代码,但他管的事儿可不少:产品侧的需求获取、需求生成、需求建模转化、需求验证、需求管理……这些需要他参与;研发侧的结构设计、模块设计、依赖设计、接口交互、架构设计等需要他亲力亲为;测试侧的测试方案、测试用例设计、覆盖分析、功能与性能测试指标等,需要他的决策;更多需要考虑的事项,如安全、并发、资源调度等,同样需要他做最顶层的设计,甚至,连交互设计这类可能极其专业的领域,也需要他参与进来,考虑与之相关及耦合的更多潜在因素……可见,这个所谓的“总什么什么师”就是“什么什么总在管”,那么对这个人的能力要求,也是极其高的(当然,薪水也得高)。他不会参与更细节的事务,具体细节的东西由各个部分相应的伙伴们完成。当然,即使是一个人不关注细节,仅考虑以上所有所谓的“高层设计”,把以上每个方面都做好,也是极其辛苦的。所以,面对一些比较大的项目,很多“总什么什么师”,会把一些模块,或者一些职责,转交给产品经理或者能力比较强的研发人员、测试人员等。我所见到的集中式管理的项目,明显的优势是有这么一个对全局掌控特别强的“中心”,不管项目中有什么问题,或者有什么新需求项需要增加,他总能站在全局,做出一个考虑各个因素后的综合决策。不过在这种模式下,真要对项目做一个更新,那么更新的周期也是比较长的。一个在开发或者测试看来很明显和简单的修复,有可能会在产生比较大的冗余工作后,才会得到解决。
与集中式项目管理模式相对应的,就是分布式项目管理模式(这也是我自己给它起的名字)。和集中式项目管理模式不同的是,分布式项目管理中不存在一个“什么什么师”角色在每个环节中身体力行,项目的各个要素由各个领域的负责人搞定:产品经理负责需要管理方面的一切形式、细节、流程;研发人员负责研发过程中一些设计、编码等环节;测试人员负责测试的方案、形式、用例……当然,这其中也会有一个人负责各个环节的推进,这个角色一般由产品经理担任。不过产品经理也仅是在全流程的角度上进行跟进和流程控制,细节方面还是由各个环节的专业人员去完成。分布式的项目管理模式将一个复杂系统的交互协调工作进行了拆解与分配,拆解与分配可能由一个架构师完成,也可能由各个环节的专业领域根据需求协商完成。虽然各个专业方向的人承担了更多的工作责任,但拿项目总体上来讲,是可以有效提升效率的。不过,分布式项目管理模式也充满了更多的不确定性:各个环节的专业人员素质的良莠不齐,可能直接影响到该环节与其相邻环节是否可以进行有效沟通;由于缺少一个对全局有掌控的人,所以问题定位可能也会更烦琐一些,遇到一个问题,常常会遇到你问到了某同事A,A把皮球推给B,B把皮球又推给C……也有可能,一个专业领域内的队友可能不是很专业,会拖慢项目整体进度,而且这种情况下项目整体会缺乏有效的解决办法;还有可能,各个环节内的专业人员各有自己的做事习惯,也就造成项目总体上缺乏统一的风格。
我们的项目采用的是分布式的管理模式,产品经理赫雅负责总体流程的控制。我们每个人把计划做好,赫雅按照排期表一一盯对每个人的进度是否与预期一致。
终于可以按照自己的想法做模块设计了,想到了之前做模块设计做到了一半被迫放弃,这次我已做足了多加班的准备。不过,这次做模块设计,反而快速了很多。有了之前项目的经验,对哪些功能模块可能会被复用,哪些功能模块之间可能存在依赖有了基本的把握。在进行总体设计时,思路清晰了很多,之前不知道该怎么布局的功能,这次不再迷糊。虽然有时还会遇到一些之前没有遇到过的问题,但一想到这些问题最终还是会被解决,心里也没有什么慌张的感觉,反而因为有了些模块设计的经验以后,多了一份信心。最终,用了比预想中少得多的时间,一张我自己看着像模像样的“模块结构图”印在了Visio上,也印在了我的脑中。在这段自己亲手“设计”系统的时间里,我常常会想到我的第一个项目,那个项目虽然完成得不太完美,代码更是不忍让同行瞅到一眼,但它让我可以以一个完整、全面的角度,从项目的视角来看待写代码这件事。第一个项目让我的想法有了实践与落地的载体,在以后的日子里,我做过了很多的项目,养成了在多个项目中被认可的系统架构观与比较成熟的设计思想,但我知道,这其中大部分思想的形成过程,都是在那个不太完美的项目中诞生的。
接下来,该真正写代码了。果然,理清脉络以后,写代码也迅速了好多。手指在键盘上飞舞,才觉得自己真正是一个程序员。不过,确实如之前我看到的程序员一样,写代码时,最担心的事不是遇到了什么棘手的问题(因为,问题总会是被解决的),而是正在你全神贯注地在“改变世界时”,被什么意外所打断。有时,产品经理过来确认一个细节,或者一个测试同学过来确定一个用例,再或者,有同事询问关于你维护的另一个项目的问题或使用方法,那么写代码的节奏和思路即被中止。可能在一些人看来,写代码时被打断了,一会接着写不就完了。可如果你亲身经历过了这一过程,你会发现事情并没有那么简单。这就像你正在一张桌子上完成一幅难度很大的拼图,这个时候你的妈妈突然告诉你要吃饭,把你桌子上的拼图全都拿开,放上午饭,等你吃完午饭,要做的并不是接着刚才的节奏继续拼图操作,而是把刚才被移开的拼图再小心翼翼地拿回来,尽可能把各个碎片放到和当时被移开时同样的位置。在这个过程中,难免会有碎片会找不到,你得花很多时间去找;也很难避免已经拼好的图发生破裂;还有可能,在“恢复现场”时,拼图碎片或半成品放的位置与之前的位置相去甚远,这样,你需要重新去把所有的碎片再看一遍,再想下一步怎么拼。本来,可能一鼓作气搞定这个拼图用一个小时就可以了,但如果被中断一次,中断前后用时加起来,就得多用了几分钟或者十几分钟,这在一个视效率如生命的人(比如程序员)的眼里,这是非常难以忍受的。对于程序员来讲,编程时脑子里的想法和思路,就好比如上所说的拼图,想法和思路被打断,就好比上面所说的拼图被移走,再要进行恢复时,不光过程很麻烦,还会有信息失真……在我刚工作时,要是我正在写代码,同事找我有事,我会优先处理他们的请求,默默忍受着写代码被打断这种痛苦。到后来,实在是不能忍了,再加上自己慢慢成了“老员工”,就任性起来:钉钉狂闪,就当没看见;找我有事,要不是急事儿,一会再说……总归,能找到一大片可以一直在写代码的时间,是一件幸事儿。这也只能在经历了这些,才能深深感受得到。
要是有比写代码被打断更痛苦的事,那就是被打断的原因是需求变更了。需求变更,这是一件可以让需求提出方(产品经理)和需求实现方(程序员)直接干起架的事。如果说写代码被打断像是拼图被移走,一会再拿回来让你拼,那么需求变更就像是直接拆了你的拼图,让你重拼另一幅拼图……需求变更在一个项目里,是避免不了的。需求在当初设计时有的想法,和一个需求被剖析细节和融合更多信息后的想法有所出入是很正常的一件事。在深入细节后或者整合了更多信息以后,需求可能会细化,会增加许多新的内容;需求也可能因为考虑了更多的因素,发生完全的改变;也有可能,某些需求直接可以抛弃不用……那为什么不能先把这些完全考虑清楚,再进行下一步模块设计和编码过程呢?从我的经历来看,主要原因有三个:第一个原因是工期需求,如果在所有细节和问题都被确定了再进行下一步,那么工期就会被拉得很长,专门去确定细节需求,是一件很耗时的事,而且,最终确定下来的需求,也不见得真正就可以完完全全实现。这对于讲究“天下武功,惟快不破”的互联网公司来讲,工期被拉长是可以致命的。第二个原因,有些需求是随着时间的流逝而变化的,比如一个企业客户的某资料管理系统,可能在进行需求评审时,客户管理的资料品样,与产品最终被完成时的资料种类,有很大的不同,并且客户管理的资料种样是在不断变化、不断更新、不断扩展的,待客户的管理资料稳定再进行系统建设,这是不现实的。第三个原因,很多的需求,尤其是一个项目中的细节需求,都是在项目不断地进行过程中,才可以被挖掘和发现的。在确定需求时,很多的细节问题,不太容易被及时想到,只有随着项目一步一步地进行,基本的雏形一点一点被显现,那些模糊的需求才可以变得清晰。比如,在设计一个后台信息传输接口时,后端程序员发现了一个可能引起用户隐私数据泄露的需求项,此时,就需要将隐患同步给产品经理或安全专家,对该需求项进行调整和更新。
既然需求变更是避免不了的,那作为程序员,能做的当然只有“原谅”。怎么去面对不确定的需求变更,这对程序员的功力而言是一个很大的考验,也可以体现出在写代码之前设计软件模块的重要性。代码逻辑结构设计不好,一旦出现了需求变更,代码就很有可能像一团乱七八糟、互相缠绕的线一样,让人理不清头绪,同时也容易引起“牵一发而动全身”的高耦合风险。而代码逻辑结构设计得好的话,这样的麻烦就会少很多。针对哪个模块进行的修改会影响哪些部分,简单明了,一眼便知。优秀的模块设计能力如何养成?读一些相关的书籍(如《设计模式》之类的)可以提升代码逻辑结构的设计能力。更重要的是,通过实际的业务和经验,去积攒这样的设计方法。一个资深的大佬程序员,看到一个需求,就对接下来可能有什么样的需求变更有数,这样在进行架构设计时,就会对可能出现的“意外”进行兼容和规避。而这些,是需要经验和业务上的积累和锻炼的。当然,需求的变动是无常的,即使有了足够的经验,需求的变动也很有可能超出我们的意料。此时,最佳的反应,就是保持平静的心态,只要养成了良好的逻辑设计能力,这些变动,其实也并没有那么的“突如其来”。
在需求的约束与折磨下,终于写完了代码,接下来就要面对另外一个不好伺候的主——测试。测试与开发都是为了让项目产品最终能没有问题地顺利运行所不可缺少的参与者,不过看上去两者的利益指标是相反的:开发人员的最佳产出,是一份没有Bug的项目代码(虽然这很难);测试人员的最佳产出,是发现开发设计的代码里尽可能多的Bug和隐患。如果哪个领导定下一个KPI,把测试检查出来的Bug数量作为测试同学的KPI收益项,同时又作为开发人员的KPI损失项,那这个过程必然会节外生枝,搞出不少扯皮的事儿。比如,常会听到这样的对话:
“你这块需要改下。”
“这又不是Bug,没有必要改吧。”
“这块应该是个Bug。”
“怎么就是个Bug了?”
……
好在A公司在这方面还是比较成熟的,它规定了项目上线无故障作为测试与研发共同的KPI,所有Bug和修改只做记录,不作为KPI考察项。虽然是一个非指标、不明确的KPI,但作为专业的测试和开发来讲,这样的KPI完全足够了,有了这样的KPI,感觉大家在对待测试这件事上,目标还是一致的。
针对单个模块或者几个模块组成的子系统,测试方案常有黑盒测试、白盒测试和介于二者之间的灰盒测试。黑盒测试就是测试人员把待测试的系统或者模块当作一个看不到内部细节的黑盒来测试,测试人员只需要测试系统或者模块与外界交互逻辑是否正常即可;白盒测试就是测试人员把待测试的系统或者模块当作一个可以看到内部细节的白盒来测试,测试人员需要根据产品需求,检查大多数(或者必要时检查每一个)逻辑项是否正确;灰盒测试就介于两者之间了,测试人员了解系统或者模块的部分内部逻辑,不进行全部内部逻辑的测试。具体在项目里采用哪种测试策略,这是由测试人员决定的。这与项目的特性和测试人员的熟悉程度有关。对处于单元测试阶段的测试任务,或者测试人员第一次接触的项目,再或者是本身逻辑不是很复杂的任务,为了尽可能保证项目的每个环节都被照顾到,测试人员更可能采用让自己可以了解更多代码细节的白盒测试;对于系统测试,或者测试人员比较熟悉的项目,再或者是上一版本测试环节本身已经高质量通过,同时工期也比较紧张,测试人员基于之前的工作或者文档可以比较完整还原项目细节,或者系统过于复杂,让一个测试人员了解全部细节并不现实,此时,就更可能采用黑盒测试或者灰盒测试的方法。
测试人员看似是按照需求文档的内容,把各个需求项在实现的系统上检查一遍,虽然最理想的情况正是这样,不过现实却极其骨感。测试人员不光要考虑需求本身的逻辑,还要考虑更多需求之外的逻辑。比如,我们设计接口,需求项拆解为通过该接口获取用户的昵称、积分等信息,而测试人员会考虑的,除了需求的逻辑,还有:如果请求的用户没有注册,系统应该怎么反应?如果用户没有取昵称,该系统会返回什么?怎么保证请求的用户是用户自己点击,而不是用的抓取工具?……有大佬讲:一个完整的系统,20%的代码来处理80%的工作,80%的代码来处理20%的异常。为了保证项目是100%没有问题的,测试人员常常面对着80%的代码,编写各种形形色色的测试用例,来验证那20%的异常,其辛苦与费脑程度,丝毫也不逊于一个程序员了。
一个项目,可能会有很多的测试人员参与,比如,我们这个项目里,就有三个测试人员:一个前端测试、一个应用端测试、一个数据服务端的测试。刚开始,他们自己确定测试策略,各自测试自己的模块,涉及交互的部分,他们自己写用例,或者直接观察产出结果。各自测试完成后,就是集成测试和系统测试阶段了。各个环节的专业人员,把各自的系统“连接”起来,组成一个完成的系统。系统搭建完成后,要测试相邻子系统与子系统间的功能逻辑,这个步骤即为集成测试;在子系统间的测试完成后,要进行完整系统的全流程测试,这个过程即为系统测试。完成了以上那么多测试过程,但测试还没有结束,像什么压力测试、安全测试、性能测试等关卡在等着这个要历经更多“磨难”的系统……
测试通过,一切就绪,终于可以上线了。
上线就是要将各个测试通过的软件代码,部署到要运行这些代码的机器上。上线操作可能由研发人员操作,也可能由另一个工种操作,不光如此,这个工种还会在整个系统运行期间,对其进行整体与全程的维护与负责,这些人就是运维。其实,运维在架构设计的时候就可能会参与,一起确定最终软件架构的选择。项目上线后,运维人员会对系统运行过程中的重要指标进行监控。这些指标包括操作系统级别的指标监控,如磁盘占有率、内存占有率、CPU占用率等,还会对与应用直接相关的指标做监控,比如像QPS(每秒请求次数)、失败请求比例等。一旦发现了问题,运维可以采取必要的措施及时进行像扩容、重启等补救,或者直接通知相关的研发进行处理。除了对正在运行的系统进行监控,运维人员还可以决定线上程序运行的最基本原则与策略:是用虚拟机还是物理机?是否需要域名?如何进行动态扩容?如何针对各种线上程序进行最恰当的机器与配置选型?这些都是运维人员需要考虑的。对于一个线上互联网系统来讲,和运维人类似的,还有DBA(数据库管理员)。DBA是专门对程序用到的数据库的性能与安全负责的工种。此外,DBA还负责产品的数据库选型与数据库性能调优等工作。
有些项目,可能在上线后,又会发现Bug,那么项目就需要紧急修复并二次上线,更严重的是,很有可能会暂时下线该项目。如果到了这一步,那么就可以算作是一次事故了。对于一个服务于千千万万互联网用户的系统来讲,事故的后果是很严重的。一次事故会直接影响用户对该互联网产品的信心,同时也会给用户体验造成不可估量的损害。这是谁也不希望看到的结果。所以,不管是研发人员、测试人员也好,产品经理、运营人员也好,对待项目的细节,都不能马虎。
在项目上线后,系统与用户的交互,就会产生非常多的数据。这些数据直接被回收,会被数据分析师、产品经理、运营人员进行不同维度的解析:数据分析师可能会更注重各个数据属性间的关系;产品经理可能会更关注收益和一些重要指标;运营也会关注一些指标,不过这些指标更多是有关用户表现与活动整体效果的。掌握了这些数据,产品、运营就可以根据业务目标和系统反馈,投入到接下来的版本迭代和新产品设计与开发过程中了。
进入A公司半年多,从0到1做了两个系统,我才比较自信地认为,自己对互联网是有了解的。互联网行业就像社会里的各行各业一样,都有属于自己的流程与规矩,这些规矩,是在一次一次的实践中总结与归纳出来的。各行各业的与众不同之处,也反映了各个行业工作本身的特点。互联网公司讲求快速思变,重效率,重结果,这也造就了互联网公司流程相对精简、版本迭代更新较快、反感冗余与重复工作等特质。
每个互联网产品诞生前,都要经历这个有模有样的过程,每个过程除了要把本身质量做到极致以外,最重要的,就是一个“快”字了。有人说:互联网人都是急性子。虽说这话说得有些绝对了,不过,可以肯定的是,在每个深夜加班的互联网人身后,确实存在着一项属于自己的需要“马上”完成的任务。
这几天,有一个同事要离职。本来,离职对任何一家公司来说都是一件很平常不过的事,不过,这个同事的履历,倒是引起了我的兴趣。他本科毕业于国内前十的大学,后来到国外知名大学读了硕士,回来在A公司干了五年。本来是不错的履历,但在这五年里,他一次也没有被评为优秀,绩效也一直平平,没有什么突出的地方。最早,我也不知道这其中的原因。是评价体系有问题?不应该啊,感觉公司人员还是蛮稳定的,这应该跟大多数人比较满意自己的现状是有正相关关系的。或者,是他的能力有问题?也不应该啊,之前如此耀眼的履历,可以证明他的实力。我把这个问题抛给了海布,海布给了我如此的答案:他的技术能力确实很棒,只是没有在业务中得到比较好的使用。第一次,技术与业务,这对经常一起出现的词,被我放在一个必须重视的位置上。
学生时代与刚工作时的我,一直把成为一个技术牛人作为自己的一个职业目标,虽然这个目标本身没有问题,但在工作中经常接触到的实际场景里的问题,让我意识到了自己在设定职业目标的过程中,缺少了非常重要的一部分内容。海布的回答,告诉了我缺少的是什么——业务能力。
技术,是完成一件产品所需要的知识和方法;业务,是各行各业内需要解决的具体问题。技术的存在,最终目的还是要用在业务当中,解决实际业务问题的。要解决各行各业的业务问题,需要用到技术。很显然,技术储备越多,就更可能解决更多更复杂的业务问题。同时,业务的发展与进化,也会反过来促进或者抑制技术的进步。比如,原油储量比较大的国家,其探测、采集油矿的技术水平就会比原油储量较少的国家更先进一些;一家地图应用的互联网公司,其空间计算的技术能力与水平,相对于其他非空间应用的互联网公司就会更加优秀……因为要解决像原油采集、地图空间计算等实际业务问题,就促进了和这些业务问题最相关的技术的发展。
技术储备虽说是多多益善,但具体到某一项业务,可能会用到的技术储备并不太多。拿一家公司来说,接下来要做什么样的业务一旦确定下来,那么哪些技术会被“临幸”也就大致清晰了。一项项的业务,不断地刺激着公司技术储备中与业务相关的技术的发展,没有被照顾到的技术就会被冷落。这样,经过很长一段时间,一家公司的某些技术就会如参天大树一般,成为公司的技术拳头。不同公司间的技术优势不同,其实也是各家公司业务不同的反映。有些技术项,如互联网后端服务接口、前端界面布局等,被各种形形色色的业务所共同使用,就会有人把这些技术功能提炼出来,形成技术上的框架或者成熟的软件,供广大技术人员方便使用。这些框架或者软件的形成,直接来看是技术进步的结果,但说到底,这其中还是有业务在推波助澜。从更宏观的角度来讲,业务的提出,是为了解决人们生产生活中的各种问题,或者提升人们生产生活中的效率,满足人们的各种生产需求、生活需求、心理需求等。所以有人讲,现在比较成熟的技术形态,直接反映了当今人类的需求形态,个人以为还是有一定道理的。
对于一个有盈利压力的组织(比如公司)来说,业务做得好坏与盈利与否直接相关,用业务去驱动技术,就是这些组织最常使用的模式。此外,还有另一种直接发展技术的方式——直接投资进行研究。一些国家科研院所,一些盈利能力比较强、利润比较丰厚的公司或者投资人,会弱化业务对技术的驱动,不去计较当前的盈利与否,直接面向技术进行研究。说是弱化业务对技术的影响,实际上只是弱化了当前业务对技术的影响,这样直接发展技术的方式,是国家或者资本方,在面向未来人类可能的需求直接进行的布局。譬如,有大佬觉得再过几年或者十几年,自动驾驶将会是人类生活中非常重要的、不可缺少的一部分,大佬认为它会解决很多人类驾驶过程中的问题,提升车辆运输相关的业务整体效率。而且,大佬或者其组织也有些闲钱,为了在未来能抢先一步参与自动驾驶的相关业务,当前他们会投资研究像深度学习网络等有关自动驾驶的技术。一旦时机成熟,即自动驾驶的技术趋于完善,更广泛的关于自动驾驶的业务可以被顺利开展,并且可以有盈利,那么这些最早投资了自动驾驶技术的大佬,不仅可以先人一步,稳赚一大笔,而且因为在自动驾驶的技术投入更早,积累更加深厚,相应的业务也可以做到更优秀、更稳定,风险更小,具备更大的优势。当然,这样的技术投资或者业务投资,风险也是极其大的。比如,自动驾驶要是最终没有被大家接受,相关的业务始终开展不起来,没有办法盈利,那么这样的技术投资就打了水漂,对技术本身的发展来讲,是一件好事,不过对投资者来讲,这句话也只能安慰安慰自己。虽然失败的技术投资会让投资方不是很爽,不过有时“有心栽花花不成,无心插柳柳成荫”却让技术本身充满了有趣与魅力。比如,高跟鞋最早被发明,是法王路易十四为了让自己显得更高大,并且骑马更方便,但后来却演变成了天下爱美女士的标配;空调的发明,本是为了降低工厂厂房的温度,后来却走进千家万户;GPU的发明是用来做图形渲染计算的,结果后来机器学习发展起来,GPU被大范围用在机器学习和深度学习计算……业务会驱动技术进步,这属于我们意料之中的发展;但技术也会丰富业务的维度与思路,这就属于我们意料之外的惊喜了。
对于一个从事技术方面工作的人来说,在上学的时候,学校会教授给我们很多技术方面的东西:微波技术、通信技术、计算机技术、电子技术、土木工程、材料工程、水利工程、生物工程……对于互联网领域的技术人来讲,上大学期间会接触各种编程语言,如C/C++、Java、Python、PHP、Ruby、JavaScript、Go……其实也都是技术领域的范畴。在以前的大学教育中,是缺乏对业务思考能力方面的培养的。学会了技术,学生们只能在一项项“任务”中去练习自己的技术,这些任务就是所谓的一次次考试、一次次实验、一次次作业……真正有机会在业务中去认识技术的机会是很少的。这样的好处在于培养了一些对技术充满崇拜的人,而缺点也很明显,很多人看不到技术能起到的巨大作用,而选择了放弃技术。优劣哪个更多,也不好下定论。但基于业务场景的思考模式,不管是迟是早,总归是被需要的,这一点毋庸置疑。好在,研究生教育可以弥补一部分这方面的缺陷,而且,近几年,大学的实践实习机会也越来越多,这对于全面认识技术的作用和未来职业的选择,是大有裨益的。
在公司,不管是现在的业务也好,未来的业务也好,最终还是要盈利的。作为一家互联网公司,有时这个所谓的“利”,并不都是钱,还包括很多像用户数量、用户活跃度等指标。A公司营利能力虽然还不错,不过我们这个部门,貌似不用考虑太多利润方面的东西,我们要考虑的,就是怎么把用户“伺候”好。让用户开心,喜欢用我们的产品,就是我们的“初心级别的业务”了。许许多多的用户会用我们的产品,就会有更多的机会以另一些方式(如广告、电商等)出现,让公司赚到钞票。定了“让用户喜欢用我们的产品”这个大方向,产品经理会把这个大方向分解出很多小的业务场景,这些小的业务场景有可能接着拆解,形成一个个具体的业务需求。我们这些技术人,就受着这些业务需求的指使和驱动,用自己会的技术,实现这一个个的需求。有时这些需求就是一次次的修改和变更;有时这些需求会被整合,形成一个个项目……这就是业务在如何驱动我们程序员干活的过程啦。
在互联网公司,可以代表技术一方的是程序员,可以代表业务一方的是产品经理。程序员与产品经理,是每家互联网公司里不得不提的一对儿,他们的关系,用“又爱又恨”来形容,再准确不过了。他们背后所代表的技术与业务的碰撞,常常在这两种职位(或者说是工种)之间直接闪出火花。
产品经理。如果打开任何一个招聘网站,我们去看产品经理的title,五花八门:有像视频产品经理、电商产品经理、金融产品经理等直接按照行业划分的,也有像前端产品经理、后端产品经理这样按职能划分的产品经理,还有像平台产品经理、数据产品经理等按具体业务模式进行的划分……常有互联网圈外的同学和朋友问我:产品经理是干什么的,是不是也算个官儿?刚开始我会很认真地告诉他们像“整合需求”“梳理业务逻辑”“负责业务流程全链路的运作”,然后,只能看到他们似懂非懂的眼神里,透露着一个“哦”字……反而,像后来“提需求”这样的回答,倒是能引起几个点头。有心直口快的朋友于是就讲了:那产品经理这活儿是不能人人都能干?那你们技术直接干了不就完了,为什么要多设置这么一个职位?在入互联网圈之前,其实我也有一些类似的想法(嘘……)。但真正经历过了几个项目,才知道产品经理的职位是多么重要。“人人都是产品经理”,这句话给了很多人进互联网公司的希望,不过也让资深的产品经理略显尴尬。
A公司的校园招聘产品经理一职每年都会有这么一道笔试题:产品经理的职责为( )?正确的选项是:负责产品从需求分析、设计、实现等全流程进行控制、把握与管理。产品经理虽然不像程序员那样,有一个可以看得到的技能,但作为业务的代表,要做好业务的事情,则需要更多看不见的技能。
1.将一个比较宽泛的业务问题细化成许许多多较小的可实现的需求,是产品经理必备的技能
一个业务问题,尤其是一个从0到1的全新业务问题,它的描述本身是很模糊的。比如,一个地图APP公司,要做顺风车业务,那么业务最早的雏形,就可能仅仅是“顺风车”三个字。至于顺风车这个业务的具体形态,比如分几个界面,每个页面什么布局,司机怎么注册,司机和乘客怎么发布行程,司机怎么抢单,乘客怎么通知近似路线的司机,已形成的订单如何取消,用户信用体系怎么建立,取消订单怎么影响用户信用……一个业务问题,有可能会被拆解成几十项甚至上百项需求,这些需求要尽可能地覆盖用户的需要,还要尽可能不有冗余,这需要一个脑洞比较大,同时做事细心、洞察力比较强的人来做这件事。要事无巨细地考虑到这些细节,是极其消耗精力的,无法想象,让一个被代码折磨的程序员去客串这件事的结果……所以,产品经理的存在是极其必要的。
2.将需求进行有序、精细的组织和管理,同样是产品经理必备的技能
在此过程中,我们还要及时发现点与点之间的约束和影响。这个过程有多么辛苦,或许只有做过这些的产品经理知道,别以为把业务问题拆成了需求,这件事就接近于完成了,更准确地讲,这才刚刚开始。一个个的需求摆在眼前,这些需求里哪些之间会有依赖,需求与需求的先后关系是怎样的,哪些需求需要额外的数据资源做支持,要是出现了异常情况该如何应付……这些都需要一点一点深挖细节,才捋得清楚。还拿顺风车业务打比方,进入初始页面后,会跳转到哪些功能,需要产品经理设计;如果确定了初始界面后,乘客可以发布行程,可以查看司机发布的行程,这就算是完成了组织的第一步;乘客发布行程后,可以取消发布,回主页,也可以直接选择发布行程。行程发布后,会有行程信息,这个行程信息的产生,会不会影响到主页界面布局,或许说,还会影响到哪些页面的信息……一个一个的需求就如一个个散点一样,产品经理需要用线把他们串起来。
3.果断的决断能力和可以承担风险与责任的魄力,是产品经理需要的又一能力
业务拆解成需求,是一个不断地把抽象的概念具体化的过程。在这个过程中,很多时候,具体化的方案不限于一种,而且,在几种方案中,哪种方案更优是无法在短期内搞清楚的,或者几种方案并没有什么本质上的区别。这个时候,为了让项目有序推进,就需要产品经理果断地做出决定,勇敢地承担风险。比如,顺风车界面整体布局采用什么样的主色调;乘客与司机取得联系并确认行程后,是先完成订单再付款,还是先付款再去完成订单……这些不同的选择,每一个都有它被选择的道理;每一个选择,也都会有像设计师、程序员等其他各领域内更专业的人对其支持或者反对……面对众多的选择和林林总总的意见建议,产品经理作为整个项目的舵手,需要做出一个他所认为的最优决定,并为这个决定承担责任。当然,这个决定不是随随便便就可以做出来的,做这个决定,不仅要考虑各个专业领域内的专业人士的意见和与意见匹配的原因,还要考虑这个决定对整个项目的整体影响,甚至,还要考虑很多像社会心理学、经济学等更开放的学科知识……一个合格的产品经理,一定是一个敢做敢当的人,这一点,毫无疑问。
4.与人进行高效、良好沟通的能力,是胜任产品经理工作不可或缺的技能
产品经理要协调各方资源,把控各个环节使之顺利进行,就需要与各个环节的主体——人进行交流与沟通。虽然说有“工作”这个原始驱动力,每一方都会努力完成自己的任务,但产品经理需要良好的沟通能力,去让这个过程更加顺滑。产品经理通过沟通,一方面可能会及时发现之前需求中没有发现的细节,及时进行调整与更新;另一方面,通过沟通,产品经理可以将各方信息进行同步,对需求细节进行确认与强调,保证项目各方都能按照需求,高效有序进行工作;还有可能,良好与积极的沟通,可以直接影响到工作心情,起到非常微妙的作用。
说到产品经理的沟通,就不得不提到与之构成互联网公司中“欢喜冤家”的另一半——程序员。前面说到过,在一个项目里,程序员是技术的代表,他们常常会以“技术的角度”思考问题。很多的程序员在刚刚接触技术时,并不是从“为了解决什么问题”的角度来学习技术,而是受了某种影响,觉得什么技术有用,就以“这个技术能干什么”的角度去学习技术,一旦发现某种自己会的技术能做一件很多人做不了的事,不管有什么用,技术人总是觉得很酷、很过瘾。这样,很多程序员被养成的过程,是被深深地打上了与技术本身具备一致特点的烙印的。技术有它经过长期发展而形成的原则,比如,技术人经常讲“封装”“抽象”“低耦合”……,是经过无数前辈经验的浓缩而被总结出来的。这些被高度概括与归纳原则,被很多程序员当作信条一样的东西所崇拜(或者炫耀)。但是,业务问题本身是非常具体与多变的,不管前人做了多少浓缩与总结,在实际解决问题时,业务很可能与前人在总结那一套把式时遇到的情况相似但不尽相同。作为技术人来讲,最令其难受的地方正在于此。于是,作为业务方代表的产品经理和作为技术方代表的程序员,在项目要启动时,就会有这样一个矛盾诞生。面对这样的矛盾,产品经理需要有更大的责任,靠自己的沟通,去坚持对用户体验更好的方案的同时,还尽量不让程序员有过多的负面情绪。能做到这一切,简直是处理人际关系能力的高人呐。对此,很多产品经理已经总结出了令人叹为观止的沟通技巧。比如:撒娇卖萌法,一口一个“小哥哥”,先软化你再说;以理服人法,一条一条告诉你为什么这么做,一点一点告诉你这么做的意义是什么;客客气气法,和技术沟通需求时,就像是遇到了长辈一样,客客气气,小心翼翼……也有很多产品经理,最终选择了妥协于技术的方案,但除非真的有理有据,不然这样的隐性风险还是不小的。试想,如果让一个程序员去管理需求,他一定会以自己最擅长的技术可以实现的手段去选择需求方案、补充需求细节,这种以技术驱动需求的方式,就不免会有更大的“脱离群众”的风险。好在,越来越多的程序员,不再难以相处,而是放弃了固执的态度、技术人的情怀,能以解决问题、体现自身价值为根基的。所以,只要在“努力解决问题”这一大前提上达成一致,需求沟通的过程,其实并不存在什么大问题。
除了与程序员的沟通,产品经理还需要与项目中各个环节的代理人做好同样的沟通工作。他们需要与测试及时协调好测试资源,并确定测试目标与原则;他们需要与运营同学确定好上线时间,并商议好风险预防策略;他们还需要向上及时汇报项目进度与问题,并把领导的意见与消息及时与各个环节的伙伴进行同步……这其中,不仅需要把事情理清楚的能力,还需要高超的沟通技巧;不仅要保证信息被传递和交流过,更要确保信息被各方真正接受与知会……到现在,谁还敢说产品经理是可有可无的一个角色呢?
5.技术思想与顶层设计的思维方式,是产品经理锦上添花的技能
在一个分布式管理方式的项目里,是没有一个架构师或者系统设计师的,此时,产品经理成了那个唯一具有全局视角的角色。在具备全局视角的基础上,如果具备一些技术思想或者顶层设计的思维方式,无疑是如虎添翼。
技术思想,即产品经理主动去了解一些技术方面的东西。虽然说在产品经理的职责里,并不包括必须要懂技术这一项,但要是产品经理懂一些技术知识,了解一些技术概念,那么对项目整体进度的把控和整体风险的认知,是多了一个重要的维度的。最明显的一点就是,近几年有很多程序员开始转行当了产品经理,在与这些有技术背景的产品经理打交道时,程序员会有一种格外的轻松感。此时的产品经理,因为更了解技术,会把一个个的需求整理成程序员(就是以前的自己)更容易理解的技术思维方式;同时,由于自己在以前的需求中踩过很多坑,“程序员产品经理”更知道每个需求中哪些细节容易被忽略,哪些需求在实现时更可能有变更,并提前给程序员提出具有强大建设性的建议……所有的想法,都是要围绕技术要落地实施,对技术有更多的了解,对提升沟通质量、提高工作效率、减少冗余工序、规避上线风险是大有禆益的。
顶层设计的思维方式,是指把整个项目的各个因素,包括业务需求、开发测试、运营维护等,都当作一个个的子模块,产品经理需要做的,是将这些子模块进行总体设计,以求项目各方收益的和达到最大化。顶层设计的思维方式,并不是指让产品经理亲力亲为地参与每一件事(实际上,这么做就太越权了),而是说让产品经理从总体利益的角度出发,做出最有利于总体目标的安排。比如,前文我们一直在说,因为产品经理代表着业务,业务与企业利润、用户体验最为相关,所以,通过业务去驱动技术,是比较正常的操作。但有些比如数据挖掘类的任务,最终产出的多少,瓶颈在于算法与技术团队可以有什么比较好的策略或者算法,如果此时一味追求指标,拿业务指标去过度压迫产出,不光整体产出质量极可能被打折扣,还有使团队建设出现不稳定、造成团队凝聚力与战斗力严重受损的风险。再比如,技术的定位,就是为业务服务的,但不同的公司,由于技术储备的多少有不同,技术人员的能力水平也有不同,公司的技术能力也就有了一个边界。产品经理如果可以以宏观设计的视角观察这些,了解突破技术边界要付出的代价,了解业务会产出的大致收益,就不会在是否因为技术边界而放弃实现某个需求方面摇摆。顶层设计的思维让产品经理更重视整体最优,即使放弃了局部看起来还不错的选择,也坚定而无悔。
如果把一个项目比作一个运转的机器,那么产品经理就如同这个机器的润滑剂,机器要想畅快地运行,项目要想顺利地运转,离不开一个靠谱的产品经理。作为一个程序员,如果能遇到一个精明能干、聪明靠谱、有规划有想法的产品经理,会有一种如沐春风般的默契感,干起活儿感觉异常得心应手,效率也会有意外的加成。当然,并不是所有的产品经理都能做到上面说到的那些,这也是大多数互联网公司的现实。即使如A公司这样的大公司,能完全做到上面所说的,也屈指可数。对于一家公司来说,由于“产品经理”的需求量还是比较大的,再加上评价产品经理的这些看不见的能力标准不一,所以公司在招聘产品经理时,鱼龙混杂的现象会相对突出一些。这其中,最令人反感的,无疑是那种不进行需求整理,直接拍脑门做决定的产品经理。产品经理应该是一个深思熟虑后将需求进行有效规整的角色,但这些产品经理可不知道“深思熟虑”是什么,他们拿到了业务需求,想起什么就让研发和算法去做什么,研发和算法正在进行他的上一个“需求”(如果这也算是需求的话)时,他马上就提出了“需求变更”……一个个小需求被多次提出,一个个变更越发频繁……于是,一个项目就被他天马行空般的想法,弄得如一团乱麻一样。当然,即便是这样,项目依旧可能上线,指标也依旧可能达到,但会消耗过多无谓的冗余和对项目质量、团队士气带来潜在的风险。这些就如定时炸弹一般,并不能让人真正平静。
还有一类产品经理,做事风格也是蛮让人不舒服的。在收集需求时,他们不断在妥协:听开发说什么,他们就按照开发说的去制定需求;听了测试在说什么,他们就又按照测试说的去制定需求……貌似最终的需求,大部分取决于最后一个人的说法。而在项目真正执行时,他们却又不管不顾,任由各个环节的“自由沟通”。这样,唯一具备全局视角的角色没有发挥作用,项目的进展缓慢不说,不可控的风险亦会进一步增加。
产品经理与程序员是每家互联网公司里“你中有我,我中有你”的存在,发生在他们之间的更多的是一些让人啼笑皆非的故事。见到过程序员通过在工位上贴上收款二维码,并粘上“修改需求一次X元”的方式调侃产品经理的需求变更;也见到过产品经理在需求评审会上说“这些问题我们开发都搞得定”,让程序员们冒出只想把电脑一摔,并甩一句“那你来搞定吧”的冲动;还见到过产品经理与程序员们把各种好吃的都共享出来,大家一起其乐融融商量需求与方案的和谐画面……为了做好一件事,一个团队需要有分工,产品经理和程序员就是分工的存在,大家都做好各自的小事,最终的大事才能顺利完成,最终的目标才能实现,世界才能被改变得更好。
转眼间,进入A公司已经八个月了。
在正式工作前,常听长辈讲:在工作中可不比在学校里,领导是要巴结的,同事也都是利益关系。加上之前在研究院读研与实习时的经历,虽然我觉得长辈的这句话是有些过了,但却是不无道理。来A公司的这八个月,我一直觉得有些隐隐的不对劲,后来才发现,不对劲的地方在于:氛围实在是太好了,好得让人感觉不太真实:领导不用巴结,该奖奖,该罚罚;同事之间也不用刻意在乎什么利益纠葛,一旦有什么活儿,只要有人有空,就会主动揽下来。如果说这是短期内的“装模作样”,倒还算是一个有依据的理由;可这不算短的八个月一直如此,就不得不让人好好研究一下这其中的奥妙了。
我直接汇报工作的对象是海布,海布是我们组的组长,海布汇报的对象是如风,他是我们部门的老大。在工作后最初的几个月里,海布是与我打交道最为频繁的Leader,我有个技术问题、业务问题、个人发展问题,除了问立刚,就是直接咨询海布了。和部门主管如风的直接接触不算多,不过平时总见他这儿跑跑,那儿跑跑,跟各个组长聊聊业务,聊聊方案。再有,就是不知道去什么地方开什么会去了。
这八个多月,我和如风直接交流过两次。一次是我刚进来不久,如风找我聊天。之前耳濡目染了很多领导对校招新生的打鸡血的方式,无外乎是“把你招进来,说明你有能力,有潜力,加油干”;或者以某个校招生前辈作为例子,说说他的经历和成功之处;再或者,称赞一下之前面试或者交流过程中新人表现出来的优点或者细节,末了加上一句“我很看好你”之类的……有了这些道听途说的印象,在与如风沟通前,我仔细想着应对如上套路的各种方案。
如风首先介绍起我们部门的各种业务。他先给我展示了一张架构图,然后把架构图每一块的业务内容提纲挈领地描述了一遍。如风作为部门的老大,对部门发展有着完整和整体规划,所以对于业务框架这些,他早已了然于心,讲得滔滔不绝。我也难得有机会全景式地看看我所在的团队的业务,了解了解我即将要参与的相关业务的作用。接着,比较出乎意料的是,如风讲了一些我不曾听到过的东西。如风说:“在咱们这个团队里,最终怎么评价一个人干得怎么样?首先,你做的项目要真正能起到实际的作用;然后,你在其中做出了非常大的贡献。在做最终的评价时,这两个方面的考虑缺一不可,而且也不会再节外生枝。”这是一句很客观、很实在的话,实在到足以让人感觉到工作之外的真诚。听多了“只要你努力干,就一定有好的回报”这种言语,突然听到如风这么说,立马有些蒙,不知道自己该做什么反应。反正,在这次聊天前做的各种方案,算是用不上了。如风还说,作为校招生,现在的主动决策能力还有限,最现实的,就是把被安排的活儿做到最好,等自己成长了,再反哺团队和项目,在项目本身的作用和自己的贡献两方面都有最积极的结果。如风给我讲了一个现实版的“努力不一定有收获,但不努力一定没有收获”的道理,如果他直接跟我这么说,我会认为他也如同大多数“领导”一样,只是给我画了一张饼而已,但他告诉我的,几乎每一条都是可以直接执行落地的,而且处处都结合了当前业务的发展现实,我突然觉得,他不是在鼓励一个校招生,而是在帮助我制订我的职业发展规划。如风让我知道,在团队里,努力做好自己的事是最重要的,但这并不意味着最终的结果就是好的,和最终的结果相关的因素太多了。不管作为什么身份,把自己能做的一些做到最好,把自己可以决定的对自己发展最好的事做到极致,怎么着都没错。但如风最后说的那个“不会再节外生枝”,我却有些捉摸不透,是包含有其他意思?还是我自己想多了?如风没容我想多久,就又开始说话了:“好了,就说这么多,我们招你进来,是看重了你的能力和潜力的,好好干,海布跟我说了,挺看好你的。加油。”正当我沉浸在如风前几句话的思考里的时候,他却突然说出了方案里面的套路,我原本以为这些方案已经没什么用了,忘得已经差不多了,这又一次突然袭击,让我又一次蒙掉。“谢谢。”能马上想起来的可以回答的词,就剩这一个了……
当天午饭时,我偷偷问许楠和俊崖,那个“节外生枝”是怎么回事,是不是我想多了。他们跟我说:如风是一个对做事要求很高的人,同时他也不希望因为私人的关系和个人的情绪影响到对工作的评价。A公司对于管理者和员工价值观的要求也正是如此,如风绝对是践行这一价值观最好的几个人之一。他们还给我讲了几个真事:有一次,如风因为业务问题与一个开发负责人大吵了起来,但年终绩效给了该技术负责人很高的评价;还有一次,一个员工以送礼等方式巴结他,被他非常果断地拒绝并且训斥了这个员工一番……他俩在讲这些事时,显得格外有活力,还不时地透露着对如风的崇拜。他们的回答和表现,让我终于明白了所谓的“节外生枝”。想想接下来的日子,不用考虑什么乱七八糟的(而且是我不擅长的)“领导礼节”问题,可以专注做些事情,还是蛮期待的。
不搞空话、套话,直接从最具体、最现实的关注点切入,以发现与解决问题为价值导向,这是通过我与如风的第一次接触,对他产生的印象。虽然这些口号很多人在喊,但真正能把这些落实并且展现得如此纯粹的,如风是我见过的第一人了。
我与如风的第二次接触是在我的转正答辩上。
A公司对于新人的发展也是有制度支持的,新人转正答辩就是其中的一项。不管是校招还是社招,加入公司后都有三个月的试用期。试用期末了,会有一个转正答辩,由直接上级、部门领导和一个HR同事参加,三人共同考核决定新人的去留问题。关于转正答辩本身,我是不担心的。此时我刚完成了我在A公司的第一个项目,得到了很多人的好评(虽然代码不忍让人目睹),再加上我本身行事谨慎(也就是怂),自以为踏实老实,作风和价值观肯定也没什么问题。所以,只要我正常发挥,转正问题肯定不大。但考虑到部门的老大如风和另一个之前没怎么接触过的HR要来看我的表现,为了展示自己的实力,我还是抽了很大一部分精力在准备这一场“秀”。
关于做PPT演讲或者展示,形式上我是不陌生的。上大学和读研时,对一些开放性的课题或者一些如英语等本身比较Open的课上,老师经常会布置一些做演示的作业。虽然我并不是特别热衷做这玩意,但为了完成课程,为了拿到学分,也为了高分,我又非常努力地完成每一个演讲展示。最近的一次类似的展示,应该就是毕业论文的答辩了。在工作后不久,同样的展示形式又一次出现,反倒也没什么让人紧张的。
转正答辩要求新人对自己做的工作做展示,并说说自己的心得体会和对未来的规划与想法。手里拿着一个刚出炉的项目,答辩的素材也就有了。我开始设计自己的展示逻辑:工作介绍部分,我打算从需求背景说起,先说说为什么要做这个项目,为此,产品经理提出了哪些具体的需求;然后讲讲针对这些需求我做了哪些工作,怎么设计的工程结构,设计了哪些接口,都是怎么实现的。最后说说上线效果和收益。工作内容的介绍就这么定了。在心得体会方面,讲讲被这个项目折磨的过程,再说说自己心智上的成长,像“终于感觉自己是个互联网人了”“对技术有了不一样的认识”之类的,应该问题也不大。最后的未来的规划,就说自己要成为一个能解决各种问题的优秀工程师,做更多的项目,能承担起更大的责任……保险起见,我把做好的PPT给立刚看了看。立刚看完,给了几处小修小补的意见,我对应做了修改和补充后,自我感觉准备工作已经是非常充分和到位了。
答辩当天,海布、如风和一个HR同事坐在一个能容纳八个人左右的小会议室里,我把电脑投影到墙上,没说多少客套话,我就开始按照我设计好的结构开始讲。海布对我和这个项目自然是比较了解的,我在讲这些东西时,只见他不时点点头,以这种方式给我鼓励。HR是一个看起来30多的皮肤发黑的男同事,一边听我讲,一边低头记录着些什么。如风与他们都不同,他双手交叉抱成一个大拳,撑着下巴,眼睛有神,一脸严肃,没有任何的动作,虽然不知道他在想什么,但他的脑子里一定不是平静的。在我讲到接口设计这部分的功能时,如风突然开口了:
“现在线上接口设计的QPS(每秒请求数)是多少?”
“50左右吧。”
“QPS为什么这么小?”
“因为考虑到是个内网使用的场景,所以QPS应该也不会太高。”
“谁说内网QPS不会太高了?先不说这个,如果现在请求突然增加了,要提高服务的性能,你的系统怎么改造?”
“我会申请一台新机器,然后把服务部署在新机器上,再更改一下负载均衡的配置。”
“数据库的读写峰值你分析过没有?”
“没……”
“消息队列的读写峰值呢?”
“也没考虑……”
“那你确定直接扩容不会影响到数据库和消息队列?”
“这个……不确定。”
问完这些,如风冷冷说了句“继续吧”,就又恢复了刚才的样子。
被问得灰头土脸的我又开始了所谓的“表演”,只不过,接下来的工作阐述中结巴了好几次。如风的问题让我有些措手不及,这些问题都是我在之前做项目和准备这次答辩时不曾想过的。其实所谓的性能瓶颈之类的问题,之前也有听说,但总觉得这些东西离我还有很远,我需要再锻炼一段时间才会考虑这些东西。然而,事实证明,我还是对自己太宽容了……技术和业务深度不够的缺点被如风的几个问题暴露无遗,此刻,我突然有了一种危机感:“转正答辩就是走过场”的想法可能不太对,这个事儿,也许没那么顺利。
我一边讲,一边想趁他们不注意擦擦汗,心想,如风可千万别问什么问题了。但墨菲说:“你还是太年轻了。”如风放下手,又开始问了:
“这一步,用户读出信息后,进行了修改,又写回。如果有很多用户同时读出同一个单元的数据,同时进行了修改,再依次写回。有什么问题没有?”
“如果不加以控制的话,最终此单元的状态值和最后一个用户写入的值是保持一致的。但这个流程是有问题的,前一个用户以为自己写入了某个值,而后马上就被后一个用户改写,这样很可能引起像丢失更新、读取脏数据、不可重复读的数据同步问题。这些问题在当前业务里是不允许被接受的。所以,我运用了数据锁,在用户读取数据修改时上锁,用户修改结束后释放,如果有其他用户想在此时进行修改,那么就会得到一个返回的‘有其他用户正在编辑’的信息。通过这种方式,就可以避免刚才说到的这种问题。”
“具体是怎么实现的?”如风追问道。
“用的是两段锁协议。”
“什么是两段锁协议?”
之前做项目时有好好学习过的内容,印象还是蛮深的。我开始一点一点讲起了两段锁协议的内容和最终可以达到的效果。
“好,那你觉得对于咱们这个业务来讲,有没有其他的数据同步问题?”
“这个……我想下……”
这个问题又进入了我的盲区,我用着留给我不多的时间从头开始迅速扫描每个流程、每个环节。最后,生拉硬扯,结结巴巴地说了几个我也不确定是不是数据同步问题的问题。如风听了,再次恢复到之前的姿势,同样说了一句“继续。”
终于把工作介绍部分说完了,原以为就可以进入介绍心智成长的开放环节了。没想到,如风又说话了:
“等下,问你啊,现在你处理完全部后台服务要用的数据,需要用多长时间?”
“大约10个小时吧。”
“如果我现在只给你一个小时时间,你的处理流要怎么设计?”
“这个……我可能……会用分布式的方法试一下吧。现在的处理流是在单个服务器上运行的,分布式的处理方法应该会大大提升效率。”
“分布式你打算采用哪个框架?怎么设计处理过程?”
我发现,如风的提问方式是很有讲究的。他找两个点作为切入点,一个是我进行阐述时说出的业务点,另一个是我没有说出来的,但对于业务实现很重要的要点。他会先问一个业务环节的细节,然后针对这个细节和要点,再深挖一步细节的细节、要点的要点,一直迭代提问,直到问到最基础的知识或者业务逻辑,再或者问到我答不上,提问即终止。我猜,如风想通过这种提问方式,深挖应答者的知识深度和厚度。了解几个技术概念的人很多,可真正花时间研究技术细节的人,真正在业务中去思考技术机理的人,却屈指可数。对这些要点理解的深度和厚度,反映了一个技术人对业务投入时间的多少,对技术投入思考和精力的多少。通过这样的问法,如风可以更加了解一个技术人真实的技术实力和业务实力。对我这样技术水平还不够的程序员来讲,如风这么问,有很大概率会问到我答不上来的问题或者我不熟悉的内容。对此,我个人觉得,最聪明的做法就是:如实全招。会的东西就好好回答,不会的就说自己不知道,似懂非懂的,就说出来自己懂的那些,说明自己不懂哪些……既然大佬想了解你,就应该把最真实的自己告诉他。要是一直遮遮掩掩,自己是什么水平,其实大佬也都看得清清楚楚,这样的“小丑”行为,在很大程度上会给大佬留下不懂装懂的印象,反而是偷鸡不成反蚀把米。真正的精力,应该放在平时的努力积累,刻苦钻研,以不变应万变。
想了想这,又想起如风刚问的关于分布式的问题,深呼一口气:
“分布式框架我之前只是听说过,还没有用过。如果项目上需要我解决这个问题,我会先好好研究一下分布式常用的框架、特点和用法,然后再确定最后的方案。”
我想,这应该是我自认为可以给出的最好的答案了。
如风还是面无表情,点了点头,示意继续。
接下来,我开始讲心得体会和个人发展。讲心得体会时,如风把头稍微低了一下,不言不语,应该是相同类似的话听得耳朵都起了茧子吧。此时HR开始活跃起来,以一种很显轻松的姿态,问了问我这三个月的收获,什么事情给我的印象比较深,还有觉得同事怎么样。一向自我感觉价值观正向无害的我,对于这些问题自然也没什么可以注意和避讳的,很自然地想什么说什么即可。讲到个人发展,我主要把今后的技术发展方向定为技术架构和架构师方面,HR首先提问了为什么我会定下这样的职业发展方向的原因。自我感觉,心里关于互联网技术还没有一个全面的认识,在入职的头几个月里,我把主要的精力都放在了学习上。不过,我真觉得互联网技术是蛮有趣的,现在从事的工作还是挺有意思,挺有成就感的。想了想,我回答HR:“因为兴趣。”此时的如风,两手交叉在胸前,很自然放松地靠在椅子上,脸上少了一些严肃的神态,眼睛也睁得更大了。我心中暗暗一惊,还以为如风又要问什么问题了,好在,如风并没有提问,而是开始做总结。
如风首先指出了我的优点:热情高、干劲足、潜力大。可能作为刚入门的互联网新人来讲,这可能也是仅有的优点了……然后就是缺点:业务理解深度不够,广度也欠佳,技术积累还有待增长……如风说这些看起来也没顾忌一个新人的感受,说得直白有力,听着这些我也知道是大实话,虽然有心理准备,不过还是有些不太好受……之前取得的所谓成功看来根本不算什么,要学习的东西还有很多啊。说完了这些,如风脸上多了些微笑,对我的目标和现在的情况进行了分析,并指明了接下来要达到目标该怎么走,该向谁多学习,该看什么书,该怎么去找切入点分析业务问题。每一个建议意见并非什么高屋建瓴式的指导,而是一个个具体可落实的方案,回想起第一次与如风打交道时,如风同样是给出了对我来讲更切实可行的方法论,真诚又实用。在我看来,这些方法论才是如风身上最宝贵的东西。可能对如风来讲,花拳绣腿的把式并没有什么价值,能认认真真做事才是他最看重的。
这样,我算是“有惊无险”地通过了转正答辩。略微曲折的过程,现在看来,虽然难以忘记,但类似的心智上的成长经历,在人的一生中并不怎么少见。倒是如风的问题,以及这些问题反映出的如风的思考方式,才是对我有着震撼级影响的东西。来A公司以后,我一直在思忖和寻找着一个优秀的技术人应该有的样子,如风以最全面的方式展示给我这个样子:全能的技术手段,深入到细节的业务思考,对于复杂问题极富逻辑性的分析方法……有了这些模式作标杆,未来的行动就有了方向。
与如风的第一次接触,让我感性了解到了如风的领导风格;与如风的第二次接触,让我实实在在感受到了如风的做事准则。由于我的父母亲属几乎没有人与互联网行业有过如此亲密的接触,他们常会告诉我些适合他们的职场“技能”,如“做事是其次的,与领导搞好关系,刷存在感才更重要”。而在如风的管理下,这些所谓的过来人的职场技能是发挥不了作用的。也不知道这是互联网行业占大多数的工作风气,还是极其非主流的具有“如风特色”的管理方式。不管怎么样,对于我这样不善沟通、性格偏内向、专心搞技术(虽然水平还不行)的人来讲,这样的环境是极好的。
嗯,我还是蛮幸运的。