.markdown-body{word-break:break-word;line-height:1.75;font-weight:400;font-size:15px;overflow-x:hidden;color:#333}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{line-height:1.5;margin-top:35px;margin-bottom:10px;padding-bottom:5px}.markdown-body h1{font-size:30px;margin-bottom:5px}.markdown-body h2{padding-bottom:12px;font-size:24px;border-bottom:1px solid #ececec}.markdown-body h3{font-size:18px;padding-bottom:0}.markdown-body h4{font-size:16px}.markdown-body h5{font-size:15px}.markdown-body h6{margin-top:5px}.markdown-body p{line-height:inherit;margin-top:22px;margin-bottom:22px}.markdown-body img{max-width:100%}.markdown-body hr{border:none;border-top:1px solid #ddd;margin-top:32px;margin-bottom:32px}.markdown-body code{word-break:break-word;border-radius:2px;overflow-x:auto;background-color:#fff5f5;color:#ff502c;font-size:.87em;padding:.065em .4em}.markdown-body code,.markdown-body pre{font-family:Menlo,Monaco,Consolas,Courier New,monospace}.markdown-body pre{overflow:auto;position:relative;line-height:1.75}.markdown-body pre>code{font-size:12px;padding:15px 12px;margin:0;word-break:normal;display:block;overflow-x:auto;color:#333;background:#f8f8f8}.markdown-body a{text-decoration:none;color:#0269c8;border-bottom:1px solid #d1e9ff}.markdown-body a:active,.markdown-body a:hover{color:#275b8c}.markdown-body table{display:inline-block!important;font-size:12px;width:auto;max-width:100%;overflow:auto;border:1px solid #f6f6f6}.markdown-body thead{background:#f6f6f6;color:#000;text-align:left}.markdown-body tr:nth-child(2n){background-color:#fcfcfc}.markdown-body td,.markdown-body th{padding:12px 7px;line-height:24px}.markdown-body td{min-width:120px}.markdown-body blockquote{color:#666;padding:1px 23px;margin:22px 0;border-left:4px solid #cbcbcb;background-color:#f8f8f8}.markdown-body blockquote:after{display:block;content:""}.markdown-body blockquote>p{margin:10px 0}.markdown-body ol,.markdown-body ul{padding-left:28px}.markdown-body ol li,.markdown-body ul li{margin-bottom:0;list-style:inherit}.markdown-body ol li .task-list-item,.markdown-body ul li .task-list-item{list-style:none}.markdown-body ol li .task-list-item ol,.markdown-body ol li .task-list-item ul,.markdown-body ul li .task-list-item ol,.markdown-body ul li .task-list-item ul{margin-top:0}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:3px}.markdown-body ol li{padding-left:6px}.markdown-body .contains-task-list{padding-left:0}.markdown-body .task-list-item{list-style:none}@media (max-width:720px){.markdown-body h1{font-size:24px}.markdown-body h2{font-size:20px}.markdown-body h3{font-size:18px}}
这是我参与更文挑战的第17天,活动详情查看: 更文挑战
假设一切都将运行良好
我们总是会假设: 一切都将运行良好, 每一项任务仅花费它所"应该"花费的时间
这里要求我们在做项目排期时, 要尽可能的考虑到所有的情况, 不要盲目自信, 也不要畏首畏尾, 要做到自信和迟疑相平衡, 在这里也可能会出现设计缺陷, 过早设计和过早优化. 但是是这种情况是所有项目不可避免的, 我们能做到的就是从全局出发, 统筹安排.
从全局出发
- 评估项目中所有会设计的点
- 确定项目的规划, 预期和目标
- 确定项目的开发规范, 文档的维护, 代理的管理
- 确定项目中的重要的时间节点, 也就是Milestone
- 确定参与项目的部门, 人员
- 罗列项目中有可能会遇到的问题, 如将要用到的新框架, 之前没有写过的新功能
深入局部之内
- 严格的细分功能模块, 及模块间的通信原则与方式
- 确定各个模块的人员, 及各个模块完成的时间结点
- 确定各个模块的工期安排
- 明确各个模块的完成的时间结点, 确定它们的主要顺序, 依赖顺序
最后根据全局分析和局部分析的结果, 来确定我们整个项目的安排.
人月神话
用人月作为衡量一项工作的规模是一个危险和带有欺骗性的神话.
错误的将进度与工作量相互混淆, 好比人员的数量和时间可以互换.
成本会随着开发产品的人数和时间的不同, 有着很大的变化, 进度却不是如此.
我们总是将人和工作量进行等价划分, 认为1个人做10天可以完成的项目, 10个人做1天就可以完成.
当意识到进度的偏移时, 下意识的反应是增加人力. 犹如用汽油灭火一样.
向进度落后的项目中增加人手, 只会使进度更加落后.
但是我们可能没有仔细思考过工作可能是不可切割的.
当向当前项目中增加人手时, 我们可能会遇到以下问题:
- 增加人员的培训成本
- 模块之间的耦合度很高, 不易拆分
- 人员之间的沟通成本增加
- 代码的质量参差不齐
因此, 在一个进程已经落后的软件项目中增加人手, 只会使它更落后.
对项目进行进行实时监督
由于对自己的估算缺乏信心, 我们通常不会有耐心持续地估算这项工作, 因此我们要持续的对项目进行估算.
对进度缺少跟踪和监督.
在每个项目中项目排期, 都是一个很让人头疼的问题. 那么我们如何更好的去进行项目的评估呢
-
严格的模块划分, 尽量减少模块间耦合
-
要持续不断的坚持项目的排期, 在每次的排期和项目结束后, 吸取经验和教训, 以对之后的项目评估有更好的安排
-
每次项目完成之后都要进行项目总结
a. 项目是否如期完成, 是什么原因导致的项目延期
b. 项目中遇到的问题, 以及为什么会出现这些问题, 在之后的开发中, 我们能否避免
c. 在当前的排期中, 是否有不可控因素
d. 是否有需求不明确导致, 或者有更紧急的任务要处理
e. 是否我们缺少对项目进度的跟踪与监督
如何管理好一个工程项目?
在进行项目评估时, 我们要时刻去思考这些问题?
- 是否有清晰的目标?
- 是否有充足的人力?
- 是否有充足的材料?
- 是否有足够的时间?
- 是否有足够的技术?
- 是否有充分且透彻的沟通?
- 是否通过沟通进行了有条不紊的组织?
不变是愿望, 变化才是永恒
普遍的做法是, 选择一种方法, 试试看; 如果失败了, 没关系, 再试试别的方法. 不管怎么样, 重要的是先去尝试.
软件维护
当我们进行软件的维护时, 要认识到软件维护的本是对设计缺陷的修复
对于一个程序, 其维护总成本通常是开发成本的40%或者更多. 该成本受用户数目的影响很大. 用户越多, 所发现的错误也就越多.
上一个版本中被发现和修复的bug, 在新的版本中仍会出现.
新版本中的新功能会产生新的bug.
解决了这些问题以后, 程序会正常运行几个月, 接着错误率会重新攀升.
是因为用户对软件的使用达到了新的熟练水平, 他们开始运用新的功能.
程序维护中的一个基本问题 - 缺陷修复总会以固定的几率(20%~50%)引入新的bug. 前进两步, 后退一步.
为什么bug不能彻底的被修复?
看上去很微小的错误, 似乎仅仅是局部操作上的失败, 实际上却是系统级别的问题.
"事物在最初总是最好的"
写给自己: 不要当一个斐波那契程序员, 每天都在改昨天和前天的bug. 在我的感觉中改bug可能比写功能更需要我们去分析和思考. 也更值得我们去探索和改进, 可能也是我们水平提高的一种很重要的方式与方法.
软件开发与软件维护
系统软件开发是减少混乱度的过程, 所以本身处于亚稳定的状态.
软件维护是提高混乱度的过程, 即使是最熟练的软件维护工作, 也只是放缓了系统退化到非稳定状态的进程.
自上而下的设计
清晰的结构和表达方式更容易对需求和模块功能进行精确的描述
模块分割和模块独立性避免了系统级的bug
细节的控制使结构上的缺陷更加容易识别
设计在每个精华步骤上都是可以测试的, 所以测试可以尽早开始, 并且每个步骤的重点可以放在合适的级别上
如何保证一个大型项目的进度?
制定一个严格的进度表, 该进度表由里程碑和日期组成
里程碑必须是具体的, 特定的和可度量的事件, 能进行清晰的定义
每个小阶段的延期, 最后就会造成整个项目进度的大的延迟
一天一天的进度落后比起重大灾难更难以识别, 更不容易防范和更加难以弥补我们一直都知道的是: 千里之行, 始于足下, 万里之堤, 溃于蚁穴. 可是在实际的工作生活中, 我们总是大大咧咧, 对于小事情毫不在意, 尤其在模块间耦合度较高的情况下, 可能牵一发而动全身. 因此当我们制定好计划后, 一定要有严格的执行标准, 保证排期的顺利进行.
人月一直是个神话
人月之所以不能成为现实, 是因为增加人手的同时也增加了人与人之间的沟通成本. 增加了新人的培训成本, 而不是简单的1 + 1 >= 2的结果.