1-软件构造与设计基础

来源:互联网 发布:三菱gxworks2软件下载 编辑:程序博客网 时间:2024/06/06 11:36

1-软件构造基础

1.1 软件构造的概念

1.1.1 什么是软件构造

  1. 软件构造是编码和调试
  2. 部分的详细设计和单元测试
  3. 软件构造≠编码实现

image

1.1.2 什么是调试和测试

  • 测试是为了发现错误
  • 调试是为了修正错误而确定错误产生的原因

1.1.3 软件构造活动的具体任务

  1. 验证基础工作已经完成,可以进行创建工作;
  2. 创立数据类型并命名变量
  3. 设计和编写子程序与模块
  4. 选择控制结构并组织语句块
  5. 持续进行单元测试并修正错误
  6. 评审其他小组的细节设计和代码,同时接受其他小组的评审
  7. 通过仔细的格式化和征集意见改进编码
  8. 调整优化编码,使其更精悍更快

1.2 软件构造的重要性

  1. 构建活动是软件开发的主要组成部分:构建活动在整个开发活动总时间所占比例一般在30%-70%
  2. 构建活动是软件开发中的核心活动:需求分析和架构设计是构建活动在开始之前的基础工作,他们可以让你有效的进行构建;系统测试则是构建活动的测试工作,用以验证正确性.
  3. 把主要精力放在构建活动上,可以大大提高程序员的生产效率.
  4. 构建活动的产物–源代码–往往是对软件的唯一精确描述.
  5. 构建活动是唯一一项确保会完成的工作.

1.3 软件构造的常用技术

  • 构造软件复用
  • 抽象数据类型
  • 类的设计和使用
  • 合约编程
  • 错误处理
  • 分布式程序构造
  • 单元测试
  • 重构
  • 极限编程

1.4 隐喻

1.4.1 什么是隐喻

在软件领域中,隐喻(Software Metaphors )并非简单地用一个名词对软件事物进行类比,它还包含了对类比事物之间的体验与分析.

启发式方法与算法

隐喻的作用更像启示而非算法

算法是一套定义明确的指令,使你能完成某项特定的任务.算法是可预测的,确定性的,不易变化的.

启发式方法是一种帮你寻找答案的技术,但它给出的答案是有偶然性的,因为它仅仅告诉你该如何去寻找而没有告诉你要找什么.

1.4.2 隐喻的重要性

  • 隐喻可以帮助开发人员借助类比的力量加深对编程的理解
  • 借助隐喻加深理解是各个研究领域都常用的方法

1.4.2 常用隐喻

  • 臭虫( bug)
  • 菜单( menu)
  • 视窗( windows)
  • 架构( architecture)
  • 服务( service)
  • 对象( object)
  • 黑盒( black box)与白盒( white box)

 写代码与写作

P.J.Plauger参考一本关于协作体裁的书<文体的要素>,将他们关于编程风格的书命名为<编程风格的要素>,并且程序员经常会讨论”程序的可读性”

这种用协作所做的隐喻,在<人月神话>而变成了不朽的思想:”要计划抛弃一个,你必定会那样,无论如何”,于是形成了如下景象:被扔进纸篓里的成堆半成品草稿.
image

文字写作这一隐喻暗示着软件开发过程是一种代价昂贵的试错.

软件播种:生成系统(growing a System)

image

一些软件开发人员认为应该将创造软件想象成类似播种和耕作的情形:你一次设计系统的一小部分,写出一段代码,做一点测试,并将成果一点点添加到整个系统中.通过这种小步前进,你可以把,诶次可能遇到的麻烦减到最小.

软件耕作这一隐喻的弱点在于它暗示了人们将无法对开发软件爱你的过程和方式进行直接的控制,你在春天播下代码的种子,然后按照农历节气向土地老儿许几个愿,你将会在秋天收获到丰盛的代码.

软件珍珠培植法:系统积累(System Accretion)

image

我们必须学习如何一次为软件系统增加一个小部分:使软件为增量式的,迭代的,自适应的,演进的.

其优势在于未做过度的承诺.

软件创建:建造软件(building software)

image

软件构造与软件生长概念想通,且这一说法暗示了软件开发中存在着诸多阶段,如计划,准备及执行等.根据锁建造的软件不同,这些阶段的种类和程度也有可能会发生变化.

你建造房子时不会去建造洗衣机冰箱门窗户等而是去购买或者定制,没在软件开发中也会这样做如:使用高级语言的库函数,或为了实现更高的要求自己定制容器,组件等.

精心计划,你可以把房子的结构的支撑规划的清清楚楚,一项规划得当的项目能够提升后期改变细节设计的能力,软件也是如此.

有助于解释为什么不同的软件项目能从不同的开发法方法中获益.

软件的变动在建筑领域也有类似的事物,如改变承重墙位置肯定比仅仅移动一面隔墙花费更高,同样对软件的结构性修改所花费的时间和成本肯定比增减一些周边功能花费的高.

让人们对超大型的软件项目认识更加深刻.超大型的结构一旦出现问题,后果非常严重,因此有必要对这样的结构进行超出常规的规划与建设.

实用软件技术:智能工具箱( The Intellectual Toolbox)

image

编程方面的知识学的越多,你脑中的工具箱就会有更多的分析工具,也会知道在何时使用这些工具,以及怎正确的使用他们

复合隐喻( Combing Metaphors)

image

因为隐喻是启发方法而非算法,因此他们彼此之间并不排斥.你可以同时使用生长和建筑这两个隐喻.

1.5 构建之前的准备工作

1.5.1 什么是构造之前的准备工作

软件构造的前期准备工作是复查性的活动

  1. 明确前导性的工作结果有哪些
  2. 重新审视前导性工作是否完成
  3. 明确前导性工作完成的程度如何

软件构造的前期准备工作中心目标是降低风险

一个好的项目规划者能够尽可能早地将主要的风险清除掉.软件开发中最常见的项目风险是:

  1. 糟糕的需求分析
  2. 糟糕的项目计划

因此准备工作就倾向于几种改进需求分析和项目计划.

1.5.2 如何理解前期准备工作(前期准备工作重要性)

在开始实现一个系统之前,必须十分清楚:这个系统应该做什么,以及它该如何做到这些!

从逻辑性的角度

  • 进行有效编程的要领之一:准备工作很重要。
    1. 从管理的角度来看,做好计划意味着可以确定项目所需的时间、人数和计算机台数。
    2. 从技术角度来看,做好计划意味着可以明确要构造到底是什么。

-逻辑的角度讲,准备工作的时间“物有所值”
1. 中国有句古话:“磨刀不误砍柴工”

从与其它事物类比的角度

image

<代码大全>P28

程序员是软件食物链的最后一环.架构师吃掉需求,设计师吃掉架构,而程序员则消化设计.

如果在一个受污染的环境中,水蝽在核废料中游泳,青鱼被PCB污染,而吃青鱼的鲑鱼又在泄漏的原油中游荡.海鸥很不幸,它位于食物链的最后一环,它吃下去的不仅仅是不健康的鲑鱼体内的原油,还有青鱼体内的PCB和水蝽体内的核废料.在软件开发中,如果需求被污染了,那么它就会污染架构,而架构又会污染构建.这会导致程序员开发出具有放射性污染,而且周身都是缺陷的软件.

image

  • 从以往数据的角度

image
image
image

1.5.3 前期准备工作的内容

前期准备工作并非一成不变,构建活动的准备工作要根据项目特点调整

1.5.3.1 辨明软件项目的类型

image
image
image
image

1. 最常见的三种类型
  • 性命攸关的系统( Embedded Life-Critical Systems)
  • 使命攸关的系统( Mission-Critical Systems)
  • 一般商业系统( Business Systems)
2. 不同类型的项目倾向于不同的开发方式
  • 商业系统倾向于使用高度迭代的开发方式
  • 性命攸关的系统往往要求更加序列式的方法
3. 迭代式开发和序列式开发

一条游泳的规则是,计划好预先对大约80%的需求做出详细说明,并稍后进行详细说明额外的需求分配一定的时间.然后在项目进行过程中实施系统化的变更措施–只接受最有价值的新需求.

另一种替代方法是,预先只对最重要的20%的需求做出最详细的说明,并且计划以小幅增量开发软件的剩余部分,随着项目的进行,对额外的需求和设计做出详细的说明,下图展示了这两种方法的不同之处:

image

  • 序列式开发
    1. 使用瀑布式模型进行开发
    2. 适用于需求相对稳定的情况
  • 迭代式开发
    1. 整个开发工作被组织为一系列的迭代过程。每一次迭代都包括了需求分析、设计、实现与测试。
    2. 适用于需求容易变化的情况
4. 如何选择序列式和迭代式开发
  • 序列式开发
    1. 需求相当稳定
    2. 设计相对简单、容易
    3. 后期改变需求、设计和编码的代价非常高
  • 迭代式开发
    1. 需求相对不稳定,或需要不断加深理解
    2. 设计复杂,具有挑战性
    3. 后期改变需求、设计和编码的代价比较低

1.5.3.2 明确问题定义

1. 问题定义( Problem Definition)
  • 问题定义:项目要解决的问题是什么
  • 明确的问题定义是第一项先决条件
  • 在开始软件构造之前首先要check是否已经对系统要解决的问题做出了明确的陈述。
2. 问题定义的别称
  • 产品设想( Product Vision)
  • 任务陈述( Mission Statement)
  • 产品定义( Product Definition)
3. 问题定义是整个开发的基础

image

问题定义应该使用客户的语言来书写,而且应该从客户的角度来描述问题.通常不应该用计算机的专业术语叙述.

4. 问题定义的注意点
  • 一个好的问题定义:我们跟不上jack的订单了
  • 一个不好的定义:我们需要优化数据自动采集系统,使之跟上jack的订单
  • 问题定义应该用客户容易理解的语言编写
  • 问题定义应该从客户的角度编写
5. 未定义问题的处罚

image

未能定义问题的处罚是,浪费了大量的短时间去解决错误的问题.这是双重处罚,因为你也没有解决正确的问题.

1.5.3.3 明确需求规约(需求的先决条件)

1. 需求定义
  • 需求定义详细规定了软件系统应该做什么
  • 明确的需求定义是另一项先决条件
  • 在开始软件构造之前要check是否已经充分详尽地描述了系统所要做的事情。
2. 需求定义的别称
  • 软件需求( Software Requirement)
  • 功能规约( Function Specification)
3. 功能需求核对表

规定开发人员必须在产品中实现的软件功能,用户利用这些功能来完成任务,满足业务需求。

  • 是否详细定义了系统的全部输入:输入的来源、精度、取值范围、出现频率等
  • 是否详细定义了系统的全部输出:输入的目的地、精度、取值范围、出现频率等
  • 是否详细定义了所有输出格式:Web页面、报表、磁盘文件
  • 是否详细定义了所有硬件及软件的外部接口:外部接口指该软件实体与外部硬件对接以及其它软件交互部分的接口
  • 是否详细定义了全部外部通信接口:握手协议、纠错协议、通信协议等
  • 是否列出了用户想要做的全部事情
  • 是否详细定义了每个任务所用及得到的数据
4. 非功能需求核对表(QoS需求)

软件产品在功能以外的服务质量( Quality ofService, QoS)方面的需求

  • 是否为必要操作定义了期望的相应时间:在实时系统中是响应时间必要的
  • 是否详细定义了其它与计时有关的考虑:处理时间、数据传输率、系统吞吐量
  • 是否详细定义了安全级别
  • 是否详细定义了可靠性:包括软件失灵的后果、需要保护的重要信息、错误检测以及恢复策略
  • 是否详细定义了内存、硬盘的使用要求
  • 是否详细定义了系统的可维护性:功能的变更、操作环境的变更和接口的变更
  • 是否包括对“成功”、“失败”的定义
5. 需求其他方面的核对表

需求的质量:需求定义自身所表现出来的质量;需求的清晰性、一致性、可测试性等
需求的完备性:需求是否可以覆盖问题定义所描述的信息;是否不包含不能实现的需求

6. 处理需求变更
  1. 检查需求核对表
  2. 确保每一个人知道需求变更的代价
  3. 建立一套变更控制程序
  4. 使用能适应变更的开发方法
  5. 放弃这个项目
  6. 注意项目的商业案例

1.5.3.4 明确软件架构的个组成部分(架构的先决条件)

架构的质量决定了系统的概念完整性,而系统的概念完整性决定了系统的最终质量.一个经过慎重考虑的架构为从顶层到底层维护系统的概念完整性提供了必备的结构和体系,他为程序员提供了指引–其细节程度与程序员的技能和手边的工作相匹配.它将多个开发者或者多个开发团队可以独立工作.

image

离开了良好的软件架构,你可能瞄准了正确的目标,但却使用了错误的方案.也许完全不可能有效成功的构建.

1. 软件架构定义

Software Architecture:软件设计的高层部分,用于支撑更加细节的设计的框架

  • 明确的架构设计也是构造的先决条件
  • 软件构造之前要check是否已经在整个系统范围内定义了相应的框架结构。
2. 架构的别称
  • 系统架构( System Architecture)
  • 顶层设计( Top-level Design)
3. 架构的重要性

软件架构是构建计算机软件实践的基础.

  • 软件架构定义了用于描述整个系统各个方面的草图
  • 是一个软件系统从整体到部分的最高层次的划分
  • 建造一个系统所作出的最高层次的、以后难以更改的,商业的和技术的决定
4. 架构的两个要素
  • 元件划分
  • 设计决定
5. 架构的典型组成部分–程序的组织结构
  • 以概括的形式对有关系统做整体的综述:综述的目的是使得所有的构造块能够形成一个整体
  • 定义程序的主要构造块:每个构造块实现一种高层功能
  • 每条需求中的功能特性都至少有一个构造块来覆盖:明确定义各个构造块的职责
  • 每个构造块负责某个特定区域的事情:明确每个构造块的通信规则;构造块相互之间的调用关系
6. 架构设计的典型组成部分–主类Major Classes

架构应描述主要的类 及其责任,已经该类与其他类如何交互

image

对那些构成80%的行为的20%的类进行详细说明

7. 架构设计的典型组成部分–数据设计

架构应描述主要文件和数据表的设计

  • 针对选择不同数据结构的理由给出解释
  • 例如:为什么用堆栈而不用数组等

架构应详细定义所用数据库的高层组织结构和内容

  • 示例:

image

8. 架构设计的典型组成部分–业务规则

对于架构所依赖的业务规则进行详述

  • 详细描述业务规则
  • 同时描述业务规则对系统设计的影响

如:客户信息的过时时间不能超过30秒

image
image

9. 架构设计的典型组成部分–UI(User Interface)用户界面设计

架构应该详细定义WEB页面格式,GUI,命令行接口等的主要元素.

image

10. 架构设计的典型组成部分–安全性

架构应该描述实现设计层面和代码层面安全性的方法.

  • 建立威胁模型
  • 制定编码规范
    1. 处理缓冲区的方法
    2. 处理非受信数据

image
image

11. 架构设计的典型组成部分–性能performance

如果需求关注性能,就应该在需求中详细定义性能目标.

主要包括各种资源(速度,内存,成本),及其之间的优先级.

12. 架构设计的典型组成部分–可伸缩性 scalability

可伸缩性是指系统增长以满足未来需求的能力

  • 架构应描述系统如何应对用户数量,服务器数量等增长
  • 若预计系统不会增长,而且可伸缩性不是问题要给出这一假设
13. 架构设计的典型组成部分–互用性 interoperability

系统与其他硬件或软件系统的交互

14. 架构设计的典型组成部分–国际化/本地化

image

  • 软件国际化( SW Internationalization, I18N)

I18N是在软件设计和文档开发过程中,使得功能和代码设计能处理多种语言和文化传统,使创建不同语言版本时,不需要重新设计源程序代码的软件工程方法

  • 软件本地化( SW Localization, L10N)

L10N是将一个软件产品按特定国家/地区或语言市场的需要进行加工,使之满足特定市场上的用户对语言和文化的特殊要求的软件生产活动。

  • G11N = I18N + L10N

  • I18N

支持Unicode字符集、双字节的字符;分离程序代码和显示内容消除Hard code使用Header files 去定义经常被调用的代码段;改善翻译文本尺寸,具有调整的灵活性支持各个国家的键盘设置;支持文字排序和大小写转换;支持各个国家的度量衡,时区,货币单位格式等的设置;国际化用户界面设计(自我定义)。
  • L10N
翻译地区文化、宗教度量衡和时区等软件用户界面( UI)联机文档 (帮助文档和功能性的PDF文档)热键设置
15. 架构设计的典型组成部分–错误处理

架构需要定义一种“一致地处理错误”的策略

  • 错误处理被认为是编码中的挑战之一
  • 错误处理需要在代码约定层进行描述

错误处理需要考虑的问题

  • 纠正还是检测
  • 主动还是被动
  • 错误消息格式
  • 异常处理
16. 架构设计的典型组成部分–容错性
  • 容错是增强系统可靠性的技术
    1. 检测错误
    2. 从错误中恢复
    3. 包容错误
  • 容错与错误处理的区别
    1. 容错强调对错误的包容
    2. 出错处理强调如何处理发生的错误
    3. 架构中应定义容错类型
      image
16. 架构设计的典型组成部分–变更策略
  • 构造变更策略的目的:令架构足够灵活,以适应可能出现的变化
  • 针对不同的变更情况描述处理策略:列出有可能变更的功能,说明如何实现;列出变更可能发生的位置,说明如何隔离
17. 架构设计的典型组成部分–架构的总体质量
  • 优秀架构的特点
    1. 描述了开发过程中的多种变更方式
    2. 描述了主要决策的动机
    3. 保持较高的编程语言无关性
    4. 指出有风险的区域
    5. 包含对系统的多个视图
18. 架构检查表

image
image

1.5.3.5 前期准备工作的时间分配

  • 前期工作的时间根据项目有所变化:一般而言,需要投入10%~20%的工作量以及20%~30%的时间
  • Check需求的时间:取决于需求的稳定性以及项目的大小
  • Check架构的时间:取决于软件的类型

1.5.3.6 开始软件构造的先决条件

  • 明确所开发项目的类型
  • Check需求定义:根据需求核对表检查相应的需求定义是否完成
  • Check软件架构:根据架构核对表检查各个组成部分是否完成

小结

1. 软件构造的概念

1.1 测试和调试的区别

  • 测试是为了发现错误
  • 调试是为了改成错误

1.2软件开发包括哪些

问题定义             需求分析       实现计划       总体设计详细设计 (部分)    编码实现       系统集成       单元测试(部分) 系统测试             校正性的维护   功能强化

1.3 软件构造活动主要是其中哪些部分?(以上黑体部分)

详细设计 (部分)    编码实现       系统集成       单元测试(部分)

1.4 软件构造的重要性

  • 构造活动是开发软件的重要组成部分
  • 构造活动在开发软件中处于枢纽地位
  • 把主要精力集中于创建活动,可以极大地提高程序员的生产效率
  • 创建活动的产品,源代码,往往是软件的唯一精确描述
  • 创建活动是唯一一项必不可少的工作

1.5 隐喻(Software Metaphors)

  • 常见的软件隐喻 (简单了解)
  • 软件书写:写代码(Writing Code)
  • 软件播种:生成系统(Growing a System)
  • 软件珍珠培植法:系统积累(System Accretion)
  • 软件创建:建造软件(building software)
  • 实用软件技术:智能工具箱(The Intellectual Toolbox)
  • 复合隐喻(Combing Metaphors)

2. 软件构造的前期准备工作

2.1 软件构造的前期准备工作有哪些?

  • 辨明软件项目的类型
  • 明确问题定义 (问题定义:项目要解决的问题是什么)
  • 明确需求规约 (需求定义详细规定了软件系统应该做什么)
  • 明确软件架构的各组成部分(软件设计的高层部分,用于支撑更加细节的设计的框架)

前期准备工作并非一成不变,构建活动的准备工作要根据项目特点调整,体细节随项目的不同会有很大变化

2.2 什么是软件构造的前期准备工作

  • 软件构造的前期准备工作是复查性的活动
    1. 明确前导性的工作结果有哪些
    2. 重新审视前导性工作是否完成
    3. 明确前导性工作完成的程度如何
  • 准备工作的中心目标是降低风险
    1. 糟糕的需求分析
    2. 糟糕的项目计划
1 0
原创粉丝点击