一起成长为架构师-02-软件工程-开发模型

98 阅读12分钟

软件开发方法是软件工程非常重要的方法学。软件研究人员经过40多年的研究,提出过很多方法论,如「结构化方法」到「面向对象的开发方法」。本文主要介绍软件生命周期、软件开发模型。


一、软件生命周期

根据国家标准 GB/T 8566-2007 《计算机软件开发规范》将软件生命周期分为10个阶段:可行性研究与计划、需求分析、概要设计、详细设计、实现、集成测试、确认测试、使用与维护。

软件开发周期 1.png

  • 可行性研究与计划
    在开发软件之前,首先需要进行可行性研究,通过可行性研究确认软件开发的必要性,并明确软件研发目标、范围、风险、成本等内容,从而制定初步粗略的研发计划。如果确定软件的必要性,需要输出《可行性研究报告》和《软件开发计划》,从而进入需求分析。
  • 需求分析
    需求分析是软件生命周期中非常重要的一环。需求分析是方向,一旦与业主方的意愿向背离,就会导致整个工程偏离,若在软件的后期才被发现,那么修正的成本是非常巨大的。可行性研究后,需求分析是对需求更细致的分析,来确定软件要做成什么样的。
  • 概要设计
    概要设计确定整个软件的技术蓝图。负责将需求分析的结果转化为技术层面的设计方案。概要设计需要明确系统架构、各子系统之间的关系、接口规约、数据库设计、编码规范等内容。概要设计将作为程序员的工作指南,供程序员来了解系统的内部原理,并在其基础上进行详细设计和编码工作。
  • 详细设计
    详细设计是在概要设计的基础上,针对模块进行详细地设计的过程,如模块内的类或类与类之间的关系。详细设计在软件开发中,不是必需的一个阶段,针对规模小的项目往往会被省略。同样,也有只针对某些模块进行单独详细设计的过程。
  • 实现
    实现过程包含编码和单元测试。编码可按照编码约束规范进行,单元测试是针对模块内的类、方法、变量等进行缺陷检测。单元测试会更细粒度地检测到代码中出现的缺陷。
  • 集成测试
    集成测试也称为「组装测试」。通过了单元测试,并不意味着没有缺陷。当程序单元被集成到一起交互时,往往会出现单元测试发现不了的问题。同单元测试不同,集成测试必须经过精心的组织指定集成测试计划确定如何将这些程序单元集成到一起按照什么样的顺序进行测试,使用哪些测试数据等问题。
  • 确认测试
    确认测试也称为系统测试,集成测试保证了模块间的接口没有问题,确认测试要确保是否与需求一致,是否达到了预期目标。与集成测试一致,也需要精心地计划和组织,逐步地验证软件系统同需要的一致性。经过确认测试的软件将投入到正常使用。
  • 使用
    测试通过后,软件正式移交至客户侧,客户和维护人员必须认真收集发现的软件错误,定期或阶段性地撰写软件问题和软件修改报告。
  • 维护
    通过了单元测试、集成测试、确认测试,也不可能发现全部的缺陷,软件系统的需求也会根据业务发展变化而变化。因此,在软件使用过程中,必须不断地对软件进行维护,修正软件中的缺陷,修改软件中已不满足当前业务的功能,增加新的功能。软件维护的过程会贯穿整个软件的使用过程。
  • 退役
    终止对软件产品的支持,软件停止使用。

二、软件开发模型

软件开发模型大致分为三种类型:

  1. 软件需求完全确定时,采用瀑布模型

  2. 软件需求不完全确定时,采用迭代式或渐进式开发模型

    • 喷泉模型
    • 螺旋模型
    • 统一开发过程
    • 敏捷开发
  3. 以形式化开发方法为基础的变换模型

1. 瀑布模型

Untitled Diagram 1.png

软件模型如上图,主要分为3个大阶段:定义阶段、开发阶段、维护阶段。

  • 定义阶段

    • 主要包含软件计划、需求分析
  • 开发阶段

    • 软件设计:概要设计、详细设计
    • 程序编码:编码、单元测试
    • 软件测试:集成测试、确认测试
  • 维护阶段

    • 使用和运维

瀑布模型的特点:

  • 严格区分阶段,每个阶段都有因果关系,每个阶段都有严格的产物

    • 需求阶段:需求文档
    • 设计阶段:概要设计和详细设计文档
    • 开发阶段:代码
    • 测试阶段:系统测试文档
  • 只适合需求明确的项目

瀑布模型的缺点:

  • 早期需求很难明确,会导致项目后期才发现;
  • 难适应需求的变化,每个阶段紧密相连,下个阶段依赖于上个阶段的成果;
  • 所有阶段全部结束后才能最终交付软件产品,所以提出需求后很长时间(项目后期)才能看到结果,难以控制开发风险
  • 瀑布模型是文档驱动的模型,会产生很多与客户无关的文档,但完成对客户无意义的文档却要花费大量的人力

2. V模型(瀑布模型变种)

瀑布V模型强调的是瀑布模型的变体。随着对瀑布模型的使用,人们发现缺陷在每个阶段都是无法避免的,为了在早期发现更多缺陷让测试工作前移。测试是非常重要的一环,测试的质量直接决定了产品质量。

瀑布模型-V模型.png

  • 需求分析与系统测试之间存在依赖关系
    这指的是,需求分析的结果将作为系统测试的准则,即需求分析阶段也将产生同需求一致的系统测试;同时软件产品是否符合最初的需求将在系统测试阶段得到验证。
  • 总体设计(概要设计)与集成测试存在依赖关系
    这指的是,概要设计的结果将作为集成测试的准则,即基于概要设计阶段产生同设计一致的集成测试
  • 详细设计与单元测试存在依赖关系
    这指的是,详细设计的阶段也会产生与详细设计保持一致的单元测试

特点:V模型不但保持了瀑布模型的「阶段式文档驱动」的特点,而且更强调了「软件产品的验证工作」。
注意:此处有考点,某种测试在哪个阶段进行?

3. 演化模型

  • 演化模型是怎么提出来的呢?

    • 瀑布模型看起来很好,随着一个接一个的阶段,软件系统被建立起来了。但是,人们发现很难一次性完全理解需求,设计出好的架构,开发出可用的系统。 因为人的认知是会有一个不断渐进和深化的过程,复杂的软件系统与人的认知紧密相连,也会有一个循序渐进的过程。基于以上观点提出了演化模型。
    • 演化模型的特点是,一般情况下,一个演化模型可以看做若干个瀑布模型的迭代,当完成一个瀑布模型后,重新进入到下一个迭代周期,软件在迭代中得以演化、完善。根据不同的迭代特点,演化模型可以演变为螺旋模型、增量模型和原型法开发。

3. 螺旋模型

螺旋模型是「瀑布模型」和「演化模型」的结合,不仅继承了两者的特性,更强调了风险分析的重要性。螺旋模型把项目分为需求分析、风险分析、工程实现、评审4个阶段。由这4个阶段迭代,每迭代一个周期软件就会精进一步。

螺旋模型.png

如上图所示,螺旋模型是在「瀑布模型」的开发阶段前增加了风险分析的过程。它把项目拆分成多个小项目,每个小项目都被标识出一个或多个风险,直至所有的风险都被确定。

螺旋模型强调的是风险分析,开发者与用户可在不同的演化层识别不同的风险,对出现的风险都有所了解,继而做出应有的反应。

因此,螺旋模型特别适合庞大而复杂的的系统,对于这些系统,风险是软件开发潜在的、不可忽视的不利因素,它可能会损害软件系统的开发过程,影响软件产品的质量。 **减小软件风险的目标是在造成危害之前,及时对风险进行识别、分析、决定采取何种对策,进而消除或较少风险的损害。

与瀑布模型相比,其优点和缺点是什么呢?
优点:

  • 支持用户需求的动态变化
  • 有助于提高目标软件的适应能力
  • 为项目管理人员及时调整管理决策

缺点:

  • 对风险分析能力要求高。需要具有相当丰富的风险评估和专业知识。在风险较大的项目中,若未能及时识别风险,势必会造成重大损失。
  • 过多的迭代次数会增加开发成本,延迟提交时间。

4. 增量模型

演化模型的另一个形式是增量模型。在系统的技术架构成熟、风险低的时候,可以采用增量的方式进行系统开发,这样可以提前进行集成测试、系统测试缩短初始版本的发布周期提高用户对系统的可见度

增量模型分为两种策略:

  • 增量发布的办法
    首先,做好系统的分析和设计工作;
    然后,将系统划分为若干不同的版本,每一个版本都是一个完整的系统,后一版本以前一版本为基础进行开发,扩充前一版本的功能。
    在这种策略下,第一版本往往是最核心的功能,可以满足用户基本的需求,随着增量发布,系统功能逐步丰富。试用的问题可以很快地反馈到后续开发中,从而降低了系统的风险。

    在应用模型中需要注意:

    1. 每一个版本都是完整的系统。
    2. 版本间增量要均匀。每个版本发布的工作量相当。
  • 原型法
    同增量模型不同,原型法每一次迭代都经过一个完整的生命周期。当用户需求不明确技术架构中存在很多不可知因素的时候,可以采用原型法。
    在初始的原型中,针对一般的用户需求进行快速实现,并不考虑算法的合理性或系统的稳定性。

    这个原型主要目的是获得精确的用户需求,或验证计划架构的可行性。 一般情况下,在后面的开发中会抛弃这个原型,重新实现完整的系统。

5. 构件组装模型

随着技术的发展,人们开始使用拼积木的方式组装构件,即构建组装模型。在构件组装模型中,当经过需求分析定制出软件功能后,将对构件组件结构进行设计,将系统划分为一组构件的集合。明确构件之间的关系,确定构件后,则将独立完成每一个构件。可以开发新构件、重用已有构件、采购第三方构件。构件是独立、自包容的。构件之间通过接口进行交互。

构件组装模型一般的开发过程:

构件组装模型.png

优点:

  • 易扩展、易重用、降低成本、安排任务更灵活

缺点:

  • 架构设计要求高,要求经验丰富的架构师,设计不好的难重用;
  • 强调重用牺牲其他指标(如性能)
  • 第三方构件质量难控制

「拓展」
基于构件的软件工程(CBSE)主要体现了「购买而不是重新构造」的思想,其特征:

  • 可组装性:所有外部交互必须通过公开定义的接口进行。
  • 可部署性:构件总是二进制形式的,能作为一个独立实体在平台上运行。
  • 文档化:用户根据文档来判断构件是否满足需求。
  • 独立性:可以在无其他特殊构件的情况下进行组装和部署。
  • 标准化:符合某种标准化的构件模型。

构件的组装:

  • 顺序组装:按顺序调用已存在的构件,可用两个已存在的构件来创造一个新构件。
  • 层次组装:被调用接口 必须与调用方的请求兼容。
  • 叠加组装:多个构件合并形成新构件,新构件整合原构件的功能,对外提供新的接口。