软件固有的复杂性

定义软件的复杂性

工业级软件的特征是,单个开发者要理解其设计的所有方面非常困难,几乎是不可能的。武断地说,这些系统的复杂性超出了人类智能的范围。不幸的是,我们所说的这种复杂性似乎是所有大型软件系统的基本特征。从根本上来说,我们可以掌握这种复杂性,但不能消除这种复杂性。

软件开发团队的任务就是制造简单的假象

软件的复杂性是一个基本特征,而不是偶然如此

这种固有的复杂性有4个原因:

  • 问题域的复杂性
  • 管理开发过程的困难性
  • 软件中随处可见的灵活性
  • 刻画离散系统行为的问题

问题域的复杂性

我们在软件中试图解决的问题常常涉及不可避免地复杂性,在其中我们可以发现数不清的竞争性需求,甚至是相反的需求。系统的基本功能已经很难理解了,现在还要加上所有的(常常是隐含的)非功能需求,如可用性、性能、成本、健壮性和可靠性。这种无限制的外部复杂性是导致任意复杂的原因之一。

管理开发过程的困难性

就在几十年前,只有几千行的汇编程序就已经是软件工程能力的极限了,但在今天,常常看到交付系统的代码规模达到几十万甚至几百万行。没有哪一个人能完全理解这样一个系统。所以这就需要启用团队,有更多的开发人员就意味着更复杂的沟通,因此更难以协调,特别是当开发团队在地理上是分散的时候。

软件中随处可见的灵活性

一家造房屋的公司通常不会自己经验林场,砍伐树木以获取原木。我们也很少看见一家建筑公司建造一个现场的钢铁厂,为新的建筑提供定制的大梁,但在软件行业,这种情况却经常发生。软件提供了非常大的灵活性,所以开发者几乎有可能表达任何形式的抽象。但是,这种灵活性变成了一种难以置信的诱人的属性,因为它也迫使开发者打造几乎所有的初级构建模块,高层的抽象将建立在这些初级构建模块之上。建筑行业读原材料的品质有着统一的编码和标准,但软件行业却很少有这种标准。

刻画离散系统行为的问题

如果向空中抛出一个球,我们肯定可以预测出它的路径,因为我们知道在正常情况下,某些物理定律会起作用。如果因为我们在抛球时用的力大了一些,结果它就在飞行到一半的时候突然停下来,然后直接往上冲,那么我们将会感到非常惊奇。但是在一个调试得不太好的模拟球的运动的软件中,类似这样的行为却很容易发生。

在大型应用中,可能有成百上千个变量以及多个控制线程。系统中的这些变量、它们当前的植、当前的地址和每个过程的调用栈一起构成了应用当前的状态。因为我们是在数字计算机上执行软件,所以我们的系统具有离散的状态。与此形成对比的是,像抛球运动这样的模拟系统是连续的系统。“当我们说系统是由连续函数描述的时候,我们是说它不会包含任何隐含的惊奇。输入中的小变化总是会导致输出中相应的小变化”。但对于软件系统来说,系统之外的任何一个事件都有可能让系统进入一个全新的状态,而且,状态与状态之间的转换关系并非总是确定的。当然,这是对系统进行大量测试的主要原因。