码途有道—-基于系统观的核心能力构建
有感于同学们在大学中如何学习计算机技术有些感概,将我书(老码识途)中的序言整理了一下,并补充了一些后来的想法,比如什么是系统观的新认知。
如果你想成为高级程序员或架构师,什么才是技术上的核心竞争力?仅仅是知识吗?在这个随时可求助于Google的年代,它似乎已变得非常廉价。而青春的流失并不能给我们留下技术财富,似乎只是将我们变成自嘲的“码奴”。核心竞争力究竟在哪里?笔者认为它的一个关键要素就是“系统观”,这是高级软件人才必备的素质。系统观是美妙的,它能自我生长,自我完善,你有了它就拥有了一颗能成长的原核。它是核心知识架构和对它们不断运用所形成的思维方式的复合体。
总之,我认为关键是培养系统观,抓住底层核心的东西,以不变应万变,才能游刃有余,基础牢靠。
学什么,少即多:系统观
学什么?记得在internet网还没有成为主流的时代,有个学通信的硕士被一IP路由器问题困扰了一个多礼拜。笔者最好的朋友,学空气动力学,他玩了10多年DOS系统。从没实际接触过网络,只是“看”过一本资料,还不是IP网络,仅花两天就解决了问题。为什么有人学了很多技术和语言却不如未学习该技术的人呢?该问题另一个问法就是“什么才是我们最需要掌握的?”。
笔者的看法是:“少就是多,将这个少变成多”。下足功夫将“少”做深、做厚、变多,就是将来应对千变万化的舵。这个“少”就是计算机的系统观。看看上面的例子,那个朋友对DOS的熟悉已经到了任何一段地址空间作用都了如指掌的地步,自己还实现过一个汉化DOS。这无疑建立起坚实系统观。这个系统观能指导他按照计算机的“逻辑”方式思考,而路由器不过是这种思维方式的一个例子罢了。有了系统观,学习新东西时,用它去猜测构想学习对象的可能做法并实证分析,是一种迅捷的办法。笔者一次处理SaaS软件中hibernate将同一持久化对象存入不同库的问题时就是这样,虽然没用过hibernate,但通过猜测和调试,用了约半天时间解决了(搜索并非银弹,该问题当时中英文网上均未查到)。
系统观
在写老码识途时,我自己也还处于比较模糊的阶段,那个东西知道在那里,但就是说不清楚。有朋友也赞成这个观点,但他们定义也无法说服我。因此在老码识途中,我是实用主义者的看法:
到底什么是系统观?有些东西更可意会,难以言传,且见仁见智。这时,纠结含义不如能够运用。诗词意境颇似系统观,诗人自身可能都说不清其内涵,可他能运用这种意境,运用为王。其实我们只要能建立系统观就好了。如何建立?一种方法是从无到有自己撰写一个系统级软件(哪怕是实验性的),如嵌入式数据库、小型操作系统或编译器。这非常有效,那位朋友得益于撰写汉化DOS的经历,在没有学过嵌入式的情况下,一月时间就解密了一个单片机太阳能系统,并汉化。但该方法需要较长一段时间完全投入,且难度不小。针对这些问题,老码识途给出了另一种方法。
后来,在一次开会前,和同事谈及,突然有所明悟,慢慢思考去,就有了下面的观点:
计算机系统观是计算机核心知识架构和对它们不断运用所形成的思维方式的复合体,不可割裂。单纯的通用思维训练和仅仅摄取知识信息均无法形成系统观。它是能自我生长,自我完善和成长的原核。在摄取新技术和面临黑箱时,它具有极强的剖析、探索和学习能力。这赋予了高端计算机人才最重要的素质。
核心知识架构涵盖计算机领域最本质部分的规律,笔者认为应包括:计算机组成原理、系统结构、操作系统、编译和链接、算法、数据库原理和实现。
为什么系统观在学习技术和解决难题方面具有“以少胜多”和“一劳长逸”的特点呢?下面笔者试从系统观的三个功能分析:类比、构建和简化。
-
类比 因为系统观包含了核心知识架构,其涵盖的计算机领域本质规律在所有计算机应用领域均可借鉴和举一反三。太阳下没有新鲜事物,应用领域的技术多是在老技术上的不断包装、组合和抽象。一位云计算公司的CTO告诉笔者,他要解决存储或并发的问题时,习惯找六七十年代最早的算法文章(因为它将根本性问题描述得非常清楚),在此基础上就很容易适配到现在的问题中。笔者一位朋友很多年前做汉化DOS,后来他第一次做单片机破解,只花了一月就将其破解并汉化。他明确指出DOS汉化经验起了很大帮助。笔者第一次面对linux驱动的C语言编程问题时,却运用面向对象的经验,花数分钟解决了学生因回调语义错误引起的bug。因为基于接口编程思想在整个软件甚至硬件领域都是一致的,在面向对象是虚函数,在内核是回调函数。这三个例子均运用系统观中存在的基本模式和知识去类比解决第一次面临的难题,体现了系统观“少即多、旧即新、基础即先进、不变应万变”的特点。
-
构建 系统观思维具有构建式的特点。形象地说就是“我来做怎么做?”这样的思维方式,在学习新系统或技术时能首先从构建的角度分析,从而对关键点产生疑问。带着疑问学习,效率就高。笔者一次寻找hibernate操控同结构多数据库的方案时,从构建角度分析如果自己做怎么做出扩展性,假想出了可能的扩展点,然后带着这些假设用调试去检验,虽第一次接触hibernate,用了半天就解决了。笔者曾用“我来做怎么做”的思维模式训练研究生,有人反映这是其研究生期间学到的最有价值的东西。
-
简化 面临复杂未知时,同时面临太多未知点,人们必然无所适从,难以下手。如果能迅速化繁为简,主动“忽略”过滤掉暂时无关大局的细节,那么就能寻找到症结,从而快速击破解决难题。系统观的底层特点使其具有底层视角,再加上其反复淬炼出解析能力,使其能够完成这一简化和忽略的任务。能体现简化和忽略特性的最直接例子即逆向工程。面对高级语言源代码往往人们要找到下手点都无所适从,何况面对的是反汇编代码?要完成任务必须快速找到关键点,一击而破。在高层应用领域分析理解面向对象框架也是如此,往往从关键的虚函数入手,通过调试找到其调用关系,并最终找到可能的装配逻辑。
综上所述,因系统观涵盖计算机本质规律的掌握和运用,并具有类比、构建和简化功能,所以有很强的自我学习、扩展、探索和长效性特点。这使得学生培养了系统观后,可在其职业生涯中一直发挥核心竞争力的作用。而其覆盖本质规律的简约性,又使得其培养开销相对经济,性价比高。
两种构建系统观的方法
正向构建式(用系统观的构建和类比特性进行训练)
该方法的核心就是构建,并非构建简单的应用软件,而是构建系统级软件。即撰写操作系统、编译器、链接器和数据库(非数据库应用软件)。例如,构建CPU上实现操作系统、编译器。该方案最大优势是自底向上完全打通软硬件,形成最完整和坚实的系统观。其限制在于时间和个体能力。即使在985高校中,也只能是优秀学生才能完成。但这个优秀不是你成绩的排名,只要你有兴趣,有毅力,你就能完成。相信我,我遇到过女生自己独立数月也完成了os的撰写。原因是该女生意志比较坚定
逆向析构式(用系统观的简化特性进行训练)
它提供了一种剑走偏锋的方法:自底向上,以逆向反汇编入道,贯穿从机器码至框架的学习。因为,逆向是一把匕首,小巧,却能劈开黑箱直见根本,实乃实证利器。它不仅让我们多了一种能力,更将OS、Compiler等相关知识从压箱底处翻到台面,并通过逆向有效整合在一起。你会发现,这些原来似乎抽象的知识,完全渗透到我们破疑解惑中了。这里说的逆向并非狭义的破解,比如底层的攻防(例如溢出攻击及其防御的代码撰写),分析bug,逆向分析工作原理并用以解决问题(这个特别有用,与我而言,逆向从一开始到现在就是这个含义,而破解只最近才做了一个玩)等。
老码识途就采用的这种方法。
我的码道:三步斩“码”刀
修炼系统观不是简单知识积累,它需要一种道。笔者的“道”就是:猜测–实证—构建。
-
“猜测”让我们主动思考,发现问题。这样学习不再是按部就班,而是“寻找式”,对症下药有选择吸收,迅速且直指症结。如老码识途1.3.1小节学习call指令时,不直接看其解释,而是先分析机器码,猜测哪部分可能包含转跳地址。最后经多次猜测实证才搞清。这样,将一般被动接受式学习变成了主动研究式的破疑。简单说就是学习任何不懂的技术或框架前,先不急于看它怎么做,而想想自己怎么做,要想到可实证的细节,否则无意义!
-
“实证”体现为每个知识点都可触摸:或调试、或编程、或使用,能验证。许多人猜测后认为一些东西“很显然”,而不验证。往往此时,“真知”就从指间溜走了。如老码识途2.9.3
-
小节猜测状态保存时,细分了局部变量、参数,并考虑优化。
-
实证与猜测相悖处即前进动力:我们常感叹不善提问,而实证就是最好的发问者.
-
实证时往往一个知识点牵扯了很多复杂因素,看来几乎无法实证。此时关键就是“领悟精髓,则繁就简”。老码识途第3章展示了如何通过摸索理清链接关键逻辑,构建一个2~3天能完成的inker核心小程序。
-
-
“构建”要求尽量将学到的知识通过编写程序模仿出来。这非常有助于以系统观思考问题。而构建中会出现意想不到的问题,它们又是进步的阶梯。比如,多年前学习《Windows核心编程》中内存访问API时,笔者抛开书上例子,用这些API编写了游戏修改器。而之后就发现了问题:遍历整个线性地址空间寻找某个整数耗时太长,速度完全无法和真正的修改器比拟。最后基于最基本的对齐原理解决,就不用挨个字节搜索。基础知识在一个个构建、意外及调试解决中被贯穿起来,终成系统观。
其实码途之道最重要的就是“快乐”。有了它你就有自己的“道”。当在逆向的迷宫里游历后,一个个失望和惊喜掠过内心,清亮的阳光穿过0-1bit的迷雾晒到皮肤上,这是生命的味道。
现在,逆向析构法已经升级为逆向析构+加病毒轻量级构建的方式了,系统能力敏捷之路:安全的逆袭。效果更显著。