Code Copied

系统架构设计中的常用设计准则

一、动机

当我们开始设计或开发系统时,有很多需求是需要考虑的。
有些需求相对于系统来说属于特定的需求,而有些则是一些共通的需求。
我们可以将需求归类为功能性需求和非功能性需求。
在不同的系统中,需求都是各不同相同,变化多端的。
下面陈述的这些内容是系统设计开发中的一些常用准则,尤其是在那些具有较长生命周期的行业软件中,这些准则显得尤为重要。
这些准则不一定每一个对系统的设计开发都很重要,但是我们可以确定的是这些准则常常会出现在我们所经历的项目中。

二、常用设计准则

1.Maintainability(可维护性)

随着系统的体积越来越庞大,预计的生命周期变得越来越长,维护这样的系统将会对开发人员来说是越来越大的挑战。
通常地,原始的团队成员开发出的系统经历过很多版本之后,已经不适用于现在的情境。或者这些开发人员已经忘记了系统中的很多细节,甚至文档都可能已经过时或者缺失了;与此同时,一些新的紧急的实际业务需要在系统中迅速实现。
以上列出的这几种情形的系统,无疑是非常难以维护的,也是让开发人员非常头痛的。难以维护的系统甚至能够迫使开发人员不停地在更换,以至于系统的维护始终处于恶性循环之中。
可维护性是指软件的质量,它决定了系统是否能够轻松有效地变更新的版本。
在系统维护中,我们常常会碰见以下几种情形。
也许现在我们必须修复系统新发现的一个bug(系统修正维护),或者由于一些操作环境的变化导致系统需要作出变更,或者你需要添加新的功能来满足业务需求(系统改善性维护)。
如果系统的可维护性较高,这将会增强组织的灵活性并能降低系统的持续投入成本。

因此,我们应该将可维护性作为系统的设计目标之一,并伴随着诸如可靠性、安全性和可伸缩性等。

2.Testability(可测试性)

一个可测试的系统,能够让我们有效地测试系统的各个部分。
设计和编写有效的测试与设计和编写可测试应用程序代码一样具有挑战性,尤其是在更大更复杂的系统中。
一���方法论诸如测试驱动开发(TDD)要求你在编写每个的功能实现代码之前写好单元测试,这样的技术设计目的是为了提高应用程序的质量。
这样的技术也能够有助于扩展单元测试的覆盖,减少系统退化的可能性,使重构变得更加容易。
然而,作为测试过程的一部分,你也应该把其他类型的测试,如验收测试、集成测试、性能测试、压力测试纳入到测试过程中。
由于是在现实环境中测试需求,执行这些测试是需要花费一些金钱和时间成本的。
例如,测试一个基于云应用程序需要我们将应用程序部署到云环境中,并在云环境中运行测试。如果我们采用TDD,在云环境中运行所有的测试可能会不切实际,因为我们需要花时间去部署应用程序,即使是在本地的模拟云环境中也是如此。在这种情景下,我们可能使用测试替身(简单stubsor可验证的模拟)代替云环境中真正的组件,通过测试替身实现测试,因此可以让我们在TDD的开发周期中单独地运行单元测试。

可测试性应该伴随着可维护性和灵活性作为系统的另一个设计目标,一个可测试性高的系统通常也易于维护。

3.Flexibility and Extensibility(灵活性和可扩展性)

灵活性和可扩展性也经常作为企业应用程序开发和实施需要考虑的目标。
由于业务需求的多变性,两者经常发生在应用程序的开发和产品运行之后,在设计应用程序时我们应该尽量让它保持灵活和较高的可扩展性,这样在系统运行后,当有业务变更或新的业务需求时,我们可以较为轻松地添加一些新的功能。
比如,我们可能需要将原本在本地运行的程序迁移云环境中运行,如果应用程序在设计时没有考虑良好的灵活性和可扩展性,那么迁移可能就会失败,甚至我们为了让应用程序适应云环境不得不再做一次开发工作。

4.Late Binding(延迟绑定)

在某些应用场景,我们的应用程序可能需要支持延迟绑定。
如果需要替换系统的某些模块而不想重新编译,延迟绑定在这种场景下就能发挥较好的作用。
场景1:应用程序中有一个模块支持多个关系型数据库,我们可以通过灵活配置的方式告诉应用程序运行时使用什么样的关系型数据库。
场景2:如果已开发的系统中伴随着很多插件,延迟绑定机制则可以很方便地让用户通过系统定制化自己需要的插件。
场景3:在某些开发的文件系统中,可以通过指定系统的配置或者约定,让系统扫描指定目录的文件。
以上这3个场景都使用了延迟绑定的机制,我们并不需要额外地修改一些代码来实现用户业务上的需求。当然以上这些场景也包含了应用程序设计时的灵活性和可扩展性。

5.Parallel Development(并行开发)

当我们正在开发大规模(甚至是中小规模)的系统时,让整个开发团队同时地工作在一个功能或组件上是不切实际的。
实际上,我们会把整个团队拆分成几个小的group,然后同时给各个group分配一些不同的功能或组件。
尽管这种方法能够使我们减少整个项目的持续时间,但是它引入额外的复杂性:我们需要同时管理多个团队,并且确保我们可以准确地集成不同团队完成的功能和组件。

6.Crosscutting Concerns(横切关注点)

企业应用程序通常需要解决一系列的横切关注点,例如如验证、异常处理和日志记录等。
可能在应用程序中的许多不同领域都需要这些功能,或许我们想通过一个标准的、一致的方式来实现这些功能,以提高系统的可维护性。
理想情况下,我们希望有一种机制能够有效透明地向对象添加一些新的行为,而且无论是在设计时还是在运行时都不需要更改已经存在的class。
通常地,在某些情况下我们需要在运行时配置这些功能,或者需要在现有的应用程序中添加功能来解决一个新的横切点。

7.Loose Coupling(蔬耦合)

我们可以通过确保应用程序中各个部分的设计结果是否是松散耦合的,来解决很多前面我们已经列出的系统设计要求。
在应用程序中有很多组件,松散耦合意味着减少这些不同组件之间的依赖关系。
松散耦合能够更容易地、更安全地在应用程序的某个部分作出变更,因为应用程序的各个部分已经很大程度上和其他部分是独立的。