网络时代,获取信息的渠道变的更多,也更便捷。然而在汪洋如海的知识里,如何能找到自己的方向,这确实需要一些技巧。
新的技术,都不会是凭空而出,往往是之前的一些技术,发生了一些突破,创新后变成了一种新的概念,描述,然而本质不会改变,我们要找寻的便是,通过网络零零散散的知识,如何快速形成自己的学习计划。基于此目的,今天我们聊聊天,谈谈心。
首先,我并不标榜自己有多成就,也不想说这便是唯一正确的姿势。我只是尽力的去总结自己的学习技巧,希望读写能够阅读完后,能够提供一种途径,有所收获即可。有可能此方式,并非放之四海而皆准,所以才有因材施教,我也只愿抛砖引玉,也算功德一件。
很多人遇到新的知识,总是显得焦虑,却总是不得章法,导致很迷茫,有些慌乱,却反反复复,没啥进展,原地转圈,时间成本很大,却收效甚微。究其原因,在于没得思路,不知该如何去学习。
◇
大学,教会的除了视野,还有自由之外独立的思考,自学的能力。如果还是一成不变,按部就班,按时上下课,按时完成作业,那就大错特错了。在一遍遍失败的经验之后,自成一套,整理了一些快速掌握新的技术的方法。
一个新的知识出来,首先要看的是它是什么,它能做什么,对你而言你是要致力于这个方向,还是只是蜓蜓点水,浅尝辄止?因为每个人的精力有限,有时要学会借力打力,见招拆招。而不是自己奋力先自行修炼,认为自己可以出山,才出关道士下山。
如今,知识爆炸时代,如果门门都去掌握,肯定是不现实的。如此就要去关注,自己感兴趣的方向,然后深入,将核心掌握,然后抽离出来模型,放入实战之中验证,完成自己的一套知识体系。
我们举个例子,手机系统,我们抛开其他,先做一个暴力的模型,手机组成为硬件,驱动,软件。经历过单片机,嵌入式开发版的人来说,拿到一些板子,外接一个LCD,然后自己去照着手册,编写驱动程序,封装一些接口,让做应用软件的人员,直接使用调试好的这些接口,来完成功能实现。
◇
当开发复杂的应用的时候,发现要做多任务,同时显示界面没有一套UI库,于是就开始找一些开源的系统,比如μC/OS II 和uclinux,等等一系列的操作系统便涌了出来,解决你的任务,进程创建,调度现场保护等等,让你可以不用关注太多细节,便可快速使用多任务,多进程,完成更加复杂的事情,界面控件,响应,可以借助别的GUI系统,比如wxwidget和 qt等等,来完成搭建我们的界面库,通过将其移植过来,配合我们的系统,来实现绘制,响应。
而关于操作系统,关于GUI的内部实现,我们不必深究,但是我们必须了解其机理,懂的操作系统的大致实现进程的方式,比如构造一个PCB表,构造堆栈控件,线程切换保护现场模式。要能够自己打通,形成自己的一套概念。
技术千变万化,却万变不离其宗。脚本语言,出现了那么多,实质就是一个解析器。按照约定,去读取,解析,然后执行。然后我们把这个约定,叫做语法,把解析叫做语法分析。将很多东西,进行一句话总结,我们再来说一个,android是什么?本质就是linux系统加一个dex虚拟机。在这基础上,进行了一些客制化,比如binder,出现的原因就是linux我们本身的通信方式,效率不高,于是就开发出来一套,称之为binder。于是binder就是一种进程间通信方式。
一句话模型,是自己先对某个知识,形成一个简单的概念,然后顺着这个方向,去细化知识,理解实现原理,然后回过头来,加深一句话的总结,做到心中有数。
在刚接触一个新的知识的时候,首先要做的是,搜索概念,了解它是干嘛的,然后去看下大家都用它在做什么。然后看下它是否能解决你的诉求。比如这里我就拿近期的SDL框架来说,第一件事便是了解,它主要解决什么?它主要解决图片的渲染,就是如何将一帧画面显示在各个平台。那么我们用它来做个图库,肯定是可行的了。我们想用它播放视频,我们知道它就是图片显示,那么视频解码出来就是一帧图片,如果我们借助其他的库将视频解码出来,拿过来让SDL去显示,就可以播放视频了。于是就找到了ffmpeg+SDL组合,完成视频播放器。
◇
那么它做游戏可以吗?可以。想做复杂的,比如有地图文件,物理碰撞,粒子炸弹效果,界面GUI,我们发现SDL本身没有,所以要用它就需要移植。有人会说,何必呢?有一些现成的游戏引擎,支持的很好了。比如cocos2d和libgdx,开发游戏来说更加方便,快捷。确实如此,那么我们用SDL的意义在哪呢?其实SDL要做的很简单,比如你开发了一个游戏,比如之前是在一个特定显示器的,然后自己想移植到PC上或者ios或者android来玩,那么你要做的就是事件匹配,触摸匹配,以及绘制匹配,而这些SDL已经帮你做好了,你就可以参照SDL的官方文档将游戏移植过来了。
讲了一些无关紧要的事,感觉有些跑题。当然这也是我的一贯作风,从来不会命题作文,都是随意展开,随处收尾。
那么,回到主题,我们怎么快速的掌握一个新的知识呢?
首先,官网介绍。官网会将它的用途讲解出来。这个概念,你要快速形成模型,要决定是否需要学习,自己是否能够短时间掌握。有些事情,不必勉强,不擅长的切勿勉强,一味逞强去学习,到头来自己迷茫,也没啥收获,自己就开始怀疑人生了。比如之前学习手写识别,做过一些demo,做出来效果,但是识别率比较低,而自己尝试了下,发现这个领域,自己是没法短期突破,因为不着思路,所以就要退出,说明这个方向不适合自己,就不要瞎去研究。当然,如果你说,我有的是时间,我必须要研究,那就另当别论了。
从开始的技术流,看到什么都去学下,导致很多东西都是略知皮毛,导致都没深度,没有深度,意味着没有竞争优势。某个方向,发展成自己的优势,尤为重要。技术流是做技术的核心竞争,但不可太过零散,要做到收放自如,哪些必须掌握,哪些可以一笔带过,哪些需要研究一番,抓住主干,切不了细枝末节都牢牢抓住。当然,如果就是专攻此方向,那就另说。
◇
学会整理,鉴别,快速搜寻答案。比如开发应用,三方库很多,我们简单说个,比如图表库,网上有很多对比,MPchart和hellochart,讲的很多,我自己快速选择了hellochart,原因比较简单,我快速的就能上手了,并且它能解决我的诉求。当然开发完了,用完发现它也是比较郁闷,做的很多地方比较死板,让开发的人员用起来比较别扭。当然,这个就是时间问题了,如果觉得自己是长线要做图表的,那就每个都看看,找到更适合自己的就好。
很多开源的,都不会直接就OK,都是需要简单调试的,于是你的能力会在快速找出,可以使用,如果不行,快速更换,调整,小的问题,需要有能力阅读代码,完成修改。我来说个简单的greendao,一个非常好用的三方数据库方案,我在使用的时候,发现不能创建两个实例,也就是不能有两个db文件被创建,比如有很多人开发,想账户和应用数据想独立存储,放在两个db里面,那么可以确定,greendao做不到,因为它的单例模式,不允许,它的很多内容,用了一个全局变量。于是你想做两个db,那么请换其他开源库。那么如果你不是必须要两个db,那么我们可以做两个table来解决此问题。
上面就是举个例子,要有能力解决问题,开源库会磨炼你的技术,让你提升定位,修改问题的能力。
在看完官网的介绍,觉得满足自己的需求,那么你就可以继续阅读,主要看下它的wiki,或者示例,效果。自己搭建环境,调试,看下是否能够完成,如果过程中发现不是太好,就需要重新去找别的项目,不需在此过多逗留。
学完demo,发现适合,那就研究下开发过程,它的基本开发套路,能够形成一个简单轮廓,向自己的目标靠近。如果途中出现问题,要能够从它的文档中找出问题点,当然首先先百度,google搜索,去甄别答案。
◇
说了一些快速找到自己需要的开源项目,那么我们找到一个开源项目,发现有些功能受限,比如glide,我就想客制化,发现它的加载图片功能不够(当然本身glide做的已经比较好了,我们一般做的是封装),于是需要研究代码。
阅读代码,最好是有一条思路,有技巧的去看。一般就是带着一个问题,比如某个方法,我想扩展下,觉得它的返回,或者回调里面信息不够,然后去追踪,分析,定位。这里需要强调的一点是,不要盲目一路去追代码,学会总结,不要被一些细枝末节的代码,导致迷失方向,比如一个方法,就是比较一个点是否在矩形区域内,我们如果不是必须研究算法,那么我们就只关注这个返回值的判断地方。对于有些宏,case项,可以看看枚举值,它对于你的理解有帮助。比如播放一个音频文件,发现有个case有一个枚举,TYPE_MP3 那么就可以去看看这个都有哪些枚举,就能知道这里都支持哪些格式的播放。同时如果有些枚举上有个宏控,那就知道这个功能是需要配置,有可能没有开启。
代码阅读的技巧太多,这里肯定讲不完,也没有必要。这个东西每个人自成一套,只要努力去阅读,失败后总结,便会有自己的一套学习方法。所谓条条大路通罗马,没有说只此一条通道。
学习完后,做了demo,文档看了一堆,发现真是雪中送炭,解决了自己的燃眉之急。于是,你就可以很欢快的将它收入囊中。不过,如果这个项目,你后续会多次使用,那么你要研究它便是迟早的事情了。于是,就要花费大量的时间,快速整理出来学习思路。通常就是按照它的demo,跟踪代码,理解,掌握。然后能够打通,同时不会陷入细节里面。
通过官网阅读,查看demo,验证效果之后,如果OK,那么已经完成了新的技术的认识。后续便是是否想继续挖掘,学习,那么就要不断的穿梭在代码,文档之间,同时借助百度,google搜索,来扫除理解的一些障碍。比如SDL里面,最先出现的一些概念,比如surface texture 以及render这些概念,都需要先行理解,因为理解它,你就有了层次感,随后的跟踪,调试,就知道围绕着什么展开。
比如android,需要理解一些概念,linux操作系统,虚拟机,surfaceflinger,AMS服务,binder通信机制,以及jni等等,概念先行,会将整体框架搭建起来,那么你去追一条线的时候,则不会迷失,能够知道自己当前追到哪里了,是否需要继续追。比如追一个view.post,我们追到最终,到达message.post则可以结束了,同时需要贯穿一下,就是放入消息池中,从哪里取出,消费的。也就是handle message 和looper的关系。
思考,总是需要有所突破。不能每次都沉浸在别人研究的结论上,在别人的结论上,继续深入挖掘,才能变成自己的独特的见解。这个观点适合很多情景,叫做比别人多走一步,或者叫站在巨人的肩上。要有自己的总结,以及更深更透彻的理解,这才是真正的收获。
◇
当你经历了太多,比如语言的演变,你就能透彻的理解,演变的背后,往往跟随着科技的进步。从之前的斤斤计较,对于内存,硬盘,以及堆栈区域大小,跳转空间限制等等,到现在不需太多关注,编译器优化,已经能够做的很好,更加便捷。
追求效率,以及追求品质,永远是在制衡,到达一个平衡即可,切勿过度,导致顾此失彼,得不偿失。现在的开发,若非实时要求非常严格,必须精准的计算执行时间,我们平时开发,基本对于效率不会过度追求,对于计算排序算法,我们不会太过较真,只为在我容忍的时间内,解决问题即可。
比如脚本需要,去过滤文件,将一些内容提取,生成其他报表之类的,即使我们文件很深,也会在十几分钟内完成,相比于我们手动搜索,查找,过滤,那根本不是一个级别,如此去计算,十几分钟简直神速。在不太频繁的使用,大面积推广的时候,此算法效率可以不做优化,达到可用即可。
◇
学习,在于技巧的掌握,以及目标。当你有计划学习,找到自己喜欢的课题,记得深入学习。如果自己不喜欢,却比较流行,那就学个demo,了解背景,做到知晓即可,不需通达。
开发应用,很多时候不做研究,就是拿来使用,发现OK,即可合入项目。但是,如果是偶然开发,那么风险可以稍后推延,做到大致心中有数,如果是长线开发,比如公司,团体,那么初次使用,可以不做过多计较。如果第二次继续使用,则需要注意,我们需要研究下代码,评估风险,做到心中有数,对于此开源库的优点,缺点,适合场景等等,做出基本判断。
学习,永无尽头,能有一套自成体系的学习方法,比之熟练掌握几种语法,要有优势的多。因为知识不断在迁移,技术在修正,迭代更新。手握自己的渐变陈旧的技术,却无力快速适应新的知识体系,理论,那么,技术革新的车轮,则会毫无情面的碾过你,连同你所经历的岁月。