零、基本常识 & 缩写
- 软件生命链:requirement -> design -> coding -> testing -> evolution
- 测试种类:单元测试,集成测试,系统测试
- CASE:computer-aided software engineering
- SRS:software requirement specification
- TBD:to be determined
- SCM:Software Configuration Management
- V&V:Velidation and Verification
一、General
- quality对不同的人意味着不同的事情,并且可能互相矛盾。
- productivity和quality负相关
- cost和quality正相关
- 需求是变化的,并且在任何阶段都几乎不可避免,用户看到的越多就想要的越多。
- 了解需求是重要的,没有真正的用户就去模拟一些
- 明确需求的优先级
- 原型(prototype)分为一次性/进化型两种,选择哪种的关键在于核心需求是否明确,不明确->一次性。一次性原型:快点做,只做不确定的功能,进化型原型:只做确定的功能。
- 每次更新一点点
- 对于复杂问题的简单解决方案要警惕
- 使用某种技术之前要了解它的原理,否则没法好好使用
- 目标在任何时候都是重要的
- 开发之前就要写文档,而非开发完成后。
- 不要害怕犯错
- 不要盲从,无论是新技术,还是大多数人的观点
- 活到老学到老:conferences, magazines
- 技术文档:尽量在选词和句子结构上保持一致。不是为了美,是为了效率
- 要负责!
二、Requirement
- 目的是明确问题和需求,并且明确系统的外部行为(满足需求的方式)而非细节
- 明确需求:不能错,不能少。明确对于不同的用户,每个需求到底意味着什么。
- 及时和用户交流:少变。必要时和用户一起工作
- 收集数据、充分分析
- 多用原型
- 尽早发现问题,尽早解决
- 需求和设计分开
- 记录每个需求的背景、变更历史,需要包括时间、场合、相关人员(便于追溯)
- SRS需要各方审核
- SRS需要适当的分类方式与展示结构
- SRS需要简洁
- SRS需要尽量减少歧义性
- 修改记录需要保留,方便了解背景和历史。
- 文档需要分为自然语言和代码语言两种。先写前者,后写后者。
- 可靠性(Reliability)很难简单量化,需要靠其他具体指标来量化,例如错误率等
- 文档中需要写到环境和预期不符的情况下,系统如何处理。例如QPS超了
- 文档中可以由不确定项,但是必须表明,何时由谁负责确定这一项
- 需求最好用数据库存储。表的内容包括:id、内容、与其他需求的关系(父子关系等)、重要性、预期冲突、来源、产品版本号等
三、Design
- 设计系统框架,明确每个部分的功能
- 用requirement-design表格来维护需求和设计的关系。行是每个design components,列是需求
- 方案n选1,多角度衡量,选最好
- 需求文档是设计的先决条件,必须贴近需求来设计
- 注意封装
- 能复用就复用,不要重复造轮子
- special cases不利于管理,如果special cases过多就重构
- 开发者和维护者都需要【完全理解】(划重点)设计文档
- 设计文档需要注意层次,便于reader自顶向下的理解
- 系统需要维持一致性(例如各个模块的错误信息、调用方式等)
- 注意模块化
- 设计时,需要注意:错误情况、是否好维护、通用性、算法复杂度
- 一个模块的设计文档应该包含且仅包含它的下游模块需要知道的信息,例如接口、变量、依赖、基本功能等
- clean,simple,elgant,fast,maintainable,easy to implement
- 设计时需要考虑到外部条件,包括硬件条件、输入情况、qps等
- 需要处理无效输入,返回错误,而非当作正常输入一样处理
四、Coding
- 避免开发过快,开发前一定要提前考虑好requirement和design
- 自顶向下的coding
- 先写注释,后写代码
- 一定记住代码先是给人看的,其次才是给机器看的
- 每个部分单独单测,不要一起测试太多
- 做好CR(CR时间=开发时间)
- 语言知识是次要的,quality programming的常识才是最重要的
- 代码风格很重要!
- 避免tricks
- 数据模块单独封装
- 尽量少用全局变量,不好控制,尽量封装
- 避免嵌套过多
五、Testing
- 用requirement-test表格来维护需求和test的关系,方便确定test优先级,好维护
- 测试的目的就是找到错误,暴露错误,不要怕犯错
- test planning应该和开发并行,设计者应该阅读SRS
- 需要独立的test planner和执行者,rd只应该负责debug和单元测试,qa应该负责check单元测试和实施集成测试、系统测试
- error具有模块集中性,50%的错误出现在20%的模块中
- 白盒+黑盒
- 测试用例中应该包括预期结果
- 测试用例应该包含各种无效输入
- McCabe标准:测试程序复杂度
- 测试需要有标准:结束标准(新发现的错误率,钓鱼的错误有没有发现),覆盖率(覆盖多少语句,覆盖多少分支,覆盖多少路径)
- 测试出错误后,需要分析错误原因(方法论,而非具体执行)
六、Management
- 管理包括:planning,controlling,monitoring,reporting
- 理解用户需求是最重要的
- 员工质量>员工数量
- listen to 员工 & 以身作则
- 办公区要保持安静,和其他区域隔离开
- 必须要有优先级
- productivity衡量方法:source lines of code(SLOC)每人月和function points(FP) 每人月。但是两种方法都不完美
- productivity与语言有关
- team productivity是重要的,不一定是个人*n,与配合有关
- 不要设定不现实的ddl
- 及时调整排期
- 计划要细致:PERT图记录不同任务之间的依赖;甘特图记录时间;milstones设定;文档和代码规范;人员分配
- 及时更新计划:需求变了,时间安排延误了,发生了严重的错误,原始条件变了,等等
- 延迟的计划只会越来越延迟
- 十个最重要的风险点:人员问题,不现实的时间安排,不理解用户需求,用户界面不好,浮夸的修饰,需求变更没有控制好,复用,外部表现功能,响应时间,超出当前技术范围
- 选择适当的process model:waterfall,一次性原型,增量开发,螺旋模型等等
- 汇报的重点在于现实和计划的差别
- 硬件的更新换代要持乐观态度,软件的更新换代要持悲观态度
- 正视错误和失败,越逃避越严重
七、Product Assurance
- Product Assurance 包括Software configuration management, Software quality assurance, Software verification and validation, Testing
- SCM:如何反应软件问题,需求变更如何反馈,有个board安排需要变更的需求,等等
- SCM最好和开发团队互相独立
- SCM不能只安排新人和渣渣,牛人也应该轮换去做
- 中间版本的产出要有名字和编号
- 注意备份,备份变更之前的版本
- change发生的时候,首要解决变更需求,如果中间发现了其他问题,次要解决
- 每次change要详细记录:需求,背景,发生的时间、地点、原因和人物,影响的产品功能
- V&V:第三方验收,包括Validation(顺序验收,检查每个功能是否满足前一步的需求)和Verification(每个功能是否满足用户需求)
八、Evolution
- Evolution包括:新需求,优化代码性能,修复bug
- change是不可避免的,即使真的需求能保持不变,环境也在变化
- 熵增原理:系统的复杂度会上升,组织程度会下降
- 马太效应:错的越多的越可能错
- 系统越老,维护的成本越大
- 语言影响维护难度
- 维护阶段比开发阶段产生的错误更多
- fix problem之前必须完全的理解它,否则会引入新的问题
- fix problem之前先修改SRS,让所有角色都知晓
- fix problem之后必须做回归测试
- 提升性能之前,先检查哪里占用资源最多(profiler)
- 一次比平均规模更大的更新,很可能质量比较差