有人可以靠中彩票,然后一夜暴富;有人随随便便发几张自拍,就一不小心一夜成名。可技术成长,要一步一个脚印地练习,才能掌握某项特定技术。等到我们掌握了学习的技巧,才能用更短的时间,来掌握某项特定的技术。
而练习,也不是一天里写一万行代码,也不是重复写一百行代码,而是在一百天里,每天写下一百行代码。它需要一定的技巧,不懈的坚持,还有一些休息。因此在这篇文章里,我将分享工作几年里的练习技巧:
当然,练习有一个大前提是:我们有充足的时间。时间是一种很珍贵的资源,特别是对于长期加班的开发人员来说。因为技术能力不足导致的加班,会变成恶性循环。
如果你还没工作,那么便相当的幸运,你有相当多的时间。工作的时候,大家都忙于实现业务功能,没有时间让你提升自己。如果你已经工作了,那么你需要每天预留一些时间,才有机会去练习。每天会占用一些游戏、看电视时间,哪怕只是半个小时,一周、一个月、一年下来,帮助就很大了。
进行这些练习之前,请不要忘了根本——能熟练地用框架、语言完成工作。完成工作,相当于必须达到的 60 分及格要求。在胜任工作之外,提高能力到 80、90 分,追求更好的技术能力,才是正确的路线。
下面,让我们开始第一部分的内容吧~。
编程的时候,我们只是在码字——编码的过程(即思路)实际 上是在脑子里完成的。娴熟的码字能力,可以帮助我们更好地编程。
小学时,自参加了五笔打字比赛之后,便开启了我的编程生涯。可当工作的时候,已经可以熟练的完成工作的我,仍然无法打对每一个字符。有一天,看到了一个名为 Typing(https://typing.io/) 的在线代码打字练习工具。练习了一次之后,发现它会给出一些建议,便开始进行了一些编码练习。但是得到的反馈能表明,在打字这方面,仍然有一些提升的空间:
我的“自我解释”是:今天的编程语言设计得不合理——使用了各种字符,导致了右手在这方面的负担比较大。在那之后,我便陆续进行了一些基础的练习,并整理他们的因果关系,便有了下面的一些练习项目:
这些练习,可以让我们成长为一个更专业的程序员。
对于语言与框架的练习,算是比较简单的。于我而言,这种练习过程便是:
因此,只需要找一个合适的网站、APP,作为模仿的对象,一步步往下练习即可。唯一的难点在于,第一次写 Web 应用的时候,可能会多花费更多的时间。新手期的程序员,对很多的概念都不清楚,如若能找到一个新手社区、群体,提高起来就会方便多了。
熟练使用语言或者框架,不能帮助我们成为一个『优秀』的成员。只能带领我们成为一个“胜任”的程序员,即我们可以凭借着这种练习,找到一份养家糊口的工作。
工作的时候,写的都是业务代码,纯技术上的实践并不多。这意味着,多年的工作经验,与技术能力的关系并无太大关联。如果有一天,我们看到几年前写的代码,和今天写的代码并没有太大的区别,那么说明了:我们已然陷入了这样的一个瓶颈。
在学校写的代码,与工作写的代码,最大的区别在于:软件工程实践。单单凭借工作经验,那么在软件工程实践上的提高可能不会太大。受限于上线 deadline 的影响,多数项目的软件工程实践,并不能做到最好,甚至可能很差劲。如我们所见,国内的大部分公司(包括BAT)在这方面的实践也很难做全,更不用说做好。这些实践包括:
而对于一个优秀的开源软件来说,为了保证好项目的质量。拥有者往往付出了很多的精力,在提高软件工程的实践上。因此,对于软件工程实践来说,最好的练习,便是模仿开源软件,并自己去创造一些轮子。以 React 为例,其在首页拥有下面的几个徽章(badge):
分别是:
那么,我们在实践的时候,就可以模拟这样的项目组成,一步步往下实践:
最难的实际上是最后一步,制定一个目标并实现。它可以是测试覆盖率要达到 90% 以上,这就需要一步步的来完成。如先将目标放到 60%,再慢慢地往上提升,直到 90%,甚至 100%。在这个过程中,会不断地遇到一些挑战,如难以测试的代码,为了编写测试而修改功能代码等等。但是,它能确确实实地帮助我们提高工程能力。
编码的时候,如果我们心里想输入的是一个 print
,结果打下的字符是 oront
,那么我们就需要删了重来。又或者是小心翼翼地,边看键盘边输入一个个字符。虽说,编码只是一个打字的过程,但是很多时候,经常出现的错字会中断我们的思路。因此,盲打应该成为程序员的基本技能。而这里的盲打,指的并不是我们可以闭上眼晴打字聊天,而是可以完成编程工作,即能盲打下 26 个字母,及各种字符,还有各种功能键。
而在进行这一类练习的时候,我们经常会遇到的一个障碍:度量。即以某种方式来衡量练习的成果,我们做了很多的练习来提高自己,但是没有数据来支撑。它不像编码,我们写了几行代码,完成了一个功能,那么写下的这些代码的价值就是可以衡量的。因而练习的时候,我们可以寻找一些合适的工具,如 http://Typing.io、http://Keybr.com 这一类工具。如 Typing 使用的是真实的代码片段,它能帮我们发现真实场景下:我们容易打错哪些字,容易按错哪些键,我们的打字速度是多少等等的内容。
对于可以衡量的打字练习,我们可以订下每天十几分钟的时间,一段时间要提升到什么水平的目标。这样它便能满足SMART原则,就能让我们看到我们在这段时间内的提升。
当时,我拿 Typing 练习的时候,差不多练习了一个月,每天大概半小时左右。因为打字的速度比较快,所以容易出错,所以便将注意力放在减少错误上。而对于有些人来说,则是相反的,即打字速度比较慢,但是准确率比较高。而这个练习的主要目的是,能熟练地做到盲打,不让它影响我们的效率。
掌握了熟练开关机、键盘上的各种按键后,我们就在使用工具上做一些效率的提升。
刚工作的时候,发现每个有经验的程序员,几乎可以不用鼠标编程。熟练的使用各种快捷键,进行代码重构、打开新页面、开启新窗口等操作。慢慢的,我觉得自己在这方面上有相当大的提升空间。
这意味着,我要学习、探索开发工具的功能,也要能使用快捷键来控制。尽管在日常结对编程、代码检视、交流的时候,可以请从别人身上学习。但是理想的方式,还是应该自己去练习。
对于大部分的开发工具,它们都有对应的手册、Keymap 或者 cheatsheet,即“作弊表”。如下是 Intellij Idea Keymap 的截图:
上面列出了其可用的快捷键,及其相应的用途。因而只需要打印好,放在眼睛能看到的地方,就能有效的改善。除了打印成纸质资料,他们还可以有不同的形式,如鼠标垫、杯子的形式。需要的时候,便可以一眼看到;平常多看到几次,也能多多少少的多记住一些。
需要注意的是:对于开发工具而言,没有必要掌握所有的快捷键,而是只掌握常用的功能。我曾陷入了一个误区,练习使用快捷键的时候,边练习一些重构的技巧,同时也花费了时间在练习一些『屠龙之术』上——一些非常少用的功能,除了炫耀,也没有什么用。时间一久,我便忘了很多的快捷键。
再举些例子:如 Vim,对我而言,一般用于服务器维护及 Git 修改。因此,主要使用的功能便是:快速地改几个字符、更新配置,保存并退出。如 Chrome 浏览器,在日常使用时,配合下 Vim 插件,便不需要鼠标。在进行前端开发的时候,便需要使用鼠标来调试。
对于大部分的工具来说,我们只需要一个 CheatSheet。复杂的工具,如 Vim、Emacs,则需要有一本更专业的书。它们是高度可定制的,这也意味着我们需要一步步的定制这些工具,寻找合适的插件,自定义快捷键,又或者是使用别人的配置。
而,要衡量快捷键使用方面的提升,目前还没有看到有效的度量工具。如果有的话,那么就是编码的时候,使用鼠标的频率。因此,在某些特定的时候,可以通过禁用鼠标来提升自己在这方面的能力。
尽管我在上面指出,学习新框架的最好姿势是:基于现有的业务来学习。即从工作中学习,从做中学。但是,如果一直只使用新的框架来重写旧的业务,那么你的成长就会趋近于 0。第一次,使用新框架时收获可能颇丰;第二次,收获的东西就更少了;第三次,你可能就学不到东西。
因此,在业余的练习时间里,不要一直练习新的框架,不要再拿 Vue、React Native 去高仿一些应用。当且仅当,你所处的项目正在使用新的框架,这种练习才是有意义的。
经过上面的练习,我们提高了我们的工作效率。同时,在别人的眼里,我们更像是一个专业的程序员。在这之上,我们还需要提高顶层的能力。下面介绍的是,我尝试过的一些,比较有效果的提升方法:
总的来说,收获还是蛮多的,特别是造轮子,能有更大的提升。与其他的练习稍有不同的是,因为涉及到代码设计,这里的练习有些难以衡量。这时候,我们应该是保持着练习的心态,并意识到我们是在做这方面的练习。
如果在工作环境中,没有代码写得比较好的人,那么我们就只能从开源代码中去学习。笔者之前写过一篇《如何以“正确的姿势”阅读开源软件代码》的文章,文中我建议的阅读开源软件代码的方式是:
可只读这些代码,不能让我们显著的提高水平,我们应该结合『重构』这个技能来练习。从我的练习经验看来,对于重构的练习是最有意思的。我们可以见证,一段不好的代码在我们的调教之下,焕发出新的光彩。当我们重构一段坏味道的代码,对比重构前后的代码,便会发现自己竟然有这样神奇的能力。
如果找不到合适的练习项目,可以到 GitHub 上找一些 star 多,但是没有测试、缺少 CI 等的项目练习,这样的项目在 GitHub 上也是蛮多的。
有一次,我在寻找一个迷你的 Markdown 解析器,看到 GitHub 有一个精巧的实现。它有 100+ 的 star,但是没有测试、四百行的代码里,有一个方法有三百多行等等的坏味道。于是,便花了几天的时间,边思考边重构这个项目。这样对编码的提升比较大,因为工作的时候,完成任务是第一优先级,然后才是质量。
因此,对于我们练习来说,我们只需要:
需要注意的是:不同的人对于代码设计,有着不同的观点。因此,在这时如果只是因为代码的设计不好,而不是代码里有各种坏味道(code smell),那么,就不应该去给别人的代码提 Pull Request。
与阅读代码、重构相比,造一个自己的轮子,来实现同样的功能,便是一个更不错的选择。在 Web 开发领域,大部分的开发框架本身都是『通用型』的框架。即它拥有相当多的功能,其中有很多的功能都不会用到。如你使用 jQuery 的时候,你可能只会使用到其中的 Ajax、Event等功能,那么你就可以写一个新的框架,兼容这两个接口。
练习时间充裕的时候,便可以自己动手去做一个。上面说到的阅读框架代码,是一种好的方法。除此无论是前端还是后端,我们都可以找到从零创建框架的资料,来帮助我们理解框架的组成。
通过阅读诸如 Python 里的 Flask、 Ruby 里的 Sinatra 等轻量级的框架,我们就能理解一个框架所需要的元素,并模仿他们做出一个新的系统。这些框架的关注点是:处理 HTTP 请求的 CGI、与数据库交互的 ORM、控制逻辑的 Controller 层、返回 HTML的 View 层等等。除了相关的框架,我们还能在 GitHub 上看到很多人模仿这些框架。做一个这样的后台框架,搭建自己的博客,那就能理解好这一系列的逻辑了。
对于前端来说,也是类似的,诸如 Building React From Scratch,可以让我们在 250 行理解 React 的原理,并做出一个类似的框架。除了 MVC,还有模块化设计、数据请求等等的内容。在两三年前,《JavaScript框架设计》就是这方面一个不错的选择。
我曾经造过一个名为 Lettuce 的前端框架,它的主要目的就是用于:学习前端框架的设计,便在自己的多个业余项目上使用这个框架。而在前端领域,定制自己的 UI 框架、CSS 框架也是一个很不错的选择。再用到自己的博客上,再写上『自豪地采用xx框架』,岂不是更加的自豪?
在底层领域,又有各式各样的《自制操作系统》、《自制编程语言》、《自己动手设计物联网》等等的书籍,它们都能让我们从底层理解一个系统的组成。除此,还有各种各样的剖析类书籍,可以让我们理解底层机制的同时,也能让我们制作出一个框架。
最后,我们只需要能不改写或少数改写代码,将我们的应用运行在上面,便是成功的一个仿造的轮子了。
设计模式,不同的人有不同的看法。在我看来,一个优秀的程序是要能『看懂』的。即不一定要精通,但要能识别出来,它是一种设计模式。当我们看到了一次又一次的相似设计时,应该猜想到,其背后应该是一种设计模式。如在前端开发框架中的『双向绑定』,它实际上就是发布-订阅模式,又或者称观察者模式的一种实现。
在笔者看来,模式就是一种高级的语言。当别人一说『工厂模式』,多数人瞬间就明白了,不犹得会发出:原来如此,这一类的感叹。认识了一些模式后,一遇到一些特定的场景,我们就能一下子套用这种模式。
可只凭阅读 GoF 的《设计模式》一书,又或者《Head First 设计模式》、《重构与模式》等设计模式书籍,我们所学的知识便是有限的。我们要做的是:
要对设计模式进行练习,不是一件容易的事。并且很多时候,容易模棱两可的情况,即适合使用 A 模式,又适合使用 B 模式。这是因为我们是在为设计而设计,因此会尽可能的贴近现有情况。
不同的领域里,都有自己领域的优秀思想。如我们熟知的设计模式,便是受建筑领域的《建筑的永恒之道》中描述的 253个 建筑模式的启发。又如今天流行的精益思想,最早是来自汽车制造业,可它对软件行来说,有着令人受益匪浅的启发。好的框架、软件是会相互学习,如 iPhone 与 Android,都在不断地借鉴——通知中心,但是又在那之上做一些改进。
又比如,今天的前端框架里,很多思想都是从后端“借鉴”过来的。如 Angular 中采用的依赖注入,便是深受 Java 语言的影响。近一点来说,Redux,框架最初是用在 React 上,但是它已经被推广到了 React 和 Vue.js 上。
因此,当我们发现一个新的优秀思想产生时,便可以尝试引入到自己的领域里。又或者我们所处的领域,正遇到一些难题,答案可能就在别的领域里。可在这方面的练习,往往都是一些创新性的练习。多数时候,我们的探索可能没有结果,但是它往往能对自己有更大的启发。
每天能有半小时、一小时甚至更长时间的稳定练习,比三天打鱼两天晒网的效果要好得多。清理出一些固定的时间,用于为自己腾出时间来提高自己。既然,你都有时间到这篇文章,那么你应该属于能腾出时间的人。
如果不能的话,那么我们也可以尝试去挤出一些时间,如从上下班去寻找空间。即使是同一公司,不同的人都有不同的上下班时间,所花费在路上的时间也有所不同。有的人,需要在几环外坐个一个多小时的地铁,再转公交才能到公司;有的人,只需要出门左转,走个十分钟就到公司了。因为在路上花费的时间不同,也在一定程度上影响了学习、练习等等的时间。
因此,如果可能的话,应该减少花费在上班路上的时间,才能避免继续陷入这样一个恶性循环:租不起近的房子,花费大量的时间在路上,没有时间提升技能。
早上
早上的练习,是一种慢慢进入一天工作状态的感觉。一旦上班时间到来的时候,就已经进入工作姿态了——对于“资本家”来说,可谓好事一件。早晨刚醒来,总会想不起昨天项目做到哪一步,便更容易反思哪里做得有问题。
如笔者已经习惯了,每天七点起床、洗漱,随后写会代码,再去上班。有时候,可以有一个半小时的练习时间,有时候会有半个小时,将这些时间浪费在梦里总是有些可惜。同时,之前为了能成功地上公交,便提前半个小时到公司,写一些开源软件的代码。毕竟,作为一家非产品公司,你无法和别人解释说,我们做了些什么、取得了哪些成就。
在很多地方,这是一个很好的策略:错开高峰期上下班,路上就不容易堵车。所花在路上的时间就缩短了,那么我们就有时间来练习了。
需要注意的是:练习的时候不要关注时间,而是关注怎么于提高。关键点在于:让每天进步一点。
中午
吃完饭后,因为米饭血糖指数高的缘故,容易犯困。对于北方的同学来说,因为主食不是米饭,所以这就不算是一个问题了。这个时候,身体会妨碍我们进行一些练习。可如果你的午休时间比较长,那么也可以做一些练习,再去休息片刻。
碎片时间
对着屏幕写代码,时间一久,集中力就会开始涣散,便应该休息会儿。刷刷资讯、朋友圈,又或者收集各种资料,开放我们的视野。接收各种新的知识,来扩大自己的视野,以便于自己了解整个市场的水平。
常见的方式有:
将这些内容存储到 Evernote、WunderList、OneNote 等各式各样的云笔记里,然后定期清理、定期清理、定期清理。收集只是一种方式——没有啥用的方式,因此建议先读完一遍,再去收藏这样的文章。多数时候,我们会发现自己收藏了很多的内容、买了很多的书,但是却没有时间去读。
晚上
经历了漫长的加班,回到住的地方,可能就会想休息了。如果白天没时间练习,晚上也不能抽出时间练习,长期以往,一年的工作经验就要变成五年来用了。
晚上练习的同时,我们应该注意:在睡觉前 30~60 分钟停止编码,否则上床的时候,脑子里可能还是这些代码,就容易失眠。万一灵感一来,那就还要爬起来继续写。这个时候,可以阅读一些相关或者无关的书籍、资料。在阅读的过程中,尽管我们已经不在思考内容。但是潜意识里还在思考中,这时就能很容易就会遇到一些灵感。
最后,休息的时候,尽情睡觉吧~。
在上文里,我们只谈论一些方法和技巧,可是它们并没有什么用。每个人都知道所谓的『一万小时理论』,但是真正要坚持下来,并没有我们想象中的那么容易。
我们需要从娱乐时间里抽到一部分,原本舒适的玩游戏、睡觉、刷微博时间,现在要成为另外一种『痛苦』?可是,既然这些“无聊的事情”我们都能上瘾,那么我们是不是没有找到合适的路?
按上文中的分法,练习可以分为:日常固定时间的练习,及针对某一特定主题的练习等多种类型。当我们开始练习某一个具体的技术、框架、模式时,最好能制定一个简单的练习计划,如每几天练习某一内容、多少天内用某一个框架实现什么功能。
先设计一个小的目标,并且能在短期实现。当发现自己可以轻松地坚持下来时,再慢慢的扩大目标,直至我们能做得更好。可是,设定一个练习目标也不是一件简单的事,它也有很多考量的地方。
毕业的时候,在公司接受了针对于毕业生的培训,期间学习到了一个用于制定任务、目标的 SMART 原则:
经常能在微信朋友圈看到,朋友的 100 天英语阅读计划,这样的目标就是合理的——可实现的、具体的、有时间限制、可度量的。
如果我们想每天固定时间进行练习,那么我们应该做一个短暂的尝试,如七天,再慢慢的不断扩大时间目标,二十一天、两个月,随后再扩大到一个更大的目标。
我们可以使用 GitHub 上的 Contributions 来激励自己,每一天的痕迹都很明显,甚至于可以拉拢一些小伙伴,与我们一起参加类似的活动。GitHub 本身具有社交属性,可以让我们看到别人做了什么,做了多久。
由于 GitHub 的服务器在国外,访问的时候可能会受限于网络。国内的开源中国的码云和 Coding 也有类似的活跃度,建议访问 GitHub 有问题的读者,可以使用这些服务。
上文中提到的朋友圈 100 天英语阅读计划,也是相似的,它可以让别人监督你是否完成——前提是,有人一起和你做相同的事,因此可以找个人和你一起练习,相互监督。
刚开始练习的时候,练习的内容基本上很充实。时间一长,可能就会陷入一些瓶颈:要么找不到合适的练习内容,要么觉得练习过于乏味。因此这个时候,可以切换不同类型的练习项目——如,做一些自己觉得有意思的小项目练习。又或者,当我们完成一个目标时,给自己一些奖励,以此来鼓舞自己。
网站声明:如果转载,请联系本站管理员。否则一切后果自行承担。
添加我为好友,拉您入交流群!
请使用微信扫一扫!