作者:Phodal,工作三年,著有《自己动手设计物联网》、《全栈应用开发:精益实践》。 作为技术专家审阅了《Angular 2 Services》、《Smart IoT》等四本外语书。 在 GitHub 开源有《Growth:全栈增长工程师指南》等七本电子书,并译有《物联网实战指南》。
学习新框架的最好姿势是:基于现有的业务来学习。即从工作中学习,从实践中学。但是,如果一直只使用新的框架来重写旧的业务,成长也会趋近于0。第一次,使用新框架时收获可能颇丰;第二次,收获的东西更少;第三次,你可能已经学不到东西。
因此,在业余的练习时间里,不要一直练习新的框架,不要再拿 Vue、React Native 去高仿一些应用。当且仅当,你所处的项目正在使用新的框架,这种练习才是有意义的。
经过上面的练习,提高了工作效率。但要成为更加专业的程序员,还需要提高顶层的能力。下面介绍一些,比较有效的提升方法:
阅读开源软件与重构代码。
造自己的轮子来重写应用。
结合设计模式。
引入其它领域的思想。
总的来说,收获还是蛮多的,特别是造轮子,能有更大的提升。与其他的练习稍有不同的是,因为涉及到代码设计,这里的练习有些难以衡量。这时,我们应该是保持着练习的心态,并意识到我们是在做这方面的练习。
如果在工作环境中,没有代码写得比较好的人,那就只能从开源代码中去学习。这里,我建议阅读开源软件代码的方式是:
clone 某个项目的代码到本地。
查看这个项目的 release 列表。
找到一个看得懂的 release 版本,如1.0或者更早的版本。
读懂上一个版本的代码。
向后阅读大版本的源码。
读最新的源码。
可只读这些代码,不能让我们的水平显著提高,应该结合“重构”这个技能来练习。从我的练习经验看来,对于重构的练习是最有意思的。我们可以见证,一段不好的代码在我们的调教之下,焕发出新的光彩。当重构一段坏味道的代码,对比重构前后的代码,会发现自己竟然有这样的潜力。
如果找不到合适的练习项目,可以到 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 上。
因此,当我们发现一个新的优秀思想产生时,便可以尝试引入到自己的领域里。又或者我们所处的领域,正遇到一些难题,答案可能就在别的领域里。但在这方面的练习,往往都是一些创新性的练习。多数时候,我们的探索可能没有结果,但对自己可能有很大启发。
每天能有半小时、一小时甚至更长时间的稳定练习,比三天打鱼两天晒网的效果要好得多。清理出一些固定的时间,用来提高自己。
如果不能的话,那么我们也可以尝试去挤出一些时间,如从上下班的通勤时间。即使是同一公司,不同的人都有不同的上下班时间,所花费在路上的时间也有所不同。有的人,需要在几环外坐个一个多小时的地铁,再转公交才能到公司;有的人,只需要出门左转,走个十分钟就到公司了。因为在路上花费的时间不同,也在一定程度上影响了学习、练习的时间。
因此,如果可能的话,应该减少花费在上班路上的时间,才能避免继续陷入这样一个恶性循环:租不起近的房子,花费大量的时间在路上,没有时间提升技能。
早上
早上的练习,是一种慢慢进入一天工作状态的感觉。一旦上班时间到来的时候,就已经进入工作姿态了。对于“资本家”来说,可谓好事一件。早晨刚醒来,总会想不起昨天项目做到哪一步,便更容易反思哪里做得有问题。
有时候,可以有半小时的练习时间,将这些时间浪费在梦里总是有些可惜。同时,提前半个小时到公司,写一些开源软件的代码,也是个不错的选择。
需要注意的是:练习时不要关注时间,重点关注怎样提高。目标是:让每天进步一点。
中午
吃完饭后容易犯困。这个时候,身体会妨碍我们进行练习。可如果你的午休时间比较长,就可以做一些练习,再去休息片刻。
碎片时间
对着屏幕写代码,时间一久,集中力就开始涣散,应适当休息会儿。刷刷资讯、朋友圈,又或者收集各种资料,拓展一下视野。接收各种新的知识,扩展自己的格局,以便于了解整个市场水平。
常见的方式有:
阅读个人博客、微信公众号。
维护自己的 Awesome 列表——寻找自己觉得好的开源项目。
IT 新闻、技术文章聚合网站——我很不喜欢聚合网站,大部分的聚合站点的行为无异于文章抄袭。
GitHub Trending
将这些内容存储到 Evernote、WunderList、OneNote 等各式各样的云笔记里,然后定期清理、定期清理、定期清理。收集只是一种方式——没有啥用的方式,因此建议先读完一遍,再去收藏这样的文章。多数时候,我们会发现自己收藏了很多内容、买了很多的书,但却没有时间读。
晚上
经历了漫长的加班,回到住的地方,可能只想睡觉。如果白天没时间练习,晚上也不能抽出时间练习,长此以往,一年的工作经验就要分成五年来用了。
晚上练习的时候要注意:在睡觉前 30~60 分钟停止编码,否则上床时,脑子里可能还是这些代码,容易失眠。万一灵感一来,还要爬起来继续写。晚睡之前,可以阅读一些相关或无关书籍、资料。在阅读的过程中,尽管大脑已经不再思考了,但潜意识还在运转中,这时很容易抓住一些灵感。
最后,困倦的时候,就尽情休息吧!
在上文里,我们只谈论一些方法和技巧,然而没什么用。每个人都知道“一万小时理论”,但真要坚持下来,很难。
我们需要从娱乐时间里抽出一部分,原本舒适的玩游戏、睡觉、刷微博时间,现在要成为另外一种“痛苦”?可是,既然这些“无聊的事情”都能上瘾,那么是不是代表我们还没有找到合适的路?
练习可以分为:日常固定时间的练习,及针对某一特定主题的练习等多种类型。当我们开始练习某一个具体的技术、框架、模式时,最好能制定一个简单的练习计划,如每几天练习某一内容、多少天内用某一个框架实现什么功能。
先设计一个小的目标,并且能在短期实现。当发现自己可以轻松地坚持下来时,再慢慢的扩大目标,直至我们能做得更好。可是,设定一个练习目标也不是一件简单的事,需要考量很多。
之前的一个内训,让我学到了一个用于制定任务、目标的 SMART 原则:
具体的(Specific)。即我们要有一个明确的目标,如在一周内用 Django 写一个博客系统,而不是用 Django 写个东西。
可度量的(Measurable)。即衡量是否达成目标,我们只需要能创建、查看、删除博客,那么我们就算完成了这样的任务。它可以用来不断地突破自己。
可实现性(Attainable)。即这个目标一定是可以实现的,不能实现的目标没有啥意义。与此同时,练习初期定下的目标不能困难。
相关性(Relevant)。即目标与其他目标的关联情况,例如,我们练习 Django 是为了提高 Django 或者后台的技能。如果我们的大目标是提高前端技能,那么这个目标对于当前的意义并不是太大。
时限(Time-based)。即时间限制,如上面提到的一周内用 Django 写一个博客系统的期限。
经常能在微信朋友圈看到,朋友的 100 天英语阅读计划,这样的目标就是合理的——可实现的、具体的、有时间限制、可度量的。
如果我们想每天固定时间进行练习,那么我们应该做一个短暂的尝试,如7天,再慢慢的不断扩大时间目标,21天、两个月,随后再扩大到一个更大的目标。
我们可以使用 GitHub 上的 Contributions 来激励自己,每一天的痕迹都很明显,甚至可以拉拢一些小伙伴,与我们一起参加类似的活动。GitHub 本身具有社交属性,可以让我们看到别人做了什么,做了多久。
上文中提到的朋友圈 100 天英语阅读计划,也是相似的,它可以让别人监督你是否完成——前提是,有人一起和你做相同的事,因此可以找个人和你一起练习,相互监督。
刚开始练习的时候,练习的内容基本上很充实。时间一长,可能就会陷入一些瓶颈:要么找不到合适的练习内容,要么觉得练习过于乏味。这时,可以切换不同类型的练习项目,例如,做一些自己觉得有意思的小项目。又或者,当我们完成一个目标时,给自己一些奖励,用来鼓舞自己。