如何避免程序员的大脑超载?
富含逻辑与计算的程序员职业,并非任何人都可以胜任,那么对于身处其中的开发者,该怎么做,才能减轻自己脑部的压力?作者 |Javier Casas Velasco译者 |弯月,责编 | 屠敏出品 | CSDN(ID:CSDNnews)以下为译文:心理学中有一篇古老但非常重要的论文《神奇的数字:7±2:我们信息加工能力的局限》(The Magical Number ...
富含逻辑与计算的程序员职业,并非任何人都可以胜任,那么对于身处其中的开发者,该怎么做,才能减轻自己脑部的压力?
作者 | Javier Casas Velasco
译者 | 弯月,责编 | 屠敏
出品 | CSDN(ID:CSDNnews)
以下为译文:
心理学中有一篇古老但非常重要的论文《神奇的数字:7±2:我们信息加工能力的局限》(The Magical Number Seven, Plus or Minus Two: Some Limits on Our Capacity for Processing Information)。作者对大脑处理信息的极限进行了定量研究:人脑可以同时处理5-9个概念。这其中有许多有趣的含义,但对于我们这些软件开发人员来说,有两个含义非常重要:
-
构造(模型、实现、设计、模式等等)越简单越好,因为你可以用更少的概念来描述它们。
-
良好的抽象自带的特殊规则越少越好,而且最好没有惊喜和意外,因为同样你只需用更少的概念来描述它们。
说到底,这是一场努力让占据大脑空间的概念趋近最少的战斗,因为大脑空间非常稀缺。
简单的构造
查尔斯·霍尔曾说:
构建一项软件设计有两种方式:一种是将软件设计得足够简单以至于明显找不到缺陷;另一种是软件设计得足够复杂以至于找不到明显的缺陷。
不幸的是,他还补充了一句:
第一种方法要困难得多。
在软件开发中,添加一个模块、一个类非常容易,代码也会越来越多。这固然可以解决大多数软件的需求,但需要的代码越来越多,获得的结果却越来越少。Jamie Zawinski曾说:
每个程序都会尝试扩展,直到能够阅读邮件。无法进行这种扩展的程序都将被它们所取代。
本质上,我们扩展程序是为了提供越来越多的功能。我们添加更多模块、更多类和更多的代码,而且添加的每一段代码都需要与之前的代码协同工作,故而随着各段代码之间的交互无限扩展,程序的复杂性也呈指数激增。我们这么做是因为这种做法很简单,至少在刚开始的时候很简单。
另一方面,制作尽可能简单的东西实际上非常困难。你需要寻找潜在的模式和行为,还需要去除不适合的东西。但是,最终这种方式制作的东西更好,因为你使用的概念较少,也无需浪费过多脑细胞就可以描述这些模式和行为,这意味着你可以专注于整体,而不必在意太多细节。
检测过于复杂的构造
实际上,检测过于复杂和臃肿的构造也并非难事。你只需查看一下手册。如果手册用大量文字描述了构造的上下文,则表示这个构造可能过于复杂。
让我们来看一个例子:AbstractFactory模式。为了描述该模式的工作方式,我们需要描述很多名称:
-
AbstractFactory:接口
-
<<creates>>:操作
-
Factory1(ConcreteFactory)
-
ProductA、ProductB:接口
-
ProductA1、ProductB1:类
-
new:关键字
-
抽象工厂类图
-
:Client、factory:Factory1:序列图
所有这些名称和图表之所以存在是因为制造复杂度比减少复杂度更容易。同时,它还会迫使程序员为创建这些对象而制定出过于特定化的解决方案,而忽略其他解决方案——例如重用存储在某处的对象等。实际上,我们可以降低复杂度:
-
从整个模式中删除“Factory”名称。
-
删除关键字new和<< creates >>操作。
现在,这个模式只有一个返回ProductA或ProductB实例的对象。它可以实例化类,从数据结构中获取预先构建的对象或从不明区域获得对象,这都无所谓,因为我们所关心的是开始的时候我们没有对象,结束的时候却有一个对象。现在,上述列表变成了:
-
两个操作:
-
第一个操作:通过接口ProductA获取对象
-
第二个操作:通过接口ProductB获取对象
你可以将操作放在一个类、一个结构或指针中,放在哪儿都行(甚至是你家客厅)。使用的时候,可以通过任何参数调用其中一个操作,然后它们会为你提供相应的对象。设置的时候,可以将第一个操作设置为生成ProductA的操作,将第二个操作设置为生成ProductB的操作。没有类图,没有序列图,没有额外的类,没有额外的词语。没有歧义,因为你可以执行的操作无非是调用它,将它作为参数传递,返回它并存储它。因为函数和操作只不过是带参数的值。那么如何通过ProductA接口获得对象呢?ProductA能返回怎样的对象呢?只能是第一个操作,因此你只能使用它。
构造良好的抽象能很好地组合
上述我们通过修改AbstractFactory描述了一个构造良好的抽象。构造良好的抽象能很好地组合,这句话包含两部分:
构造良好的抽象
AbstractFactory模式是一个糟糕的抽象,因为它暴露了我们不关心的细枝末节,例如它是抽象,它必须创建对象,以及它使用new关键字。作为用户,我们并不关心这些细节,但所有这些都出现在我眼前时,就必须处理。
相反,我只想要“一个操作,一个能够让我通过ProductA接口获取对象的操作。”我调用这个操作,而它则返回一个ProductA。我不知道,也不在乎它获取对象的过程。
很好地组合
AbstractFactory模式是一个糟糕的抽象(再说一次),因为它没有进行组合。它有两个对象:一个创建ProductA,另一个创建ProductB。为什么我必须把它们放在同一个Factory里?为什么我不能分开这两个操作?如果有人想合并在一起,则可以将它们放在同一个元组中。即便它们在同一个类中,也没有良好地组合。我该如何合并它们?如果我在某处需要ProductA的其他操作该怎么办?该操作是否需要了解AbstractFactory的错误链?
AbstractFactory myFactory = new Factory1();
ProductA myProduct = myFactory.createProductA();
AbstractFactory somethingDifferent = new SomethingDifferentFactory();
SomethingDifferent result = somethingDifferent.fabricate(myProduct);
return result
相反,如果我有“一个能够让我通过ProductA接口获取对象的操作”,以及另一个通过ProductA构造不同东西的操作,那么我就可以先调用第一个操作来获取ProductA,然后再调用第二个操作。类型定义如下:
-
operation : () -> ProductA
-
otherOperation: ProductA -> SomethingDifferent
因此,只需调用otherOperation(operation())即可。
检测良好的组合能力
不幸的是,我们很难检测良好组合能力的语义,因为我们这些开发人员习惯于那些没有组合能力的东西,我们不知道能够很好地组合的东西“长什么样子”。良好的组合能力很容易感觉到。感觉就像乐高积木,每一块都可以很轻松地与其他块拼凑起来,制作一个大型作品的过程也很简单:
我有一个三角形的凸起,看看哪里有三角形的孔。
如果你有良好的组合能力,就无需再使用适配器(或者你甚至无需命名适配器,因为它们都很简单)。如果你有良好的构造,则只需将各个部分连接起来就可以构成一个整体,而不必担心各个部分之间会以意想不到的方式相互作用。
总和即为各部分的求和,不多不少。
总结
在本文中,我们看到AbstractFactory违反了七大规则,它将一个简单的概念“获取ProductA”变成了:
一个Abstract的Factory,实现了createProductA 方法,该方法利用new来<<construct>>一个包含ProductA << interface >>的ProductA1。
这句话中包含了10个单词和概念,超出了大脑的处理极限。更糟糕的是,它过于刻板,因为它只允许创建对象,却不允许重用对象。
这就是编程工作困难重重的原因之一:因为我们自己给自己制造了困难。
原文:http://www.javiercasas.com/articles/rule-of-seven
【End】
国家承认的Python工程师有哪些能力要求?
5G进入元年,物联网发展愈加火爆!
你是否身怀绝技、却无人知晓;别让你的IoT项目再默默无闻了!
继第一届AI优秀案例评选活动之后,2019年案例评选活动再度升级,CSDN将评选出TOP 30优秀IoT案例,赶快扫码参与评选吧!重磅福利,等你来领!
热 文 推 荐
☞雷军:小米推动山寨机灭亡;苹果回应禁止第三方换电池;Javascript 引擎 V8 7.7 发布 | 极客头条
☞比特币勒索出新招,佳能单反被黑客攻破,白帽却利用一个漏洞赎回了照片,这波操作简直了……
点击阅读原文,输入关键词,即可搜索您想要的 CSDN 文章。
你点的每个“在看”,我都认真当成了喜欢
更多推荐
所有评论(0)