这是一本很散的书,记录和讨论了许多软件工程中会遇到的问题。作者对这些问题的本质进行了讨论,并且给出了自己认为的较好的处理方式。
至于为什么这本书的观点非常散乱,可以参考这本书后大半段的大量讨论:没有银弹
所以这篇读后感,主要就是一些摘抄和观点的总结,并且导向另一篇在看这本书中笔者对于整个国内互联网软件系统发展的思考。
摘抄
编程为什么有趣?作为回报,它的从业者期望得到什么样的快乐?首先是一种创建事物的纯粹快乐。如同小孩在玩泥巴时感到愉快一样,成年人喜欢创建事物,特别是自己进行设计。我想这种快乐是上帝创造世界的折射,一种呈现在每片独特、崭新的树叶和雪花上的喜悦1。其次,快乐来自于开发对其他人有用的东西。内心深处,我们期望其他人使用我们的劳动成果,并能对他们有所帮助。从这个方面,这同小孩用粘土为“爸爸办公室”捏制铅笔盒没有本质的区别。第三是整个过程体现出魔术般的力量——将相互啮合的零部件组装在一起,看到它们精妙地运行,得到预先所希望的结果。比起弹珠游戏或点唱机所具有的迷人魅力,程序化的计算机毫不逊色。第四是学习的乐趣,来自于这项工作的非重复特性。人们所面临的问题,在某个或其它方面总有些不同。因而解决问题的人可以从中学习新的事物:有时是实践上的,有时是理论上的,或者兼而有之。最后,乐趣还来自于工作在如此易于驾驭的介质上。程序员,就像诗人一样,几乎仅仅工作在单纯的思考中。程序员凭空地运用自己的想象,来建造自己的“城堡”。很少有这样的介质——创造的方式如此得灵活,如此得易于精炼和重建,如此得容易实现概念上的设想。(不过我们将会看到,容易驾驭的特性也有它自己的问题)
对于创造者,只有在实现的过程中,才能发现我们构思的不完整性和不一致性。
总之,在众多软件项目中,缺乏合理的时间进度是造成项目滞后的最主要原因,它比其他所有因素加起来的影响还要大。
软件经理很早就认识到优秀程序员和较差的程序员之间生产率的差异,但实际测量出的差异还是令我们所有的人吃惊。在他们的一个研究中,Sackman、Erikson和Grand曾对一组具有经验的程序人员进行测量。在该小组中,最好的和最差的表现在生产率上平均为10:1;在运行速度和空间上具有5:1的惊人差异!简言之,$20,000/年的程序员的生产率可能是$10,000/年程序员的10倍。数据显示经验和实际的表现没有相互联系(我怀疑这种现象是否普遍成立。)
对于效率和概念的完整性来说,最好由少数干练的人员来设计和开发,而对于大型系统,则需要大量的人手,以使产品能在时间上满足要求。如何调和这两方面的矛盾呢?
Mills建议大型项目的每一个部分由一个团队解决,但是该队伍以类似外科手术的方式组建,而并非一拥而上。
也就是说,同每个成员截取问题某个部分的做法相反,由一个人来进行问题的分解,其他人给予他所需要的支持,以提高效率和生产力。
要特别注意传统的两人队伍与外科医生——副手队伍架构之间的区别。首先,传统的团队将工作进行划分,每人负责一部分工作的设计和实现。在外科手术团队中,外科医生和副手都了解所有的设计和全部的代码。这节省了空间分配、磁盘访问等的劳动量,同时也确保了工作概念上的完整性。
第二,在传统的队伍中大家是平等的,出现观点的差异时,不可避免地需要讨论和进行相互的妥协和让步。由于工作和资源的分解,不同的意见会造成策略和接口上的不一致,例如谁的空间会被用作缓冲区,然而最终它们必须整合在一起。而在外科手术团队中,不存在利益的差别,观点的不一致由外科医生单方面来统一。这两种团队组建上的差异——对问题不进行分解和上下级的关系——使外科手术队伍可以达到客观的一致性。
另外,团队中剩余人员职能的专业化分工是高效的关键,它使成员之间采用非常简单的交流模式成为可能。
扩建过程的成功依赖于这样一个事实,即每个部分的概念完整性得到了彻底的提高——决定设计的人员是原来的七分之一或更少。所以,可以让200人去解决问题,而仅仅需要协调20个人,即那些“外科医生”的思路。对于协调的问题,还是需要使用分解的技术,这在后续的章节中会继续进行讨论。在这里,可以认为整个系统必须具备概念上的完整性,要有一个系统结构师从上至下地进行所有的设计。要使工作易于管理,必须清晰地划分体系结构设计和实现之间的界线,系统结构师必须一丝不苟地专注于体系结构。总的说来,上述的角色分工和技术是可行的,在实际工作中,具有非常高的效率。
如何得到概念的完整性? 这样的观点是否要有一位杰出的精英,或者说是结构设计师的贵族专制,和一群创造性天分和构思被压制的平民编程实现人员? 如何避免结构设计师产出无法实现、或者是代价高昂的技术规格说明,使大家陷入困境? 如何才能与实现人员就技术说明的琐碎细节充分沟通,以确保设计被正确地理解,并精确地整合到产品中?
对于给定级别的功能,能用最简洁和直接的方式来指明事情的系统是最好的。只有简洁(simplicity)是不够的,Mooers的TRAC语言和Algol 68用很多独特的基本概念达到了所需的简洁特性,但它们并不直白(straightforward)。要表达一件待完成的事情,常常需要对基本元素进行意料不到的复杂组合。而且,仅仅了解基本要素和组合规则还不够,还需要学习晦涩的用法,以及在实际工作中如何进行组合。简洁和直白来自概念的完整性。每个部分必须反映相同的原理、原则和一致的折衷机制。在语法上,每个部分应使用相同的技巧;在语义上,应具有同样的相似性。因此,易用性实际上需要设计的一致性和概念上的完整性。
因此,系统的结构师,如同建筑的结构师一样,是用户的代理人。结构师的工作,是运用专业技术知识来支持用户的真正利益,而不是维护销售人员所鼓吹的利益。
体系结构同实现必须仔细地区分开来。如同Blaauw所说的,“体系结构陈述的是发生了什么,而实现描述的是如何实现3。”他举了一个简单的例子——时钟。它的结构包括表面、指针和上发条的旋钮。当一个小孩知道了时钟的外表结构,他很容易从手表或者教堂上的时钟辨认时间。而时钟的实现,描述了表壳中的事物——很多种动力提供装置中的一种,以及众多控制精度方案的一种。
同样的划分方法也适用于编程系统。例如,美国的Fortran IV标准,是多种编译器所遵循的体系结构标准。该体系结构下有多种可能的实现:以文本为核心、以编译器为核心、快速编译和优化以及侧重语法的实现。相类似的,任何汇编语言和任务控制语言都允许有多种编译器或调度程序的实现。
手册不但要描述包括所有界面在内的用户可见的一切,它同时还要避免描述用户看不见的事物。后者是编程实现人员的工作范畴,而实现人员的设计和创造是不应该被限制的。体系结构设计人员必须为自己描述的任何特性准备一种实现方法,但是他不应该试图支配具体的实现过程。
周例会是每周半天的会议,由所有的结构师,加上硬件和软件实现人员代表和市场计划人员参与,由首席系统结构师主持。会议中,任何人可以提出问题和修改意见,但是建议书通常是以书面形式,在会议之前分发。新问题通常会被讨论一些时间。重点是创新,而不仅仅是结论。该小组试图发现解决问题的新方法,然后少数解决方案会被传递给一个和几个结构师,详细地记录到书面的变更建议说明书中。
随着实现的推进,无论规格说明已经多么精确,还是会出现无数结构理解和解释方面的问题。显然有很多问题需要文字澄清和解释,还有一些仅仅是因为理解不当。显然,对于存有疑问的实现人员,应鼓励他们打电话询问相应的结构师,而不是一边自行猜测一边工作,这是一项很基本的措施。他们还需要认识到的是,上述问题的答案必须是可以告知每个人的权威性结论。一种有用的机制是由结构师保存电话日志。日志中,他记录了每一个问题和相应的回答。每周,对若干结构师的日志进行合并,重新整理,并发布给用户和实现人员。这种机制很不正式,但非常快捷和易于理解。
这个故事在很多方面和不同层次都是非常深刻和富有教育意义的。让我们将它仅仅作为纯粹的工程项目,来看看有什么值得学习的教训。这个项目到底有多好的先决条件?他们是否有:1. 清晰的目标?是的,尽管幼稚得近乎不可能。而且,项目早在遇到这个基本的限制之前,就已经失败了。2. 人力?非常充足。3. 材料?在美索不达米亚有着丰富的泥土和柏油沥青。4. 足够的时间?没有任何时间限制的迹象。5. 足够的技术?是的,金字塔、锥形的结构本身就是稳定的,可以很好分散压力负载。对砖石建筑技术,人们有过深刻的研究。同样,项目远在达到技术限制之间,就已经失败了。那么,既然他们具备了所有的这些条件,为什么项目还会失败呢?他们还缺乏些什么?两个方面——交流,以及交流的结果——组织。他们无法相互交谈,从而无法合作。当合作无法进行时,工作陷入了停顿。通过史书的字里行间,我们推测交流的缺乏导致了争辩、沮丧和群体猜忌。很快,部落开始分裂——大家选择了孤立,而不是互相争吵。
产品负责人的角色是什么?他组建团队,划分工作及制订进度表。他要求,并一直要求必要的资源。这意味着他主要的工作是与团队外部,向上和水平地沟通。他建立团队内部的沟通和报告方式。最后,他确保进度目标的实现,根据环境的变化调整资源和团队的构架。
那么技术主管的角色是什么?他对设计进行构思,识别系统的子部分,指明从外部看上去的样子,勾画它的内部结构。他提供整个设计的一致性和概念完整性;他控制系统的复杂程度。当某个技术问题出现时,他提供问题的解决方案,或者根据需要调整系统设计。用Al Capp所喜欢的一句谚语,他是“攻坚小组中的独行侠”(inside-man at the skunk works.)。他的沟通交流在团队中是首要的。他的工作几乎完全是技术性的。
存在三种可能的关系,它们都在实践中得到了成功的应用。产品负责人和技术主管是同一个人。
技术主管作为总指挥,产品负责人充当其左右手。
产品负责人作为总指挥,技术主管充当其左右手。这种方法有一些困难。很难在技术主管不参与任何管理工作的同时,建立在技术决策上的权威。
实践是最好的老师。- PUBILIUS 实践是最好的老师,但是,如果不能从中学习,再多的实践也没有用。- 《可怜的理查年鉴》
当系统设计者认为对用户而言,常驻程序内存的形式比加法器、磁盘等更加有用时,他会将硬件实现中的一部分移到内存上。相反的,其他的做法是非常不负责任的。
该从整体上来进行评价。没有人可以在自始至终提倡更紧密的软硬件设计集成的同时,又仅仅就规模本身对软件系统提出批评。
由于规模是软件系统产品用户成本中如此大的一个组成部分,开发人员必须设置规模的目标,控制规模,考虑减小规模的方法,就像硬件开发人员会设立元器件数量目标,控制元器件的数量,想出一些减少零件的方法。同任何开销一样,规模本身不是坏事,但不必要的规模是不可取的。
慢慢的,他逐渐认识到这些文档的某些部分包含和表达了一些管理方面的工作。每份文档的准备工作是集中考虑,并使各种讨论意见明朗化的主要时刻。如果不这样,项目往往会处于无休止的混乱状态。文档的跟踪维护是项目监督和预警的机制。文档本身可以作为检查列表、状态控制,也可以作为汇报的数据基础。
Cosgrove主张把所有计划、里程碑、日程安排都当作是尝试性的,以方便进行变化。这似乎有些走极端——现在软件编程小组失败的主要原因是管理控制得太少,而不是太多。不过,他提出了一种卓越的见解。他观察到不愿意为设计书写文档的原因,不仅仅是由于惰性或者时间压力。相反,设计人员通常不愿意提交尝试性的设计决策,再为它们进行辩解。“通过设计文档化,设计人员将自己暴露在每个人的批评之下,他必须能够为他的每个结果进行辩护。如果团队架构因此受到任何形式的威胁,则没有任何东西会被文档化,除非架构是完全受到保护的。
只要能力允许,高层人员必须时刻做好技术和情感上的准备,以管理团队或者亲自参与开发工作。这是件工作量很大的任务,但显然很值得!
组建外科手术队伍式的软件开发团队,这整个观念是对上述问题的彻底冲击。其结果是当高级人才编程和开发时,不会感到自降身份。这种方法试图清除那些会剥夺创造性乐趣的社会障碍。
对于一个广泛使用的程序,其维护总成本通常是开发成本的40%或更多。令人吃惊的是,该成本受用户数目的严重影响。用户越多,所发现的错误也越多。
程序维护中的一个基本问题是——缺陷修复总会以(20-50)%的机率引入新的bug。所以整个过程是前进两步,后退一步。
作为引入新bug的一个后果,程序每条语句的维护需要的系统测试比其他编程要多。理论上,在每次修复之后,必须重新运行先前所有的测试用例,从而确保系统不会以更隐蔽的方式被破坏。实际情况中,回归测试必须接近上述理想状况,所以它的成本非常高。
系统软件开发是减少混乱度(减少熵)的过程,所以它本身是处于亚稳态的。软件维护是提高混乱度(增加熵)的过程,即使是最熟练的软件维护工作,也只是放缓了系统退化到非稳态的进程。
和古老的神话里一样,现代神话里也总有一些爱吹嘘的人:“我可以编写控制航空货运、拦截弹道导弹、管理银行账户、控制生产线的系统。”对这些人,回答很简单,“我也可以,任何人都可以,但是其他人成功了吗?”
上述方法所意味的详尽体系结构设计正是出于这个目的。Bell实验室安全监控系统项目的V.A.Vyssotsky提出,“关键的工作是产品定义。许许多多的失败完全源于那些产品未精确定义的地方。1”细
好的自顶向下设计从几个方面避免了bug。首先,清晰的结构和表达方式更容易对需求和模块功能进行精确的描述。其次,模块分割和模块独立性避免了系统级的bug。另外,细节的隐藏使结构上的缺陷更加容易识别。第四,设计在每个精化步骤的层次上是可以测试的,所以测试可以尽早开始,并且每个步骤的重点可以放在合适的级别上。
当遇到一些意想不到的问题时,按部就班的流程并不意味着步骤不能反过来,直到推翻顶层设计,重新开始整个过程。实际上,这种情况经常发生。至少,它让我们更加清楚在什么时候和为什么抛弃了某个臃肿的设计,并重新开始。一些糟糕的系统往往就是试图挽救一个基础很差的设计,而对它添加了很多表面装饰般的补丁。自顶向下的方法减少了这样的企图。
简言之,Wirth的流程将设计看成一系列精化步骤。开始是勾画出能得到主要结果的,但比较粗略的任务定义和大概的解决方案。然后,对该定义和方案进行细致的检查,以判断结果与期望之间的差距。同时,将上述步骤的解决方案,在更细的步骤中进行分解,每一项任务定义的精化变成了解决方案中算法的精化,后者还可能伴随着数据表达方式的精化。在这个过程中,当识别出解决方案或者数据的模块时,对这些模块的进一步细化可以和其他的工作独立,而模块的大小程度决定了程序的适用性和可变化的程度。Wirth主张在每个步骤中,尽可能使用级别较高的表达方法来表现概念和隐藏细节,除非有必要进行进一步的细化。
如同我们看到的,必须关心每一天的滞后,它们是大灾祸的基本组成元素。
一线经理的利益和老板的利益是内在冲突的。一线经理担心如果汇报了问题,老板会采取行动,这些行动会取代经理的作用,降低自己的威信,搞乱了其他计划。所以,只要项
目经理认为自己可以独立解决问题,他就不会告诉老板。
不过,当项目经理了解到老板收到项目报告之后不会惊慌,或者不会越俎代庖时,他就逐渐会提交真实的评估结果。
流程图是被吹捧得最过分的一种程序文档。事实上,很多程序甚至不需要流程图,很少有程序需要一页纸以上的流程图。流程图显示了程序的流程判断结构,它仅仅是程序结构的一个方面。当流程图绘制在一张图上时,它能非常优雅地显示程序的判断流向,但当它被分成几张时,也就是说需要采用经过编号的出口和连接符来进行拼装时,整体结构的概观就严重地被破坏了。
大家熟悉的软件项目具有一些人狼的特性(至少在非技术经理看来),常常看似简单明了的东西,却有可能变成一个落后进度、超出预算、存在大量缺陷的怪物。因此,我们听到了近乎绝望的寻求银弹的呼唤,寻求一种可以使软件成本像计算机硬件成本一样降低的尚方宝剑。
一个相互牵制关联的概念结构,是软件实体必不可少的部分,它包括:数据集合、数据条目之间的关系、算法、功能调用等等。这些要素本身是抽象的,体现在相同的概念构架中,可以存在不同的表现形式。尽管如此,它仍然是内容丰富和高度精确的。我认为软件开发中困难的部分是规格化、设计和测试这些概念上的结构,而不是对概念进行表达和对实现逼真程度进行验证。当然,我们还是会犯一些语法错误,但是和绝大多数系统中的概念错误相比,它们是微不足道的。
让我们来考虑现代软件系统中这些无法规避的内在特性:复杂度、一致性、可变性和不可见性。复杂度。规模上,软件实体可能比任何由人类创造的其他实体要复杂,因为没有任何两个软件部分是相同的(至少是在语句的级别)。如果有相同的情况,我们会把它们合并成供调用的子函数。在这个方面,软件系统与计算机、建筑或者汽车大不相同,后者往往存在着大量重复的部分。
一致性。并不是只有软件工程师才面对复杂问题。物理学家甚至在非常“基础”的级别上,面对异常复杂的事物。不过,物理学家坚信必定存在着某种通用原理,或者在夸克中,或者在统一场论中。爱因斯坦曾不断地重申自然界一定存在着简化的解释,因为上帝不是专横武断或反复无常的。软件工程师却无法从类似的信念中获得安慰,他必须控制的很多复杂度是随心所欲、毫无规则可言的,来自若干必须遵循的人为惯例和系统。它们随接口的不同而改变,随时间的推移而变化,而且,这些变化不是必需的,仅仅由于它们是不同的人——而非上帝——设计的结果。
可变性。软件实体经常会遭受到持续的变更压力。当然,建筑、汽车、计算机也是如此。不过,工业制造的产品在出厂之后不会经常地发生修改,它们会被后续模型所取代,或者必要更改会被整合到具有相同基本设计的后续产品系列。汽车的更改十分罕见,计算机的现场调整时有发生。然而,它们和软件的现场修改比起来,都要少很多。
日常生活中,建筑有可能发生变化,但众所周知,建筑修改的成本很高,从而打消了那些想提出修改的人的念头。
所有成功的软件都会发生变更。现实工作中,经常发生两种情况。当人们发现软件很有用时,会在原有应用范围的边界,或者在超越边界的情况下使用软件。功能扩展的压力主要来自那些喜欢基本功能,又对软件提出了很多新用法的用户们。其次,软件一定是在某种计算机硬件平台上开发,成功软件的生命期通常比当初的计算机硬件平台要长。即使不是更换计算机,则有可能是换新型号的磁盘、显示器或者打印机。软件必须与各种新生事物保持一致。简言之,软件产品扎根于文化的母体中,如各种应用、用户、自然及社会规律、计算机硬件等等。后者持续不断地变化着,这些变化无情地强迫着软件随之变化。
不可见性。软件是不可见的和无法可视化的。例如,几何抽象是强大的工具。建筑平面图能帮助建筑师和客户一起评估空间布局、进出的运输流量和各个角度的视觉效果。这样,矛盾变得突出,忽略的地方变得明显。同样,机械制图、化学分子模型尽管是抽象模型,但都起了相同的作用。总之,都可以通过几何抽象来捕获物理存在的几何特性。软件的客观存在不具有空间的形体特征。因此,没有已有的表达方式,就像陆地海洋有地图、硅片有膜片图、计算机有电路图一样。当我们试图用图形来描述软件结构时,我们发现它不仅仅包含一个,而是很多相互关联、重叠在一起的图形。这些图形可能描绘控制流程、数据流、依赖关系、时间序列、名字空间的相互关系等等。它们通常不是有较少层次的扁平结构。实际上,在上述结构上建立概念控制的一种方法是强制将关联分割,直到可以层次化一个或多个图形2。
它们的出现都消除了开发过程中的非本质困难,允许设计人员表达自己设计的内在特性,而不需要表达大量句法上的内容,这些内容并没有添加什么新的信息。对于抽象数据类型和层次化类型,它们都是解决了高级别的次要困难和允许采用较高层次的表现形式来表达设计。不过,这些提高仅仅能消除所有设计表达上的次要困难。软件的内在问题是设计的复杂度,上述方法并没有对它有任何的促进。除非我们现在的编程语言中,不必要的低层次类型说明占据了软件产品设计90%,面向对象编程才能带来数量级上的提高。对面向对象编程这颗“银弹”,我深表怀疑。
人工智能。很多人期望人工智能上的进展可以给软件生产率和质量带来数量级上的增长4,但我不这样认为。追究其原因,我们必须剖析“人工智能”意味着什么,以及它如何应用。Parnas澄清了术语上的混乱:现在有两种差异非常大的AI定义被广泛使用。AI-1:使用计算机来解决以前只能通过人类智慧解决的问题。AI-2:使用启发式和基于规则的特定编程技术。在这种方法中,对人类专家进行研究,判断他们解决方法的启发性思维或者经验法则⋯⋯。程序被设计成以人类解决问题的方式来运作。
例如,我觉得很难去发现图象识别技术能给编程开发实践带来什么样的差异。同样,语音识别也差不多——软件开发上的困难是决定说什么,而不是如何说。表达的简化仅仅能提供少量的促进作用。
更加基本的是,如同我们上面所争论的,软件非常难以可视化。即使用图形表达出了流程图、变量范围嵌套情况、变量交叉引用、数据流、层次化数据结构等等,也只是表达了某个方面,就像盲人摸象一样。如果我们把很多相关的视图叠加在所产生的图形上,那么很难再抽取出全局的总体视图。对VLSI芯片设计方法的类推是一种误导——芯片设计是对两维对象的层次设计,它的几何特性反映了它的本质特性,而软件系统不是这样。
程序验证不意味着零缺陷的程序。这里并没有什么魔术,数学验证仍然可能是有错误的。因此,尽管验证可能减少程序测试的工作量,但却不能省略程序测试。
更严肃地说,完美的程序验证只能建立满足技术说明的程序。这时,软件工作中最困难的部分已经接近完成,形成了完整和一致的说明。开发程序的一些必要工作实际上已经变成对技术规格说明进行测试。
因此,软件开发人员为客户所承担的最重要的职能是不断重复地抽取和细化产品的需求。事实上,客户不知道他们自己需要什么。他们通常不知道哪些问题是必须回答的。并且,连必须确定的问题细节常常根本不予考虑,甚至只是简单地回答——“开发一个类似于我们已有的手工处理过程的新软件系统”——实际上都过于简单。客户决不会仅仅要求这些。复杂的软件系统往往是活动的、变化的系统。活动的动态部分是很难想象的。
因此,现在的技术中最有希望的,并且解决了软件的根本而非次要问题的技术,是开发作为迭代需求过程的一部分——快速原型化系统的方法和工具。
软件系统的快速原型对重要的系统界面进行模拟,并演示待开发系统的主要功能。原型不必受到相同硬件速度、规模或者成本约束的限制。原型通常展示了应用程序的功能主线,但不处理任何如无效输入、退出清除等异常情况。原型的目的是明确实际的概念结构,从而客户可以测试一致性和可用性。
不过,我不认为我们可以用相同的方式取得下一次进步。低劣设计和良好设计之间的区别可能在于设计方法中的完善性,而良好设计和卓越设计之间的区别肯定不是如此。卓越设计来自卓越的设计人员。软件开发是一个创造性的过程。完备的方法学可以培养和释放创造性的思维,但它无法孕育或激发创造性的过程。
其中的差异并不小——就象萨列里和莫扎特。一个接一个的研究显示,非常卓越的设计者产生的成果更快、更小、更简单、更优雅,实现的代价更少。卓越和一般之间的差异接近于一个数量级。
就我的经验而言,在系统工作中所遇到的大多数困难是组织结构上的一些失误征兆。试图为这些现实建模,建立同等复杂的程序,实际上是隐藏,而不是解决这些杂乱无章的情况。
我曾作为物理学家接受过培训,因此倾向于用更简单的概念来描述“复杂”事物。现在你可能是正确的,我无法断定所有的复杂事物都容易用有序的规律表达⋯⋯同样的道理,你不能断定它们不能。⋯⋯昨天的复杂性是今天的规律。分子的无序性启迪了气体动力学理论和热力学的三大定律。现在,软件没有揭示类似的规律性原理,但是解释为什么没有的重担在你的身上。我不是迟钝和好辩的。我相信有一天软件的“复杂性”将以某种更高级的规律性概念来表达(就像物理学家的不变式)。我并没有着手于Lukasik提倡的更深层次的分析。作为一个学科,我们需要更广泛的信息理论,它能够量化静态结构的信息内容,就像针对交互流的香农信息论一样。这已经超越了我的能力。作为对Lukasik的简单回应,我认为系统复杂性是无数细节的函数,这些细节必须精确而且详细地说明——或者是借助某种通用规则,或者是逐一阐述,但决不仅仅是统计说明。仅靠若干人不相干的工作,是不大可能产生足够的一致性,能用通用规律进行精确描述。
过程的思考,当时写了一篇随笔: