==============================
复杂度
尽可能简单,但别简单过了头
==============================
触发了unix十几年混乱内战的几个核心东西,将在本章得以阐述。本章从已形成的unix实践和专业术语出
发,然后走得比本书剩下部分稍微更深入些,我们并不是简单地尝试给出这些问题的答案,因为根本没有
答案——我们希望你能在概念上有所收益,从而挖掘出自己的答案。
13.1 谈谈复杂度
13.1.1 复杂度的三个来源
对于简单性、复杂度和软件最佳规模的疑问,unix世界注入了极大的热情。unix程序员学到了一种世界观:简单即美即雅即善,而复杂即丑即怪即恶。unix程序员追求简单的激情,源自于注重实效的事实:复杂度就是成本。
复杂度定义初探:
程序员代码实现的角度:为了能够试图理解一个程序,从而建立其思维模型并调试该程序的困难程度。
用户角度:程序界面的复杂度,它与用户记忆负担成正比。
代码量是第三个度量标准。(更多行的代码意味着更多的bug,而调试常常是开发中最昂贵最耗时的部分)。
代码量、接口复杂度和实现复杂度是复杂度的三种表现形式,三种面孔。
用户界面,如果设计时首先考虑容易实现或代码规模,可能就会简单地将许多底层任务抛给用户。迫于保持代码库适度规模的压力,不得不使用极端晦涩复杂的实现技法,这往往会导致系统实现复杂度的层层叠加,成为无法调试的乱麻。(如用汇编)。如果项目设计者对实现复杂度特别敏感,则会更倾向于编写重复的、专用的代码,而不是复用性高的代码,从而导致代码庞大,难于维护。
13.1.2 接口复杂度和实现复杂度的折中
《lisp:好消息,坏消息以及如何大获全胜》(lisp: good news,bad news,and how to win big
)[Gabriel]。“差即是好”观点(The rise of worse is better)。
Gabriel的中心论点是关于实现和接口复杂度间的一个精准权衡,它正好是我们在本章中检视的分类。gabriel在更关注接口简单性的“MIT”哲学和更重视实现简单性的“new jersey”哲学之间进行了比较,然后提出,尽管MIT哲学能够引导软件在抽象上做到更好,但new jersey模型(差者)更具传播特质。随着时间的推移,我们更多的注意力都集中到了new jersey风格,所以它提高得更快。差的变成了好的。 实际上,MIT和New Jersey哲学同unix设计传统自身冲突有的趋势有些相像。unix思想中的一个主
题是强调工具小巧锐利,设计从零开始,接口简单一致。这种观点最著名的支持者是Doug Mcllroy.另一种思潮则强调创作简单的可工作实现,然后快速发布,方法笨无所谓,边界情况不妨搁置。Ken Thompson的代码和他关于编程的信条常有这种倾向。
一个garbiel文章中没有提到的划时代实例来自于分布式超文本系统。早期的分布式超文本工程,诸如NLS和Xanadu,严重局限于MIT哲学的假定:无被指物的链接在用户界面上是一个不可接受的障碍;这就限制了系统要么只能在一个受控制的闭集文档中浏览(例如在单个CD-ROM上),要么必须实现各种日益复杂的复制,缓存,索引方法来防止文档的随机丢失。tim berners-Lee转而用经典的new jersey方法解决了这个疑难杂症。他所采用的简单实现就是允许“404:not found”可以作为一个响应,这就使得万维网非常轻便,并获得了广泛的传播和巨大的成功。
Gabreil自己尽管坚持“坏的”更具感染性而往往能取得最后胜利,但关于其潜在 复杂度的是否确实是一件好事,他已经数次公开地改变了意见。他的不确定性恰好反映了许多在unix社区中正在进行的设计争论。
我们并不能提供一个放之四海而皆准的答案。对于本章大多数的问题,良好品味和工程判断力要求,情况不同,则答案不同。重要的是要培养斟酌每一个设计的习惯。正如我们在讨论软件模块性之前的建议一样,复杂度的算盘必须打好。
13.1.3 本质的、选择的和偶然的复杂度
在理想世界,unix程序员只愿意手工打造小巧完美的软件宝石,每个都那么小巧、那么优雅、那么完美。然而现实很不幸的是,太多复杂问题需要复杂的解决方案。仅仅十行的程序,再优雅也无法控制喷气客机。那儿有太多的装备、太多的通路和界面,太多不同的处理机——太多不同操作人员定义的子系统,他们甚至连基本的约定都无法统一。即使能够成功地将航空控制所有的个体软件部分做得优雅,但拼装结果很可能是一堆庞大、复杂、糟糕的代码,当然也有个优点,就是确实能够工作。
喷气客机的复杂是必然的。过去有个相当尖锐的观点,不能为简单性而牺牲掉功能,因为飞机必须要能飞。正是这个事实,航空控制系统并不会产生关于复杂度的圣战——unix程序员往往敬而远之。
偶然复杂度:可以由良好的设计或重新设计来去除;
选择复杂度:只能由改变工程的目标去除。
当无法区分选择和偶然复杂度时,设计争论就会变得异常混乱。“什么是工程目标”的夹杂着简单即美的问题,也会牵扯到人们是不是足够聪明。
13.1.4 映射复杂度