一项系列实验中,研究者着手探索困难与认知之间的关系。他们给两组人员安排了相同内容的测试,一组的测试内容在格式上更加易读,而另一组则相对较为困难。在所有的实验中,困难组的表现一直保持领先。隐含在这项实验背后的理论向我们表明,默认状态下,我们依赖一种自动的、简单的以及原始的系统进行逻辑推理,但是,如果我们面对的事物违反直觉或者难以理解,我们就会切换到一种更深层次的、有意识的、分析型的思考模式。

我一直在思考如何将这一理论引入到编程领域。编程是一种智力挑战型任务,但是幸好我们发明了各类工具,从而使得这项任务具有了一定的可管理性。我发现任何一门编程语言、开发框架,或者编程库的直觉性和易用性,可能均有其相应的副作用。从我的个人经历以及帮助初学者的感受来看,我注意到一种现象,当我们使用一种符合我们直觉的工具时,任何时候只要遭遇到困难,我们就会觉得手足无措。而且,尽管我们或许已经具备了克服困难的必要技能,我们还是会尽力寻求帮助,并且重新回顾我们的已有工作。我们宁愿直接找寻与开发框架相关的最佳实践,也不愿意自己动手解决问题。在这一方面,最典型的例子就是那些 Stack Overflow 上的问题,如『如何使用 jQuery 实现 X 功能?』 或者类似的回复,如 『使用 jQuery [插件] 就可以实现 X 功能』,在这里,X 泛指从基本算法到 websockets 之类的任何对象。

开发框架负向空间

我们在使用一种开发框架时,一些特定问题将会变得很容易解决。如果我们一直待在这个开发框架的应用范围之内,编程显得非常直观。我们把这个应用范围称为『开发框架直觉空间』。另外一方面,我们把其它那些这个开发框架无法解决的问题范围称为『开发框架负向空间』。负向空间不是一个开发框架的缺点,它原本就不属于这个框架的应用范围。但是,如果一名程序员在直觉空间滞留的时间过长,那么,当他一旦进入负向空间,就会感觉不舒服或者特别尴尬。

当那些初级程序员发现自己身处负向空间的时候,他们常常期待编程库的作者能够让他们重回直觉空间。这就是为什么任何一种流行的开发框架,都有着完整且自成一体的生态系统 - 这些插件及扩展库帮助这个开发框架,在表面上扩大了直觉空间的覆盖面。如果程序员的生产效率借此得以大幅度提升,似乎也无可厚非。但是,它很可能导致一系列无法预料的后果:

  1. 程序员对编程库生态系统持续增长的依赖。
  2. 招致技术债务的同时,将架构决策责任全部转移给了各类编程库。
  3. 助长了『编程应该总是简洁直观的』这一错误的编程观念。

开发者与编程库作者的代码依赖

我其实在开始的时候就应该说,从技术上来讲,这是一种错误的二分法。在任何编程过程中,所有的程序员都承担着这两种角色。你也许正在为产品逻辑编写代码,然后你转而构建一个可以帮助你多处复用的具有通用价值的抽象模型。但是,在开源软件世界,我发现人们更倾向采用这种二分法策略。

在开源世界里,通向成功的最简单办法,就是自己动手将负向框架空间转换为直觉框架空间。也就是说,编写各种插件和扩展库。当一个开发框架日渐流行的时候,越来越多的的开发者(通常都是一些初学者)将会开始抱怨:在这个框架中实现 X 功能如何如何困难(其实我们都知道,X 功能与这个框架的设计初衷根本没有关系)。就像在真实商业世界一样,开源软件之间竞争异常激烈,当你开始为大家解决一个已知问题的时候,很多人也就有了更多无需进入负向空间的机会和可能。这将会大大强化『程序员理应将所有时间花在直觉空间上』这一错误观念。

小结

我认为,修复这一问题的根本解决办法,就是要回归教育。当一个人在最早期学习编程的时候,我们的文化过分强调了工具的重要性。我自己就收到过很多这方面的问题,如『有哪些最好的工具或者编程语言值得我学习呢?』 在我看来,这些问题提出的时间过早。我过去经常这样回复:『这取决于你正在构建的究竟是什么』或者『选择一个对初学者友好的社区』或者『投资在那些成长型的编程语言上』。尽管我觉得所有这些都是很好的答案,但是对于一名编程初学者而言,所有这些并没有看起来那么重要。当你正在学习如何编程的时候,核心内容并无差异。更有甚之,这种风格的回答还容易导致过于沉迷工具的习惯。

对于软件工程来说,代码重用、编程库、分享以及开源软件都非常重要。但是我们应该小心仔细地处理这些事务 - 不要建立错误的观念,以为编程本身就像把不同的对象粘接在一起那么简单。事实上,在过去的一段时间里,我总是对那些看似简单的编程活动保持高度警惕。如果编程真的那么容易的话,这一领域早就自动化了。


作者:Amjad Masad,程序员,就职于 Facebook JavaScript 基础架构团队。

原文:Overcoming Intuition in Programming

感谢:Qingniu 帮助审阅并完成校对。