mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-17 08:46:40 +08:00
1177 lines
36 KiB
HTML
1177 lines
36 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
|
||
|
||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
|
||
<head>
|
||
|
||
<head>
|
||
|
||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||
|
||
<link rel="icon" href="/static/favicon.png">
|
||
|
||
<title>20 如何应对让人头疼的需求变更问题?.md.html</title>
|
||
|
||
<!-- Spectre.css framework -->
|
||
|
||
<link rel="stylesheet" href="/static/index.css">
|
||
|
||
<!-- theme css & js -->
|
||
|
||
<meta name="generator" content="Hexo 4.2.0">
|
||
|
||
</head>
|
||
|
||
|
||
|
||
<body>
|
||
|
||
|
||
|
||
<div class="book-container">
|
||
|
||
<div class="book-sidebar">
|
||
|
||
<div class="book-brand">
|
||
|
||
<a href="/">
|
||
|
||
<img src="/static/favicon.png">
|
||
|
||
<span>技术文章摘抄</span>
|
||
|
||
</a>
|
||
|
||
</div>
|
||
|
||
<div class="book-menu uncollapsible">
|
||
|
||
<ul class="uncollapsible">
|
||
|
||
<li><a href="/" class="current-tab">首页</a></li>
|
||
|
||
</ul>
|
||
|
||
|
||
|
||
<ul class="uncollapsible">
|
||
|
||
<li><a href="../">上一级</a></li>
|
||
|
||
</ul>
|
||
|
||
|
||
|
||
<ul class="uncollapsible">
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/00 开篇词 你为什么应该学好软件工程?.md.html">00 开篇词 你为什么应该学好软件工程?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/01 到底应该怎样理解软件工程?.md.html">01 到底应该怎样理解软件工程?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/02 工程思维:把每件事都当作一个项目来推进.md.html">02 工程思维:把每件事都当作一个项目来推进.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/03 瀑布模型:像工厂流水线一样把软件开发分层化.md.html">03 瀑布模型:像工厂流水线一样把软件开发分层化.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/04 瀑布模型之外,还有哪些开发模型?.md.html">04 瀑布模型之外,还有哪些开发模型?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/05 敏捷开发到底是想解决什么问题?.md.html">05 敏捷开发到底是想解决什么问题?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/06 大厂都在用哪些敏捷方法?(上).md.html">06 大厂都在用哪些敏捷方法?(上).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/07 大厂都在用哪些敏捷方法?(下).md.html">07 大厂都在用哪些敏捷方法?(下).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/08 怎样平衡软件质量与时间成本范围的关系?.md.html">08 怎样平衡软件质量与时间成本范围的关系?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/09 为什么软件工程项目普遍不重视可行性分析?.md.html">09 为什么软件工程项目普遍不重视可行性分析?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/10 如果你想技术转管理,先来试试管好一个项目.md.html">10 如果你想技术转管理,先来试试管好一个项目.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/11 项目计划:代码未动,计划先行.md.html">11 项目计划:代码未动,计划先行.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/12 流程和规范:红绿灯不是约束,而是用来提高效率.md.html">12 流程和规范:红绿灯不是约束,而是用来提高效率.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/13 白天开会,加班写代码的节奏怎么破?.md.html">13 白天开会,加班写代码的节奏怎么破?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/14 项目管理工具:一切管理问题,都应思考能否通过工具解决.md.html">14 项目管理工具:一切管理问题,都应思考能否通过工具解决.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/15 风险管理:不能盲目乐观,凡事都应该有B计划.md.html">15 风险管理:不能盲目乐观,凡事都应该有B计划.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/16 怎样才能写好项目文档?.md.html">16 怎样才能写好项目文档?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/17 需求分析到底要分析什么?怎么分析?.md.html">17 需求分析到底要分析什么?怎么分析?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/18 原型设计:如何用最小的代价完成产品特性?.md.html">18 原型设计:如何用最小的代价完成产品特性?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/19 作为程序员,你应该有产品意识.md.html">19 作为程序员,你应该有产品意识.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
<a class="current-tab" href="/专栏/软件工程之美/20 如何应对让人头疼的需求变更问题?.md.html">20 如何应对让人头疼的需求变更问题?.md.html</a>
|
||
|
||
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/21 架构设计:普通程序员也能实现复杂系统?.md.html">21 架构设计:普通程序员也能实现复杂系统?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/22 如何为项目做好技术选型?.md.html">22 如何为项目做好技术选型?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/23 架构师:不想当架构师的程序员不是好程序员.md.html">23 架构师:不想当架构师的程序员不是好程序员.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/24 技术债务:是继续修修补补凑合着用,还是推翻重来?.md.html">24 技术债务:是继续修修补补凑合着用,还是推翻重来?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/25 有哪些方法可以提高开发效率?.md.html">25 有哪些方法可以提高开发效率?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/26 持续交付:如何做到随时发布新版本到生产环境?.md.html">26 持续交付:如何做到随时发布新版本到生产环境?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/27 软件工程师的核心竞争力是什么?(上).md.html">27 软件工程师的核心竞争力是什么?(上).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/28 软件工程师的核心竞争力是什么?(下).md.html">28 软件工程师的核心竞争力是什么?(下).md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/29 自动化测试:如何把Bug杀死在摇篮里?.md.html">29 自动化测试:如何把Bug杀死在摇篮里?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/30 用好源代码管理工具,让你的协作更高效.md.html">30 用好源代码管理工具,让你的协作更高效.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/31 软件测试要为产品质量负责吗?.md.html">31 软件测试要为产品质量负责吗?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/32 软件测试:什么样的公司需要专职测试?.md.html">32 软件测试:什么样的公司需要专职测试?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/33 测试工具:为什么不应该通过QQ微信邮件报Bug?.md.html">33 测试工具:为什么不应该通过QQ微信邮件报Bug?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/34 账号密码泄露成灾,应该怎样预防?.md.html">34 账号密码泄露成灾,应该怎样预防?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/35 版本发布:软件上线只是新的开始.md.html">35 版本发布:软件上线只是新的开始.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/36 DevOps工程师到底要做什么事情?.md.html">36 DevOps工程师到底要做什么事情?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/37 遇到线上故障,你和高手的差距在哪里?.md.html">37 遇到线上故障,你和高手的差距在哪里?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/38 日志管理:如何借助工具快速发现和定位产品问题 ?.md.html">38 日志管理:如何借助工具快速发现和定位产品问题 ?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/39 项目总结:做好项目复盘,把经验变成能力.md.html">39 项目总结:做好项目复盘,把经验变成能力.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/40 最佳实践:小团队如何应用软件工程?.md.html">40 最佳实践:小团队如何应用软件工程?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/41 为什么程序员的业余项目大多都死了?.md.html">41 为什么程序员的业余项目大多都死了?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/42 反面案例:盘点那些失败的软件项目.md.html">42 反面案例:盘点那些失败的软件项目.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/43 以VS Code为例,看大型开源项目是如何应用软件工程的?.md.html">43 以VS Code为例,看大型开源项目是如何应用软件工程的?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/44 微软、谷歌、阿里巴巴等大厂是怎样应用软件工程的?.md.html">44 微软、谷歌、阿里巴巴等大厂是怎样应用软件工程的?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/45 从软件工程的角度看微服务、云计算、人工智能这些新技术.md.html">45 从软件工程的角度看微服务、云计算、人工智能这些新技术.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/一问一答第1期 30个软件开发常见问题解决策略.md.html">一问一答第1期 30个软件开发常见问题解决策略.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/一问一答第2期 30个软件开发常见问题解决策略.md.html">一问一答第2期 30个软件开发常见问题解决策略.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/一问一答第3期 18个软件开发常见问题解决策略.md.html">一问一答第3期 18个软件开发常见问题解决策略.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/一问一答第4期 14个软件开发常见问题解决策略.md.html">一问一答第4期 14个软件开发常见问题解决策略.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/一问一答第5期 22个软件开发常见问题解决策略.md.html">一问一答第5期 22个软件开发常见问题解决策略.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/学习攻略 怎样学好软件工程?.md.html">学习攻略 怎样学好软件工程?.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/特别放送 从软件工程的角度解读任正非的新年公开信.md.html">特别放送 从软件工程的角度解读任正非的新年公开信.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
|
||
|
||
|
||
<a href="/专栏/软件工程之美/结束语 万事皆项目,软件工程无处不在.md.html">结束语 万事皆项目,软件工程无处不在.md.html</a>
|
||
|
||
|
||
|
||
</li>
|
||
|
||
</ul>
|
||
|
||
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
|
||
|
||
<div class="sidebar-toggle-inner"></div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<script>
|
||
|
||
function add_inner() {
|
||
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
|
||
inner.classList.add('show')
|
||
|
||
}
|
||
|
||
|
||
|
||
function remove_inner() {
|
||
|
||
let inner = document.querySelector('.sidebar-toggle-inner')
|
||
|
||
inner.classList.remove('show')
|
||
|
||
}
|
||
|
||
|
||
|
||
function sidebar_toggle() {
|
||
|
||
let sidebar_toggle = document.querySelector('.sidebar-toggle')
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let content = document.querySelector('.off-canvas-content')
|
||
|
||
if (sidebar_toggle.classList.contains('extend')) { // show
|
||
|
||
sidebar_toggle.classList.remove('extend')
|
||
|
||
sidebar.classList.remove('hide')
|
||
|
||
content.classList.remove('extend')
|
||
|
||
} else { // hide
|
||
|
||
sidebar_toggle.classList.add('extend')
|
||
|
||
sidebar.classList.add('hide')
|
||
|
||
content.classList.add('extend')
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
function open_sidebar() {
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
|
||
sidebar.classList.add('show')
|
||
|
||
overlay.classList.add('show')
|
||
|
||
}
|
||
|
||
function hide_canvas() {
|
||
|
||
let sidebar = document.querySelector('.book-sidebar')
|
||
|
||
let overlay = document.querySelector('.off-canvas-overlay')
|
||
|
||
sidebar.classList.remove('show')
|
||
|
||
overlay.classList.remove('show')
|
||
|
||
}
|
||
|
||
|
||
|
||
</script>
|
||
|
||
|
||
|
||
<div class="off-canvas-content">
|
||
|
||
<div class="columns">
|
||
|
||
<div class="column col-12 col-lg-12">
|
||
|
||
<div class="book-navbar">
|
||
|
||
<!-- For Responsive Layout -->
|
||
|
||
<header class="navbar">
|
||
|
||
<section class="navbar-section">
|
||
|
||
<a onclick="open_sidebar()">
|
||
|
||
<i class="icon icon-menu"></i>
|
||
|
||
</a>
|
||
|
||
</section>
|
||
|
||
</header>
|
||
|
||
</div>
|
||
|
||
<div class="book-content" style="max-width: 960px; margin: 0 auto;
|
||
|
||
overflow-x: auto;
|
||
|
||
overflow-y: hidden;">
|
||
|
||
<div class="book-post">
|
||
|
||
<p id="tip" align="center"></p>
|
||
|
||
<div><h1>20 如何应对让人头疼的需求变更问题?</h1>
|
||
|
||
<p>你好,我是宝玉,我今天分享的主题是:如何应对让人头疼的需求变更问题?</p>
|
||
|
||
<p>我以前在国内做开发的时候,加班加点是家常便饭。这几年在美国工作,极少加班,但是产出却并没有下降,所以我一直在思索其背后的原因。这里面涉及因素很多,包括大环境、管理水平、配套设施等,但是有一个因素至关重要,那就是需求变更。</p>
|
||
|
||
<p>在国内很多软件公司,需求变更是常态,开发到一半,很多原始需求就发生了变化,这时候当初的设计已经不能满足要求了,很多代码需要修改,不得不加班加点来赶上进度。</p>
|
||
|
||
<p>反观不加班的美国公司,需求确定后很少变更。这样开发人员就可以针对需求有良好的架构设计,而不用考虑太多可能的变更,从容地在项目计划的时间内完成任务,而不需要加班加点。</p>
|
||
|
||
<p><strong>在需求变更这个事情上,没有赢家,每个人都是受害者。</strong></p>
|
||
|
||
<p>程序员自己辛苦的工作白费了,得不到成就感,因为频繁变更的需求,不得不在设计的时候考虑很多可能的变更,导致代码臃肿,代码质量降低,加班加点成了常态。甚至有人说:“杀一个程序员不需要用枪,改三次需求就可以了!”</p>
|
||
|
||
<p>产品经理也觉得很委屈:“客户要改,我有什么办法?”程序员和产品经理似乎变成了两个对立的岗位,程序员怪产品经理乱改需求,产品经理觉得是客户造成的,人人都觉得自己委屈。客户同样不满意,觉得做出来的软件不是他想要的,进度总是在延后,还想加钱?</p>
|
||
|
||
<p>既然大家都不满意,那么我们就需要想办法去改善,这也是软件工程这门学科存在的目的和意义。</p>
|
||
|
||
<p>目前也已经有很多管理需求变更的解决方案,比如这两个常见的解决方案。</p>
|
||
|
||
<p><strong>方案一:增强需求变更流程,让需求变更规范起来。</strong></p>
|
||
|
||
<p>这个方案简单来说,就是通过严格的流程,来避免一些没有意义的变更,从而达到管理需求变更的目的。</p>
|
||
|
||
<p><strong>方案二:快速迭代,缩短版本周期。</strong></p>
|
||
|
||
<p>这个方案是另一个思路,就是将大的功能拆分,每个版本周期仅实现一部分功能需求,周期较短,这样需求发生变更时,就可以快速响应。</p>
|
||
|
||
<p>不过,在看到这两个方案后,我还是希望你不满足于当前的答案,自己停下来思考一下这两个问题:</p>
|
||
|
||
<ol>
|
||
|
||
<li>这些方案是否解决了你当前项目的问题?</li>
|
||
|
||
<li>如果换一个项目环境,当前方案是否依然适用?</li>
|
||
|
||
</ol>
|
||
|
||
<p>之所以要思考这样的问题,是因为对于像软件工程这样偏理论知识的学习,你一定不要仅仅停留在了解有什么样的解决方案上,<strong>而是要追本溯源,研究问题背后的原因,研究理论背后的来龙去脉。</strong></p>
|
||
|
||
<p>因为,就算你记住了再多的解决方案,换个项目环境可能就不适用了。所以我们要多去思考和分析逻辑,这样未来遇到类似的问题时,才可以做到对症下药,选择合适的解决方案,甚至在没有现成解决方案的情况下,能自己创造合适的解决方案。</p>
|
||
|
||
<h2>为什么建筑工程中少有需求变更?</h2>
|
||
|
||
<p>要解决需求变更的问题,你首先要知道,软件开发行业中的需求变更是怎么来的。</p>
|
||
|
||
<p>我很喜欢拿软件工程和建筑工程进行对比,你可以思考一下,同样是工程,建筑项目也是有需求变更的,但却不会像软件项目这么频繁和失控。为什么呢?</p>
|
||
|
||
<p>我总结一下,这里有两个主要原因:<strong>需求的确定性和需求变更的成本。</strong></p>
|
||
|
||
<h4>原因一:需求的确定性</h4>
|
||
|
||
<p>建筑需求是很具象的,而软件工程的需求是抽象的。所以建筑项目里面,无论是提出需求还是变更需求,客户和施工方都明确地知道他们想要什么。</p>
|
||
|
||
<p>软件需求则经常是抽象、模糊、不精确的,模糊不清的需求导致在软件开发有了雏形后,才慢慢想清楚真正的需求是什么,从而导致需求变更。</p>
|
||
|
||
<p>举个例子,客户最开始对软件界面的颜色是没有任何要求的,当第一版本的软件给客户看的时候,客户觉得白色背景太难看了,希望换成蓝色的;第二版本换成蓝色后,客户现在已经觉得黄色更好看,希望改成黄色背景;第三版本的时候,产品经理担心客户还想换颜色,就直接做成了换皮肤功能,用户可以自己选择颜色,客户还是不满意,问能不能把背景换成图片……</p>
|
||
|
||
<p>是不是很熟悉?类似的事情其实经常发生在我们日常的工作场景里。</p>
|
||
|
||
<h4>原因二:需求变更的成本</h4>
|
||
|
||
<p>建筑项目里面的需求变更,我们都很容易和成本挂钩,因为这些东西已经是生活常识了。而与此相对的是,很多人,包括很多老板都对软件项目需求变更导致的成本增加缺少系统认识。</p>
|
||
|
||
<p>举个例子,装修房子的时候,如果墙面已经刷成白色了,但是客户想都刷成蓝色,那么他会很清楚,这涉及一系列成本:需要重新购买涂料、需要找人重新粉刷。</p>
|
||
|
||
<p>但换成一个软件项目,客户想把界面的白色背景换成蓝色的,他会觉得这是很简单也是理所当然的,甚至产品经理也会这么想,他会对程序员这么说:“不就是换个颜色吗?几行代码的事,客户让换就换了嘛!”</p>
|
||
|
||
<p>但是实际上,软件项目的需求变更,哪怕是换一个背景颜色,同样是要涉及成本的:需要修改所有涉及背景颜色的代码,需要更新相关测试代码,还需要对涉及的界面重新测试。</p>
|
||
|
||
<p>你可以说这成本是架构设计水平不到家导致的,但是如果设计时就考虑到要有支持换背景颜色的功能,那么开发的工作量从一开始就上去了,成本同样是提升了。</p>
|
||
|
||
<p>回到文章开始时我们提到的美国程序员不加班的问题,为什么美国的产品经理不敢随意更改需求?因为在美国很多 IT 公司都是工程师文化,工程师相对比较有话语权,正常情况下是不会加班加点的,所以产品经理变更需求的成本很高,在确定需求时,必须慎之又慎。</p>
|
||
|
||
<h2>如何解决需求变更问题?</h2>
|
||
|
||
<p>说完了原因,咱们再来看看解决方案。</p>
|
||
|
||
<p>首先,你需要意识到,在软件项目开发中,需求变更其实是不可避免的,一味抵制需求变更也是不可取的。你能做的就是利用软件工程的知识,理解需求变更背后深层次的原因,找到合适的方案来改善,积极拥抱合理的需求变化,减少不必要的需求变更。这是大的前提条件,也是共识的基础。</p>
|
||
|
||
<p>好,既然引起需求频繁变更的原因我们已经清楚了,那么,怎样有针对性地想解决方案呢?这里你也不妨停下来思考一下,你会想到哪些办法?</p>
|
||
|
||
<p>我的经验是从源头着手,既然需求变更的原因是需求不确定和需求变更成本太低,那么我们就针对性地提出相应的解决方案:</p>
|
||
|
||
<ul>
|
||
|
||
<li>
|
||
|
||
<p><strong>提升需求确定性,把需求分析做好,减少需求变更;</strong></p>
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
<p><strong>提高需求变更的成本,让客户或者产品经理不能太容易就变更需求,这样就可以达到减少需求变更的目的。</strong></p>
|
||
|
||
</li>
|
||
|
||
</ul>
|
||
|
||
<p>但在实施的时候,我们会发现一个问题,假如一味提高需求变更的成本,会让客户满意度下降,也造成了产品经理和开发人员之间的对立,不利于项目协作。</p>
|
||
|
||
<p>所以我们从另一个角度思考:需求变更之所以让你痛苦不堪,也是因为需求变更让项目成员付出了高昂的代价,例如返工、加班,如果我们可以低成本地响应需求变更,那么一样可以达到管理需求变更的效果。</p>
|
||
|
||
<p>所以解决方案上可以再加上一条:</p>
|
||
|
||
<ul>
|
||
|
||
<li><strong>降低响应需求变更的成本,可以方便快捷地响应需求变更。</strong></li>
|
||
|
||
</ul>
|
||
|
||
<p>接下来,我来举一个在实际项目遇到的案例,我们一起来分析一下,通过对这个需求变更场景的分析,来解决以上提到的这些问题。</p>
|
||
|
||
<h4>案例分析</h4>
|
||
|
||
<p>我有个大学同学叫加龙,毕业后自己开了个公司,早些年企业建站火的时候专门接企业网站的活。刚开始的时候很艰苦,也没几个人,甚至都没有专门的产品经理。</p>
|
||
|
||
<p>开发流程比较简单,就是先把项目谈下来,客户提一个建站的需求,然后他们去开发网站,开发好了拿给客户演示。而客户在看到网站演示后,几乎每次都会提出很多变更的需求,例如说颜色变一下、布局变一下、给留言功能加上关键字过滤功能等等。客户还喜欢直接在 QQ 上找负责开发的程序员,让给改一下。</p>
|
||
|
||
<p>创业初期,加龙同学真的是不容易,每天和几个程序员一起加班加点,就是为了应对客户这种频繁变更的需求。如果你是加龙,参考前面总结的几种解决方案,你会怎么做?</p>
|
||
|
||
<p>加龙作为软件工程专业毕业的学生,我觉得他当时运用软件工程知识去改善需求变更问题上是做得非常好的。他其实并没有采用一个单一的解决方案,而是分阶段逐步改进。</p>
|
||
|
||
<p><strong>第一步:规范变更流程,提升客户变更成本。</strong></p>
|
||
|
||
<p>加龙其实也知道,通过提升需求确定性,做好需求分析,和客户多沟通确认,是可以有效减少需求变更的。但是他当时确实人手太有限,也没有专业的产品经理,不能短时间内去提升需求分析、产品设计的水平,所以他第一步选择提升客户变更需求的成本,这样可以马上产生效果。</p>
|
||
|
||
<p>于是在后面的项目中,在和客户签订合同时,他会和客户约定,如果有需求变更,先统一提交到他那里,然后他甄别后再决定是否做,什么时候做,是否要重新签订新的附加合同(增加额外费用)。通过制定一系列标准,让双方合作的流程变得更规范。</p>
|
||
|
||
<p>这样,程序员就可以专注于开发,也不会因为频繁的需求变更影响进度,大家不用那么累,收入也在稳步上升。但是需求变更的情况还是时有发生。</p>
|
||
|
||
<p><strong>第二步:用原型设计低成本响应需求变更;做好需求分析和确认,减少需求变更。</strong></p>
|
||
|
||
<p>加龙在挺过最艰难的创业初期后,雇佣了一个全职的产品经理,专门去和客户确认需求。这个产品经理很专业,每次在了解完客户的需求后,不急于让程序员马上去写代码,而是自己先用 Axure 这样的原型设计工具,做一个简单的交互原型,给客户演示。</p>
|
||
|
||
<p>于是客户会针对原型的效果提出一些修改意见,他再快速地修改原型,这样反复确认,等到客户没有什么修改意见后,再让开发着手实现。</p>
|
||
|
||
<p><strong>通过原型设计的方式,不仅可以方便地与客户沟通需求,还可以灵活响应需求变更。</strong></p>
|
||
|
||
<p>通过提升需求确定性,加龙的公司进一步降低了需求变更的情况发生,营收又上了一个台阶,又增加了几个程序员和产品经理。</p>
|
||
|
||
<p><strong>第三步:通过灵活的架构和强大的配置,低成本响应客户需求变更。</strong></p>
|
||
|
||
<p>加龙公司经过两年的发展后,敏锐地发现其实大部分企业网站的功能都是很相似的,主要差别还是在界面样式上。</p>
|
||
|
||
<p>这些年大部分网站的开发其实都是把前一个网站复制一份,修修改改,但是这样还是效率太低,如果可以做到定制化,就可以更高效地定制网站。</p>
|
||
|
||
<p>于是加龙从公司抽调了几名骨干程序员,成立了一个专门的项目组,把这两年做的网站类型做了分析,做了一套建站系统,有点类似于后来流行的像 WordPress 这样的博客系统,可以通过换皮肤的的方式来定制界面,通过插件的方式增加功能。</p>
|
||
|
||
<p>由于前期积累充分,大约半年后他们就开始使用这套系统去建站,一下子就把建站的成本大大降低啦。而且当客户的需求有变化时,只要后台做简单的配置就可以马上支持需求变更。</p>
|
||
|
||
<p>但是这个模式也有问题,就是有些特别个性化的定制需求,还是满足不了。不过这也没关系,对于需要个性化的客户,要么增收额外的费用,要么就直接放弃掉。</p>
|
||
|
||
<p>如果咱们对他这三步采取的方案做一个总结,还就是我前面说的三个方案:</p>
|
||
|
||
<ol>
|
||
|
||
<li>提升需求确定性;</li>
|
||
|
||
<li>提高需求变更的成本;</li>
|
||
|
||
<li>降低响应需求变更的成本。</li>
|
||
|
||
</ol>
|
||
|
||
<p>只不过他根据公司不同阶段的特点,来灵活运用。这就是我的同学加龙在处理需求变更时分阶段采取的方案,是不是跟你想的一样?</p>
|
||
|
||
<h2>总结</h2>
|
||
|
||
<p>今天我通过对比建筑工程中的需求变更,和你一起分析了软件工程中需求变更产生的原因。需求频繁变更,主要是由于需求不确定和变更成本过低导致的。并由此提出了三种不同的解决方案。</p>
|
||
|
||
<ol>
|
||
|
||
<li>提升需求确定性,来减少需求的变更。这种方案的优势就是对需求理解透彻,后期返工少,缺点是对产品经理的需求分析能力要求很高。</li>
|
||
|
||
<li>提高需求变更的成本,规范需求变更流程,减少需求变更。这种方案的优势就是可以马上起到效果,缺点就是过于繁琐的流程不利于项目协作。</li>
|
||
|
||
<li>降低响应需求变更的成本,积极应对需求变更。这种方案的优势在于可以快速响应需求变更,能快速试错尽快调整,缺点在于对软件架构和项目管理要求比较高。</li>
|
||
|
||
</ol>
|
||
|
||
<p>就像我的同学加龙那样,你可以根据项目的实际情况,对比这些方案的优缺点,选择适合你的解决方案。</p>
|
||
|
||
<p>例如你是做企业外包项目的,客户不懂又喜欢瞎掺和,那么就可以适当提高变更成本,甚至每次变更都可以计入项目成本中;如果你是做互联网项目,需要快速推出产品,那么就可以选择降低响应变更成本,快速迭代,快速试错,尽快调整。</p>
|
||
|
||
<p>如果你是项目经理,希望你通过这次对需求变更的学习,能针对项目特点,制定合适的需求变更流程,选择适合项目的开发模式,管理好需求变更,从而提升整个项目的开发效率,避免重复返工导致的浪费。</p>
|
||
|
||
<p>如果你是产品经理,希望你通过这次学习,对需求变更导致的成本有很高的重视,努力提升专业水平,勤于和客户、开发测试人员沟通,勤总结,尽可能将需求变更的可能性降到最低。</p>
|
||
|
||
<p>如果你是开发或者测试,希望你在以后遇到需求变更时,不要置身事外,抱怨产品经理不专业,因为需求并不是产品经理一方的事情,项目参与者都有责任一起把需求分析做好。</p>
|
||
|
||
<p>在一些需求分析和变更的关键阶段,要主动参与其中,从开发和测试的角度提供一些专业的建议,去思考需求产生的背景,避免对立情绪。</p>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div>
|
||
|
||
<div style="float: left">
|
||
|
||
<a href="/专栏/软件工程之美/19 作为程序员,你应该有产品意识.md.html">上一页</a>
|
||
|
||
</div>
|
||
|
||
<div style="float: right">
|
||
|
||
<a href="/专栏/软件工程之美/21 架构设计:普通程序员也能实现复杂系统?.md.html">下一页</a>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
|
||
|
||
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
|
||
|
||
</div>
|
||
|
||
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997c65e8ea3cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
|
||
|
||
</body>
|
||
|
||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
|
||
|
||
<script>
|
||
|
||
window.dataLayer = window.dataLayer || [];
|
||
|
||
|
||
|
||
function gtag() {
|
||
|
||
dataLayer.push(arguments);
|
||
|
||
}
|
||
|
||
|
||
|
||
gtag('js', new Date());
|
||
|
||
gtag('config', 'G-NPSEEVD756');
|
||
|
||
var path = window.location.pathname
|
||
|
||
var cookie = getCookie("lastPath");
|
||
|
||
console.log(path)
|
||
|
||
if (path.replace("/", "") === "") {
|
||
|
||
if (cookie.replace("/", "") !== "") {
|
||
|
||
console.log(cookie)
|
||
|
||
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
setCookie("lastPath", path)
|
||
|
||
}
|
||
|
||
|
||
|
||
function setCookie(cname, cvalue) {
|
||
|
||
var d = new Date();
|
||
|
||
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
|
||
|
||
var expires = "expires=" + d.toGMTString();
|
||
|
||
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
|
||
|
||
}
|
||
|
||
|
||
|
||
function getCookie(cname) {
|
||
|
||
var name = cname + "=";
|
||
|
||
var ca = document.cookie.split(';');
|
||
|
||
for (var i = 0; i < ca.length; i++) {
|
||
|
||
var c = ca[i].trim();
|
||
|
||
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
|
||
|
||
}
|
||
|
||
return "";
|
||
|
||
}
|
||
|
||
|
||
|
||
</script>
|
||
|
||
|
||
|
||
</html>
|
||
|