面向大脑的程序设计

2020-08-15 14:12:22

1956年的论文“魔术数字7,加或减2”是“心理学评论”杂志126年历史上被引用最多的论文。作者乔治·A·米勒被认为是认知科学领域的奠基人之一。他的历史性论断是,你一次只能在大脑中处理5到9件事。

据我所知,尽管多年来存在一些争议,但这个7±2的数字经受住了持续的可再生性危机,它似乎捕捉到了关于我们大脑实际如何运作的深刻真相。

许多人对这一说法持怀疑态度,因为7听起来似乎是一个荒谬的数字,如果你正在做一些复杂的事情,比如编写软件,或者为此策划一场婚礼,你肯定会在几十到数百件事情之间纠结吗?事实证明你不是。至少不是一下子。

2005年,陆超背诵了67,890位圆周率,这是一个令人难以置信的天才和训练有素的头脑的展示。然而,给出一系列随机的个位数,他平均能回忆起其中不到9个,准确地说,他被测量的数字跨度为8.83,这完全符合米勒的发现。太神奇了!

赵小兰记忆派的方式和讲故事的人曾经记住吉尔伽美什的长篇故事一样,但他一次只能变戏法地处理几件事。我觉得这真的很令人欣慰,他并不是一个天生的怪胎,至少不像YouFirst想象的那么怪异。

我们能记住很多东西的错觉几乎与我们的视野到处都是高分辨率的错觉是一样的。它令人难以置信地令人信服,因为当我们想知道那里有什么时,我们会快速扫视,并立即获得对那里到底是什么的高分辨率视图。我们问这个问题,我们会立即得到答案,所以感觉答案一直都在那里。

这张照片夸大了中心凹有多大,它实际上只有手臂长度的25美分那么大。

一般说来,思维方式与视觉非常相似。这并不令人惊讶,因为它是使用相同的大脑硬件实现的。当我们快速地从一个想法到另一个想法,从一个概念到另一个概念时,我们会翻阅必要的细节,但我们脑海中的个人想法永远不会超过九个。

我们的工作记忆大小似乎受到如此巨大的限制,我们该如何驾驭这个复杂的世界呢?我们使用的两个主要工具是分块和层次结构。

当我们想到一辆车时,我们自然会把车分成几个高级部件,如发动机、仪表盘、座椅、轮子。然而,当我们在头脑中放大发动机时,它会毫不费力地分解成更多的部件:发动机机体、活塞、火花塞。我们可以继续放大,尽管我们能放大多远很大程度上取决于我们对汽车和整个世界的了解程度。

在面向对象编程中,驯服复杂性的最简单方法之一是将对象限制在七个属性左右。在某些语言中,属性称为成员变量或字段。许多程序员立即对这个问题犹豫不决。当然,这适用于玩具示例,但我正在编写严肃的软件,我的对象有时需要10个、20个或50个属性。他们会说,你一定是在做简单的事情。我的问题很特殊,所以我的代码必须不同。

软件开发的最大陷阱是很容易写出你自己不能理解的软件,而其他人也不能理解。即使是新手,尤其是新手,也能在几周内写出地球上没有人能轻易思考或推理的软件。这令人沮丧,但在某种程度上也令人印象深刻。强大的力量伴随着巨大的责任。

具有太多属性的对象是软件难以理解的主要原因。有人总结说,问题出在面向对象的编程本身。这不是一个疯狂的想法,还有其他的编程方法,它们确实有优势,但根据我的经验,大多数归因于面向对象编程的缺陷都源于做得不好,而男孩很容易做得不好。

要认识到的关键是具有许多属性的单个对象本身不是面向对象的。相反,它是变相的20世纪70年代风格的结构程序,对象的属性是程序的全局变量,对象的方法是程序的函数。每个函数都可以自由地访问每个全局变量,这就是导致许多问题的原因。

具有七个以上全局变量的结构化程序是麻烦的,如果程序中的许多对象本身实际上是杂乱无章的结构化程序,那么您确实有大麻烦了。在高层次上,您正在进行面向对象的编程,但是在低层次上,您又回到了20世纪70年代,努力处理一个又一个令人困惑的程序。

我们如何拯救这艘正在沉没的船?我们通过积极主动地将每个对象的属性数量保持在7个或更少来保存它。如果你做不到这一点,你就是在把问题推给你未来的自己,根据定义,你未来的自己将很难解决这个问题。

赛尔夫。名称=名称自我。Start_ns=start_ns自身。End_ns=end_ns自身。类别=类别本身。Process_id=process_id自身。Thread_id=线程id自身。Args=kwargs self。阶段=阶段。

这就是8个属性,既然8个属性只超过了1个极限,我们应该等到对象变大吗?不,我们现在就处理吧。为了减少属性的数量,我们引入了两个新的类或结构:span和Origin。每个对象只有两个属性,但是现在原来的对象已经缩小到六个属性,一切又都很好了:

赛尔夫。名称=名称自我。SPAN=SPAN(start_ns,end_ns)self。类别=类别本身。Origin=Origin(process_id,thread_id)self。Args=kwargs self。阶段=阶段。

虽然这是一个很小的改变,但比较两个版本,改进后的版本看起来更好,即使你站得很远,眯着眼睛也是如此。

这看似微不足道,但如果你不进行这些类型的改变,它最终会导致难以处理的复杂性,这种类型的复杂性会导致项目和公司失败,这种类型的复杂性会诱使人们每年浪费数十亿美元编写不起作用的软件。

引入子对象的好处远远不止是减少属性的数量。虽然访问属性有点混乱,但与self.start_ns相比,我更喜欢self.span.start_ns的声音,但更重要的是,我们现在可以将Span和Owner传递给函数,精简并分块它们的参数列表。

我们已经引入了两个自然而有用的概念,它们将带来持续的红利,但更好的是,不要只考虑您的代码现在是怎样的,而要考虑它将如何随着时间的推移而增长。你的单一的整体物体萌发了两个花蕾。现在,您可以将功能向下推入这些芽中,它们可以长成分支,稍后可以萌发自己的芽。

例如,我们现在可以给Span一个get_uration_ns()方法。同样,它看起来很小,但是编写span.get_uration_ns()比编写span.end_ns-span.start_ns要好,特别是如果您要在许多不同的地方这样做的话。

然而,真正的魔力在于,当你将你的整体物体转换成一棵结构复杂的树,它有机地发芽、发芽和分枝时,纪律严明的好处将会积累起来,就像复利一样。你将从这个更好的设计中获益,你在软件上工作的每一分钟都会让你受益,而软件也会从你改善的情绪和保持专注的能力中受益良多。

代码,就像大多数人类创造的艺术品一样,可以是美丽的,所以这里有麻醉的回报,但真正的大奖是,如果你勤奋地照料和梳理这棵树,你将创造一个软件设计,它会以最小的小题大做和摩擦进入你的大脑,并以类似的方式进入其他人的大脑。

我们发现自然环境比人造世界更舒适,比混凝土丛林更舒适,这不是偶然的。自然世界的设计往往更符合我们大脑对那个世界的看法。游戏认可游戏。

随着时间的推移,您将发展出一个您和其他人可以理解、维护、调试和扩展的系统。几年后,甚至在遥远的将来,当人们看到你的代码时,他们会从你的勤奋和努力中受益。笑点是,做这一切并不难。事实上,做这项工作比不做要容易得多。

与精心制作、与你的思维相容的东西一起工作会更容易、更令人愉悦。不断地与你不理解的东西搏斗是很难的,也是令人不愉快的。尽早地、经常地修剪、修剪和塑造你的头发。你的大脑会感谢你的。