Saleri

The Essence of Software.Chapter.01.我为何写这本书

最后一次修改于

本科在物理系就读时,我就被这样一个理念所深深吸引:世界可以用类似于 F = ma 这样简单的等式来概括。当我成为一名程序员,并在此后成为一名计算机科学研究员时,我被形式化方法(formal methods)领域所吸引,因为它承诺能为软件做类似的事情:用简洁的逻辑来表达其最本质的属性。

对设计的热情

自从获得博士学位以来的 30 年间,我主要的研究贡献是 Alloy,这是一种用于描述软件设计并对其进行自动分析的语言。对我而言,这是一段激动人心且令人满足的旅程,但随着时间的推移,我逐渐意识到,软件的本质并不在于任何逻辑或分析。真正让我着迷的并不是消耗了大多数形式化方法研究人员精力的那个问题——即如何检查一个程序的行为是否完全符合其规范——而是设计的问题。

我在这里所说的“设计”,与其他设计学科中使用该词的含义相同:塑造某种人工制品以满足人类的需求。正如建筑师克里斯托弗·亚历山大(Christopher Alexander)所言,设计关乎创造一种契合特定背景(context)形式(form)。对于软件而言,这意味着确定软件的行为应该是什么:它将提供哪些控制,以及作为回报它将提供哪些响应。这些问题没有非黑即白的答案,只有好坏之分。

我想知道,为什么有些软件产品看起来如此自然、优雅,只要掌握了基础操作,它们的反应就具有可预测性,并能让你以强大的方式组合它们的特性。同时,我也想明确为什么其他产品却显得不对劲:充斥着不必要的复杂性,并且行为表现出乎意料且前后不一。我坚信,一定有一些基本原则、某种软件设计理论,可以解释这一切。它不仅能解释为什么有些软件产品好而有些差,还能帮助你修复问题,甚至从一开始就避免这些问题。

计算机科学与其他领域中的设计

我开始四处探寻。在我自己的子领域(形式化方法、软件工程和编程语言)中,对于你可以称之为“内部设计”的东西——即代码结构的设计——是存在这样一种理论的。程序员拥有一套丰富的设计语言,以及区分好设计与坏设计的成熟标准。但是,对于面向用户的软件设计,即决定如何将软件作为处于特定背景下的形式来体验的设计,却不存在这样的语言或标准。

内部代码设计非常重要,并且主要影响着软件工程师所谓的“可维护性”,这意味着随着需求的发展,代码随着时间推移进行更改的难易程度。它也会影响性能和可靠性。但是,决定一个软件应用程序或系统是否实用并能满足其用户需求的关键决策却在别处,在于塑造功能以及与用户交互模式的那种软件设计之中。

这些大问题曾经在计算机科学中处于更核心的地位。在软件工程领域,它们出现在关于软件设计、规范和需求的研讨会上;在人机交互领域,它们渗透在图形用户界面和用户行为计算模型的早期工作中。

但随着时间的流逝,它们变得不再流行,并逐渐消退。软件工程的研究范畴变窄,消除缺陷——无论是通过测试,还是通过更复杂的手段(如程序验证)——成了软件质量的代名词。但是,这条路走不通:如果你的软件设计方向错了,无论消除多少缺陷都无法修复它,除非回到原点并修复设计本身。

人机交互(HCI)领域的研究则转向了新颖的交互技术、工具和框架、利基领域,以及其他学科(如民族志学和社会学)。软件工程和人机交互都热情地拥抱了经验主义,很大程度上是出于一种误导性的希望,即认为这会带来学术上的声望。相反,对具体的成功衡量标准的需求似乎引导研究人员转向了不那么雄心勃勃、更容易评估的项目,并阻碍了在更大、更重要的问题上取得进展。

令人费解的是,即使对设计的兴趣似乎已经减弱,关于“设计”的讨论却无处不在。实际上这并非矛盾。这些讨论几乎无一例外地都是关于设计的过程,无论是在“设计思维”(对迭代设计过程的一种引人注目的包装)的背景下,还是在“敏捷”软件开发的背景下。这些过程无疑是有价值的(只要明智地应用它们,而不是把它们当作灵丹妙药),但它们在很大程度上是缺乏实质内容的。我说这话不是为了贬低,而是为了描述。例如,设计思维可能会告诉你,在加深对问题理解的同时,同步开发解决方案,或者交替进行头脑风暴(“发散”)和删减(“收敛”)。但是我读过的任何一本关于设计思维的书中,都没有深入探讨过任何具体的设计,以及这些过程如何为其带来启发。设计思维恰恰因为独立于特定领域,可能是其广泛吸引力和适用性的关键——但这也是它对某个特定领域(如软件)中更深层次的设计挑战鲜有建树的原因。

设计中的清晰与简洁

当我开始 Alloy 项目时,目标是创造一种经得起自动分析的设计语言,我对现有的建模和规范语言持批评态度,因为它们缺乏工具支持,导致它们变成“只写(write-only)”的。这种带有讽刺意味的否定并非毫无根据。毕竟,如果你构建了一个精心设计的设计模型后却不能用它做任何事情,那你为什么要费这个劲呢?我特别强调,设计师的努力应该立刻得到“一键式自动化”的回报,它能即时以令人惊讶的场景形式给你反馈,从而促使你更深入地思考你的设计。

我认为我没有错,并且 Alloy 的自动化确实改变了设计建模的体验。但我低估了把设计写下来的价值。事实上,在形式化方法研究人员(他们渴望通过在现有设计中发现缺陷来证明其工具的有效性)之中,有一个并非防守得很严密的秘密:很大一部分缺陷在工具运行之前就被发现了!仅仅将设计转化为逻辑就足以揭示严重的问题。软件工程研究员迈克尔·杰克逊(Michael Jackson)认为,这不在于逻辑本身,而在于使用逻辑的难度,他还曾调皮地建议,如果只是要求设计师用拉丁文记录他们的设计,软件系统的质量可能会有所提高。

清晰度不仅有利于事后发现设计缺陷。它本身就是优秀设计的关键。在过去三十年教授编程和软件工程的过程中,我越来越确信,当你开发软件时,决定成败的关键并不是你是否使用了最新的编程语言和工具,也不是你遵循的管理流程(敏捷或其他),甚至也不是你如何构建代码结构。很简单,它仅仅在于你是否知道自己想要做什么。如果你的目标是清晰的,你的设计是清晰的——而且你的设计如何满足这些目标也是清晰的——那么你的代码往往也会变得清晰。如果出了问题,你也会清楚如何去修复它。

正是这种清晰度,将卓越的软件与其余的区分开来。1984年苹果 Macintosh 问世时,人们立刻就明白如何使用文件夹来整理文件;之前操作系统的复杂性(比如 Unix,在其中即便是将文件在文件夹间移动的命令也很复杂)似乎都烟消云散了。

但是,这种清晰度究竟是什么?它又是如何实现的?早在20世纪60年代,“概念模型(conceptual models)”的核心作用就已被认识到。挑战不仅仅在于将软件的概念模型传达给用户,以便其内部版本(“心智模型(mental model)”)与程序员的模型相一致,更在于将其本身作为一个独立的设计课题来对待。有了正确的概念模型,软件就容易被理解,从而也容易被使用。这是一个伟大的想法,但似乎没有人去深入探究,因此直到现在,“概念”仍然是一个模糊的,尽管鼓舞人心的概念。

这个项目是如何产生的

坚信概念模型确实是软件的本质之后,我大约在八年前开始试图弄清楚它们可能是什么。我想赋予它们具体的表达形式,以便我可以指出某些软件的概念模型,并将其与其他软件的概念模型(以及用户的心智模型)进行比较,从而在设计讨论中提供一个明确的焦点。

这看起来并不难。毕竟,对于概念模型的一种似是而非的初步尝试,可能仅仅是对软件行为的描述,经过适当的抽象,去除了附带的和“非概念性”的方面(例如物理用户界面的细节)。事实证明,更困难的是在模型中找到合适的结构。 我隐约觉得概念模型应该由“概念”组成,但我并不知道概念是什么。

例如,在 Facebook 这样的社交媒体应用中,我感觉应该有一个与点赞事物相关的概念。这个概念肯定不是一个函数或动作(比如绑定到你点击来赞一个帖子的按钮上的行为);这样的东西太多了,它们只说明了部分情况。它也肯定不是一个对象或实体(比如你的动作产生的“赞”本身),因为至少这个概念似乎是关于事物和它们的赞之间的关系。对我来说,关键还在于点赞的概念并不与任何特定种类的事物相关联:你可以赞帖子、评论、页面等等。用编程行话来说,这个概念是“泛型(generic)”或“多态(polymorphic)”的。

本书:开启一场对话

本书是我迄今为止探索的成果。在广泛使用的应用程序中的数十个设计问题的驱动下,我发展出了一种全新的软件设计方法,并在这一过程中对其进行了完善和测试。这个项目的一个令人高兴的方面是,每一次应用故障或挫折都有其一线希望:这是扩展我的案例库的机会。当我分析发现设计师所面临问题的全部复杂性时,它也让我对他们产生了更大的同情和尊重。

当然,软件设计的问题并没有被完全解决。但正如我的朋友 Kirsten Olson 曾明智地建议我的那样:一本书的目的应该是开启一场对话,而不是结束它。在就这个项目发表多次演讲的过程中,我兴奋地发现它似乎比我以前的任何演讲都更能引起听众的共鸣。我猜测这是因为软件设计是我们所有人都想谈论的话题,但我们一直不知道如何开展这场对话。

所以,致各位读者——也就是同行研究人员、设计师和用户们——我将这本书作为我的开局,希望能以此开启一场富有成效且令人愉快的对话。