什么是软件设计

软件设计思想的发展

为什么要设计

  • 事物的复杂性 VS 思维的有限性
    • 7±2规则
    • 关注点分离与层次性

Why software is inherently complex?

“The complexity of software is an essential property, not an accidental one” — F. Brooks

  • The complexity of the problem domain
  • The difficulty of managing the development process
  • The flexibility possible through software
  • The problems of charactering the behavior of discrete systems

设计的复杂度

  • 事物复杂度 VS 载体复杂度
    • 对外表现 与 内部结构
  • 设计复杂度 = 事物复杂度+载体与事物的适配复杂度

软件设计的核心思想-分解与抽象

分解与抽象的并用和层次性

什么是设计?

  • [wiki]Design is the planning that lays the basis for the making of every object or system.
  • [Brooks 2010]认为上述定义的精髓在于计划、思维和后续执⾏
  • [Ralph 2009]将设计定义为:
    • 设计(名词):⼀个对象的规格说明。它由⼈创造,有明确的⽬标,适⽤于特殊的 环境,由⼀些基础类型构件组成,满⾜⼀个需求集合,受⼀定的限制条件约束
    • 设计(动词):在⼀个环境中创建对象的规格说明

软件设计

什么是设计

  • 设计经常需要⼀个设计师考虑⼀个对象或过程的审美、功能以及其他⽅⾯,这通常需要进⾏相当的研究、 思考、 建模、 交互调整和重新设计

⼯程设计与艺术设计

  • [Faste2001]认为软件设计要:时刻保持以⽤户为中⼼,为其建造有 ⽤的软件产品;将设计知识科学化、系统化,并能够通过职业教育产⽣合格的软件设计师; 能够进⾏设计决策与折中,解决设计过程中出现的不确定性、信息不充分、要求冲突等复杂情况
  • Vitruvius(《De Architectura》,公元前 22 年)认为好的建筑架构要满⾜“效⽤(Useful)、 坚固 (Solid)与美感(Beautiful)”三个⽅⾯的要求。
  • Brooks2010]认为重要的美感因素包括:简洁、结构 清晰和⼀致
  • Smith1996]认为在软件设计(尤其是⼈机交互设计)中艺术始终都处于中⼼地位,⽐⼯程性更加 重要,为此设计师需要学会:发散性思维和创新;与⽤户共情,体会他们的内⼼感受;进⾏相关因 素的评价和平衡,例如可靠性与时尚(Fashion)、简洁性与可修改性等;构思与想象,设计软件产 品的可视化外观(Visualization)

Rational or Pragmatic? 理性主义or经验主义?

理性主义代表

  • 理性主义更看重设计的⼯程性,希望以科学化知识为基础,利⽤模型语⾔、建模⽅法、⼯具⽀持,将软件设计过程组织成系统、规律的模型建⽴过程[McPhee1996]
  • 在考虑到⼈的因素时,理想主义认为⼈是优秀的,虽然会犯错,但是可以通过教 育不断完善⾃⼰ [Brooks2010]
  • 设计⽅法学的⽬标就是不断克服⼈的弱点,持续完善软件设计过程中的不⾜, 最终达到完美[McPhee1996]
  • 形式化软件⼯程的⽀持者是典型的理想主义

经验主义代表

  • 经验主义者则在重视⼯程性的同时,也强调艺术性,要求给软件设计过程框架添加⼀些灵活性以应对设计中⼈的因素
  • [Parnas1986]曾指出没有过程指导和完全依赖个⼈的软件设计活动是不能接受的,因为不能保证质量和⼯程性。但是[Parnas1986]也指出⼀些⼈的因素决定了完全理性的设计过程是不存在的:
    1. ⽤户并不知道他们到底想要怎样的需求;
    2. 即使⽤户知道需要什么,仍然有些事情需要反复和迭代才能发现或理解;
    3. ⼈类的认知能⼒有限;
    4. 需求的变更⽆法避免;
    5. ⼈类总是会犯错的;
    6. ⼈们会固守⼀些旧有的设计理念;
    7. 不合适复⽤
  • 所以,[Parnas1986]认为软件设计需要使⽤⼀些⽅法弥补⼈的缺陷,以建⽴⼀个尽可能好的软件设计过程。⽂档化、原型、尽早验证、迭代式开发等都被实践证明能够有效弥补⼈类的缺陷[Parnas1986, Brooks 2010]

软件设计的演化性

设计的决策

  • [Freeman1980]认为:软件设计是⼀种问题求解和决策的过程;问题空间是⽤户的需求和项⽬约束,解空间是软件设计⽅案;从问题空间到解空间的转换是⼀个跳跃性的过程,需要发挥设计师的创造性,设计师跳跃性地建⽴解决⽅案的过程被称为决策。
  • 软件设计的问题求解与决策⽐普通数学问题的求解与决策要困难的多,因为软件设计⾯对的问题通常都是不规则的(Ill-Structured)[Simon1978],包含有很多的不确定性和信息不充分情景,所以进⾏设计决策时并不能保证决策的正确性,往往需要在很⻓时间之后才能通过验证发现之前决策的正确与否

决策的约束性

  • 约束满⾜与决策
    • 约束:
      • 需求;环境;资源;技术…
      • An initial need determines the most basic constraints and requirements on a design situation.
      • In general, more constraints are eventually discovered during the design work itself.
      • The constraints that apply both to the designed artifact and to the processes and participants involved during the design activity
    • 约束满⾜

设计的决策依据

决策的多样性

  • 决策的选择性
  • 多个同样好的⽅案,选择⼀个
  • The solution space for design problems is very large and its sheer size eliminates exhaustive search as a possible problem solving technique
  • “design” is characterized by a series of decisions between various design alternatives

决策的演化性

  • 遵循路线:问题决策验证下⼀个问题
  • 决策的顺序影响
  • 前⼀个决策会影响后⼀个,⽽且不可预⻅
  • Each divergent perspective may influence the progress of the design in different and unpredictable ways.
  • 决策的不可逆性
  • ⽆法完全消除⼀个前期错误的决策
  • 决策要⼀致

设计的演化性

决策的概念完整性

软件设计的分层

程序设计的建立

  • 1950s
    • 第⼀代语⾔,第⼆代语⾔
    • 语句为最⼩单位
  • 1960s
    • 第三代语⾔
    • 类型与函数:第⼀次复杂系统分割
  • 1970s
    • 类型与函数的成熟:形式化⽅法
    • 数据结构+算法=程序

低层设计

  • 将基本的语⾔单位(类型与语句),组织起来,建⽴⾼质量的 数据结构+算法
  • 常⻅设计场景:
    • 数组的使⽤,链表的使⽤,内存的使⽤,遍历算法,递归算法…
  • 经典场景:
    • 堆栈,队列,树,排序算法,查找算法…
  • 数据结构与算法审美:
    • 简洁、结构清晰,坚固(可靠、⾼效、易读)
    • 数据结构与算法课程
    • <计算机程序设计艺术>

低层设计的本质

  • 屏蔽程序中复杂数据结构与算法的实现细节!

底层设计:代码设计

  • 对⼀个⽅法/函数的内部代码进⾏设计
  • ⼜被称为软件构造“software construction”,通常由程序员独⽴完成
  • 依赖于语⾔提供的机制(程序设计课程)
    • OO or Structural
    • Reference or Address Point

模块划分

  • 1970s
    • 函数的成熟与模块的出现
  • 模块划分
    • 将系统分成简单⽚段
      • ⽚段有名字,可以被反复使⽤
  • 名字和使⽤⽅法称为模块的抽象与接⼝
  • 模块内部的程序⽚段为精化与实现

中层设计

中层设计的开始

  • 模块划分隐藏⼀些程序⽚段(数据结构+算法)的细节,暴露接⼝于外界

模块化的目标:完全独立性

  • 完全独⽴有助于
    • 理解
    • 使⽤与复⽤
    • 开发
    • 修改

模块化的问题与困难

  • 程序⽚段之间不可能是完全独⽴的
  • ⽅法:实现尽可能的独⽴
    • 模块化
    • 信息隐藏
    • 抽象数据类型
    • 封装

中层设计总结—设计目标

  • 最终审美⽬标:简洁性、结构清晰、⼀致性、质量(可修改、易开发(易理 解、易测试、易调试)、易复⽤)
  • 直接评价标准:模块化;信息隐藏;OO原则

中底层设计的问题

  • 《Programming-in-the-Small VS Programming-in-the-Large》
  • 过于依赖细节
    • 连接与依赖,接⼝与实现
  • 忽略的关键因素: ⽆法有效抽象部件的整体特性
    • 总体结构
    • 质量属性

高层设计

高层设计:体系结构

  • 部件承载了系统主要的计算与状态
  • 连接件承载部件之间的交互
  • 部件与连接件都是抽象的类型定义(就像类定义),它们的实例(就像类的对象实例)组织构成软件系统的整体结构,配置将它们的实例连接起来
  • 连接件是⼀个与部件平等的单位

敏捷观点

  • 只有⾼层设计良好,底层设计才可能良好
  • 只有写完并测试代码之后,才能算是完成了设计
  • 源代码可能是主要的设计⽂档,但它通常不是唯⼀⼀个必须的

软件设计过程、方法和模型、描述

软件设计过程的主要活动

软件设计的方法和模型

设计的方法

  • 软件设计的⽅法可以分为以下⼏种[SWEBOK 2004]:
    • 结构化设计⽅法、
    • ⾯向对象设计、
    • 数据为中⼼设计、
    • 基于构件的设计、
    • 形式化⽅法设计

静态模型vs动态模型

  • 描述软件设计的模型,通常可以分为两类:
    • 静态模型
      • 静态模型是通过快照 的⽅式对系统中时间不变的属性进⾏描述。通常描述的是状态,⽽不是⾏为
        • ⽐如:⼀个数字的列表是按⼤⼩排序好的。
    • 动态模型。
      • 动态模型通常描述的是系统⾏为和状态转移。
        • ⽐如:排序的过程中如何进⾏排序

结构化设计模型和⾯向对象设计模型

  • 在结构化设计中
    • 静态模型
      • 实体关系图
    • 动态模型
      • 数据流图、结构图(Structure Chart)和流程图(Flow Diagram)
  • 在⾯向对象设计中
    • 静态模型
      • 设计类图、对象图、构件图、部署图;
    • 动态模型
      • 交互图(顺序图和通信图)、状态图、 活动图等

软件设计描述

软件设计描述规范

  • 早在 1998 年,IEEE 组织就提出了 IEEE 1016-1998 号标准[IEEE1016-1998]以规范软件设 计的⽂档化描述
  • 在 2009 年 3 ⽉,IEEE-SA 标准委员会修订了 1016 号标准[IEEE1016-2009]。 IEEE 的标准并没有限定设计描述⽂档的具体结构,⽽是通过解释⼀系列概念说明了软件设计 描述⽂档应该遵循的思路和基本内容

软件设计描述模型

设计视角

利益相关者

  • 设计视⻆必须符合在需求(Requiement)中利益相关者(Stakeholder)的设计关注点 (Design Concern)
  • 设计对不同的利益相关者来讲,有着不同的意义[Pfleeger 2009]:
    • 顾客想要确认现有的软件设计⽅案能够保证其所期望的系统的功能和⾏为可以实现
    • 架构师想要知道软件单元、计算平台和系统环境⾜够实现需求中要求的⾮功能性需求
    • 设计⼈员想要了解系统的整体设计,以确保系统的每个设计决策和系统功能都能实现
    • 开发⼈员想要知道所开发的单元的精确描述,以及与其它单元的关系。
    • 测试⼈员想要确认怎样测试设计的所有⽅案
    • 维护⼈员系统想要在修复问题和添加新特性时,能够保持体系结构的完整性和设计的⼀致性
    • 因为每个利益相关者⽬的不⼀样,对设计就会产⽣不同的设计关注点。⽽我们的设计得全⾯考量各个利益相关者的设计关注点,给出相应的设计视⻆下的设计视图

设计理由

设计描述文档模板

设计文档书写要点

  • 充分利⽤标准的⽂档模版,根据项⽬特点进⾏适当的裁剪
  • 可以利⽤体系结构⻛格的图,让读者更容易把握⾼层抽象
  • 利⽤完整的接⼝规格说明定义模块与模块之间的交互
  • 要从多视⻆出发,让读者感受⼀个⽴体的软件系统
  • 在设计⽂档中应体现对于变更的灵活性