技术标签: 文档 产品 软件工程和UML 测试 construction 工作 任务
1. 传统开发流程的问题 随着我们所开发的软件项目越来越复杂,传统的瀑布型开发流程不断地暴露出以下问题: (1)需求或设计中的错误往往只有到了项目后期才能够被发现例如:系统交付客户之后才发现原先对于需求的理解是错误的,系统设计中的问题要到测试阶 段才能被发现。 在传统的瀑布模型中,需求和设计中的问题是无法在项目开发的前期被检测出来的,只有当第一次系统集成时,这些设计缺陷才会在测试中暴露出来,从而导 致一系列的返工:重新设计、编码、测试,进而导致项目的延期和开发成本的上升。
2. 采用迭代化开发控制项目风险
与传统的瀑布式开发模型相比较,迭代化开发具有以下特点: (1)允许变更需求 需求总是会变化,这是事实。给项目带来麻烦的常常主要是需求变化和需求"蠕变",它们会导致延期交付、工期延误、客户不满意、开发人员受挫。通过向 用户演示迭代所产生的部分系统功能,我们可以尽早地收集用户对于系统的反馈,及时改正对于用户需求的理解偏差,从而保证开发出来的系统真正地解决客户的问 题。 在传统的项目开发中,由于要求一下子集成系统中所有的模块,集成阶段往往要占到整个项目很大比例的工作量(最高可达40%),这一阶段的工作经常是 不确定并且非常棘手。在迭代式方法中,集成可以说是连续不断的,每一次迭代都会增量式集成一些新的系统功能,要集成的元素都比过去少得多,所以工作量和难 度都是比较低的。 迭代化开发的主要指导原则就是以架构为中心,在早期的迭代中所要解决的主要问题就是尽快确定系统架构,通过几次迭代来尽快地设计出能够满足核心需求 的系统架构,这样可以迅速降低整个项目的风险。等到系统架构稳定之后,项目的风险就比较低了,这个时候再去实现系统中尚未完成的功能,进而完成整个项目。 开发人员通过每次迭代都可以在短期内看到自己的工作成果,从而有助于他们增强信心,更好地完成开发任务。而在非迭代式开发中,开发人员只有在项目接 近尾声时才能看到开发的结果,在此之前的相当长时间,大家还是在不确定性中摸索前近。 每次迭代都会产生一个可运行的系统,通过对这个可运行系统进行测试,我们在早期的迭代中就可以及时发现缺陷并改正,性能上的瓶颈也可以尽早发现并处 理。因为在每次迭代中总是不断地纠正错误,我们可以得到更高质量的产品。 |
(6)保证项目开发进度
每次迭代结束时都会进行评估,来判断该次迭代有没有达到预定的目标。项目经理可以很清楚地知道有哪些需求已经实现了,并且比较准确地估计项目的状 态,对项目的开发进度进行必要的调整,保证项目按时完成。
(7)容许产品进行战术改变
迭代化的开发具有更大的灵活性,在迭代过程中可以随时根据业务情况或市场环境来对产品的开发进行调整。例如为了同现有的同类产品竞争,可以决定采用 抢先竞争对手一步的方法,提前发布一个功能简化的产品。
(8)迭代流程自身可在进行过程中得到改进和精炼
一次迭代结束时的评估不仅要从产品和进度的角度来考察项目的情况,而且还要分析组织和流程本身有什么待改进之处,以便在下次迭代中更好地完成任务。
迭代化方法解决的主要是对于风险的控制问题,从下图可以看出,传统的开发流程中系统的风险要到项目开发的后期(主要是测试阶段)才能够被真正降低。 而迭代化开发中的风险,可以在项目开发的早期通过几次迭代来尽快地解决掉。在早期的迭代中一旦遇到问题,如某一个迭代没有完成预定的目标,我们还可以及时 调整开发进度以保证项目按时完成。一般到了项目开发的后期(风险受控阶段),由于大部分高风险的因素(如需求、架构、性能等)都已经解决,这时候只需要投 入更多的资源去实现剩余的需求即可。这个阶段的项目开发具有很强的可控性,从而保证我们按时交付一个高质量的软件系统。
迭代化开发不是一种高深的软件工程理论,它提供了一种控制项目风险的非常有效的机制。在日常的工作我们也经常地应用到这一基本思想,如对于一个非常大型 的工程项目,我们经常会把它分为几期来分步实施,从而把复杂的问题分解为相对容易解决的小问题,并且能够在较短周期内看到部分系统实现的效果,通过尽早暴 露问题来帮助我们及早调整我们的开发资源,加强项目进度的可控程度,保证项目的按时完成。
3. 管理迭代化的软件项目
当我们在实际工作中实践迭代化思想时,Rational统一开发流程RUP(Rational Unified Process)可以给予我们实践的指导。RUP是一个通用的软件流程框架,它是一个以架构为中心、用例驱动的迭代化软件开发流程。RUP是从几千个软件 项目的实践经验中总结出来的,对于实际的项目具有很强的指导意义,是软件开发行业事实上的行业标准。
3.1 软件开发的四个阶段
在RUP中,我们把软件开发生命周期划分为四个阶段,每个阶段的结束标志就是一个主要的里程碑(如下图所示)。
这四个阶段主要是为了达到以下阶段性的目标里程碑:
。先启(Inception):确定项目开发的目标和范围
。精化(Elaboration):确定系统架构和明确需求
。构建(Construction):实现剩余的系统功能
。产品化(Transition):完成软件的产品化工作,将系统移交给客户
每个目标里程碑都是一个商业上的决策点,如先启阶段结束之后,我们就要决定这个项目是否可行、是否要继续做这个项目。每一个阶段都是由里程碑来决定 的,判断一个阶段是否结束的标志就是看项目当前的状态是否满足里碑中所规定的条件。
从这种阶段划分模式中可以看出,项目的主要风险集中在前两个阶段。在精化阶段中经过几次迭代后,我们要为系统建立一个稳定的架构,在此之后再实现更 多的系统需求时,不再需要对该架构进行修改。同时,在精化阶段中,我们通过迭代来不断地收集用户的需求反馈,便得系统的需求逐步地明确和完整。
3.2 关于开发资源的分配
基于 RUP风险驱动的迭代化开发模式,我们只需要在项目的先启阶段投入少量的资源,对项目的开发前景和商业可行性进行一些探索性的研究。在精化阶段再投入多一 些的研发力量来实现一些与架构相关的核心需求,逐步地把系统架构搭建起来。等到这两个阶段结束之后,项目的一些主要风险和问题也得到了解决,这时候再投入 整个团队进行全面的系统开发。等到产品化阶段,主要的开发任务已经全部完成,项目不再需要维持一个大规模的开发团队,开发资源也可以随之而减少。在项目开 发周期中,开发资源的分配可以如下图所示。
这样安排可以最充分有效地利用公司的开发资源,缓解软件公司对于人力资源不断增长的需求,从而降低成本。另外一方面,由于前两个阶段(先启和精化) 的风险较高,我们只是投入部分的资源,一旦发生返工或是项目目标的改变,我们也可以将资源浪费降到最低点。在传统的软件开发流程中,对于开发资源的分配基 本上是贯穿整个项目周期而不变的,资源往往没有得到充分有效地利用。
基于这种资源分配模式,一个典型的项目在项目进度和所完成的工作量之间的关系可能如下表中的数据所示。
先启 精化 构建 产品化
工作量 ~5% 20% 65% 10%
进度 10% 30% 50% 10%
3.3 迭代策略
关于迭代计划的安排,通常有以下四种典型的策略模式:
(1)增量式(Incremental)
这种模式的特点是项目架构的风险较小(往往是开发一些重复性的项目),所以精化阶段只需要一个迭代。但项目的开发工作量较大,构建阶段需要有多次迭代来实 现,每次迭代都在上一次迭代的基础上增加实现一部分的系统功能,通过迭代的进行而逐步实现整个系统的功能。
(2)演进式(Evolutionary)
当项目架构的风险较大时(从未开发过类似项目),需要在精化阶段通过多次迭代来建立系统的架构,架构是通过多次迭代的探索,逐步演化而来的。当架构建立 时,往往系统的功能也已经基本实现,所以构建阶段只需要一次迭代。
(3)增量提交(Incremental Delivery)
这种模式的特点产品化阶段的迭代较多,比较常见的例子是项目的难度并不大,但业务需求在不断地发生变化,所以需要通过迭代来不断地部署完成的系统;但同时 又要不断地收集用户的反馈来完善系统需求,并通过后续的迭代来补充实现这些需求。应用这种策略时要求系统架构非常稳定,能够适应满足后续需求变化的要求。
(4)单次迭代(Grand Design)
传统的瀑布模型可以看作是迭代化开发的一个特例,整个开发流程只有一次迭代。但这种模式有一个固有的弱点,由于它对风险的控制能力较差,往往会在产品化阶 段产生一些额外的迭代,造成项目的延误。
这几种迭代策略只是一些典型模式的代表,实际应用中应根据实际情况灵活应用,最常见的迭代计划往往是这几种模式的组合。
3.4 制定项目开发计划
在迭代化的开发模式中,项目开发计划也是随着项目的进展而不断细化、调整并完善的。传统的项目开发计划是在项目早期制定的,项目经理总是试图在项目 的一开始就制定一个非常详细完善的开发计划。与之相反,迭代开发模式认为在项目早期只需要制定一个比较粗略的开发计划,因为随着项目的进展,项目的状态在 不断地发生变化,项目经理需要随时根据迭代的结果来对项目计划进行调整,并制定下一次迭代的详细计划。
在RUP中,我们把项目开发计划分为以下三部分:
(1)项目计划
确定整个项目的开发目标和进度安排,包括每一个阶段的起止时间段。
(2)阶段计划
当前阶段中包含有几个迭代,每一次迭代要达到的目标以及进度安排。
(3)迭代计划
针对当前迭代的详细开发计划,包括开发活动以及相关资源的分配。
项目开发计划也是完全体现迭代化的思想,每次迭代中项目经理都会根据项目情况来不断地调整和细化项目开发计划。迭代计划是在对上一次迭代结果进行评 估的基础上制定的,如果上一次迭代达到了预定的目标,那么当前迭代只需要解决剩下的问题;如果上一次迭代中留有一些问题还没有解决,则当前迭代还需要继续 去解决这些问题。所以必须注意,迭代是不能重叠的,即你还没有完成当前迭代时,你决不能进入下一迭代,因为下一次迭代的计划是根据当前迭代的结果而制定 的。
In[1]:from matplotlib import pyplot as pltimport numpy as npimport matplotlib as mplmpl.rcParams['font.sans-serif'] = ['SimHei'] # 中文字体支持对于折线图的绘制,在之前博客的示例中都有使用,在面向对象绘图方法中,一..._请完成以下程序填空,用matplotlib面向对象的绘图库设计一个包括散点图和折线
poj 1006 题的思路不是很难的,可以转化数学式:现设 num 是下一个相同日子距离开始的天数 p,e,i,d 如题中所设!那么就可以得到三个式子:( num + d ) % 23 == p; ( num + d ) % 28 == e; ( num + d ) % 33 == i;p,e,i,d 是我们输入的,那么我们需要求出num即可,为了方便,我们将num..._east central north america 1999, poj 1006, 程序设计实习2007.
一个数组先升序再降序,用最优时间复杂度,求最大值?例如[1,2,2,2,2,3,1]public int getMax(int[] arr) { if (arr.length < 2) return arr[0]; int lo = 0, hi = arr.length - 1; while (lo < hi) { int mid = lo + (hi - lo) / 2; if (arr[mid_先升后降数组找最大值
JDK8新特性1. Java8概述1. Java8概述Java 8 (又称为jdk 1.8) 是Java 语言开发的一个主要版本。Java 8 是oracle公司于2014年3月发布,可以看成是自Java 5 以来最具革命性的版本。Java 8为Java语言、编译器、类库、开发工具与JVM带来了大量新特性。*..._jdk8优点
只需要一个pinyin4j-2.5.0 目前新版本下载地址:http://download.csdn.net/download/m0_37828590/9809067import net.sourceforge.pinyin4j.PinyinHelper;import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;imp
业务需求:后台返回的时间是一串数字格式,我们需要把它转换为需要渲染的日期格式 : 2020/12/6 12:00:071.原始的后台数据const oldtime = 16072224062.先用new Date()转换成标准格式const date = new Date(oldtime);得到日期标准格式3.处理成自己想要的日期格式const year = date.getFullYear();const month = date.getMonth() + 1;_js时间 一串数字
之前用stm32驱动过esp8266,最近又接触8266的时候,发现原子哥更新了8266的固件库,可以连接原子云,最最重要的是,还是免费的,用起来。目录1.工具(串口工具,固件更新工具,原子云固件)2.烧写原子云固件2.1 硬件信息2.2 烧写固件时接线2.3 烧录过程3.原子云注册4.连接原子云5.出现dns fail!1.工具(串口工具,固件更新工具,原子云固件)链接:https://pan.baidu.com/s/1dhbE7jNIl_rjYqTh6yL2._正点原子atk-esp8266程序
A.门牌制作题解624#include<iostream>using namespace std;int nums[10];void solve(int i){ while(i) { nums[i%10]++; i /= 10; }}int main(){ for(int i = 1; i <= 2020; i++) solve(i); cout << nums[2]_第11届“蓝桥杯”大赛河南省java程序设计大学组b组
想要实现规约转换必须先得理解modbus rtu/ascii/tcp 规约. 我吃了这个亏,一开始就专注于小组的代码, 导致看了半天云里雾里, 随开始找资料, modbus规约那份pdf可以看看, 理解三点:(1) 上下行报文的概念 (2) 正常报文和异常报文 (3) RTU/ASCII报文帧之间的差别. 前面一点那份文档一点没提, 对我这种刚入行的人来说看起来不知所云. 关于理解ASCII模...
查看该表,发现并没有实现实例化接口。 通过下面方法反射出所有的属性,发现确实多了一个$change 和一个serialVersionUID。public static void showAnnotationWrodOther(){ Field[] fields = DbApp.class.getFields(); for (Field field : fiel..._c# update 不存在字段
目前我在项目中需要对播放的音频设置不同的速率(0.8、1、1.3倍),存在如下的疑惑:1.使用MediaPlayer,这个类是使用的最广泛的,但不提供相应的设置速率的方法。2.SoundPool,适合播放游戏中的急促 短暂的音效,只能播放大概10秒的音频,且不提供读完音频的回调方法。3.AudioTrack,这个类可以进行速率的设置,但只能播放已经解码的PCM文件流,如果是文件的话只支持wav格式..._android播放pcm怎么快进
封装json,获取url参数_h5跳转展示表格数据