【AICon】探索八个行业创新案例,教你在教育、金融、医疗、法律等领域实践大模型技术! >>> 了解详情
写点什么

多数程序员难以用简单的方式开发应用?

  • 2019-08-22
  • 本文字数:2825 字

    阅读完需:约 9 分钟

多数程序员难以用简单的方式开发应用?

心理学中有一篇相当古老、但又非常重要的论文,题为《魔法数字七(上下浮动二):人类信息处理能力中的一些限制》。这篇文章衡量了大脑处理信息的极限,并给出了一个具体的数字:人脑可以同时容纳五到九个概念。我们当然能够把这个有趣的结论延伸到诸多领域当中,但对软件开发人员而言,下面两项含义最为重要:


  • 构造(模型、实现、设计、模式等……)越简单越好,因为其概念更易于描述。

  • 构造良好且组合良好的抽象,应该具有较少的特殊规则与意外情况,同样是因为其概念更易于描述。



总而言之,这是一场以降低概念描述难度为目标的心理战,夺取的是珍贵的心理容纳空间。

简单构造

正如英国计算机专家 Hoare 所言:软件设计构建有两种方法,一是使其尽可能简单,从而一目了然确定其中不存在缺陷;另一种方法则是使其极为复杂,以至于看不出什么明显的缺陷。


遗憾的是,他还补充道:第一种方法其实要困难得多。


在软件开发当中,添加新的模块、新的类以及越来越多的代码是件很简单的事。这能够解决软件需要面对的更多用例,但更大的代码量所产出的结果却越来越少。正如 Jamie Zawinski 所说:每一个程序都会不断扩展,一直扩展到像人一样会收邮件、看邮件。而那些无法扩展的程序,最终会被能够扩展的程序所取代。


从本质上讲,我们一直在不断扩展程序。我们向其中添加更多模块、更多类以及更多代码,而且对于每一段代码,我们都需要确保其能够与原有代码顺畅协作,从而在这个复杂性呈指数增长的过程中继续保持进一步扩展的空间。之所以会这样作,是因为增量总是更简单的——至少在起步阶段更简单。


在另一方面,越是简单的东西开发起来就越困难。这要求开发人员考虑潜在的模式与行为,并消除一切不必要的元素。但最终,这样的思维方式能够成就更出色的成果,因为我们只需要使用极少的概念与精力,就可以描述并理解程序,确保大家专注于更多宏观目标、而非细枝末节。

检测过于复杂的构造

实际上,发现这类复杂而臃肿的构造并不困难。我们看看程序手册就能知道个大概,如果其中有专门的章节来描述结构背景之下的众多词汇,基本可以断定程序复杂度已经失控。


下面来看一个例子,即 Abstract Factory(抽象工厂)模式。为了描述其工作原理,我们需要定义很多名称:


  • AbstractFactory 接口

  • <<creates>>活动

  • Factory1(或者 ConcreteFactory)

  • ProductA 以及 ProductBinterfaces

  • ProductA1 以及 ProductB1classes

  • new 关键字

  • Abstract Factory 类图

  • :Client 以及 factory:Factory1 序列图


之所以存在这么多名称与图类,是因为复杂性比简单性更易于实现。这也迫使程序员采用针对性过强的对象创建方式,而无法选择复用存储在某处的对象等其它可能的解决方案。通过以下方式,我们尝试降低其整体复杂性:


  • 从整体模式当中删除“Factory”名称。

  • 删除 new 关键字以及 <<creates>>活动。


现在,该模式只关注能够返回 ProductA 或者 ProductB 实例的对象。它可以对该类进行实例化、从数据结构中获取预先构建的对象,或者从某处提取该对象——具体方法无穷无尽,但这些都不重要;真正重要的是我们的目标:开始时没有对象,结束时有了对象。现在再来看名称列表,两项操作:


  • 第一项,利用接口 ProductA 获取一个对象。

  • 第二项,利用接口 ProductB 获取一个对象。


这样,我们可以自由地将该操作放在某个类、某个结构或者是某个指针当中。在使用时,我们只需要配合必要的参数对该操作进行调用,它就会为我们提供相应的对象。


在设置中,我们可以将第一项操作设置为任何能够生成 ProductA 的形式,并将第二项操作设置为任何能够生成 ProductB 的形式。没有类图、没有序列图、没有额外的类、没有不必要的字,也没有歧义——因为我们能够对某项操作做的只有调用,将其作为参数进行传递,获取返回结果并加以存储。毕竟函数与操作在本质上就是带有参数的值。我们要如何利用接口 ProductA 获取某个对象?如何才能返回一个 ProductA?答案很简单:使用第一项操作。

构造良好的抽象

我们已经在 Abstract Factory 的修正版中描述了拥有良好构造的抽象结构。


构造良好的抽象


AbstractFactory 模式显然不是什么好抽象,因为它包含一切开发者不关心、也没必要关心的繁琐细节——例如属于抽象、必须创建对象,以及使用 new 关键字等。作为用户,我并不关心这么多细节,但这些细节就在眼前,想躲都躲不开。


相反,我只希望拥有“一项能够利用 ProductA 接口为获取对象的操作。”我只需要进行调用,它就能返回 ProductA 的结果。至于具体获取方式,我不知道、也不在乎。

组合良好的抽象

AbstractFactory 模式不是什么好抽象,因为它没有得到良好组合。看看它用到的两种方法:其一是创建 ProductA;其二是创建 ProductB。为什么要把它们放在同一个 Factory 当中?为什么不能把这两项操作分开,并让希望将二者一同使用的用户将其放进同一个元组中?A 和 B 在同一个类中,绝对不是什么良好的构造方式。我该如何组合?如果其它地方也有需要使用 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”这样一个简单的概念:一个 Factory 即为一个 Abstract,其通过 createProductA 方法利用 new 以 <<construct>>一个拥有 ProductA <<interface>>的 ProductA1。


这里单是关键字与概念就多达 10 个,超出了最聪明的大脑所能轻松处理的极限。更糟糕的是,由于太过刻板,我们只能使用这项操作创建对象、而无法复用对象。这也是编程为何如此困难的原因之一:我们毫无意义地抬高了它的难度。


原文链接:


http://www.javiercasas.com/articles/rule-of-seven


2019-08-22 13:5819449

评论 1 条评论

发布
暂无评论
发现更多内容

Sentinel源码改造,实现Nacos双向通信!

王磊

Java

小巧高效的音频录制 Piezo 最新激活版

胖墩儿不胖y

Mac软件 音频处理器 音频录制

QSpace Pro for Mac(多窗文件管理器)

展初云

文件管理 Mac软件

玩转MaxCompute SQL训练营! 数据分析挖掘迅速出师

阿里云大数据AI技术

大数据 数据分析

以烟草行业为例,聊聊如何基于 PLC + OPC + TDengine,快速搭建工业生产监测系统

TDengine

tdengine 时序数据库

PaddleX解决分类、检测两大场景问题?实战精讲教程来了!

飞桨PaddlePaddle

AI 飞桨 套件

Servlet、HTTP详细解释!

百度搜索:蓝易云

Java Linux Web HTTP Servlet

Youtrack Linux 安装

HoneyMoose

LAS Spark+云原生:数据分析全新解决方案

字节跳动数据平台

数据库 大数据 数据中台 数据研发 企业号10月PK榜

新晋技术管理者如何推动组织变革?

LigaAI

团队管理 研发管理 进阶 技术管理 企业号10月PK榜

英语学习工具:Eudic欧路词典 for Mac增强版

展初云

Mac 欧路词典 英语学习工具

使用流量管理工具保护 Kubernetes 的六种方法

NGINX开源社区

Kubernetes DOS攻击 Web应用防火墙 原生云

iPhone手机维护推荐 PhoneRescue for iOS 最新中文激活

mac大玩家j

Mac软件 手机助手

李彦宏:我们即将进入一个AI原生的时代|百度世界2023

飞桨PaddlePaddle

百度 大模型 文心一言

原料所属权管理领先实践,助力造币厂来料加工原料管理降本增效

用友BIP

领先实践 原料所属权管理

2024北京国际物联网展览会(物联网展)

AIOTE智博会

物联网展览会 物联网展会 物联网博览会 物联网展 世亚智博会

图文结合丨Prometheus+Grafana+GreatSQL性能监控系统搭建指南(下)

GreatSQL

greatsql

Linux之进程掩码umask详解。

百度搜索:蓝易云

云计算 Linux 运维 云服务器 umask

DevOps2023现状报告|注重文化、以用户为中心是成功的关键

SEAL安全

人工智能 DevOps DORA 企业号10月PK榜 技术报告

百度世界大会2023重磅发布进行时,小度全新智能音箱重构家居美学新乐章

新消费日报

小程序技术在信创操作系统里的应用趋势

没有用户名丶

商用显示设备包括哪些?

Dylan

企业 设备 显示器 LED显示屏

全面解析内存泄漏检测与修复技术

华为云开发者联盟

程序员 开发 内存 华为云 华为云开发者联盟

代码的艺术 - Writing Code Like a Pianist | 京东云技术团队

京东科技开发者

代码质量 整洁代码 企业号10月PK榜 系统质量

校源行 | 开放原子开源社团(西北工业大学)授牌仪式成功举行

开放原子开源基金会

List.of() Vs Arrays.asList()

越长大越悲伤

Java

用友 Fast by BIP引领专业技术服务企业快速迈向数智化创新

用友BIP

Fast by BIP

SoundSource for mac(音量控制工具)

展初云

Mac软件 音量调节

使用 ChaosBlade 验证 DLRover 的弹性和容错的稳定性

AI Infra

人工智能 开源 开发者 云原生 大模型

我与极客时间的故事

穿过生命散发芬芳

我和极客时间的故事

如何从构建到运营?数科公司数智创新研讨会成功举办

用友BIP

数科公司

多数程序员难以用简单的方式开发应用?_语言 & 开发_Javier Casas_InfoQ精选文章