1.1 “预测需求变化”概述
需求的变化总是存在于项目的实施过程中,因为客户大多“走一步看三步”,只在试用了软件后才肯提出进一步的需求
造成这种情况的根本原因是:客户在项目初期并不准确地理解软件能做什么
在需求变化过程中,软件采用不同的结构(模式/技术/规范...)后,软件改动所需要的工作量却也是大相径庭
项目组应该努力使软件具有易于修改的结构/模式,主要的依据当然是“预测需求变化”。既然客户在项目初期并不确切地清楚该软件能做什么,他是无法准确表达他的期望的,那么项目组只能勉为其难,自己努力地试图预测需求变化
当然项目组也可以不去预测这种需求变化,直接根据需求书划分软件模块(然后被动地等待需求变化),但这显然是违背了计划工作的初衷
只有在软件工程中强制要求“预测需求变化”的阶段,才能说软件工程体现了软件开发本身的特点
在这个“预测需求变化”的阶段,项目组了解了对软件需求(或者还包括其它信息)后,通过考虑预测需求变化,确定“什么样的软件结构最有可能在软件完工时能满足用户的使用要求”
//2.1 改进工作量与需求变化.例子
做一个属性设置的功能:
0.基本界面是一个对话框,该对话框将用于设置企业的物流中的产品/零件属性
1.对话框的左边是一个树控件,右边是一些标签页
树控件是标签页的目录,一个根结点代表一套属性配置
标签页上则分页显示了所有要设置的属性,每种属性标签页对应一个属性数据类
2.属性配置有多个子结点,每个子结点都分别对应若干个属性数据类,选中该结点后显示相应的标签页供用户修改
例一:要求调整属性配置的子目录结点的位置,多加一个文件夹,把几个同类的结点放到该一个文件夹下(于是不同文件夹有了同名结点)
只要你结点的标识不是显示名(指:通过结点的显示名确定相关的属性数据类),只是在改变一下插入结点的顺序就可以了
但是你是用结点上显示名变量来作为结点标识的话,那么由于同名结点的出现,基本上目录树得重写了
例二:要求为每个配置集增加调度分类的概念:把原来的那套属性全部更名为“自制零件”配置,然后再增加“外购零件”的配置
先为每个数据类加一个Scheme 的成员(这就涉及几乎所有的属性数据对象的操作,保存/加栽/查找...)
然后改目录树(这包括大部分的目录树代码,调整结点插入顺序,确定结点关联的数据类对象的代码...)
这个改动必然会涉及了本功能代码的所有方面,但这个要求肯定是项目组无法拒绝的,无奈吧,无奈地改程序吧
//2.2 改进工作量与需求变化.编程经验
前一个例子中,减少改动工作量应该依靠丰富的编程经验,就是看程序员有没有好的代码习惯
我们可以把这些情况理解为代码兼容性的的问题,因为从预防的角度来理解,它们都是可以有放之四海而皆准的模式,可以依靠采用通用的模式来提高代码的可修改性
比如例一情形,在MFC 中的树控件的结点有个int 类型的额外空间(叫做ItemData)可以用来作为结点标识,其它也有一些类库提供了string 类型的额外空间可用作结点标识的
在这类的需求变化中,如果开始不知道,是写完代码后被要求移植到第一次接触的系统上,那么辛苦你了,一丝一毫地分析,一点一滴地对待吧;但是如果你已经接触过类似的问题,只要注意一下相关的地方,移植工作是一点工作量也没有
对于“放之四海而皆准的模式”,比较合理的解决方案是设立研发部,它就专职研究能在各个系统/情况下大多通用的代码模式,按主题(如,数据库访问代码的兼容性、打印绘图代码的兼容性、树控件操作代码的兼容性...)向开发部门发布一些编程注意事项
另外,如果目录树的组织不是十分符合专业的习惯的话,当然也影响着产品的质量,但客户是不会强烈坚持这些要求变化的,所以这大多不会成为验收的障碍,不需要花太多精力在这些方面计较
如果改动量太大的话而有其它的更重要的事,只管把要求挡回去就是了
挡不回去的兼容性要求也有,比如数据库访问,这类课题如果不是在一开始就提出来的话,肯定是可以获得提高价钱延缓验收之类的优惠,那就不太一样了嘛,可以坐下来再谈的嘛
//2.3 改进工作量与需求变化.预测业务性的需求变化
最后一个例子说的是,真正的难以拒绝的“需求变化”来自于业务逻辑
定性地说,客户提出的需求变化的预兆都是会在应用业务内蕴涵着的,进而言之,为了制作行业软件,项目组要必需要首先成长成为领域专家,不仅仅是能够于客户用行业术语熟练地交流,还要包括精通业务流程等每个方面
但大多数的项目内,项目组在项目初期是没有时间成长成行业专家的,项目组拿到的只是一份需求说明书被要求立即作出软件,仅此而已
偶的对策是整理需求,从已知的需求中整理发掘需求的变化
偶是通过整理需求书绘制数据流图,建立起所有数据类型字典,然后根据数据类型的业务语义重绘数据流图,把新的数据流图作为未来的程序的“运行时结构”的发展蓝图。高斯的成功在于他依靠了逻辑的完备性,根据数据的语义能达到某种程度的完备性
比如前面例子中,在接到客户要求“要设置零件的一些属性”的要求后(基本上客户就是这样措辞的,而不是说自制件属性,这就是问题所在),应该对照重绘后的“数据流图”,考察各种数据类型对该功能的扩展
既然在PDM的别处都区别了“自制件/外购件”的概念,那么在结合所设置属性的使用方式后(自制零件关心的是加工的工作安排,外购零件关心的是供应商和价格),是很容易可以分辨出客户在这里的“零件”是指“自制零件”还是“外购零件”,或者两者皆可
所以偶觉得在最初发出对话框的任务单之前就可以避免这个问题,偶认为这不是合理范围内的成本提高!关键的问题是项目经理没有放对话框放在项目的全局里,没有找到“自制零件”、“外购零件”这两个概念,没有结合这两个概念来考虑这个功能需求
注:
从根本上说,没有专业的需求变化的预测,整个项目进度仍然是无法保证的
所以,“归纳了基本数据类型后,根据数据类型的业务语义重绘数据流图”也不例外,它并不完美,有的时侯需求的增加也会改变(而不只是增加)数据流类型
//3.1 软件结构.简述
具有兼容性的结构/模式是需要时间积累或组织攻坚,它不应该是在特定项目的计划阶段中考虑的问题
项目的计划要对付的问题是“业务性的需求变化”
//3.2 软件结构.业务性的需求变化
“只有在发现了软件的结构/模式不适用需求变化,才会有大量源代码需要被改写重写”
比如上面的例子中,如果先考虑到设立Scheme 允许按照调度分类进行扩展,就不需要从头到脚再挖一遍代码
如果原先未使用恰当的结构/模式,一般一个对话框的改动量是3 人*天,如果情况更坏的话,原来的代码都报废,重写!这样就导致了工作量的反复,项目进度才会变得不易控制了
既然软件的结构/模式如此重要,那么到底什么是软件的结构/模式呢?软件结构可以指“源代码的组织结构”,也可以是“程序运行时的结构”
如过你仔细考虑后会发现,需求的改变所影响到的不是“源代码的组织结构”只是“程序运行时的结构”,顶多是通过后者影响前者
客户的要求不会直接针对你的“源代码的组织结构”,实际上他只会要求改一些功能,只有在“程序运行时的结构”无法支持新的功能时,程序员才会被迫改变“程序运行时的结构”,这时才有可能会影响“源代码的组织结构”,导致工作量的反复
仔细地辨别这个过程是有意义的,在这个过程中,你会发现从“源代码的组织结构”到“程序运行时的结构”的编译过程中消失的那些特性,都可以被证明与“业务性的需求变化”无关
偶的观点是:以“程序运行时的结构”这个概念来理解概要设计阶段的工作内容将使工作更加中肯有效
这样你在这个阶段中才会专心考虑:有那些数据会被加载到内存,何时加载,用列表还是树的形式组织内存中的数据;是否预留额外的状态成员...
而不是:软件的结构选COM DLL还是API DLL,用名字空间还是用类组织代码,编译链接时可以用这个选项...
如果不用程序运行时来理解的话,偶觉得大部分的人是会概要设计阶段考虑COM DLL还是API DLL这类问题的,但这个问题稍晚讨论也将对项目无碍
也许项目组在这个阶段应该暂时撇开“软件开发”本身,忘了以往那些熟悉的计算机术语,无论是名字空间、类、成员变量或是重载、继承...
请专注于学习业务逻辑和构造优秀的运行时结构/模式!运行时结构恰好将忽略软件的结构中与“业务性的需求变化”无关的许多东西
在严酷的考场中,哪怕是同一个老师讲的课,专心的人可以拿满分,不专心却可能连补考的机会也没有
//附录 杂谈
编程经验杂谈:
“使用具有兼容性的程序模式”是编程水平的重要方面。当程序员交差的时候,至少经理布置的任务在字面上的要求肯定是达到的,如果程序员不注重兼容性的话,有任何一点的改动,整个代码就得重写
采用何种程序模式在代码量上的差别并不大,但它留给维护人员的工作量却是差别巨大。只有在项目是一次性买卖,没有维护需求,你才不必在乎程序模式的兼容性
如果没有专门的研发部,或者研发部未致力于“具有兼容性的程序模式”,那么这种程序员只能靠程序员的自己积累,如果程序员不注意的话,可能他/她会有编程经历而没有编程经验(只能做一次性买卖了)
预测业务性的需求变化杂谈:
有人说例三是合理的成本增加,说实施一个大项目就是需要两年时间,偶无言以对
如果所有的软件项目都不去预测的话,结果对某个公司来说也没什么差别,就像没有空调前用电风扇也可以过夏天一样
“根据数据类型的业务语义重绘数据流图”其实这只是个人经验而已,结合使用了数据流图和数据字典两种方法。也不是偶不爱时髦,实在是觉得OOP太神奇伟大了,强大却自由得不易把握,所以偶个人不习惯用
软件维护杂谈:
一般的项目验收后都会流10%的尾款,等正常运行一段时间后再付。于是软件工程又多了一个主题,维护软件捉BUG。捉虫的基本步骤是这样的,在接到缺陷报告后,维护程序员首先在程序的调试状态中重现缺陷,然后设置断点监视变量的取值,在确定哪个变量的值不对时,就是找到了臭虫
为了研究“设置断点监视变量”的过程,我们可以把一个运行单位(如一个菜单命令的执行、一个鼠标单击消息的处理...)看作一条生产流水线,它将是对程序运行时结构的一个子集,是指运行时结构中与本次运行单位相关的所有部分
一个缺陷报告总是针对某条流水线的,所以捉虫工作也就是以流水线为调试对象的,也只有在了解相关的运行流水线以后,才能很快地确定运行单位中的那些变量的值是缺陷关键,选择被监视的变量就是快速捉虫的诀窍
只有真正全面地理解了运行时结构的框架以后,才能在接到缺陷报告后很快决定如何设置断点和监视那些变量
软件工程之“概要设计”杂谈:
其实捉虫工作是从项目之初就有的,但那时是原作者捉虫,维护阶段则不是。你可以回想维护别人的代码的经历,是不是有“揣摩变量在业务逻辑中的意义”这样一个过程,显然这就是从“源代码的组织结构”推断“程序运行时结构”的过程。这个过程的存在,也足以证明在软件工程中“程序运行时结构”比“源代码的组织结构”更为重要
软件的结构和程序的运行时结构是两个不同的概念,“概要设计”一词的失败就在于忽视了两者的区别“软件开发项目的过程”的定义
//主题:项目的目标
源代码(通过源代码可以得到可执行文件)
用户手册(对程序运行时结构的描述,也包括安装说明)
命令参考手册(各个菜单命令的详细说明/注意事项等,按命令罗列)
岗位操作手册(说明要实现某个操作需要怎样使用哪几个命令)
//主题:项目的计划
市场定位及可行性研究报告
软件需求说明书
软件扩展需求描述
项目开发计划
//主题:项目的实施
数据格式定义书/数据库设计说明书
软件的运行时结构定义书和发布说明书[概要设计]
软件源代码的组织单元说明书(详细设计)
测试方案说明书
测试分析报告
开发的阶段汇报(根据是开发计划中的里程碑[开发制度月报])
项目经验总结
项目文件的整理归档[模块开发卷宗]
煤炭网版权与免责声明:
凡本网注明"来源:煤炭网www.coal.com.cn "的所有文字、图片和音视频稿件,版权均为"煤炭网www.coal.com.cn "独家所有,任何媒体、网站或个人在转载使用时必须注明"来源:煤炭网www.coal.com.cn ",违反者本网将依法追究责任。
本网转载并注明其他来源的稿件,是本着为读者传递更多信息的目的,并不意味着本网赞同其观点或证实其内容的真实性。其他媒体、网站或个人从本网转载使用时,必须保留本网注明的稿件来源,禁止擅自篡改稿件来源,并自负版权等法律责任。违反者本网也将依法追究责任。 如本网转载稿件涉及版权等问题,请作者在两周内尽快来电或来函联系。
网站技术运营:北京真石数字科技股份有限公司、喀什中煤远大供应链管理有限公司、喀什煤网数字科技有限公司
总部地址:北京市丰台区总部基地航丰路中航荣丰1层
京ICP备18023690号-1 京公网安备 11010602010109号
