全端与跨领域的学习科学
我最近确实是发现了,全端开发确实能让人洞察到更多东西,尤其是那些前端和后端分别不同的坑和雷点。前端的bug有时候纯粹是后端背锅,比如出错了却只说出错,而完全不提为什么出错,导致前端除错除的寸步难行。或者反过来,前端报错,后端什么都不清楚,却「感觉」似乎是后端的问题,结果找半天发现方向错误。这些东西只有两个领域都待过才能知道,其中的「领域知识」需要实际的操作过才能明白。光看文字而没有实际体会过那种痛苦,就会始终隔著层纱。尤其是当我需要付出真实的成本去考量前后端开发时,就更是如此。只有自己体会过那段痛苦,才会有意的在开发时进行优化,付出额外的精力去顾及可能「不属于自己」的问题。
甩锅不是个好习惯,也许开发者自身是没有恶意的,但是懒惰会让人下意识节省掉一些本该有的东西,进而造成配合方的不便。往往为了克制这种懒惰,要么会使用制度来强制要求某些开发规则,要么就是靠自律——而后者是最难的。这也是踩坑带来的最大加成,它会让你下意识去自律,不是我想这么做,而是不这么做我真的会痛苦万分。只有debug de到力竭的人才能体会到那种想怒喷前/后端祖宗十八代的感觉:你就加个log,几行代码的事儿,为啥不给我弄上。双方都这么想,结果就是互相给对方上强度。当然有些情况可能是企业制度的原因,但从个人的角度看,可以在制度之外将标准做法内化,正是技术能力的体现之一。
抛开灵活性,另一方面我觉得是洞察:知识的跨领域再现。我目前在前后端使用的都是强型别语言,TS+C#的组合也让我看到许多共同的设计原则。比如DI,TS在做法上和C#几乎是一致的,也意味著我可以同时在前后端使用这种模式。亦或者是关于泛型,这对任何强型别的语言来说都是一致的。也许有人会觉得,这和全端开发不尽然相关,更多的是语言问题。但当前后端前后端使用的语言和框架都不同时,正是全端开发给我提供了这种跨语言的理解环境。否则下意识泡在舒适区的任何人,恐怕都不会每天深度在多个语言之间切换。只有工作上的要求会迫使我写完了TS前端再去看C#后端——而我在个人项目上都是TS一条龙穿到底,前端用React后端用nestJS的,谁会换另一个语言给自己找麻烦。
跨领域的再现有时会给人一种明确的「顿悟」感,我蛮享受这种感觉的。我们常说「看山不是山」,但具体如何体会却总被认为是可遇不可求的。但我认为,这种感觉完全是可以是自己主动去制造出来的产物——关键便是主动的尝试和跨领域,并用已有领域的内容来看新领域,并尝试寻找可以迁移的知识。从学习科学的角度来说,这正是重构大脑神经链接,搭建自身知识网络的过程。和教科书不同,大部分真实知识从来都不是线性、结构分明、体系明确的(数学可能例外),而是更倾向于来回跳跃。教科书上的知识也许是ABCDE,但到了具体完全可以是A到C到E最终才会回到B。因为工程上我们总是遇到了问题才会再去考虑这东西到底是啥,应用领先于理论,而应用上的我呢提也会成为我接触理论的动机和出发点。最终我掌握了理论的目的也是要让其回馈到我的工程上去,不像学校是为了应付考试。
另一个概念是「默会知识」或者说「隐性知识」。它正是一种让人难以捉摸而大多存在于人之感觉中的只是。难以成文化,而只能靠工程师的经验或直觉来把握的存在。像这种知识,在我看来体现的正是知识结构网络本身——不是以逻辑,而是以结构为存在的知识形式。隐性知识是对知识结构的把握。这种结构有时候难以言说,但却真实的储存在我的大脑之中。当需要时,从一个入口(信号)开始,我会逐渐激活整个网络,进而向前端推送出那种感觉。而这一网络是需要在不断地交互和实践踩坑中去获取的。除此之外,搭建网络的另一个有效方法,便是跨领域的知识迁移。
通过迁移,知识在不同的新领域(生理上来说可以是新的神经组成)构建链接,进而涌现出此前未曾察觉的新内容。当两个原先区隔的知识碰撞和交互时,新的知识也会在其中生成——而他们不尽然是可以言说的,也当然存在哪些作为「感觉」而存在的知识。
同时,不断地迁移过程中,我自身关于「如何学习」的元能力也会得到训练。每次迁移,我对这种跨领域就会适应一份,进而我的思维也越不会被已有的知识结构和体系限制。每次迁移,我所学到的东西都可能会和我预料不到的已有知识结构发生碰撞,进而源源不断的产生连我自己都无法得知的新东西。只有跨领域能给人这种频繁的「见山不是山」的体验,这是长期浸泡在单一领域难以体会的。
跨领域时常被人反对的一点就是深度和广度的取舍。但我觉得这里不完全是矛盾的——深度和广度可以互相促进。精力有限,我当然难以兼顾广度和深度。但是拥有极其广度知识的情况下却能培养我的另一个能力——那就是学习的能力。同时,无论是前后端,事实上又都同属于一个领域,即计算机科学。作为子领域来说,前后端的确是区分的,但他们又共同依赖著计算机科学这个大领域的知识主题。所以这里的知识结构就会体现为大的套小的,小的再套更小的。前后端,就其知识本身来说有不少都是共通的。而这种共通也会加速我学习想要学习的指定领域之知识的速度。
就拿前端来说,有些人会认为知识的深度体现为对框架和工具的使用,或者是前端优化、实作中具体操作的标准解法。但是,高难度的前端当然不只是切版:性能调优、网路协议、甚至部分后端的高并发与资料结构、演算法等等,这些不是全部,但也都是前端深度知识的构成之一。我们都说前端一年一变,可即便如此,也总有些知识能够保存下来——比如跨框架共通的设计原则——一旦吃透,那么我就可以快速掌握到深度之中。当我转换框架时,实际上已经进行了一次前端内部的「跨领域」知识迁移。只是跨的幅度不大,有时候让人难以察觉而已。
但是,如果我本就拥有经常跨领域的经验,必然会很快察觉到这里的共通性之所在。所谓的第一性的那些东西,往往都是共通的东西。如果说,长久的跨领域培养了我对第一性的洞察和学习能力,那么我对所谓「深度」知识的掌握速度,也会远远大于一个多年泡在单一领域的人。一个多年前端可能对某些具体的专精知识钻研的极深,我当然认为这样的人是值得尊重且至关重要的。但是我们对大多数人来说,我不需要知道V8框架的某个深层细节到底是啥,而需要的是快速的工程能力——即达到工程可用的深度,这才是企业所需要的。那么,如果我具备这种快速学习的能力,那我达到深度的效率也会让我在需要的时候切换状态,从广度马上转换为「可用的深度」。因此,与其担忧「广度影响深度」,不如转换视角,思考这样一点:「我真的需要那么多深度吗?」
往往说这句话的人,他们看向的是专家,而不是可用的、深度的工程师。比起前者,企业在量上反而更需要后者。除非真的是特别要求专家知识的行业,或者就立志要进入到对专家深度有明确要求的岗位,否则「广度」对个人的加成都始终是正向的,而非是像世人嘲讽的那般,所谓「多而不精」。因为他们只看到了「多」,却忽略了更本质的层面——如何多?拉开差距的正是学习能力,一个「多」者必然有其自身的快速学习方法论,否则他不可能掌握那么多。而一个能够快速学习,掌握了「元学习技巧」的人,更能够在需要的时候切换为「深度」的状态,而且还可以是「多个领域的深度」。他之所以无法达到专家是因为精力和时间有限——但如果,他中途决定转换道路或精深某一领域。他追赶并成为专家的速度和效率,也会超过那些长期只在单一领域待过的人。至少在这里,「多」从不天然成为被嘲讽的「劣势」,「如何多」才是关键。
如果我具备了能快速成为此类人的能力,自然就具备了更多的机会。跨领域作为一种优势被如此嘲弄,反而磨灭了真正能够创造价值的能力。一个有效的工具被「认为」是低效的,从工程角度来说,这毫无疑问是浪费。并且在我看来,之所以它会被这么认为,恰恰是因为大多做出此类判断的人缺少跨领域的知识——比如我就是从「学习科学」的角度来论证这件事的,若他从未接触过学习科学,他当然就看不到这样的角度。这至少就表明了拓展知识带来的附加效果,有时候角度本身就很重要。