编程十年,在海外成为全栈程序员是怎样一种体验?

阅读数:2054 2019 年 7 月 25 日 08:00

编程十年,在海外成为全栈程序员是怎样一种体验?

本文由 dbaplus 社群授权转载

一晃做程序员也有十年了,总觉得时间过的很快,仿佛第一次写程序还是去年的事情。虽然到现在也已经换了三四家公司了,但总有种自己没有做过什么的感觉。于是便想把个人的经历写下来,留给以后的自己作为个人回忆。

一、大学时代

我原本并没有想过学计算机,在高中时我搞过化学竞赛,2005 年考大学时填的志愿也和计算机无关。然而机缘巧合,我的分数只能服从专业调剂分配,误打误撞进入了计算机专业,属于没有任何编程基础的“普通学生”。

在大学的时候一直仰望着各种信息学竞赛大神,在被碾压中渡过了四年本科时光。大一大二的时候对于编程是觉得既新奇又畏惧,常常在语法上被困扰半天,又或是为了一个边界条件而调试半个小时,算法也一直是我的短板,直到现在还是会对算法面试有一种天生的紧张。

如果说在本科的大学时光中有什么事情让我对于写程序这件事情产生热爱,那便是大三时选修的一门《基于 Visual C++ 的 MFC 编程》。MFC 技术已经作古多年,知道这个名词的程序员估计也都年纪不小了。

虽然这门课程上学到的知识在后来的工作中并没有用到,但是第一次写出在 Windows 上可以运行的非常简单的界面程序,那种成就感,比大一大二抄书本调试出来的递归程序要高的多。

这门小技术也让我在大三大四的许多大作业上沾了些光:毕竟助教比起在命令行运行的指令,更喜欢鼠标点点就可以出来的界面。

自此我便在单机图形界面程序上兴趣大增,大四的时候用 C#写 WinForm 的程序作为软件工程课的大作业,和大部分其他用 Java 写出的界面“划清界限”。

二、移动应用工程师

1、我的第一份程序员实习工作

学生时代写程序并不能作为“程序员”的经历,我真正的成为一名程序员要从大四开始说起。

大四的时候保研结束,有些空闲的时间想着找一些事情做做,机缘巧合认识了一个大很多届的师兄,自己开了一个公司做智能手机应用。

那是 2009 年,现在二分天下的苹果和安卓的代表手机还是 iPhone 2G 和 HTC G1;系统的版本还是 iPhone OS 2 和 Android 1.5。

我进公司实习的第一个应用是把一个在 iPhone 上的工具类程序移植到 Android 上。当年的 Google 还可以访问,但是 Android 的代码示例也几乎只有官方的 Demo,公司里也并没有没有别的会写 Android 程序的程序员。

正是在这样一抹黑的情况下,我迈出了移动开发的第一步。当时每天去公司就是把一台 G1 连上笔记本电脑,改两行代码后花上半分钟运行一下,看看效果,不行再改两行再试,效率非常的低下。

功夫不负有心人,做了三个月之后程序终于上线了。虽然反响也并不好,没有达到 iPhone 上的营收效果,没多久就从 Market 上撤下来了。但不管怎么说,这也是我第一次写的产品代码,我在程序员的道路上迈出了第一步。

2、读研期间确定方向:移动应用开发

09 年毕业后上了研究生,研究的项目也正好是基于 Android 的,期间做过 Android 系统程序的修改,包括修改 Java 代码和底层的 C 代码,现在看来都很简单粗糙,完全不值一提。

但是最宝贵的可能就是读了大部分 Android 的框架代码,虽然现在已经面目全非,但是在以后的工作中看再大的代码库也不会觉得无力。

研究生期间”不务正业“又辗转做了几个公司的 Intern,当时为了能兼顾实验室和 Intern,特意都选择了可以 remote 的实习。其中包括两家在美国的公司。

在这两家公司最大的收获便是锻炼了英语读写说的能力,从一开始面试的时候连名词都听不明白,到后来可以和老外侃侃而谈,在这里迈出的第一步很关键。

另一个收获就是除了 Android 之外,又接触了 iOS 的编程(当时还叫 iPhone OS),学习了一门叫 Objective C 的语言,以至于很长一段时间在 Java 和 Objective C 之前切换的时候会不自觉地打出括号和点的组合。

整个研究生期间我的技能点几乎都点在了移动开发上,关注各种安卓苹果操作系统的新功能,也会借着职务的便利去玩一些新的机型硬件。

加之那几年移动应用的发展迅速,市场是对于移动应用开发者还有很大的需求,于是对自己的定位为一名移动应用开发者,并将之作为自己毕业后找工作的方向。

3、机缘巧合进入日本 IT 圈

2012 年 7 月研究生毕业,在年初的时候我开始了找工作,由于实验室的背景关系好多师兄毕业后都选择去了国外大公司工作,于是我也在期待着可以跟随师兄们的脚步。

无奈自己的硬实力不够,没有能够通过国外大厂的面试。在国内的找工作也并没有非常好的进行,大公司并没有很多移动开发者的职位,待遇比较不错的职位投递了简历却并没有得到回应。

在机缘巧合之下,有几家日本的 IT 公司来到中国招聘毕业生,我参加了其中一家公司的招聘会并顺利的通过了面试,于是来到了日本东京开始了自己的程序员生涯。

我的正式职业生涯中的第一家公司(暂且称之为 D 社),在当时是一家以移动手机游戏为主体运营业务的公司,当年凭借着功能机上的游戏地位站在日本手游界的 Top2 位置。

D 社虽然收购了美国的一家公司在旧金山也有分部,并且也连续几年在海外招聘了一些外国的毕业生程序员,但是本质上还是一个比较偏传统的日式 IT 公司。

D 社对于新加入公司的毕业生程序员的培训不得不说还是做的比较到位,首先对于海外招聘的毕业生,提供了日语的全日制培训以及之后正式入岗后的日语追加培训。

其次,在正式分配部门之前,有为期两个月的技能培训。技能培训的内容是将公司内的 Perl 框架简化后让大家进行一个类似于填补作业的项目,并全程有老师指导,每阶段需要提交代码并且答辩。答辩不通过的话需要再等两天后才可以预约下一次答辩。

现在看来过于严苛和形式主义,但是在以后的工作中,越来越体会到新人培训的重要性,因为在之后的公司从没有过这样细致到“手把手”式的培训。

我自己觉得受益比较深的几点:

1)对于每一句写下的代码,老师会问为什么这么写,有没有别的写法,各种写法有什么不同?会细扣到代码的顺序,变量名的命名,注释的语法等等。

实际上这是非常细致的代码审查(Code Review)流程,大部分新人程序员着眼于如何快速的实现功能,有时会不假思索的借鉴来代码,而我之后供职的公司并没有这样的培训,大多数的代码审查也只是停留在错误检查和性能上。

个人觉得在一开始写程序时养成良好的习惯非常重要,尤其是对于刚脱离校园环境的程序员。

2)老师也教会了很多工具的使用,比如 Vim,Git,Bash 等基本操作,比如用 Bash 完成对 Apache log 的简单统计分析等等。

这个其实是程序员的提高生产效率的方法,在之后的公司中遇到太多的新人进入公司好几个月还在 Git 提交上遇到各种困难。或者不得不耗费体力做一些简单脚本可以解决的问题。

比起教会的知识,更重要的收获是万事都可以脚本化的信念,不会因为自己的本职工作不包括写脚本而对于脚本就打退堂鼓。

在 D 社的培训结束后加入了一个临时的岗位,做了三个月的 Perl 的网站开发,之后又调去了别的部门操刀旧业,维护公司的门户 App,说实话门户 App 的技术含量真心不高,就是 WebView 封装出来的。

期间做了唯一一件有些技术含量的事情是把 App 内的聊天功能加上了推送功能。在客户端启动时,在服务器端注册客户端的推送口令,在客户端的网页里通过 api 来通知服务器把消息放进队列,服务器端有定时任务去消化队列中的消息。

这其实是一个非常普通的小系统,也比较成熟,对于个人来说主要的作用就是独立设计并且完成了一个完整的系统,并且在生产环境中实际的运行起来。

在 D 社的日子没有持续很长时间,最后在公司的半年被调任到游戏部门,做了一款基于 Unity2D 的手游,虽只有短短的四个月经历,但是也可成为是个人职业生涯中出品的第一款游戏,它是一款抄袭了 FlappyBird 的山寨游戏,在制作的过程中重温了一回用 C#,顺便熟悉了一下 Unity2D 开发环境。

反思一下自己在 D 社的一年半,在职场的第一份工作并没有能够很好的积累。而只是停留在完成布置的任务阶段,并没有去主动的学习。

三、 后端程序员

1、进入后端工作组

在 D 社待了一年半之后跳槽到了 I 社,I 社是一家在美国以工作搜索引擎为主体业务的公司,被日本 R 社收购后在日本开张了办公室。

加入 I 社的时候办公室只有二十名不到的程序员,等到离职的时候已经超过两百人,可以说见证了 I 社在东京办公室的快速发展时期。

在 I 社的前三年我一直在 SEM 组工作,SEM(Search Engine Marketing)组的主要任务是自动的将公司投放在搜索引擎上的广告优化。这是一个纯后端的组,以前的工作经验在这里并没可以发挥的地方。

我的工作内容,从一开始去开发维护一个基于 Python 的内部工具网站(后来知道老板看我的简历是做 App 的,误以为我是前端能手),三个月之后 Python 工具网站的开发告一段落,开始接触竞价算法(Java 后台程序)。

当时正适逢移动流量开始渐渐追赶并超过个人电脑的流量,针对移动端广告进行竞价调整(Bidding Adjustment)是一个重要的功能。

正是在进行这一工作的时候,我有机会去主导从 MySQL 切换到 RabbitMQ 的解决方案,解耦合算法端和 API 端的紧密联系。并且通过和系统工程师的配合,解决了首次部署 RabbitMQ 中遇到的问题,并设置了警报规则去监视系统的运行健康状况。

在切换的过程中,为了保证无故障的切换,先后采用了试运行(Dry Run)的方式模拟从 MySQL 切换到 RabbitMQ 的场景,接着运用了 A/B test 的工具分出少量流量测试 RabbitMQ 流程的稳定性,最后达到 100% 切换后进行代码的清理。

在这个项目中我学到了很多宝贵的经验,对于以后进行的一些重构式工程有很重要的方法论上的参照意义。

2、迅速成长为 Mentor

在 SEM 组的工作使我从一个入门的初级程序员,成长到可以去带新人的 Mentor,除了做每个季度组里的季度目标意外,我也参与到全公司的推进的项目中。

比如 JDK 从 1.6 升级到 1.7,从旧的部署系统迁移到新的部署系统,启用 CI/CD 模型等等,在做这些项目的同时,自己接触到了在平常的开发过程中不会遇到的问题,比如如何解决库中的 class 冲突,CI/CD 模型适用 / 不适用的情况等等。

与此同时,自己也不满足于只是去做分配下来的任务,开始观察并思索作为工程师的痛点。比如,每次上游的一些库会莫名其妙的改变一些公有接口,导致下游的项目构建收到影响,结果给下游项目的开发人员带来了额外的负担。

另一方面,上游库的开发者要想改变删除过期的接口让下游项目迁移到新的接口,又苦于在公司内部喊嗓子得不到有效的回应,下游项目的工程师没有动力去及时的跟进改变,导致过期接口的删除迟迟不能进行。在这种情况下,如何可以减少不必要的公有接口修改,同时又能提高必要公共接口修改的曝光性?

在研究了公司的构建系统之后,我决定在构建系统上,利用一些开源工具和 Java 编译插件的技术,实现了两个小功能:

  • 在发布库的新版本是总是和最后一个旧版本比较 API 的修改,如果有任何公有接口的修改或缺失则给出警报;
  • 提供编译期的注解(Annotation),让程序员可以对公有接口(类)设置过期时间,在过期时间到来之时下游的项目如果有引用则会出发构建失败。

这两个功能我是一前一后做出来并在公司内部发布,但是风评却是前一个平平偏向负面,后一个得到不少的点赞和使用,但也引起了不少麻烦。然而由于当时急功近利的心理,并没有很好地去 follow。

3、成长速度放缓,寻求改变

I 社是我从一名初级程序员向着高级程序员成长,随着在公司的时间增长,手头的工作也很快不能够满足自己的兴趣。在 SEM 组待了将近三年之后我的经理建议我换组,在经历了一番挣扎后我选择了去一个有前端以及顺带一些移动应用的组,在这里我又重操了一段做移动端应用的经历,并且又学习了一些前端方面的知识。

在 I 社待了 3 年半的时间,当公司越来越大之后,时常会感到个人的贡献越来越有限,感觉个人的成长也在逐步地缓慢。在对比了其他同事的晋升道路后,仿佛看到了自己在 N 年后的场景。

但是之前觉得在日本没有比 I 社更适合自己的公司了,于是也一直没有去寻求新的机会。去年随着几位前同事的离职,自己也开始认真考虑换工作的事情。

恰逢也同样是美国总部的 H 社在东京开始招全栈程序员,虽然同样是美国公司,但是 H 社还尚未上市,团队也较小,所以抱着施展一番拳脚的想法去面试了 H 社全栈工程师的职位,并于去年 7 月加入了 H 社公司。

四、全栈程序员

加入 H 社后首先感到的很大的 Gap,便是在公司的技术上。在 I 社,我所碰到的领域都已经有了成熟的解决方案。但是在 H 社,跟 I 社所对应的一系列基础设施建设却远远称不上完善。这让我进入公司之后很是怀疑了自己的选择。

在进入公司的前两个月,我经常会发信给全公司的程序员,去探讨为什么我们要这么做而不是那么做。并且也提交了很多改进方案,希望可以改成我在 I 社所接触到的方案。

当然这些都并不是很顺利,在 H 社的老人们给了非常强力的反击。在拿不出充分证据论证的情况下,我只好选择了暂时蛰居,先处理好眼下自己手头的工作。

加入 H 社后的首个项目是将一个年头已久的 PHP 前端 + 后端网页改成 PHP + Apache Thrift + GraphQL + NodeJS +React 的新框架。作为全栈(Full Stack)工程师,我需要从 PHP 到 React 从头到尾都做一遍。

首先便是读原来的 PHP 代码,并抽象成 Thrift 服务。其次便是在 NodeJS 服务器端将 Thrift 服务映射成 GraphQL 的 Schema,并实现 GraphQL 的 Resolver 逻辑,然后便是用一个 Node 应用代替 PHP 的前段,用 React 的框架来渲染出一模一样的网页。

在短短的几个月内,从一窍不通的 React 小白,到完成了整个页面的迁移,自己对于 React 框架的应用和一些实践有了自己的理解。

GraphQL 也是一个对我新鲜的概念,在 GraphQL 的实践中,我感到这个框架其实也很适用于我在 I 社工作的第二个组,甚至可以在脑海中把原来的 API 用 GraphQL 一一对应起来。

这种相互印证的感觉让我再次意识到做出换工作的决定并没有错误,否则我的思路会很长时间局限在 I 社的框架中。

在加入 H 社的三个月之后我想通了这样的道理:一个什么都做得很完美的公司,或许更不如一个什么都不完美的公司,因为前者让人失去了去改进的机会,而后者却给予了很多这样的机会。

于是,我便在工作中,挤出一部分精力去做一些力所能及的改变。首先便从使用的 GraphQL 入手,通过调试发现存在着过度查询(Over fetching)的情况,某些查询代价较大的字段,明明没有出现在查询语句中,但是后台却仍然将其返回。

于是我通过标注(Annotation),在 Resolver 层面讲字段和 Thrift 服务的参数进行映射,使得 GraphQL 被翻译程序 Thrift 请求时可以自动的附上请求字段的列表,在服务器端根据字段的列表可以选择性的返回字段,达到“减负”的目的。

春节期间利用闲暇时间,把公司的 A/B 测试系统进行了优化,这个优化也是我刚进入 H 社时最想改变的一点,然而遭到很多质疑的点,于是我在进公司提出的 propse 基础上做了退让,专注于解决最基本的痛点,加入了基于不同域名实行不同的分配(Bucketing)。在于现行系统并存的情况下一步一步的将功能发布了出来,在公司内获得了好评。

五、 下一个十年

从 2009 年第一次实习经历算起,一眨眼我已经做了十年的程序员。我也过了而立之年,眼看着行业里自己已经算年龄偏大的从业人员。

纵观我的程序员经历,从移动应用开发,到后端、前端,以及零星的 DevOps 和 Release Engineering 的经验,我觉得自己是朝着“全才”的方向发展。然而全才意味着什么都懂一些,但是又说不上是哪个领域的专家。

近两年来在各种媒体上看到大龄程序员的囧境,时常会思考自己以后的方向。我仍时常会关注国内程序员招岗的要求,发现大多数岗位还是需要领域专家的人才,而不是全才。

我也时常会质疑自己,是否太过贪多嚼不烂。然而我最近似乎想通了一点:领域专家 vs 全才,两种人在这个行业都是被需要的,只是一般的岗位确实会需要你只会干某一样便可以。

这并不意味着会的越多就没有施展的地方,在初期的创业公司,以及新成立的部门,这样的人才还是很有必要的。既然自己的兴趣在于了解和挑战不同的领域,不如就将其发展到极致。

下一个十年,我想我仍会热爱程序员这个工作,我会在现在的岗位上,朝着填补我技能树上的空白努力,争取在下一份工作,可以将自己全部的所学都用上。

作者介绍

赵杨阳,在海外工作,以创业为目标的软件工程师。2009 届清华大学计算机系本科生毕业;2012 届清华大学计算机系硕士研究生毕业;2012 年加入日本手游巨头 DeNA,从事移动开发;2014 年加入世界最大工作搜索引擎网站 Indeed,从后端开始涉猎广泛开发;2018 年加入互联网家装平台独角兽 Houzz,从事全栈开发。博客: www.cnblogs.com/chaosyang

原文链接

https://mp.weixin.qq.com/s/UlMufJCgKL-pUq-dUsaJBw

收藏

评论

微博

用户头像
发表评论

注册/登录 InfoQ 发表评论