目录

  1. 关注点分离
  2. 模块化
  3. 抽象
  4. 拥抱变化(Anticipation of Change)
  5. 普适性
  6. 增量软件开发
  7. 一致性
  8. 附录

本文是一篇翻译文章,阐述究竟什么是软件功工程原理

关注点分离

关注点分离是对人类在有限环境中工作的必要性的认识,有研究表明:人类的思维仅限于一次处理大约七个单位的数据,其中一个单元是一个人已经学会将某一个抽象事物或者相关概念作为一个整体来处理的东西。尽管人类抽象的能力是无限的,但抽象成为有用的工具需要大量的时间

指定数据结构时,通常关注两个问题:数据结构的基本功能是什么和数据结构专门处理什么数据。如果将这两个关注点尽可能分离,这种数据结构通常更易于使用,因为,客户可以分别处理这两个问题。此外,算法描述和实现文档的分离,也能够获得较大的益处,例如:将基本算法的数据完整性处理和异常处理分开,能够清楚明白算法的功能。

另一个原因也阐述了分离关注点的重要性。软件工程师在尝试优化产品质量时必须处理复杂的值。从算法复杂性的研究中,我们学到重要的一课:优化单个可测量的问题可以找到有效算法,但优化组合量的问题几乎总是 NP 完全的。尽管这不是一个已证实的事实,但大多数复杂性理论专家认为,NP 完全问题无法通过在多项式时间内运行的算法来解决。

鉴于此,分开处理不同的值是有意义的。这可以通过在软件开发过程中的不同时间处理不同的值来完成,或者通过巧妙的设计以便将不同的实现分配给不同的组件来完成。

例如,运行时效率经常与其他软件指标表现出不一致的现象。出于这个原因,大多数软件工程师建议:将效率作为一个单独的问题来处理。在软件满足其他标准后,可以再检查和分析它的运行时间,看看大部分时间花在了哪里。如有必要,可以修改使用大部分运行时的代码部分以减少运行时。

模块化

模块化原则是关注点分离原则的一种特殊实现。遵循模块化原则意味着根据功能和责任将软件分成组件。Parnas 写了一篇最早的论文,讨论了模块化所涉及的考虑因素。最近的一项工作 [ WWW90 ] 描述了一种责任驱动的方法,用于在面向对象的上下文中进行模块化。

抽象

抽象原则是关注点分离原则的另一种特殊实现。遵循抽象原则意味着将软件的行为与其实现分开。它表示从两个角度来看待软件和软件组件:它做了什么,以及它是如何做的
未能将行为与实现分开是耦合的常见原因。例如,递归算法中通常会引入额外的参数来进行递归的工作。完成此操作后,应通过非递归外壳调用递归,该外壳为额外参数提供适当的初始值。否则,调用者必须处理需要指定额外参数的更复杂的行为。如果随后将实现转换为非递归算法,则还需要更改原油代码。

契约式设计是处理抽象的重要方法。Fowler 和 Scott [ FS97 ] 勾勒了合同设计的基本思想。Meyer [ Meyer92a ]给出了对该方法最完整的处理。

拥抱变化(Anticipation of Change)

计算机软件是解决问题的一种自动化解决方案,问题出现在软件用户熟悉的某些领域中,域定义了用户需要使用的数据类型以及数据类型之间的关系。另一方面,软件开发人员熟悉以抽象方式处理数据的技术。他们处理结构和算法,而不考虑所涉及数据的含义。

因此,为特定领域问题制定自动化解决方案对于软件开发人员及其客户来说是一种双向学习过程。软件开发人员在学习客户工作的领域知识,他们也在学习客户的价值观:什么形式的数据表示对客户最有用,什么样的数据是关键的,需要特殊的保护措施;客户在学习软件技术可以提供的解决方案的范围,也在学习如何评估所有的解决方案,以了解其在满足客户需求方面的有效性。

如果要解决的问题很复杂,那么最佳解决方案在短时间内解决是不合理的。然而,在大多数情况下,客户需要的是及时的解决方案,他们不愿意找到完美的解决方案、他们希望尽快找到合理的解决方案,相对完美的解决方案可以在随后提出。因此,为了开发一个及时的解决方案,软件开发人员需要真实了解需求,明白软件应该如何合理地运行。拥抱变化的原则是认识到软件开发人员及其客户在软件开发中寻找解决方案的复杂性。其中,需求越早制定越好,并且这些需求可以随着开发的过程对需求进行更改。

耦合程度是推进需求的主要阻碍,这是因为,如果两个组件是强耦合的,那么在不改变一个组件的前提下,另一个组件很难做到独善其身的完成最新需求。高内聚与高耦合不同,高内聚能够有效的推进需求的演进,当需求发生变化时,内聚组件更容易重用。如果一个组件将多个任务汇总到一个包中,在需求更改时,这个高内聚的软件包可以很容易的进行任务拆分。

普适性

普适性原则与拥抱变化原则密切相关,主要的目的是设计出不受限制的软件。一个很好的例子是使用两位数来表示年份,最终导致了千年虫问题,好的软件应当预料会长久运行。普适性原则的另一个示例是不断进行自动化转型的客户。起初,客户根据它们以往自身的行为,提出软件需要满足的需求。随着客户对自动化解决方案越来越熟悉,客户才会开始认识到需要完成什么需求,而不是他们此前他们提出的需求。这种区别类似于抽象原则中的区分变化,但它的影响在软件开发过程的早期就可以感受到。

增量软件开发

Fowler 和 Scott [ FS97 ] 对增量软件开发过程进行了简短但深思熟虑的描述。通过增量软件开发这个过程,软件开发人员通过不断对软件进行较小的增量迭代来快速开发软件;例如,一次添加一个用例。增量软件开发过程简化了验证。如果通过不断添加小的功能来增量开发软件,只需要处理添加部分的验证代码就可以了。如果检测到任何错误,由于是增量验证,它们已经做到部分隔离,因此更容易纠正。精心策划的增量开发过程还可以简化对需求变更的处理。然而,通过增量软件开发,首先必须确定最有可能更改的用例,并将它们放在开发过程的最后,否则增量软件开发并不能有效的进行增量迭代。

一致性

一致性即表示:在熟悉的环境中做事更容易。例如,编码风格是排列代码文本的一致方式,如此有两个目的:首先,它使阅读代码更容易;其次,它允许程序员能够自动化的处理输入代码不必考虑命名问题,从而让程序员来处理更复杂的问题。在更高的层次上,一致性涉及开发中处理常见编程问题的习语。一致性在设计图形用户界面时有两个目的。首先,一致的外观和感觉使用户更容易学习使用软件。一旦学习了处理接口的基本元素,就不必为不同的软件应用程序重新学习它们。其次,一致的用户界面促进了交互组件的重用。

Meyer [ Meyer94c ] 将一致性原则应用于面向对象的类库。随着可用库变得越来越复杂,必须将它们设计为向客户端提供一致的借口。例如,大多数数据收集结构都支持添加新数据项,如果 API 的名称都是 add,那么学习使用集合会容易得多。

附录

Principles of Software Engineering