1)Learning
这个是第一阶段,看书、google、看视频、看别人的博客都可以,但要注意一点是“系统化”,特别是一些基础性的东西,例如 JVM 原理、Java 编程、网络编程,HTTP 协议。。。。。。等等,这些基础技术不能只通过 google 或者博客学习,我的做法一般是先完整的看完一本书全面的了解,然后再通过 google、视频、博客去有针对性的查找一些有疑问的地方,或者一些技巧。
2)Trying
这个步骤就是解答前面提到的很多同学的疑惑的关键点,形象来说就是“自己动手丰衣足食”,也就是自己去尝试搭建一些模拟环境,自己写一些测试程序。例如:
- Jvm 垃圾回收:可以自己写一个简单的测试程序,分配内存不释放,然后调整各种 jvm 启动参数,再运行的过程中使用 jstack、jstat 等命令查看 jvm 的堆内存分布和垃圾回收情况。这样的程序写起来很简单,简单一点的就几行,复杂一点的也就几十行。
- Reactor 原理:自己真正去尝试写一个 Reactor 模式的 Demo,不要以为这个很难,最简单的 Reactor 模式代码量(包括注释)不超过 200 行(可以参考 Doug Lee 的 PPT)。自己写完后,再去看看 netty 怎么做,一对比理解就更加深刻了。
- MySQL:既然有线上的配置可以参考,那可以直接让 DBA 将线上配置发给我们(注意去掉敏感信息),直接学习;然后自己搭建一个 MySQL 环境,用线上的配置启动;要知道很多同学用了很多年 MySQL,但是连个简单的 MySQL 环境都搭不起来。
- 框架封装了 DAL 层:可以自己用 JDBC 尝试去写一个分库分表的简单实现,然后与框架的实现进行对比,看看差异在哪里。
- 用浏览器的工具查看 HTTP 缓存实现,看看不同种类的网站,不同类型的资源,具体是如何控制缓存的;也可以自己用 Python 写一个简单的 HTTP 服务器,模拟返回各种HTTP Headers 来观察浏览器的反应。
还有很多方法,这里就不一一列举,简单来说,就是要将学到的东西真正试试,才能理解更加深刻,印第安人有一句谚语:I hear and I forget. I see and I remember. I do and I understand,而且“试试”其实可以比较简单,很多时候我们都可以自己动手做。
当然,如果能够在实际工作中使用,效果会更好,毕竟实际的线上环境和业务复杂度不是我们写个模拟程序就能够模拟的,但这样的机会可遇不可求,大部分情况我们还真的只能靠自己模拟,然后等到真正业务要用的时候,能够信手拈来。
3)Teaching
一般来说,经过 Learning 和 Trying,能掌握 70% 左右,但要真正掌握,我觉得一定要做到能够跟别人讲清楚。因为在讲的时候,我们既需要将一个知识点系统化,也需要考虑各种细节,这会促使我们进一步思考和学习。同时,讲出来后看或者听的人可以有不同的理解,或者有新的补充,这相当于继续完善了整个知识技能体系。
这样的例子很多,包括我自己写博客的时候经常遇到,本来我觉得自己已经掌握很全面了,但一写就发现很多点没考虑到;组内培训的时候也经常看到,有的同学写了 PPT,但是讲的时候,大家一问,或者一讨论,就会发现很多点还没有讲清楚,或者有的点其实是理解错了。写 PPT、讲 PPT、讨论 PPT,这个流程全部走一遍,基本上对一个知识点掌握就比较全面了。
碎片化时间管理
1 万小时理论听起来好像很简单,每天持续 3 小时,也不难,但实际上真正做起来是很难的,就像我们互联网的人加班加成狗,感觉身体天天被掏空,时间从哪来,这是一个现实问题,不要说每天抽 3 个小时提升自己,每天抽 1 个小时陪女朋友或者找女朋友的时间都不够。具体怎么做?
首先是找到 3 个 30 分钟:
- 第一个 30 分钟就是早上的 30 分钟,假设你习惯 8 点起床,明天你把闹钟改成 7 点半,这就多了半个小时。
- 第二个 30 分钟是睡觉前的 30 分钟,假设你习惯玩游戏到 12 点,明天晚上你玩游戏就玩到 11 点半。
- 第三个 30 分钟就是上班到你座位上的 30 分钟,有的同学担心说我这 30 分钟会不会影响我这一天的工作效率,可能加班完不成,还让我挤出 30 分钟来,这不用担心,从我的经历来看挤 30 分钟不会影响你整体的工作效率,持续一两年,你会发现自己的收益非常大。
第二点是利用或节省路途时间
我们每天上下班都是一两个小时,比如像我这种,怎么去利用时间呢?
首先是可以利用上下班路上的时间去看书、听书,也是可以做的。如果你觉得上班路上是不能看书的,或者是不可能学习的,比如你坐广州的 3 号线,这是举世闻名的挤得要命的,不要说看书了,把手伸出去都不知道去哪了,那就建议大家搬到离公司近一点位置,虽然每个月多几百块钱的房租,但是你要相信这个投资节省下来的时间用于提升自己,它最终的收益是 10 倍回报都不止的。
第三点是周末 4 小时
周末还是不用怎么加班的,周末用于放松、睡觉、看电影、娱乐,你也可以在周末里面规定自己挤出 4 个小时,也就是每天 2 个小时,这样算下来,一天大概就两个多小时,再加上你在工作中的积累,每天 3 小时也不是很难。
接下来讲一下我是怎么做的,我现在有 2 个小孩,而且我住的比较远,应该在座的比我忙的也不会很多,看一下我是怎么做的,我是坐广州的四号线,坐四号线每天来回可以看一个小时的书,每天早晚 30 分钟,周末 4 小时,有的同学可能会有疑问,周末肯定要带小孩玩,自己也要休息,哪里有 4 个小时,其实只要你去找,时间都会有的,我找的方法就是当我小孩睡觉的时候,因为小孩子睡觉一般要睡三四个小时,大人一般睡一个小时、半个小时就差不多了,所以通过这种方式,大家可以看到 2015 年我一共看了 84 本书,有专业的,也有非专业的,人文社科、历史这些都有。
不过特别提醒一下对于男程序员来说有一个时间千万不能少,就是陪女朋友的时间,因为对程序员来说找女朋友不容易,别看了这篇文章回去之后女朋友也不要了,就天天回去提升,这也不是我们想要的生活。
10000 小时理论如何轻松落地?
虽然理论上很简单,但真正要落地实行也并不那么容易,实行 10000 小时理论的关键在于坚持,我认为坚持的关键在于自己对于所从事的事业是否有“激情和兴趣”。这点当然是核心,但如果只靠激情支撑,持续 10 年也确实有挑战,正如一个朋友在分享会后问我的“要持续 10 年才能成为大牛啊,时间好长啊”!
如果说做一件事要 10 年后才能修成正果,估计很多朋友就会放弃了,毕竟像唐僧那么坚定的信仰者总是少数,大部分凡夫俗子都还是需要持续不断的激励才能有动力去做一件事,因为我们的大脑在进化的过程中已经形成了需要持续不断的奖励才能保持兴奋的机制,也就是说相对于在第 10 年给一个大奖励,还不如每年给一个小奖励。
那如何才能在 10 年漫长的路上让我们持续的坚持下去呢?答案其实就是首富的话:“先定一个能达到的小目标”!我们来看如何将“10 年成为大牛”这个目标分解为一个个能达到的小目标。我将这个方法归纳为“三段分解法”,即:将一个宏大或者长远的目标经过 3 次分解,得到一个个短期内能达到的小目标。具体的分解方法如下。
一段分解:分解“等级”
10 年成为大牛的目标虽然比较长远比较宏大,但并不意味着在没有成为大牛前,我们一直都是菜鸟。从菜鸟到大牛的过程中,中间其实有几个关键的里程碑,这些里程碑就是我们的一段目标。
以技术人员为例,技术人员典型的发展路径基本上都是下面的这个模式:
1) 0 ~ 1 年:菜鸟,需要别人手把手来教
2)1 ~ 3 年:初级,需要别人带你做
3)3 ~ 5 年:高级,能独当一面,可以带初级技术人员了
4)5 ~ 8 年:资深,能独挡多面
5)8 ~ 10 年:大牛,统筹规划,高屋建瓴
通过上面的分解我们可以看到,虽然说 10 年才能成为大牛,但是 3 年就可以达到初级水平,5 年就可以达到高级水平,8 年就可以达到资深水平,在这个过程中我们一直在成长和提升,而不是说没有成为大牛就是菜鸟;并且对于很多朋友来说,如果目标不是像首富那样要赚就赚 1 亿,能达到高级或者资深水平,其实已经可以过得比较滋润了。
通过这种分解方法,再核对一下自己目前所处的位置,然后先瞄准下一个目标,全力以赴其实也就 2 ~ 3 年时间,这样来看一段目标其实是比较容易达成的。这种目标分解的方法除了适合技术人员外,其它很多领域也都适应,比如说产品人员、运营人员、甚至公务员!
二段分解:分解“技能”
经过一段分解后,明确自己目前所处的位置和下一个目标,接下来就要看这个一段目标如何实现了。虽然说每个一段目标持续时间在 2~3 年,但 3 年时间说长不长,说短也不短,如果没有好好利用,可能到了 2 年多的时候回头一看,好像什么都没达成,还是原地踏步。因此,为了更好的利用这 3 年时间,我们需要进一步分解,这就是“二段分解”。
一段分解的维度是等级,二段分解的维度则不一样,不能再分等级了,否则等级太细就没法区别了。二段分解的维度变成了“技能”,即:为了达到一段目标,我需要具备什么样的技能。
还是以技术人员为例,假设经过自我评估,认为自己目前处于初级阶段,而且初级阶段的事情已经做得比较顺手和熟练了,那么下一个一段目标自然就是达到“高级”水平。“高级”与“初级”相比,有哪些不同的技能要求呢?
这就需要我们根据各自不同的行业和方向详细列出来了,如果自己想不出来,网上有很多资料都可以搜索到,最方便的就是到一个招聘网站,多看看几个招聘需求的描述,然后归纳总结一下。
我们随便到网上搜索一个,例如拉勾网上滴滴的“高级 Java 开发工程师”招聘:
多看几个类似的职位招聘,基本上我们就能明白“高级 Java 开发工程师”的一些基本要求。当然实际上的技能要求比招聘需求的描述还要更加细致,我个人的习惯是将这些要求整理为一个思维导图,详细列出每个技术点。例如:
注意:以上这个图只是示例,并不是说所有 Java 高级工程师都一定是这个要求,例如互联网行业和电信行业的要求不一样)
有了这样一个思维导图后,我们就可以开始真正进行二段分解了,分解的方法很简单:哪里不懂补哪里!例如:我感觉目前我的数据库水平一般,仅仅会写 CRUD 语句,其它的东西都不懂,那我就开始专攻数据库这一部分,经过一段时间的专攻来提升自己的水平。
二段目标持续时间一般建议是 6 个月,既不能太短也不能太长。太短容易让人陷入为了目标而做的误区,没有真正得到有效提升;时间太长的话,3 年时间又不够完成其它目标了,例如要是我定一个目标说 2 年提升数据库,那操作系统怎么办?网络怎么办?……等等。以 6 个月为一个周期,基本上刚刚好。
经过分解,最终的二段目标可以分解为如下的几个更小的目标:
1)2016.06 ~ 2017.01:提升数据库水平
2)2017.01 ~ 2017.06:提升 Linux 水平
3)2017.06 ~ 2017.12:提升网络和网络编程水平
当然,二段分解目标并不是一成不变的,很多时候需要根据我们工作的内容进行调整。例如老大正好安排我来负责优化系统性能,降低机器负载,那么我完全可以将“提升 Linux 水平”安排到“提升数据库水平”之前。
三段分解:分解“行动”
二段分解得到技能的小目标后,接下来的关键就是要实现这个目标,这就是三段分解的主要目的,即:将技能目标分解为具体要做的事情,然后按照计划执行。
比如说我的二段目标是“提升 Linux 水平”,那怎么样才能提升呢?可以上网搜索(知乎是个好地方),也可以去问有经验的朋友。明确要做的事情后,三段分解需要将二段分解的 6 个月目标更加细化,分为 1 个月或者两个月一个目标。
以我当时加入 UC 的情况为例,我在华为的时候是在 Windows 平台上用 VC6 进行开发,而到了 UC 的时候是在 Linux 平台上用 C++ 开发,我当时定了“提升 Linux 水平”的目标,然后通过上网查,找别人问等方法,最终将这个目标分解为几个步骤:
1)1 个月:通读《UNIX 环境高级编程》
2)1 个月:通读《Linux 系统编程》
3)2 个月:通读《UNIX 网络编程卷1》
4)1 个月:Linux 常用命令实战:tcpdump、ps、top 等
通过这种方法,将 6 个月的目标又进一步分解为 1 个月的目标,实施起来就简单多了,每 1 ~ 2 个月专注一个具体目标,每次完成后都很有成就感,既感觉自己的水平有了提升,又佩服自己能够坚持按计划按目标完成任务,双重奖赏让自己更有动力进行下一个目标。
我大约花了 2 年的时间将 Linux、网络、MySQL 三个重点技能从一无所知提升到高级的水平,很多同事都问我之前在华为是不是就是做这方面的,因为他们觉得短时间能达到这个水平是不太可能的。
综合前面的分析,我们将三段分解提炼一下:一段分解“等级”,二段分解“技能”,三段分解“行动”。通过前面我们的案例就可以看出,原本一个宏大的“10 年成为技术大牛”的目标,经过三段分解,最终得到的是 1 ~ 2 个月可执行的具体行动,通过这种一步一个脚印的行动,最终就可以达成“10 年成为技术大牛”的目标。
天天写业务代码,如何成为技术大牛?
几个典型的误区
拜大牛为师
知乎上有人认为想成为技术大牛最简单直接、快速有效的方式是“拜团队技术大牛为师”,让他们平时给你开小灶,给你分配一些有难度的任务。我个人是反对这种方法的,主要的原因有几个:
- 大牛很忙,不太可能单独给你开小灶,更不可能每天都给你开 1 个小时的小灶;而且一个团队里面,如果大牛平时经常给你开小灶,难免会引起其他团队成员的疑惑,我个人认为如果团队里的大牛如果真正有心的话,多给团队培训是最好的。然而做过培训的都知道,准备一场培训是很耗费时间的,课件和材料至少 2 个小时(还不能是碎片时间),讲解 1 个小时,大牛们一个月做一次培训已经是很高频了。
- 因为第一个原因,所以一般要找大牛,都是带着问题去请教或者探讨。因为回答或者探讨问题无需太多的时间,更多的是靠经验和积累,这种情况下大牛们都是很乐意的,毕竟影响力是大牛的一个重要指标嘛。然而也要特别注意:如果经常问那些书本或者 google 能够很容易查到的知识,大牛们也会很不耐烦的,毕竟时间宝贵。经常有网友问我诸如“jvm 的-Xmn 参数如何配置”这类问题,我都是直接回答“请直接去 google”,因为这样的问题实在是太多了,如果自己不去系统学习,每个都要问是非常浪费自己和别人的时间的。
- 大牛不多,不太可能每个团队都有技术大牛,只能说团队里面会有比你水平高的人,即使他每天给你开小灶,最终你也只能提升到他的水平;而如果是跨团队的技术大牛,由于工作安排和分配的原因,直接请教和辅导的机会是比较少的,单凭参加几次大牛的培训,是不太可能就成为技术大牛的。
综合上述的几个原因,我认为对于大部分人来说,要想成为技术大牛,首先还是要明白“主要靠自己”这个道理,不要期望有个像武功师傅一样的大牛手把手一步一步的教你。适当的时候可以通过请教大牛或者和大牛探讨来提升自己,但大部分时间还是自己系统性、有针对性的提升。
业务代码一样很牛逼
知乎上有的回答认为写业务代码一样可以很牛逼,理由是业务代码一样可以有各种技巧,例如可以使用封装和抽象使得业务代码更具可扩展性,可以通过和产品多交流以便更好的理解和实现业务,日志记录好了问题定位效率可以提升 10 倍……等等。
业务代码一样有技术含量,这点是肯定的,业务代码中的技术是每个程序员的基础,但只是掌握了这些技巧,并不能成为技术大牛,就像游戏中升级打怪一样,开始打小怪,经验值很高,越到后面经验值越少,打小怪已经不能提升经验值了,这个时候就需要打一些更高级的怪,刷一些有挑战的副本了,没看到哪个游戏只要一直打小怪就能升到顶级的。
成为技术大牛的路也是类似的,你要不断的提升自己的水平,然后面临更大的挑战,通过应对这些挑战从而使自己水平更上一级,然后如此往复,最终达到技术大牛甚至业界大牛的境界,写业务代码只是这个打怪升级路上的一个挑战而已,而且我认为是比较初级的一个挑战。
所以我认为:业务代码都写不好的程序员肯定无法成为技术大牛,但只把业务代码写好的程序员也还不能成为技术大牛。
上班太忙没时间自己学习
很多人认为自己没有成为技术大牛并不是自己不聪明,也不是自己不努力,而是中国的这个环境下,技术人员加班都太多了,导致自己没有额外的时间进行学习。
这个理由有一定的客观性,毕竟和欧美相比,我们的加班确实要多一些,但这个因素只是一个需要克服的问题,并不是不可逾越的鸿沟,毕竟我们身边还是有那么多的大牛也是在中国这个环境成长起来的。
我认为有几个误区导致了这种看法的形成:
1)上班做的都是重复工作,要想提升必须自己额外去学习
形成这个误区的主要原因还是在于认为“写业务代码是没有技术含量的”,而我现在上班就是写业务代码,所以我在工作中不能提升。
2)学习需要大段的连续时间
很多人以为要学习就要像学校上课一样,给你一整天时间来上课才算学习,而我们平时加班又比较多,周末累的只想睡懒觉,或者只想去看看电影打打游戏来放松,所以就没有时间学习了。
正确的做法正好相反:
首先我们应该在工作中学习和提升,因为学以致用或者有实例参考,学习的效果是最好的;其次工作后学习不需要大段时间,而是要挤出时间,利用时间碎片来学习。(参照前文 10000 小时理论)
正确的做法