透过文学经典理解软件设计的抽象思想

简介: 透过文学经典理解软件设计的抽象思想

博尔赫斯(Jorge Luis Borges)有一篇奇文,曰《博闻强记的富内斯》,以纪实手法杜撰了一个具有非凡记忆能力的传奇人物富内斯。博尔赫斯自云:“(《博闻强记的富内斯》)是长夜失眠的隐喻。”博尔赫斯大约是文学大师中最擅长使用隐喻的人了。他在诺顿讲座的演讲中,专门做了一次题为“隐喻”的演讲。极限编程的创始人Kent Beck非常推崇“隐喻”,并将其作为Spike阶段理解架构的重要手段,也是XP敏捷实践之一。


我在读一些文学作品时,常产生对软件设计思想的遐想。这或许可以称之为“比较学”,但我认为可以说是“隐喻”。

回到这篇奇文。博尔赫斯用诗的语言向我们描述了抽象与具象。他写道:

我们能够充分直感的形象是黑板上的一个圆圈、一个直角三角形、一个菱形;伊雷內奥却能直感马匹飞扬的鬃毛、山岗上牲口的后腿直立、千变万化的火焰和无数的灰烬,以及长时间守灵时死者的种种面貌。

伊雷內奥即富内斯,他的超凡记忆力在19岁被马摔下地的时候被神奇的触发。他能记住他之所观、所听、所感的任何一刻纷繁复杂的细节,“非但记得每一座山林中每一株树的每一片叶子,而且还记得每次看到或回想到它时的形状。”然而,富内斯却不具备抽象的能力——“富内斯几乎不会进行一般的、纯理论的思维。他非但难以理解‘狗’这个共性符号包括不同大小、不同形状的许许多多、各色各样的个别的狗;麻烦的是,从侧面看的编号为3-14的狗,名称会和从正面看的编号为3-14的狗一样。”

所以博尔赫斯说:“思维是忘却差异,是归纳,是抽象化。在富内斯的满坑满谷的世界里有的只是伸手可及的细节。”

富内斯可以是一个好的记忆者,他可以用极短的时间学会世间任何一门语言,我想,程序语言自然也不例外,所以他若从事编码工作,一定是一个不错的高效程序员;但是,他却不一定是一个好的软件设计者。Dijkstra就指出:“抽象来自于对真实世界中特定对象、场景或处理的相似性的认知,并决定关注这些相似性而忽略不同之处。”这里所谓的“决定”就是设计时的一种判断,且需要具备抽象的能力去支撑。富内斯显然做不到这一点。

抽象是一种归纳的能力,是一种识别共同特征的能力。抹掉细节,只辨其共同之处,并将其归纳为一个抽象的名词,这是设计者需要具备的。不如此,则不能化繁为简;不如此,则不能应对变化。我们很难成为博闻强记的富内斯,这就意味着当我们面对太多如枝头纷繁堆叠的叶子一般的细节时,我们不可能都能记住它们的样子。从面向对象的角度来讲,远处山林中每一株树都是一个对象实例,但我们可以以抽象的Tree名之。树上生长的每一片叶子都是一个对象实例,但我们可以以抽象的Leaf名之。

在软件设计中,抽象除了是对共同特征的概括之外,还应该是对对象边界的一种控制与分离,即通过抽象将对象分离为“外部视图”与“内部视图”。Abelson与Sussman将抽象的这种能力称之为抽象壁垒。这是用更加强烈的语气强调了“边界的意义”。

在我曾经负责设计的SaaS产品中,需要根据元数据生成报表。报表的所有元素最终需要导出到Excel与Html网页上。我借用了“绘制”的隐喻来表示导出功能,因而Excel的Sheet与Html的Page都可以视为“画布”。基于这么一个隐喻,我提炼出与导出相关的报表元素的共同特征,即针对“画布”而言,它们都是一种“绘制元素”。于是,我得到了两个抽象概念:DrawingElementReportCanvas

public interface DrawingElement {
    public void draw(ReportCanvas canvas);
    public object getElement();
}
public interface ReportCanvas {
    public void addElement(DrawingElement element);
}

DrawingElementdraw()方法负责将绘图元素绘制到ReportCanvas对象中。这种抽象提供了导出功能的外部视图,它隐藏了具体的实现细节,使得该功能是可扩展的。

抽象的方向有二:自上而下又或自下而上。

在进行自上而下的抽象时,我们往往需要遵循一些范式、模式乃至设计风格。例如针对业务模型,我们可以参考Martin Fowler的《分析模式》,直接套用该模式定义的模型对整个设计进行指导。又例如说针对一连串的数据流处理,我们可以参考Pipe-Filter模式,抽象出可以组合和扩展的filter。在自上而下抽象的过程中,偶尔需要设计者利用“隐喻”来给出一个形象而恰当的抽象概念。例如在Facebook的FBML架构中,就引入了“flavor(风味)”来形容不同上下文对输入的约束。

当面对未知领域时,又或者我们无法寻找到已有模式(范式)去follow时,我们就需要自下而上的抽象能力。这个过程就好像整理一堆打散了的扑克牌一样,我们要按照花色分类,然后再按照数值进行排序。扑克牌的花色就是抽象过程中要寻找的“共同特征”,扑克牌的数值以及排序过程则是需要封装的细节。例如在报表处理的上下文中,我们分辨出填充参数的多种实现方式,进而提炼出ParameterFilling这个抽象行为;在租赁系统上下文中,我们分辨出可以租赁的各式物品,进而提炼出Rentable这个抽象特征。

请注意,分类与识别共同特征都属于一种抽象。前者获得的是is-a的关系,后者获得的是can-do或have的关系。无所谓优劣,抽象关系的选择取决于具体的场景。

博尔赫斯杜撰的富内斯能够过目不忘地背诵冗长晦涩的拉丁文《自然史》,超凡的记忆力让他可以拥有海量的知识,但他的思维方式仍然停留在留声机的初级阶段。他记住了知识,却不能有效地运用知识,因为他无法归纳、无法推演、无法演绎,换言之,他缺乏的是提炼知识的抽象能力。

本文链接: http://zhangyi.xyz/thinking-pattern-after-reading-borges/

相关文章
|
3月前
|
算法 Java 程序员
在Java的编程世界里,多态不仅仅是一种代码层面的技术,它是思想的碰撞,是程序员对现实世界复杂性的抽象映射,是对软件设计哲学的深刻领悟。
在Java的编程世界里,多态不仅仅是一种代码层面的技术,它是思想的碰撞,是程序员对现实世界复杂性的抽象映射,是对软件设计哲学的深刻领悟。
68 9
|
6月前
|
存储 Java 编译器
用王者荣耀告诉你,什么叫类与对象,思维图+核心+架构让你一步到位
用王者荣耀告诉你,什么叫类与对象,思维图+核心+架构让你一步到位
|
6月前
|
存储 安全 算法
【软件设计师备考 专题 】软件设计的艺术:分析与集成、逐步求精、抽象、信息隐蔽
【软件设计师备考 专题 】软件设计的艺术:分析与集成、逐步求精、抽象、信息隐蔽
113 0
|
前端开发 JavaScript Java
|
存储 数据管理 人机交互
【软工视频】第九章面向对象技术
【软工视频】第九章面向对象技术
|
设计模式 JavaScript 前端开发
从浅入深学习中介者模式
在软件开发中,设计模式是一种用于解决常见问题的重要工具。其中,Mediator(中介者)/Middleware(中间件)设计模式在处理多个组件之间的通信和协调时非常有用。本文将从浅入深地介绍Mediator/Middleware模式,包括其定义、用途以及如何使用JavaScript实现它。
106 0
|
人工智能 算法 安全
8种提升程序猿编程能力的方法+编程思维四个核心:分解、抽象、模式识别和算法
对于程序员来说,提高自己的编程能力,算是给自己定的职业发展目标之一,不过定一个成为编程大神的目标很容易,具体做起来可能就不是一件简单的事了。首先,既然决定“我要变得更好”,得先知道“更好”是什么样子的。另外,不能“想变得更好”,却没有任何具体可行的措施。
920 2
8种提升程序猿编程能力的方法+编程思维四个核心:分解、抽象、模式识别和算法
|
算法 安全 架构师
软件编程概念与入门
软件编程概念与入门 1.概要 2 项目开发流程 3.编程提升
|
开发工具
软件设计体系 实验一 经典软件体系结构风格
软件设计体系 实验一 经典软件体系结构风格
|
存储 SQL 架构师
软件架构可能不是你想象的那个样子
作为一门学科,软件架构需要做出彻底的改变。人们对它的看法受制于很多关于它需要解决什么问题以及它应该如何去解决这些问题的旧观念。
148 0
软件架构可能不是你想象的那个样子