以前搞化学,自学编程 9 个月后,我成了年薪 6 位数的软件工程师
每当我开始阅读成功故事的时候,我都会马上去查找作者的背景是什么,希望能适合我。但是我从来都没发现那些人的背景跟我一致,所以我的很可能跟你的背景也不一致。
不管怎样,我希望我的故事能够激励其他人,同时能够充当一个有用的数据点补充到你的成功故事数据集上。
充分披露
高中的时候(9年前)我上过VBA的课程。我在新生工程课程(7年前)中学习了一些C、Python、Mathlab以及Labview的知识。我从一所很好的大学毕业,拿到了化学工程学位,我的GPA成绩也不错(3年前)。离开学校(高中或者大学)以后我从来都没有编过程,直到去年我决定要去学一下。
大学毕业后,我在一家精炼厂拿到了一份工艺工程师的工作。在我改行到软件工程之前我一直在那里工作。
为什么我要换职业
我喜欢解决技术问题,但我知道到了某一刻我还是要进入商业/初创企业世界的。我一直都有读MBA的想法,但每次看到顶级商学院的价格时,我的兴趣马上就没了。
2017年5月27日,我又上去Google了一下MBA,但是不知怎的就看到了软件工程方面的东西。而且这东西看起来挺适合我的。
对软件工程师的需求日益旺盛,工资水平也很高,而且也是进入到初创企业世界的完美行业,并不需要太多的启动资金。你需要知识一台计算机,而且你的机会(几乎)无限。
在这里你只需要有个想法,开始开发,然后展示给用户,再用一点点资金进行迭代就行,进入门槛也很低,其他任何一个行业都做不到这一点。在化学工程,基本上你需要有一间运营的工厂,或者需要很多钱去设计一家工厂,如果你有个新产品的想法的话。
我听说过有人辞职去参加训练营,但是我在网上看到这些情况越多,我就越意识到其实我完全可以自学,如果我够投入和专注的话。
你也许会提出不参加训练营的话岂不是会失去那里提供的关系网络和职业建议?的确,但是我很幸运,因为我生活在湾区,所以可以去出席一些回忆,在那里我建立了自己的关系。
此外,最糟糕的情况也只是我发现自己一个人学不来,真这样的话我再辞职参加训练营也不迟。
目标
你需要有目标。尤其是如果你想一边干全职一边自学的话。如果你不给自己额外的压力的话你的学习就会一拖再拖。所以你需要给自己施加内部压力。你的目标应该是简单的、可量化的。你应该进行充分研究,提出合理的目标。我的目标是这样的:
在1年之内拿到一份薪水跟我现在相同或者更好的软件工程工作。
计划
一旦你制订了目标,就需要一份计划来帮助你实现。这个时候你需要尽可能多地去了解别人的成功故事。当然他们的情况都不会跟你一致,但你可以从每个人身上吸取一些经验。我利用Reddit的子版块learnprogramming、FreeCodeCamp论坛以及Medium等资源来制订我的计划(并且不断修订)。
2017年5月27日,我决定开始我的学习编程之旅,下定决心之后我可以说是一个猛子就扎了进去。我决定每周的工作不能超过40小时,这样我就有时间在工作之后以及周末去进行编码。你很幸运,因为我把我的整个学习过程都详细记录下来了。
我的计划经过多次迭代之后,最终大概是这样的:
- 上一门计算机科学入门课程,对核心计算机科学概念有可靠的基本了解。
- 跟着freeCodeCamp学直到我自己可以开发出组合层面的全栈web app。
- 通过重构来清理代码,增加测试,专注于先进的概念。
- 给开源做贡献
- 准备面试
我的计划一开始是非常简单的。那时候我认为自己应该按照Google的技术指南去学,所以我选了一门他们推荐的入门课程,Udacity CS101。
第0个月——Udacity CS101,Harvard CS50
做出这一重大决策让我充满了能量。我一下班回到家就迫不及待开始编码而且直到上床前都不愿停下来。然后整个周末都是这样。Udacity CS101会跟踪完成百分比,这对我是一大激励。我每天编程完之后都要记录我们的完成百分比。在10天内我就完成了前面的75%。最后的25%侧重在递归方面,这对我来说有点难。总而言之,最后我用了20天完成了Udacity CS101。
我在上Udacity CS101的同时,还一边开始相当频繁地上Reddit的learnprogramming子版块去看。我我在上面了解到正在寻求改变职业的自学开发者在网上活跃是非常重要的。我决定用自己的全名在Twitter、Reddit、Stack Overflow、Medium以及Quora上面开设新的账号,以便在网上刷存在感。
此外,我还决定不再看Instagram、Facebook以及非编程方面的Reddit子版块,以免造成分心。我只有在查看编程相关的新闻和帖子时才会翻看我的手机。这一点很关键,因为可以确保我能找到最好的学习路径和学习资源。正是因为这样我才在edX上发现了Harvard CS50。
一开始我只是满足于上一门入门课程,但每个人似乎都推荐Harvard CS50,所以我决定再试试这门课程。其他学校计算机科学的学生也上了这门课,并且说他们在哈佛的CS50上面学到的东西比在自己的大学学习1、2年的计算机科学所学到的东西都要多。大家的普遍共识是这门课程很难但是值得。到了第0月的月末,我已经完成了前5节课以及家庭作业。
第1个月——Harvard CS50,Linux,第一次聚会,freeCodeCamp
大概到了这个月的一半时间时我终于完成了CS50。关于学CS50的体会我不想谈太多,因为我已经在这篇文章详细谈了我的经历。
总而言之:这是一门很棒的课程,我高度推荐。David Malan是一位优秀的讲师,而且有很多资源可以帮助你通过这门课程。你从C语言开始,然后再到Python,最后完成web开发。安排非常紧凑,涉及大量材料,但我认为是非常值得的。
在CS50之后,我决定把我的XPS 15配置成Windows和Ubuntu双启动。那是一个令人沮丧的周末。我把分区搞砸了,笔记本几乎变成了一块砖头。我差点就想把那台笔记本扔了买台新的。
我慢慢放弃了Windows,最终主要以Ubuntu作为平台。我想强迫自己适应一定程度上可行的命令行方式,但是仍然有很长一段路要走。
我开始了百日写代码之路,以确保自己保持专注和每天都写代码的节奏。记录自己的进度非常重要。如果你每天都能取得进展,尽管看起来似乎不大,但是日积月累之后回过头,你就会意识到其实你已经走了挺远了,而这又会激励你继续前进。
我知道,关系网络决定了我的成败,所以我鼓起勇气参加了自己人生中的第一次编码聚会。我此前从未参加过任何聚会,更不用说编码聚会了。所以一路上我都非常紧张,以至于开车到那里停好车走进门之后,几乎就想转身离开回家了。
这是那个团体的第一次聚会,这一点很有帮助。我迅速意识到自己没理由紧张。大家谁都不认得谁,没人来这里是为了给别人下结论的,每个人都渴望学习。而这只是一场聚会狂欢的开始。在9个月内我最终出席了超过50场聚会。
很高兴,我很早就开始参加聚会。大多数人只是在寻找工作的时候才开始出席聚会,但到那个时候几乎已经太晚了。要早点参加的理由太多了。这里仅列举少数:
- 培养关系需要很长的时间。早点开始意味着后面找工作的时候你保证可以有关系可以依赖。
- 跟陌生人讨论编程时准备面试的很好手段。
- 你可以学习新的框架,了解到走走你前面的那些人的学习资源。这些会影响你的未来学习计划。
我的编码之旅走到这个时候出现了一点不确定性。到这时候我需要决定自己想要成为什么样的软件开发者。
到最后,我选择了web开发,因为它的需求似乎非常旺盛么热切网上有很多资源。一旦我想明白了这一点,我就需要弄清楚接下来要做什么。一些人建议到这一阶段我应该考虑想要开发什么样的web app然后继续。一些人向我推荐The Odin Project或者freeCodeCamp。
那个负责筹划我每周都参加的聚会的家伙会Ruby,也想用Ruby做项目。我决定全身心投入到The Odin Project里面,这是其中的一大原因。
然后2天之后我又决定放弃这个想法了。
这就是走自学路线的缺点之一。一分钟前你以为你已经找到了前进的方向,然后第二天你又会怀疑你有没有走对路。
我了解到Ruby正在失宠,并且通过搜索对比Ruby和JavaScript的就业机会来证实了这一点,所以我最后决定开始freeCodeCamp。freeCodeCamp比较令人困扰的一件事情是项目的想法是他们想出来的,所以每一个参加训练营的人都做相同的项目。然而,一开始我感到担忧的是我希望能做应聘者当中脱颖而出。然而,我最后还是爱上了freeCodeCamp,现在我高度推荐你们要学这个。要想了解更多我关于freeCodeCamp的体验和推荐,请参考我的这篇文章。
第2个月——YDKJS,freeCodeCamp前端,React
我开始读《你不懂JavaScript(YDKJS)》,因为每个人都推荐它作为freeCodeCamp的补充。我被迫重读了好几个章节,因为它的内容特别紧凑,但这是学习词法范围、闭包、预定等你听到也想学到但因为很难从未试过的有关JavaScript的一切的完美资源。
我完成了freeCodeCamp的前端部分的学习。其检查表格式以及估算完成时间起了不小的帮助作用,这激励了我要迅速完成。我还恨不得马上进入下一章节去学习React。然而,这也意味着我的项目都是极简风格。我除了竭尽所能去实现用户故事之后就不再做别的东西了。
事后看来,也许我应该把精力放在让项目更吸引人上面。也许这会让我更深入了解CSS。
下一步就是学习React,我忙得差点缓不过气来。
我已经听说过React的很多,并且已经准备好要成为酷小孩的一员了。然而,我还有一点踌躇,因为当时的许可问题。我真的很高兴这不再是问题了。学习React对我来说很困难。当时我还没有发现任何好的教程(但是现在似乎到处都是)。
我尝试阅读文档,按照Facebook的一字棋教程去做,但我其实不是很理解它是怎么做的。我被告知这不适合我,这意味着我对JavaScript的理解还不够。于是我又返回来继续读《你不懂JavaScript》,但再次地,里面的内容对我来说太高深了。
第3个月——freeCodeCamp React,CodeClub,开始freeCodeCamp后端学习
最后,我决定去做freeCodeCamp React项目练手,看看它究竟是怎么做的。写出来的代码很难看,但的确帮助我更好地理解了React。
我参加的每周聚会决定全栈都用JavaScript而不是Ruby来做项目,并且他们还确定了第一个项目将是给这个聚会小组开发一个网站,CodeClub.Social。
我利用React和Meetup API开发了卡片,让用户可以通过我们的网站注册报名参加接下来的3场聚会活动。这对我来说有点难,因为我得暂停freeCodeCamp学习来做这个,但这是一个我不容错过的机会。我很高兴能跟一小群人一起做项目。这也帮助我学习了Git和Github。
在这个月结束前,我开始在freeCodeCamp学习后端开发。
第4个月——完成freeCodeCamp后端学习及Yeggle开发
我练完了freeCodeCamp所有的API项目,但我开始从freeCodeCamp抽身出来做Image Search Abstraction Layer这个项目。
我迫不及待想要开发全栈web应用,所以我看到这个项目的名字时马上就有了自己的项目想法。我想做一个节点app,用来存储随机imgur URL到数据库上,然后再做一个前端来输出这些随机图像的用户指定数字。大家的说法是对的:当你做一个自己想出来的项目时,你会更用功也更成功。
当我把项目做成了之后,一股自豪感油然而生。虽然它很丑很笨拙,但是最重要的是能用。
我在freeCodeCamp的学习过程中,还了解到了哪些项目是我的能力范围之内的。当时我经常会去跑步,在跑步过程中我时不时会冒出一些想法,等我回到家就把那些想法写下来。这样等我准备好时就有了一个项目清单了。
最后,我终于感觉自己已经做好准备,可以把自己的有用且光鲜的全栈web app分享给用户并且纳入我的组合里面了。我已经摩拳擦掌,迫不及待。
在找新饭店的时候,我总是会打开Yelp去看看别人的点评,然后再打开地图看看别人的点评。如果我做一个app来把这两个一起比较一下呢?
于是我做了Yeggle,这个东西用了Node/Express/React,再加上Google Maps和Yelp API。当时有好几个障碍我认为自己是没法克服的,但到最后我还是设法完成了,我对这个app也感到非常自豪。然后我把它发到了Reddit上,可是没人在意。这有点令我失望,但我是不会被这种情绪打倒的。
第5个月——StockIT
这个月我做的东西不多,因为我跑到日本和泰国度假去了,整整2周!
但是我还是开始并完成了下一个项目。我不断读到自学开发者找到工作是多么的难,于是我认为自己得做点独特的事情。我记得有一个游戏是当道琼斯股票走势图开始活动时,你有一个买入的机会和卖出的机会,其目标是击败市场。这个游戏的目的是想让你看清楚击败市场有多困难。
我的想法是做一个类似的游戏,但是你的对手不是市场,而是机器学习算法。于是我创建了StockIT。
我在Pandas和Scikit Learn上面学习了一些涵括多种机器学习技术的视频教程。我原先是希望做一些很酷的深度学习技术,但我意识到这需要大规模的数据集和时间,那些是我耗不起的。
相反,我采用了简单的线性回归模型。我以为这会是困难的部分,但其实不是。让D3跟React配合工作才是。这两个库都想控制DOM。还有一些别的库可以帮助把这两个库凑合起来,但是我认为引入新的库会让项目太臃肿了。我最终用D3生成SVG,用React处理DOM,情况看起来相当不错。
我再次把它分享到Reddit上面,这一次大家都很喜欢!
结果表明,就像VC一样,上Reddit的人也都对机器学习着迷。Reddit用户的厚爱让我的信心有了极大的提升。大家都玩我的游戏并且喜欢上了!
第6个月——jobSort(),找工作前的准备
在StockIT之后,我又开始了下一个个人项目。我希望做一个岗位看板,把一些小规模的面向技术的职位列表网站,比如Stack Overflow、Github以及Hacker News上的就业机会都集中起来展示。为了增加它的独特性,我决定根据用户对职位的技术需求以及需求程度进行排序。
比方说,假设我正在寻找一份需要了解JavaScript、React及/或Python的工作,并且招聘者对JavaScript和React的需求非常迫切,对Python就没那么关注。这种要求量化下来可能是JavaScript分数是3,React分数也是3,Python则是1.这样就能把清单排好序了。
做这个项目的时候我碰到了各种各样的障碍,图中被迫调整了几次航向,但我最后还是做出了一个自己满意的产品。我的最后技术栈用的是React/Node/Express/MySQL。我把项目发布到Reddit cscareerquestions子版块上,浏览量是650,因为他们不允许放个人项目上去所以被下架了。
“最后”的产品在这儿,如果你对我的折腾过程和重构感兴趣的话,也可以看看我的这篇文章。
由于我自己的原因,jobSort()用掉了我那个月蛮多的一部分时间。我最后跟在第一次聚会上认识的一位朋友去喝了一次咖啡,他建议我现在可以去申请工作了。我总是看到有人说自己等待了太长的时间才去申请。而且,每每我看到询问什么时候该申请工作的帖子时,被点赞最多的回答总是“现在”。
我原先的想法是按照自己的结构化计划完成个人项目组合来提高自身实力,然后再去给开源项目做一些贡献,最后再去准备面试,然后申请工作。这位朋友说服我抛弃那个计划开始申请。于是这个月我做了一份材料和简历。下一个月我将开始申请。
第7个月——测试,求职
这个月我的精力主要集中在我自己的项目以及申请工作上面。我还想学习一下测试以及Redux。
我给CodeClub.Social增加了弹性框让它成为响应式布局。我改善了jobSort()的移动UX。我给jobSort()增加了测试,我用的时mocha/chai/enzyme,这个设置很难,不过起步很容易,但是要想100%覆盖很难。
到了月末,我已经申请了63份工作。我把这看成是自我评估。我的组合/简历是不是足够好了?如果是的话,我需要做哪些事情来准备面试?一开始我是通过Hacker News: Who is Hiring和Indeed去申请的。
在Hacker News上,我用jobSort()来确定申请哪一份工作。在Indeed上,哦尝试了非软件类公司看看是不是也能拿到邀请或者面试机会。
起初,我申请很快,没有对简历/求职信做什么个性化处理。然后,我决定要对我的求职信和简历进行个性化处理,然后试着发一封邮件给公司的某人。这个办法显然比天女散花的做法更好。
那个月我收到了5个电话——其中两个是来自招聘公司的,另3个是来自软件公司的,包括:
- 在一家.com公司的DevOps/测试角色,是份合同工
- 一家B轮的视频分析公司
- 一家相当大且成功的初创企业,最近刚被一家大企业收购
我通过了其中两家HR的筛选,但是对方都没有要我去现场面试。当然我对这3个电话都比较满意,从中也学到了很多东西。
网上的每个人都提到初级开发者不要指望一开始就了解那么多,他们只需要对学习抱有激情和兴奋就行。所以我认为这是很简单的。我对学习就很有激情和兴奋感。不过我从这些来电中学到的是,没人会找一位初级开发者。他们希望你从第一天开始就知道该怎么做。
这些电话教会了我需要:
- 从第一天开始就足够好,能给对方带来价值
- 要足够自信说服他们我能从第一天开始给他们增加价值
第8个月——夜班,Redux,开源,现场面试
从这个月开始我除了全职工作外还上夜班——每周6天,每天12小时,从下午5点到凌晨5点。
我知道这个月我没法做那么多事情了,但是我有自己的目标,我想实现它,这样的话我就可以有一个月的空了。
我用Redux重构了jobSort(),令人惊喜的是这没有我想象的那么难。我收听了很多关于它的播客,也去读了关于它的博客,但是那些理论都没有太大的作用,直到我开始使用。
我真的非常喜欢Redux的数据流处理。现在看到有人抱怨Redux是很有趣的。我并不认为我有神马资格发表什么观点,但是我的确喜欢reducer模式。
这个月本来我的打算是做开源的。我计划是要做我的第一个开源贡献,这本来是对一个很好的库的一个很好的贡献。我打算给React写点东西!
每个人都说这个代码库很难读,更别说给它做贡献了。但我需要脱颖而出,我需要凸显独特。我知道我的贡献不会非常显著,但我还是想去做。
我会从阅读所有的文档开始,然后再去了解代码库。查看每一个问题,每一份新闻稿。完整阅读React文档是一次很好的练习,很高兴我做到了。但我迅速意识到给React做贡献的问题是“好的第一手问题”其实并不多,因为问题很快就被人抢走了。
一次我去参加聚会时,Anthony Ng建议我可以试试Downshift,那是Kent C. Dodds开发的一个自动完成库。这成为了一个游戏改变者。这个东西正好适合我发挥。难度合适,问题数量也合适,协作者也不太多,超级帮忙的维护者,整齐且经过很好测试的代码。除此以外,它还是我的jobSort()应用遇到的一些问题的完美解决方案。
这个月中的时候,我收到了上个月申请的一家公司的电子邮件。他们进行了一轮初步的电话筛选,然后是技术电话筛选。他们正在寻找的技术正好是我学过的——React、Redux以及D3。我主要谈了我的项目以及为什么我要做出特定的决定。此后,他们让我去现场进行面试。这是我的第一次现场面试!
我根本就没有为面试做过准备,所以我的期望很低,并不指望能拿到那份工作,但是我会收获宝贵的面试经验。因为我还在上夜班,所以每天的睡眠时间只有3个小时。幸运的是,技术部分不是写白板,而是1个小时的结对编程。这是相当直截了当的挑战,但是我非常紧张。
一开始的时候,我担心的是要确保我不用查东西也能了解一切。当我意识到自己没法完成挑战时,马上就意识到自己需要停止担心面试官会怎么看待我的事情,于是我就去Google/Stack Overflow上面找答案。我最后没有完成,预期自己会有一个悲惨结局。
既然我认为我的结对编程已经失败,在面试的剩余时间自己反而放松下来。最后,我昂首挺胸地离开了面试。最糟的情况下我也收获了宝贵的面试经验,最好的情况是我会得到我的第一份工作。
第9个月——工作邀请
从我决定改行深入学习编程的第一天开始,经过9个月零7天之后,我终于拿到了第一份工作邀请。因为第一次面试就拿到了一份offer,我感到自信满满,但与此同时,如果我不接受这份工作,如果这会是我几个月内收到的唯一一份offer的话该怎么办?我最终接受了那份工作,并且对我的决定感到满意。我希望能够通过写代码挣到钱!
建议
到这里,我基本上已经把我的故事分享得差不多了,其中也提供了一些建议。如果你读到本文的话,很有可能不是在考虑改行就是为了改行而在学习编码的过程中。我希望下面的建议能够帮助你制订计划或者坚持目前的计划,最后达成你的目标。
- 找到激励你的东西并善加利用。对我来说,这个东西是检查表,对过程的记录,以及跟不同编程社区的互动。如果你没有受到实现目标的激励的话,那任何其他东西都不重要了,因为你完成不了的。
- 制订目标并且实现目标。要我说你应该有月度目标,甚至有每天的目标更好。月度目标是为了确保你走在实现主要目标的正确轨道上,每天的目标则是为了确保你每天都能取得进展。对我有用的一个策略是前一天晚上制订次日的目标。这样的话你就不会一整天都去做没有生产力的事情却又觉得自己取得了进展。这会迫使你将每天的成就与每天的目标进行比较。
- 尽早参加聚会活动,不要等到觉得自己准备好了才去。参加聚会也许令人心生恐惧,就像我前面提到过那样。但通常每个人都是很好的,并且愿意帮忙。你也许会发现有的人对跟你讨论没有兴趣,但那是少数,而且没人喜欢当判官。此外,每个人都喜欢提供建议(就像我现在所做一样)。
- 尽早给开源做贡献,不要等到你觉得自己已经准备好才做。刚你开始编程的时候,Github似乎是个你永远也不想去的可怕地方。但其实那里是非常欢迎初学者的,而且也是学习好代码以及让别人审核你的代码的好去处。如果你仍然不相信,不妨看看我的文章《为什么你现在就应该给开源做贡献》。
- 尽早申请工作,不要等到你以为自己已经准好了才去。这一条对我而言很困难,因为我认为我不一样。我认为我不需要去市场试水一下看看是什么情况。我以为我已经知道自己什么时候已经为申请做好了准备。现在我告诉你。你不会知道什么时候可以去申请。所以其实你可以现在就去申请。当然,你不应该连for循环语句都没学就疯狂去向300家公司提出申请。但你应该知道的是,了解自己应该学什么的最好办法就是去申请工作并且去试探一下市场。
好了,现在该你上场了,去写代码吧!