多做项目
我是半路出家的,头发没剃光的那种(实际上我现在头发还茂盛得很)。我在培训机构呆了半年就出去找工作。
第一份工作失败了——底子太薄,工作撸不动,很快主动辞职了(怕被请辞就太没面子了)。
然后我花了点时间恶补了下——用今天的眼光看,那时的底子仍然薄得可怜,不过能应付初级工作。
第二份工作,我独立做了很多项目——对于菜鸟来说,能有独立项目做很重要,它能让你较早地思考设计问题,而不仅仅是 CRUD。初入编程行业,最怕的就是干了几年,除了 CRUD 啥都不会,这对后面的发展非常不利。
然而现实的悖论是,菜鸟一般很难接到独立项目(特别是对性能、稳定性有些要求的)。换你做 Leader,你会把重要的工作分给哪只鸟?
所以菜鸟一定要有主动工作的意识。要有想法,且乐意表达自己的想法。开会的时候多发言,多说说自己的想法(但要谦虚,不要争吵,千万不能让人觉得自己自负、不合群)。要想让 Leader 能分配重要任务给你,首先要获得他的信任,要让他觉得你是个潜力股,值得培养。
有一个很重要但被很多人忽略(或不屑)的点:要自己找事做。你得学会没事找事。在我的职业生涯中,对我提升很大的项目中有一半都是我自己找的。我说的项目不是项目管理那个意义上的项目,它可以是需求,也可以是系统优化,可以大到需要多个团队协作,也可以小到仅仅是个通用组件开发。
当然不是瞎找。要找公司的产品和系统有什么痛点,这些痛点你能不能解决,解决了对你和公司能带来什么好处——双赢才是唯一的出路。
我发现公司的登录流程混乱不堪,经常要接入分支流程,于是提出重构登录模块;我发现公司各系统的下载功能都是各自开发,而且数据量一大就崩溃,于是提出开发统一的下载中心;我发现公司各种管理后台系统日益增加,系统间没有一个统一登录方案,便利用加班时间开发了个 sso 系统。我还自己写框架,然后在公司内推广让别人用......
我像一只地鼠到处钻,还自己造轮子——世界上有那么多轮子,一个重要的原因是造轮子本身是团队和个人技术沉淀的有效手段。我通过开发框架理解了大部分的设计模式。
所以,如果初出茅庐,看多少经典书籍不是主要的,主要的是要多做项目,特别是有挑战的项目。不要怕失败,我有很多项目是失败的(有些功能优化被证明比优化前更糟;有些项目压根没上线),那又怎样——至少我思考过,实践过。
多看书
一味地做项目并不能大幅提升自己。编程能力跟做项目的数量没有必然关系——虽然在接触不同的钉子,但你手上拿的还是原来那把锤子。
有些人以自己“动手能力强”为借口鄙视看书。他们信奉“实践出真知”,看书无用(特别是理论性较强的)。
熟不知书籍本身就是前人的经验总结,还是牛人的经验,所以必须看,看多少都不为过。
之所以是先多做项目后海量看书,是因为在没有一定的实战经验之前,很多书你是看不明白的。
其实这个顺序并不精确,往往是同步进行,但不同时期侧重点不同。
起初一般看工具型的,如各种“深入理解”系列(深入理解 MySQL、深入理解 Redis),加深工作中密切相关的工具(你具体使用的编程语言、数据库、缓存都是工具,这里不是说编程语言 IDE、MySQL 客户端这种开发工具),稍微深入到其底层细节——但除非你对某个东西特别感兴趣,否则此阶段没必要过于深入,没必要每个工具都要研究到源码级别,烧脑是一回事,人的时间是有限的。
研究完这些工具,你会发现过去项目中一些代码实现、数据库设计是有问题的,存在优化空间的——这说明书没白看,能力提升了。能力提升的标志是能意识到之前的实现方式的不足和改进点。
接着需要多看看跟具体工具无关的书,像计算机原理、操作系统、设计模式、系统架构、算法,甚至软件工程。如果说前一个阶段的阅读重心是搞清楚如何用 Redis 做缓存系统,这个阶段则是学习系统架构中的缓存实践模式。
这种类型的书籍重点是讲思想和实践经验,所以多少有点抽象,很多书看一遍后云里雾里,觉得好像学到了什么,但又什么也没学到。这很正常,因为你的项目实战经验还不足以支撑自己去深入理解这些东西。
我在看《领域驱动设计》时,虽然处处都能感受到惊喜,但很多概念是囫囵吞枣,觉得自己理解了,又好像没理解。像聚合、聚合根、限界上下文、领域服务、应用服务,低头看书时觉得上面的东西都能看得懂,一旦抬头思考就卡住了。这一方面反映出我经验不足,另外也说明我正触碰到自己的认知边界,正在接受一种全新的知识或说认知模式——一旦得到突破,便会有质的提升。
看完《领域驱动设计》后的一个重要效果是,以后在设计系统时,我会有意识地去用 DDD 里面的东西思考设计。这时候多半会卡壳——经常卡的那种。于是我会回头再去看书,因为这时候是带着问题看的,直接找到相关主题看一遍,多半会有“原来如此”的感叹。
比如一些控制器里面代码逻辑较多,而且很可能多个控制器存在相同或相似的逻辑,但这些逻辑又明显不属于领域层,怎么办呢?我忽然想到应用服务的概念,这些逻辑应该抽离成服务,但属于应用层的服务。这样一实践,大致就理解了原本抽象的概念。任何概念都是用来解决问题的,如果你不知道一个概念是用来解决什么问题的,你就没有理解这个概念。
所以做项目和看书是不断迭代的过程,不断学习,不断实践,不断思考,你才能不断突破自己。
学习是辛苦的,突破是痛苦的。人的大脑本能地喜欢呆在舒适区。我们今天学了这门语言,明天再去学那门语言就会觉得很轻松,因为两门语言的学习模式是一样的,大脑是呆在舒适区的。但今天学习这门语言,明天去学习这门语言的实现就会很痛苦,因为这是两种不同的认知模式,大脑需要走出舒适区,一旦走出舒适区就会进入混沌态——大脑不喜欢混沌态。
要想获得大的突破,必须学会接纳处于混沌态的自己。
读些历史书。这不是必须的,但“读史使人明智”是真的。感兴趣的话读一读人类历史(不是教科书那种),以及科技史。至少要读读计算机史。历史能告诉我们一些东西为啥是这样而不是那样的。计算机为啥叫 Computer?一个字节为啥是 8 比特?键盘为啥是 QWERTY 布局?计算机一开始就用的二进制吗?为啥说冯·诺依曼是现代计算机之父?学史跟编程没有必然关系,但能开拓你的视野,让你知道那个时候人们面临怎样的问题,是怎么解决的。有些你认为的新东西其实很早就被发明或构思出来了(比如 10 年前开始流行的云服务概念其实在上个世纪 60 年代就以“计算机公用设施”的概念盛极一时)。
人们不喜欢看书的一大理由是一种人人都有的感觉:很多书看完后很多东西都不记得了。这种感觉很不好。
有句话叫“好读书,不求甚解”。我对“甚解”的理解是企图把书中每个知识点甚至每句话都搞清楚并记住。
没那个必要。除非记忆力超群(据说冯·诺依曼就有这个能力),大部分人在读完一本书后都会忘掉大部分内容(甚至读得越慢忘得越多)。但今后你再去读任何一个章节,你都会觉得很熟悉,有时候在项目实践中大脑会突然蹦出个原本已经“忘记”的知识点。这是大脑的正常生理机制,没必要跟它较劲。
我有时候读完一本书后,大脑里只剩下一个概念,其他的一概忘记了。比如我读完《设计原本》后,脑袋里只剩下“概念完整性”这个词。也许当时我真的没读懂这本书,但光这个词就让我获益匪浅。在日后的系统设计、团队管理,特别是跨团队协作开发中大型系统时,这个词不断地出现在我脑海中。很多系统上线后 bug 不断,就是概念完整性(以及概念一致性)上出了问题,比如多个系统对同一个概念定义不同;金额四舍五入规则不同;一些重要概念在系统设计之初缺失(或误用)导致系统设计上的重大缺陷;对某些概念未做澄清而导致实现和预期不一致(如什么是“用户”,什么是“会员”)。项目启动之初需要花大量时间和精力来达成概念完整性和一致性(各种会议、宣讲,各种设计文档),很多项目缺少了这些步骤导致后期混乱不堪,团队中每个人都只见树木不见森林。
所以,若能从一本书 get 到一个让自己终身受用的东西,夫复何求?
放一张鄙人的读书清单镇楼(读没读完不要紧,架势要摆出来):
多撸源码
一个人能做的项目是有限的,而且很多项目都是同一种类型。更有甚,由于各种原因(如进的公司只有 CRUD 型需求)压根没机会承接稍有挑战性的项目锻炼自己。咋办?
既然自己没项目撸,就去撸别人的吧。
有很多高质量的开源项目,撸起来津津有味。很多时候,撸完一个高质量(但不一定规模得有多大)的开源项目比自己开发一个项目收获要大得多。
你看书时存在的疑惑很多都能在撸源码的过程中找到答案。我相信你初学设计模式时一定跟我一样自认为懂了,又觉得没懂,反正感觉很抽象。撸些源码,你会发现里面用了很多设计模式,你会感叹“哦,原来这样用”。
撸源码之前最好看下对应项目的手册,使用下,有个整体了解。也可以百度找下其他人撸出来的笔记,了解下大致的技术结构。
先撸简单的。走上来就撸 nginx,很容易留下心理阴影,从此戒撸。我学 golang 的时候就是从一个很简单的缓存中间件(几千行代码)开始撸,越撸越有信心。
要写笔记。我喜欢直接从 github fork 过来,边撸边写注释。
如果真的不想撸,或者撸不动(被里面各种弯弯肠子的设计绕得云里雾里),也可以看别人撸。可以花点钱在极客时间上看大神们撸。
有些项目撸着撸着就变成自己的项目了——我的意思是面试的时候可以写入简历里面,和面试官聊的时候可以说说你对那个项目的理解,甚至能撒个谎说自己开发过类似的项目(别说我教的)。
去带团队
程序员经常问的一个问题是:做开发到后面必须要带团队吗?
这个问题我也不知道答案(很多带“必须”字眼的我都不知道答案——怎么回答呢?说必须?肯定有人反驳;说不一定?感觉像个教科书),所以不打算回答。
我想说的是,如果你有带团队的机会,就去把握——特别是比较完整的团队(不是整个公司就一个前端一个后端这种)。至少要去试试。
不是说带团队未来就一定是走管理岗,不敲代码了。带团队对自己的实力提升有很多好处,我们不说提升什么综合能力,单说资源。
职位越高,可以拥有的资源就越多。当你只是普通的开发人员时,多数时候你只能被动接受别人的任务安排,哪怕这个任务对提升能力没什么帮助。但当你成为组长、经理、总监、CTO 时,你会发现自己能决定的事情越来越多(当然责任也越来越大),能够影响的范围越来越大,能够获得的资源越来越多。
这不是说你一定要走这条路,只是说要有这个意识——毕竟国内大部分公司资源是通过“带团队”的形式获得的。
如果我铁定了走技术路线,资源有什么用呢?可能没用,比如你在某个真的靠技术论天下的大厂当资深程序员。但只要你想往架构师方向发展(首架被普遍认为是技术路线的目标),你会发现你其实非常需要资源(当然成长为架构师并不是非要带团队不可)。
我们不提什么架构师,就说普通程序员岗。所谓资源,是指为做某件事所需要的人力、财力以及时间。比如你想开发个系统,或者做个重构(从成长的角度来说对你以及团队都有好处),如果你有一定的影响力(或者权利),你就有可能说服你的上司同意你做这件事(可能要两个月时间,并涉及到几个团队的人事协作);更有甚,你可以自己决定做不做这件事情。
起码,你能成为一个团队或一个项目的技术负责人,这并不难。站在团队 Leader 的角度,也能让你的视野更加宽阔。
当然,如果你对带团队很反感(请确认并非你的大脑不想走出舒适区),你完全可以不带。这里是说带团队可以获得资源,但不是说资源只能通过带团队的方式获得。
多写东西
大神都有一个共性:喜欢写博客。
上学的时候,学习好的大多喜欢记笔记,有些老师还强制要求学生记笔记。写东西能强化记忆,还能加深对知识的理解。
写作有益于构建一个人的知识体系。比如你对 DNS 有个初步了解,大致知道它的作用是将域名解析成 IP 地址——仅此而已。但如果你打算写一篇关于 DNS 的文章,肯定不能仅此而已。你会去查资料,了解 DNS 的历史,研究现实中 DNS 解析的具体实现方式。这过程中,你了解到全球 DNS 层次结构,最上面有根 DNS 服务器,下面有顶级域服务器,再下面有权威 DNS 服务器;你了解到 IANA 和 ICAAN 的历史,顺便还了解到 IP 地址在全球是怎么统一管理的;你还了解到如何通过智能 DNS 解析实现 CDN 网络;甚至你想自己搭建个权威 DNS 服务器。如果不写博客,你很难有动力去了解这些,很难构建出 IP 和域名的完整知识体系。
对我而言,写作还有个好处是刺激思考,整理思路。有时候我面对一个问题半天没有头绪,于是我尝试把问题作为文章标题大大地写下来。第一步,我尝试写出来关于该问题我能想到的任何东西(对问题本身概念性的厘清、初步的推理、引申出来的新问题等等,只要能想得出来就写下来)——然后我会发现自己的思路像是开了闸,自此畅通无阻。写作能锻炼人的思维能力。
从长远看,写作能建立个人品牌。公司需要品牌,个人也是如此。建立个人品牌(或叫打造个人 IP)主要有三种途径:
- 混大厂。加入头部公司(如 BAT)并在里面混个不错的名头;
- 混开源。开发一款高 star 的开源软件或作为某款知名软件的重要贡献者;
- 写博客。
有些大牛三方面都占了,但如果你我做不到这点,可以尝试只做一项,比如写博客。
很多人“不善于”写作。这是借口。没有人天生就善于写作。那些所谓“善于”写作的都是长时间训练出来的。另外,写技术博客并不需要你的写作功底多么好——话能说明白就行。
还有些人觉得自己现在技术不咋地,怕班门弄斧,觉得还是等底子厚了再写。没必要,因为写博客本身就是提升技术底子的非常快速有效的手段,不要颠倒了。如果有人看你的博客更好(有人看是大部分人能持续写作的主要动力),没人看的话,权当自我提升,顺便练练手,写得多了积累得多了质量自然上来了,自然会有人看了。
还有人觉得自己想写的别人已经写了很多了,没必要再重复这些事情了。已经有那么多小说了,仍然有人在写;已经有那么多音乐了,仍然有人在谱;已经有那么多轮子了,仍然有人在造。从某方面看,《圣经》说得没错:太阳底下,并无新事。但另一种说法是一千个观众就有一千个哈姆雷特。每个人对同一个问题的看法,对同一个知识的理解都是不同的,虽然 HTTP 协议已经被讲烂了,但你的理解,你的写作风格,或许会有些新意。就算全无新意,一样会有人看,因为信息不是同步的,总有人会来到你的地盘而不是别人的。
所以,不要想得太多,写就是了。
关于写作平台,真是太多了:博客园、CSDN、知乎、简书、掘金以及自建博客等等。还有人喜欢用 github(不过对搜索引擎不太友好,所以个人不太建议)。
个人比较喜欢博客园,我觉得博客园技术氛围最浓厚,也最简洁,没那么多幺蛾子。当然,如果你打算将写作事业长久经营下去,不妨尝试去经营自己的公众号,虽然更难,但一旦你坚持住了,从长远看,它会给你带来更大的收益(成长、品牌以及资金收益)。
去当讲师
一般互联网公司都有技术分享会,但我发现很多人不愿意去抓这种机会。有些团队的分享会进行不下去,不得不给成员分配分享任务,而大多数人也是将其作为一种额外负担看待的,甚至有人抱怨 Leader 给自己加了额外的任务导致自己不得不加班。
无论你处于什么级别,能成为任何分享会的讲师都是莫大的机会,值得去把握。大牛们都十分乐意参加各种分享会,公司内部分享会,行业峰会等等。
当讲师至少有三方面的收益。
首先,快速提升专业能力。和写作一样,你必须选择一个主题,该主题可能是你非常熟悉的,但更多时候可能只是粗略了解过。所以你必须网罗材料并整理成体系。比如你想讲 Unicode,因为你先前大致了解过这块,还自己写过 UTF-8 的实现 demo,觉得对这块很在行。但当你规划讲稿结构时发现,必须要先讲讲 Unicode 出现之前的字符编码情况,据此才能引出 Unicode 的历史必要性。于是你了解到 ASCII、ISO-8859、GB 2312、Big5 以及 IBM 和微软的各种代码页;而后 Unicode 出现了,你必须搞清楚的一件事是,Unicode 如何兼容这些早期的字符集编码,于是你不得不深入 Unicode 的实现细节;当你了解到原来早期 Unicode 采用的是双字节定长编码方案时,你必须去探明为何后面 UTF-8 超越 UTF-16 成为应用最广泛的 Unicode 实现方案?如此,当你准备完讲稿时,你已经构建了自己的字符集编码知识体系(而不仅仅是了解些 Unicode 和 UTF-8 的零星的知识)。
其次,锻炼自己站台讲话的能力。随着经验的积累,职位的提升,你多少需要上台讲点话。你无需做到口若悬河,但最好也不要语无伦次。程序员平时很少有这种上台讲话的机会(机会出现了大部分人也不愿意去抓)。当讲师一方面氛围比较轻松,除非是大公司几百甚至几千人的分享或者行业峰会,否则听众基本都是平时打交道的熟人,你不会有多大心理压力(特别是做过几次分享后);另外你要讲的内容是充分打好草稿(PPT)的,心里有数。所以这种场合的演讲大部分人都能驾驭得了。但分享也是演讲,要讲究演讲技巧,要将听众带入你的世界并很容易理解你所讲的东西(很多人做技术分享就是在那里读 PPT,完全不考虑听众感受,搞到后面很多人都在那玩手机了)。这是让你体验演讲并锻炼演讲技巧的大好机会,大部分人第一次都讲不好,但多讲几次,就会不自觉地去思考并提高演讲技巧。
最后,让更多人认识你。你是不是认为大家都在一个屋檐下共事,还有谁不认识你的?除非你在公司技术圈有很大影响力(大家公认的大牛),否则不认识你的人多了去了。所谓认识,不是说人家知道你名字就完事了。所谓认识,是要人家知道你在做什么,你擅长做什么,你哪方面比较牛;进而,认识会转化为“认可”:让别人认可你,更让你的 Leader 认可你。今后有机会参加行业峰会了,也是让更多的业内人士认识并认可你——如此也就打造出你自己的 IP 了。
很多人不愿意当讲师,除了没有上台演讲的经验外,一大顾虑是认为自己并没有什么特别擅长的东西。记住一点,多数时候,不是因为你真的擅长某方面才去分享,而是你先决定分享某个你熟悉但不精通的东西,然后去钻研,在分享的同时也真正精通了这个主题。
如果一开始没有信心,就从小范围做起。从小组内部分享开始,内容也不用那么专业那么深入,随意点。然后扩展到部门或者公司层面。
做分享跟写博客一样,于人于己都百利而无一害,不要等,尽早去做。
不是因为自己行才去做,而是先做了才行的。