Home 软件工程之美
参考极客时间《软件工程之美》,所做学习笔记

0 70

通过前面的学习,我们知道在瀑布模型中,第二个阶段就是需求分析阶段,同时需求分析的结果也决定了后续的系统设计、开发、测试等阶段能否顺利如期进行。即使是用敏捷开发,同样也少不了对需求的分析整理。

 

什么是需求?

我们日常在项目中,经常会听到“需求”这个词,比如说:

  • 项目经理对产品经理说:用户给我们提了一个需求,想要一个给三个孩子玩的秋千,你分析一下;
  • 产品经理对架构师说:我们现在有一个需求,在树上拴两绳子,再吊一块板子,你做一下设计。

很明显,这两个需求的意思不一样,前面这个需求是用户需求,后面这个需求是产品需求。用户需求是由用户提出来的,期望满足自身一定需要的要求,例如用户说:“想要一个给三个孩子玩的秋千。”这种原始的用户需求通常是不能直接做成产品的,需要对其进行分析提炼,最终形成产品需求

产品需求就是在分析提炼用户真实需求后,提出的符合产品定位的解决方案。就像上面“在树上栓两绳子,再吊一块板子”,就是产品经理针对用户需求提出的解决方案。

 

需求分析是要分析什么?

需求分析,就是对用户需求进行提炼分析,最终形成产品需求的过程。

而针对每个用户需求的需求分析过程,需要经过三个步骤。

第一步:挖掘真实需求

大部分用户提出的需求都不是真实需求,要分析用户的真实需求,可以从三个角度入手。

  1. 目标用户:用户不同,诉求也不一样;
  2. 使用场景:使用场景不一样,解决方案也会有所不同;
  3. 想要解决的问题:用户背后想要解决的问题是什么。

第二步:提出解决方案

我们知道了目标用户,其使用场景和想要解决的问题,就可以结合产品定位,提出相应的解决方案

比如针对想要“更快更舒适的出行方式”日常出行的乘客,我们就可以提出汽车的解决方案,而不一定要局限于马车,汽车能更好的满足用户需求。

针对三个孩子想有一个在户外一起玩的娱乐设施这个需求,我们可以提供一个轮胎式的秋千,就可以很好的满足他们的需求,我们甚至可以建一个小型游乐园。

第三步:筛选和验证方案

在提出方案后,我们需要对方案进行筛选,比如对于秋千项目,建小型游乐园的方案虽然能满足需求,但是成本太高,需要排除掉。

在选好方案后,还需要对方案进行验证,以确保方案能解决用户需求。

在传统瀑布模型中,选定方案后,会写成产品设计文档,走相应的评审流程,评审完成后再进行设计、开发和测试,测试完成后会让客户再进行验收。而敏捷开发,在整个开发过程中,每个迭代或者关键的里程碑,也一样需要客户进行验收。通过以上三步,就可以对用户需求进行提炼分析,最终形成产品需求。

 

怎么做需求分析?

前面我介绍了对单个用户需求的分析,主要经过三个步骤:

  • 第一步:挖掘真实需求;
  • 第二步:提出解决方案;
  • 第三步:筛选和验证方案。

而软件项目的用户需求,从来就不是单一的,而是一系列需求,所以对于软件项目的需求分析,还需要增加收集整理的步骤。整个过程是迭代进行的,如下所示:

  • 收集需求:对用户需求进行收集整理;
  • 分析需求:对需求进行分析,挖掘用户真实需求;
  • 需求评估:筛选过滤掉不可行的需求;
  • 需求设计:针对用户需求提出解决方案,设计成产品方案;
  • 验证需求:验证方案是否可行。

 

总结

今天带你一起学习了软件工程中一个非常重要的知识点:需求分析。

需求分析,就是一个将用户需求变成产品需求的过程

要做好用户需求的分析,需要找出来隐藏在用户需求背后的真实需求,还要针对用户的真实需求提出解决方案,最终验证方案是不是能满足好用户需求。

需求是整个产品的源头,很多软件项目失败的原因就在于没有做好需求分析,软件中很多浪费也来源于需求没想清楚导致的返工。

做好需求分析对于软件项目来说非常的重要。要做好软件项目的需求分析,需要做好需求的收集整理工作,然后对收集好的需求进行科学的分析,评估是不是可行以及划分优先级,对可行的需求项进行设计,最后还要验证设计出来的结果是不是满足需求。

0 80

我以前看过一个投票,盘点程序员不喜欢的事,有两条和文档相关:

  • 不喜欢写文档;
  • 不喜欢项目文档太少。

看起来很矛盾,却很现实。基本上大家都认同:“项目文档很重要”,然而我们在项目中总是短期高估文档的重要性,而长期低估文档的重要性。

那么为什么程序员都不爱写文档呢?我总结了一下大致有下面这些原因。

  • 不知道怎么写
  • 太忙没时间写或者懒得写
  • 觉得敏捷开发不用写

为什么要写文档?

写文档,其实对个人、对项目、对团队,都是非常重要的事情。

  • 帮助写文档的人理清楚思路

写文档,可以让你在写代码之前,梳理清楚思路,想清楚整体结构,比如说有哪些工作是重点难点;哪些要依赖其他人,需要及早协商的;哪些是要考虑安全性的。

先写文档,就会抛开代码细节,去站在全局思考。写的时候,各个模块之间的依赖关系、各种可能的安全隐患、各种可能需要其他人配合的地方,就都冒出来了,必须要去查资料,去找人讨论,反复缜密的思考后最终写出来。

真正的障碍是没想清楚,在心中只有一些未成型的混乱的想法和概念,必须要努力把这些模糊的想法确定化和具体化,才能写出来。

  • 便于未来的维护和交接

“好记性不如烂笔头”,存在脑子里的内容是不可靠的,一个正常的项目组,如果需要长期维护,就需要一定的文档,把设计、操作流程、环境配置等内容记录下来,而不仅仅依赖于口口相传。

  • 便于团队更好的协作沟通

 

如何写好文档

1.从模仿开始

模仿就是最好的写文档方式,尤其是现在网上可以参考的例子也很多,当你写文档不知道该如何下手的时候,不妨去找一个类似的文档,模仿着写试试

2. 从小文档开始

3. 从粗到细,迭代更新

我写一个大一点的文档,都是从脑图开始的,先基于脑图,把基本结构梳理清楚。然后第二步就是写 PPT,PPT 有个好处就是不用太多文字,列个一二三,画几张图,就是个简单的文档,PPT 还有个好处就是可以用来给别人讲解,收集反馈。写完 PPT,也收集好了反馈,再写正式的文档。先按照脑图列的提纲把主要章节放上去,然后把 PPT 上的内容和画的图放到文档中,一篇文档的骨架就搭好了,剩下的就是对细节的补充了。

4. 善于画图

  • 线框图

线框图是最常用也最实用的一种图形,用简单的方框代替功能、模块、服务等,再用箭头表示关系或者数据流向,非常简单直接。

  • 流程图

流程图是软件项目文档中一种常用图形,可以方便的表示各种不同条件下的逻辑路径。要画好流程图不难,重点是要理清楚逻辑关系,各个关键节点在不同条件下的走向。

例:重置密码流程图。

  • 时序图

时序图也是软件项目所特有的一种图形,可以表示不同对象之间发送消息的时间顺序,尤其在涉及网络通信的文档中特别常用。画好时序图,关键是要列清楚所有涉及的对象或者服务,以及消息发送的先后顺序。

例:注销登录过程的时序图。

  • 各种格式截图

0 73

一个应用敏捷开发的小组日常

这个小组是做网站开发的,基于微服务负责网站的某一个小模块。标准配置 7 人左右,4 个程序员(至少有一个资深程序员,有架构能力),1 个产品经理(Scrum 里面叫 Product Owner),1 个测试,1 个项目经理(Scrum 里面叫 Scrum Master)。主要负责网站某模块的日常维护。

在分工上:

产品经理:写需求设计文档,将需求整理成 Ticket,随时和项目成员沟通确认需求;

开发人员:每天从看板上按照优先级从高到低领取 Ticket,完成日常开发任务;

测试人员:测试已经部署到测试环境的程序,如果发现 Bug,提交 Ticket;

项目经理:保障日常工作流程正常执行,让团队成员可以专注工作,提供必要的帮助,解决问题。

在敏捷开发框架下,已经形成了一些很好的敏捷实践,这个小组也是基于 Scrum 方法做过程管理,基于极限编程做工程实践,看板可视化。每周一个 Sprint。如何完成需求和修复 Bug?

Scrum:Scrum是迭代式增量软件开发过程,通常用于敏捷软件开发。Scrum包括了一系列实践和预定义角色的过程骨架。Scrum中的主要角色包括同项目经理类似的Scrum主管角色负责维护过程和任务,产品负责人代表利益所有者,开发团队包括了所有开发人员。虽然Scrum是为管理软件开发项目而开发的,它同样可以用于运行软件维护团队,或者作为计划管理方法:Scrum of Scrums.)

极限编程(Extreme Programming,XP)是一门针对业务和软件开发的规则,它的作用在于将两者的力量集中在共同的、可以达到的目标上。它是以符合客户需要的软件为目标而产生的一种方法论,XP使开发者能够更有效的响应客户的需求变化,哪怕是在软件生命周期的后期。它强调,软件开发是人与人合作进行的过程,因此成功的软件开发过程应该充分利用人的优势,而弱化人的缺点,突出了人在软件开发过程中的作用。极端编程属于轻量级的方法,认为文档、架构不如直接编程来的直接。

 

如何完成需求和修复Bug?

日常工作围绕 Ticket 来开展。

所有的需求、Bug、任务都作为 Ticket 提交到项目的 Backlog,每个 Sprint 的任务都以看板的形式展现出来。每个人手头事情忙完后,就可以去看板上的“To Do”栏,按照优先级从高到低选取新的 Ticket。选取后移动到“In Progress”栏。

 

每周一部署生产环境

上半周部署,部署很简单,按照流程执行几个命令就可以完成生产环境部署。部署完成后,需要对线上监控的图表进行观察,如果有问题需要及时甄别,必要的话对部署进行回滚操作。但轻易不会打补丁马上重新上线,因为仓促之间的修复可能会导致更大的问题。

像敏捷开发这样一周一个 Sprint 的好处之一就是,即使这一周的部署回滚了,下周再一起部署也不会有太大影响。

每周二开迭代回顾会议,总结上个 Sprint

日常站会后,迭代回顾会议 (Sprint Retrospective) 会议,目的是回顾一下在迭代中,团队有哪些做的好的地方,有哪些做的不好的地方。对于需要后续改进的,需要创建相应的 Ticket,加入到 Backlog 中,在后续迭代中改进完善。

涉及到决策,最好使用集体表决的方式,避免独裁

 

每周四迭代规划会,计划下周工作

迭代规划会(Sprint Planning Meeting)。这个会议是要大家一起讨论下一个 Sprint 的内容。

 

每周五分支切割

周五标志着一周的工作要结束了,所以下班之前(4 点左右),要做 branch cut(分支切割),也就是要把当前主干上的代码,克隆到一个分支(branch)上。

问题

1. 一周一个迭代怎么保证质量?

以前我在使用迭代模型开发时,一般是 4 周左右的迭代周期,2 周就是极限了,所以最开始看敏捷开发用 1 周的迭代周期,心中也有疑惑,1 周时间又要开发又要测试,怎么保证质量?实际实践下来,发现 1 周一个 Sprint 确实可行,而且质量也可以有保障,这里面有几个因素:

(a) 有足够比例的自动化测试代码,可以很好地保证质量。当用户的主要功能都通过自动化测试覆盖时,基本可以保证主要功能流程不会出问题。

(b) 一个 Sprint 开发完成后,并不马上部署生产环境,而是先部署到测试环境,会有 1 周时间测试。

(c) 有专业的测试人员进行测试,并非完全依赖自动化测试。有时候一些大的功能更新,甚至会组织全组成员一起测试,以弥补测试人员不足的情况。在一个 Sprint 开发结束后,并不马上部署生产环境,而是先部署测试环境测试。

也就是说,虽然是 1 周的 Sprint,但是其实还有 1 周的时间进行测试。每个 Sprint 不仅开发新功能,还要同步修复以前版本的 Bug。这样基本上可以保证有好的质量。而且这种 1 周的迭代,可以保持每周都有内容更新,还有个好处就是每周更新的内容不多,出现问题的话,很容易就定位到是什么地方导致的问题。

2. 基于敏捷开发如何做计划?

大厂里面通常会在上一年底确定第二年整年的大的开发计划,并确定上线的时间范围,每个季度再根据情况做一些调整。

这些大的计划最终会变成具体的开发任务,一个大的开发任务,会分拆到各个部门,各部门再将任务分拆到各个项目组。基于敏捷开发的话,主要就是看把这些开发任务放到哪几个 Sprint 去做,并且确保在规定的时间范围内完成。

至于工期的估算,在迭代规划会上会对每个 Ticket 进行打分,根据分数可以预估有多少工作量,要花多少时间。

3.上述案例与标准Scrum有什么不同?

首先是角色名称不一样,在 Scrum 里面是分 Product Owner、Scrum Master 和 Team 三种角色,而在这个案例中是产品经理、项目经理和团队成员,但其实只是名字叫法不一样。

还有要注意一点,就是传统的项目经理,会是偏控制型角色,Scrum Master 则更多是一种服务型的角色,主要职责是保障敏捷流程的执行,以及提供必要的帮助,很多团队的决策就是采用集体决策的方式。

另外,Scrum 有四种会议,除了前面介绍的三种:每日站会(Daily Scrum)、Sprint 计划会(Sprint Planning)和 Sprint 回顾会议(Sprint Retrospective),其实还有一种会议是 Sprint 评审会(Sprint Review)。Sprint 评审会的作用是让客户审查 Sprint 的完成结果。因为上面这个小组并没有直接的客户,都是完成产品经理提交的需求,而且沟通紧密,所以没有安排专门会议。

这个小组的站立会议并不是“标准”的站立会议,Scrum 的站立会议通常只有 15 分钟,并且只有轮流发言环节。这里增加的每天审查 Ticket 环节,主要是为了将优先级高的 Bug 修复之类的 Ticket 放到当前 Sprint,及时响应,及时处理。

有的项目组没有这个环节,是由测试人员或者 Scrum Master 直接将 Ticket 放到看板。这个小组并没有使用用户故事来开发需求,而是由产品经理事先写好需求文档。

在上一篇文章里面,提到了 Scrum 采用用户故事的方式,分拆需求,减少繁重的需求文档,在实现的过程中再沟通确认需求。这是 Scrum 推荐的一种方式,也是一种高效的方式,但并不代表这是唯一的方式。如果有产品经理,可以提前几个 Sprint 就将需求文档写详细,一样可以达到高效的理解需求的效果。

0 105

我今天分享的主题是:大厂都在用哪些敏捷方法?我将分为上下两篇,来与你一起讨论这个话题。在我还是一个野路子程序员,到处接私活做网站时,就开始好奇:大厂都是怎么开发软件项目的?直到毕业后,我前前后后加入了若干大中小型企业,包括这些年在美国高校、公司的一些经历,对大厂的项目开发有了比较多的了解。

其实大厂做项目也没有什么特别的,无非就是工程中常见的“分而治之”的策略:大项目拆成小项目,大服务拆成小服务,大团队拆成小团队。

服务之间通过商定好的标准协议进行通信,架构上将大的服务拆分隔离成微服务,大团队按照业务或者服务拆分成小组,按照一定的流程规范保障协作。最终,各个小组要负责的内容其实就不多了。

就像淘宝这种网站,不需要一个庞大的项目组,通过逐级分拆,一个小组可能就只需要负责一个页面中的一个小模块。

所以,也要归功于现在微服务、容器等新技术,可以将复杂的业务逐级拆分,让很多公司能真正敏捷起来。

 

一、和敏捷开发相关的主要流程规范

一切工作任务围绕 Ticket 开展

早些年的项目开发,都是围绕着项目计划开展的,把甘特图打印贴在墙上,方便团队成员看项目进展到什么地步了。自从敏捷化后,开始变成了看板。

所谓的看板,就是把白板分成几个栏,每一栏为一类,分别写着“To Do(待选取)”、“In Progress(进行中)”、“Done(完成)”等,再把工作任务变成一个个五颜六色的即时贴,根据状态贴在不同的栏下面。

慢慢的物理的看板变成了电子看板,通过各种项目管理软件来管理跟踪这些任务,即时贴也变成了 Ticket(也有叫 Issue 的)。逐渐的,所有与开发相关的任务也都和 Ticket 挂钩了:

  • 报一个 Bug,提交一个 Ticket ;
  • 提一条需求,提交一个 Ticket ;
  • 要重构一下代码,提交一个 Ticket 。

看板这种基于 Ticket 来管理跟踪任务的方式,看起来繁琐,但确实是很高效的一种方式。

  • 每一个任务的状态都可以被跟踪起来:什么时候开始做的,谁在做,做完没有。
  • 整个团队在做什么一目了然。
  • Ticket 和敏捷开发中的 Backlog(任务清单)正好结合起来,通过 Ticket 可以收集管理整个项目的 Backlog 和当前 Sprint(迭代)的 Backlog。

有了看板后,大家每天上班第一件事就是打开看板,看看当前 Sprint 还有哪些 Ticket 没有完成,哪些已经完成,哪些正在进行中,非常直观。

作为项目成员来说,做完手头的事情也不用去问项目经理该干什么事情了,直接从 To Do 栏选一条 Ticket 做就是了;对于项目经理,看看 To Do 栏还有多少没有被选取,就知道还剩多少 Ticket 没完成,看看 In Progress 栏就知道哪些 Ticket 正在进行中。

如果有 Ticket 在这一栏待太久或者这一栏 Ticket 太多,那可能就有风险了,就可以及时介入。

 

基于 Git 和 CI 的开发流程

如果你的团队应用瀑布模型来开发,大概会有两大烦恼:代码不稳定和部署太麻烦。

好在基于 Git 的开发流程结合 CI 的自动测试部署,很完美的解决了这两大问题。

我们假设现在 master 的代码是稳定的,那么怎么保证新加入的代码也稳定呢?

答案就是代码审查(Code Review)和自动化测试。如果代码有严格的审查,并且所有自动化测试代码都能测试通过,那么可以认为代码质量是可靠的。当然前提是自动化测试代码要有一定的覆盖比率。

Git 本来只是源代码管理工具,但是其强大的分支管理和灵活的权限控制,结合一定的开发流程,却可以帮助你很好的控制代码质量。

接下来还剩下自动化测试的问题。这时候该 CI (持续集成)出场了。如果你不了解 CI 是什么,可以把它想象成一个机器人,每次你提交一个 PR(严格来说是 Commit,这里略作简化)到源代码服务器,这个机器人马上就知道了。然后它创建一个干净的运行环境,把你提交的代码下载下来,再下载安装所有依赖项,然后运行你的所有测试代码,运行完后,把测试结果报告给你。测试结果直观的反馈在 PR 上,绿色表示通过,红色表示不通过。

关于 Git 和 CI,我在之后的文章中会展开讲解,这里只是为了展现敏捷开发方法的流程。另外,阮一峰老师写过两篇文章,《Git 工作流程》《持续集成是什么?》,你也可以先行阅读了解。

http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html

http://www.ruanyifeng.com/blog/2015/12/git-workflow.html

至此,代码审查和自动测试的问题都解决了。当一个 PR 代码审查通过,以及 CI 通过了所有自动化测试,就可以合并到 master 了,而且我们也可以认为合并到 master 后的代码也是稳定的。(PR—合并分支,CI—持续集成)

至于自动部署测试环境,反倒是简单,就是 CI 这个机器人,在你代码合并到 master 的时候,再次运行自动化测试代码,测试通过后直接运行自动部署的脚本,把 master 代码部署到开发环境或测试环境上。

在这里以一个开发任务为例,大致讲解一下应用敏捷开发方法的基本开发流程:

  • 把要开发的 Ticket 从“To Do”栏移动到“In Progress”栏;
  • 从主干(master)创建一个分支(branch),基于分支去开发功能或修复 Bug;
  • 编写实现代码和测试代码(单元测试和集成测试),是不是测试驱动不重要,看个人偏好或团队要求;
  • 持续提交代码更新到分支,直到完成;创建 PR(Pull Request,合并请求),邀请其他人帮忙 Review 代码,根据 Review 的结果,可能还需要更新几次;
  • CI 在每一次提交代码到代码库后都会自动运行,运行后主要做这些工作:– 检查代码格式是不是符合规范;– 运行单元测试代码;
  • – 运行集成测试。最终这些检查都完成后,CI 会把执行结果显示在 PR 上。通常绿色表示通过,红色表示失败;
  • PR 能合并需要满足两个条件:CI 变绿 + 代码 Review 通过;
  • PR 合并后,CI 会自动构建 Docker Image,将 Image 部署到开发环境;
  • 将相应的 Ticket 从看板上的“In Progress”栏移动到“Done”栏。

正常来讲,你是需要严格遵守开发流程的,但偶尔肯定也有紧急任务,来不及写测试代码,这种情况下,一定要再创建一条 Ticket 跟踪,以确保后续完成测试代码

 

部署上线流程

最早的时候,程序员都是自己管服务器,但是由于这样过于随意,就会导致很多问题出现。

于是后来有专门的运维团队,将开发好的程序,编译好,数据生成脚本写好,然后写成部署文档,交给运维去手动部署。这个过程无比繁琐、无比慎重,通常几周才部署一次,遇上打补丁才隔几天部署。

这些年随着容器化、微服务、DevOps 这些技术或概念的兴起,部署已经变得越来越高效,大厂已经开始在部署流程上融合这些理念。

以前是运维人员按照文档部署,现在已经变成了 DevOps 写自动化部署工具,然后开发人员自己去部署生产环境。

现在大厂的部署也都实现了自动化,但是流程上还是有一些控制。

  • 首先,部署的不再是程序代码,而是 Docker 的 Image,每次代码合并后 CI 都会自动生成新的 Image,测试也是基于 Image 测试。
  • 部署生产环境之前,先在内部的测试环境充分测试。
  • 部署生产环境前,需要审批确认,有 Ticket 跟踪。
  • 部署时,先部署一部分,监测正常后再全量部署。
  • 整个过程都有监控报警,出现问题及时回滚。

如果一切顺利的话,整个生产环境的服务部署过程通常几分钟就完成了,这在以前简直是不敢想象的事。

 

每日站立会议

是不是站着开会其实不重要,重点是要高效沟通反馈。开会时间控制在半小时以内,半小时内不能完成的应该另外组织会议。

1. 成员轮流发言

2.检查最新的 Ticket

3.停车场问题(在这个环节,大家可以针对之前来不及讨论的问题进行讨论,能在会议时间内解决的问题,就马上解决,不能解决的会后再私下讨论或者再组织会议。)

 

总结

分治策略是应对庞大复杂系统的惯用思路,但它的难点或精髓在于如何确保形散神聚。

详细计划(甘特图)VS任务状态(Ticket)

代码不稳定&环境部署麻烦
VS
代码审查&自动测试&自动部署(GIT、CI、DevOps)

上传下达VS频繁沟通、提醒、分享

大厂的敏捷开发实践,把枯燥的编码变得跟玩游戏一样。借助有效的流程与工具,能够有效节约团队成员的精力,聚焦于任务或角色,不会因频繁“统一思想”导致“技术动作变形”。而另一面,在大厂里每个人通常都是螺丝钉,长此以往也许会养成不谋全局的习惯。如果能从自己的角色中跳出来,俯瞰整个组织协作的全过程,并站在这个视角上思考问题,一定会有更喜人的收获。

0 88

一、什么是敏捷开发?

敏捷不是一种方法论,也不是一种软件开发的具体方法,更不是一个框架或过程,而是一套价值观和原则。

也就是说,当你开发做决策的时候,遵守了敏捷开发的价值观和原则,不管你是不是用 Scrum 或者极限编程,那么都可以算是敏捷开发。

敏捷开发就是快速迭代、持续集成、拥抱变化。

 

二、敏捷开发想解决什么问题?

如果你仔细读了敏捷宣言,你会发现,宣言中右边的内容其实都是瀑布模型核心的内容:流程和工具、详尽的文档、合同谈判、遵循计划。

虽然敏捷开发并未对瀑布模型的价值进行否定,但也表明了瀑布模型做的还不够好,同时提出了一套自己的价值观。

比如说,我们开始做一个新项目,需要从客户那里收集整理需求,如果按照传统的软件开发模式,我们需要在开发前获得所有需求然后和客户签订合同,在发布前都不会轻易修改需求。

但是如果我们采用敏捷开发模式来开发项目,那这样做显然违背敏捷的价值观:“客户合作高于合同谈判”。所以如果是敏捷开发,在每个迭代后,都应该向客户收集反馈,然后在后面的迭代中,酌情加入客户反馈修改的内容。

结合敏捷开发提出的背景,你其实不难发现,敏捷开发就是想解决瀑布模型这样的重型软件开发方法存在的问题,用一种轻量的、敏捷的方法来改善甚至是替代它。这些年敏捷开发也是一直这么做的。

瀑布模型的典型问题就是周期长、发布烦、变更难,敏捷开发就是快速迭代、持续集成、拥抱变化。

 

三、如果用敏捷的方式盖房子

在讲瀑布模型的时候,我拿盖房子举了个例子,

如果改成用敏捷开发的模式盖房子,则会是这样子的:

  • 客户想要盖一栋房子(初步的想法)
  • 产品经理和客户进行了初步的沟通,把用户的需求写成了一个个用户故事(用简单的用户故事代替繁重的需求文档)
  • 例如:作为一个上班族,我想要一个卧室,以便于休息;作为一个家庭主妇,我想要一个厨房,以便于做饭。
  • 施工人员根据用户故事和客户进一步沟通(客户合作高于合同谈判),然后对用户故事进行设计和实现;
  • 每个用户故事开发时,还要给一个测试机器人编写测试脚本,让机器人可以自动测试(大量采用自动化测试),并且做好的用户故事可以随时被测试验收(随时发布,持续集成)
  • 每个 Sprint 四个星期时间(时间盒子,迭代时间固定)
  • 第一个 Sprint 搭了个草棚,一张床就是卧室,厕所就挖了一个坑,厨房还来不及搭建(每个 Sprint 会选择高优先级的用户故事),屋顶还在漏水(每个 Sprint 会定期发布,客户可以随时看到可用版本,即使还不完整)
  • 第二个 Sprint 有了简易厨房,同时修复了屋顶漏水的毛病(每个 Sprint 不仅完成用户故事,还会修复 Bug)
  • 第三个 Sprint 升级成了小木屋,但是忘记加上窗户(敏捷推崇自动化测试,但可能会测试不完备)
  • 第四个 Sprint 升级成了砖瓦房,窗户也开好了,客户可以入住。但是这时候客户发现一家三口的话,完全不够用,需要扩建到 3 个卧室。于是决定下个迭代改成 3 个卧室(响应变化高于遵循计划)
  • 第五个 Sprint,升级成了 3 个卧室,升级过程中把厨房下水道弄坏了(迭代过程中可能会导致质量不稳定)
  • 第六个 Sprint,修复了下水道的问题,房子也装修好了(迭代中不断完善);
  • 客户验收使用(上线)。

用敏捷开发的方式,不再像瀑布模型那样有严格的阶段划分,会在迭代中不断完善;不再写很多文档,而是和客户一起紧密合作;不再抵制需求变更,而是即时响应变更;不再等到测试阶段才发布,而是随时发布,客户随时可以看到东西。

当然,采用敏捷开发的模式也存在一些问题,例如全程需要客户参与,由于测试相对少一些 ,问题也会相应多一些。

 

四、敏捷开发和瀑布模型的差异

这些年敏捷开发,已经逐步发展出一套 “Scrum + 极限编程 + 看板” 的最佳实践,Scrum 主要用来管理项目过程,极限编程重点在工程实践,而看板将工作流可视化。

我将基于 Scrum 和极限编程的实践,来对比一下敏捷开发模型和瀑布模型的差异。

1. 敏捷开发是怎么做需求分析的?(用户故事)

瀑布模型要求产生详尽的需求分析文档,敏捷开发的需求来源于一个个的用户故事:

  • 作为用户,我想登录网站
  • 作为客人,我想有个卧室休息

在Sprint的开发中再去确认具体需求的细节。

好处:减少了大量需求文档的编写,可以早些进入开发;

但对开发人员在需求理解和沟通的能力上要求更高了。

2. 敏捷开发是怎么做架构设计的?(一部分需求,渐进式架构,会产生技术债务)

瀑布模型在需求分析完了以后,就需要根据需求做架构设计。

而在敏捷开发中,并不是基于完整的用户需求开发,每个 Sprint 只做一部分需求,所以是一种渐进式的架构设计,当前 Sprint 只做适合当前需求的架构设计。

这种渐进式的架构设计,迭代次数一多,就会出现架构满足不了需求的现象,产生不少冗余代码,通常我们叫它技术债务,需要定期对系统架构进行重构。

3. 敏捷开发怎么保证项目质量?(编写开发功能时编写单元测试和集成测试,自动化测试)

瀑布模型在编码完成后,会有专门的阶段进行测试,以保证质量。

在敏捷开发的 Sprint 中,并没有专门的测试阶段,这就依赖于开发功能的同时,要编写单元测试和集成测试代码,用自动化的方式辅助完成测试。

相对来说,这种以自动化测试为主的方式,质量确实是要有些影响的。

4. 敏捷开发是怎么发布部署的?(持续集成,每完成一个任务构建部署,测试)

瀑布:编码–>测试环境–>生产环境

瀑布模型通常在编码结束后,开始部署测试环境,然后在测试阶段定期部署测试环境。测试验收通过后,发布部署到生产环境。

敏捷开发:持续集成

在敏捷开发中,这种持续构建、持续发布的概念叫持续集成,因为整个过程都是全自动化的,每次完成一个任务,提交代码后都可以触发一次构建部署操作,脚本会拿最新的代码做一次全新的构建,然后运行所有的单元测试和集成测试代码,测试通过后部署到测试环境。

持续集成是一个非常好的实践,极大的缩短和简化了部署的流程,而且自动化测试的加入也很好的保证了部署产品的质量。前期搭建整个持续集成环境需要一定技术要求。

5. 敏捷开发的 Sprint 和迭代模型的迭代有什么区别?

增量模型和迭代模型,这两种也是一种快速迭代的方式,那么敏捷开发和 迭代模型的区别是什么?

迭代模型本质上是一个小瀑布模型,所以在一个迭代里面,需要完整的经历从需求分析,到设计、编码、测试这几个完整的阶段。

所以像瀑布模型一样,刚开始测试的时候是不稳定的,到测试后期才逐步稳定下来,一般迭代前期也会相对轻松一点,而后期测试阶段可能会时间很紧张。

敏捷开发的 Sprint 中,没有像瀑布模型那样严格的开发阶段划分,而是一个个循环迭代的 Sprint

举例来说,一个瀑布模型的项目,可能会按照阶段分成:2 周需求分析,2 周设计,4 周编码,2 周测试,然后上线发布,一共 10 周。如果用敏捷开发的方式来进行,那么可能会是每 2 周一个 Sprint,每个 Sprint 结束后,都会发布上线,每次发布的可能只是完整功能的一部分,但是每次发布的都是一个可用的版本,通过多个 Sprint 的迭代,最终完成项目开发。具体到每一个 Sprint 的开发周期中,在一个 Sprint 中会有多个小的开发任务,这些开发任务主要是新功能的开发和 Bug 的修复。

由于每个 Sprint 周期很短,所以不能像瀑布模型那样有充足的时间去做需求分析、设计和测试,那么敏捷开发中怎么保证质量呢?在敏捷开发中,通常用“用户故事”这样的方式来代替传统的需求分析,也就是以用户故事的形式,对一个需求进行简单的描述,配合关键的测试用例,并且和需求方的紧密沟通,让开发人员可以理清楚需求;通过“只做刚刚好的设计”来节约设计上的时间;通过“自动化测试”、“持续集成”来提升测试效率。

相对来说,敏捷开发中,整个 Sprint 的节奏是比较恒定,产品也是相对稳定的,即使用户故事没有完成,也不影响版本的发布。因此,敏捷开发更注重软件开发中人的作用,需要团队成员以及客户之间的紧密协作。

五、什么时候选择敏捷开发?

条件:

  • 团队要小,人数超过一定规模就要分拆;
  • 团队成员之间要紧密协作,客户也要自始至终深度配合;
  • 领导们的支持。敏捷需要扁平化的组织结构,更少的控制,更多的发挥项目组成员的主动性;
  • 写代码时要有一定比例的自动化测试代码,要花时间搭建好源码管理和持续集成环境。

因为敏捷开发对项目成员综合素质要求更高,做计划要相对难一些。如果团队大、客户不配合、领导不支持,再好的敏捷方法也很难有效实践起来。

如果你要实践敏捷开发,建议先找个小项目进行试点,能证明可行了,再进一步推广。

有条件的话,可以和一些顾问公司合作,请人做专门的培训和指导。如果不具备条件,应该考虑先把其中一些好的实践用起来,比如说持续集成、每日站会、自动化测试等。

 

六、总结

流程、工具、文档、合同、计划都是工业化的标志。它们带来了稳定的质量、惊人的效率、超大规模的协作,对于软件工业也是如此。

然而软件工业具备轻资产、知识密集型、从业人员素质高等特点,充分发挥人的创造力和价值,是其相较传统工业更高阶的要求。加之软件工程面对的不确定性与复杂度更显著。于是“个体和互动高于流程和工具,工作的软件高于详尽的文档,客户合作高于合同谈判,响应变化高于遵循计划”的敏捷思想应运而生。

通过用户故事,理解用户需求。在迭代中采用渐进的架构设计。定期重构解决技术债务。功能开发的同时编写自动测试代码。自动化持续构建。

由于淡化了部分工业思维中兼顾稳定、质量、效率、成本的传统手段,敏捷思想的最终落地,需要素质极高的从业人员参与其中,且数量不宜过多,以此来弥补流程上的缺失。同时要团队与客户紧密协作,上级的充分信任,才能够有效发挥其灵活应变,又万变不离其宗的优势。这是大胆的返璞归真,好似回到了瀑布模型前的蛮荒时代,实则是更高级的打法,就像独孤九剑一般。所以,敏捷开发“道”的属性更浓。

敏捷开发具有快速迭代、持续集成、拥抱变化等诱人的特点,但也有苛刻的条件要求。不过,即使无法推行完整的敏捷开发,依旧可以在传统模式下,有针对性的应用敏捷开发的实践方法。

0 72

 

一、瀑布模型

瀑布模型,像工厂流水线一样把软件开发分层化。

可以这么说:瀑布模型算是现代软件工程的起源,软件工程的发展,很大部分都是构建于瀑布模型的基础之上的。我们后面所学的软件工程的很多内容,都是源自瀑布模型的衍生,或者其中某个阶段的细分。

 

软件危机的出现(边写边改模型)

在 1960 年初,软件开发刚开始起步,这时的软件开发是混沌无序的,那时候编程语言还是汇编语言为主,开发模式就是边写边改模型。如果程序员水平高,功能简单,还是可行的。后来软件开发需求越来越多,功能越来越复杂,从事软件开发的人员水平也参差不齐,这种落后的软件生产方式已经无法满足迅速增长的计算机软件需求,从而导致软件开发与维护过程中出现一系列严重问题,这个现象也被称之为“软件危机”

像这种边写边改的开发模式,为什么说不能满足复杂软件项目的需要呢?

主要是有几方面的原因:

  • 整个开发过程不可控,想基于这种开发模式做项目计划太难;
  • 项目的人数多了后,无法有效分工协作;
  • 项目开始的时候对需求几乎没有进行有效分析,对需求的理解容易出现偏差,后期导致很多返工;
  • 项目编码完成后,没有有效测试,运行时 Bug 非常多。

 

 

瀑布模型的诞生

为了解决软件危机中的这些问题,在 1970 年,Winston Royce 博士借鉴了其他工程领域的思想,比如建筑工程,提出了瀑布开发模型,指出软件开发应有完整之周期,并将软件开发过程分成了若干阶段。像瀑布一样,从上往下,完成一个阶段继续下一个阶段。

瀑布模型把整个项目过程分成了六个主要阶段:

一、问题的定义及规划这个阶段是需求方和开发方共同确定软件开发目标,同时还要做可行性研究,以确定项目可行。这个阶段会产生需求文档和可行性研究报告。

二、需求分析对需求方提出的所有需求,进行详细的分析。这个阶段一般需要和客户反复确认,以保证能充分理解客户需求。最终会形成需求分析文档。

三、软件设计根据需求分析的结果,对整个软件系统进行抽象和设计,如系统框架设计,数据库设计等等。最后会形成架构设计文档。

四、程序编码将架构设计和界面设计的结果转换成计算机能运行的程序代码。

五、软件测试在编码完成后,对可运行的结果对照需求分析文档进行严密的测试。如果测试发现问题,需要修复。最终测试完成后,形成测试报告。

六、运行维护软件开发完成,正式运行投入使用。后续需要继续维护,修复错误和增加功能。交付时需要提供使用说明文档。

瀑布模型在提出后,因为其简单可行,切实有效,马上就在很多软件项目中应用起来,一直到 2000 年前后,都是最主流的软件开发模型,即使到现在,你也能在很多软件项目中看到它的影子。也是从那时开始,有了“软件生命周期”(Software Life Cycle,SLC) 的概念。

软件生命周期是软件的产生直到报废或停止使用的生命周期。而像瀑布模型这样,通过把整个软件生命周期划分为若干阶段来管理软件开发过程的方法,叫软件生命周期模型。

 

瀑布模型的核心

1.需求

2.设计

3.编码

4.测试

 

瀑布模型的优缺点

以上案例是我参与过的、用瀑布模型开发的软件项目的一个缩影,你会发现瀑布模型其实跟我们传统的建筑建造方式非常类似。

我们拿盖房子的过程来看看瀑布模型。

客户想要盖一栋房子(初步的想法)。

客户一开始可能没想清楚想要什么样子的房子。(客户对需求还不清楚)

施工方开始找客户确认:用途是什么,要个几层的房子,什么建筑风格,希望什么时间完工,预算多少。(问题定义)

施工方根据客户提的需求,对比工期和预算,评估是不是值得做。(可行性研究)

施工方评估后觉得可行,于是和客户签订合同,约定价钱和工期。(立项,制定项目计划)

施工方开始跟客户沟通确认需求,例如每层户型如何,将来的装修风格等。(需求分析)

确认完需求后,施工方开始出建筑施工图,还画了漂亮的建筑效果图。(系统设计和 UI 设计)

施工方按照设计图开始施工。(程序编码)

这期间如果客户去参观施工情况,客户只能看到毛胚,只有最后施工完成才能看到最终样子。(在中间客户看不到结果,只有最后能看到结果)

原定二层是两个卧室,在房子施工过程中,突然客户说两个卧室不够,要改成三个卧室。这意味着施工方要对施工图重新设计,很多已经建好的房间要拆掉重建。(瀑布模型是很难响应需求变更的,而且越到后期代价越大)

工程质量检查人员对施工结果进行质量检测,如果不满足质量要求,需要修改。(测试)

最后验收通过后,客户入住。(上线)

所以你看,用瀑布模型开发软件,就像建筑工程里,盖房子一样简单和自然。每个阶段都有侧重的事情,就像需求阶段专注于搞清楚需求,编码阶段专注于实现。最重要的是,这种编码前先设计、编码后测试、整个过程重视文档的方式,开发出来的产品,质量相对是有保障的。但用瀑布模式开发,也存在一些问题。最大的问题就是不能及时响应需求变更,越到后期变更代价越大。另外,通常要到最后阶段才能看到结果是什么样子。我以前参与过的用瀑布模型方式开发的项目中,在开发和测试阶段加班是常态,原因就在于需求分析和系统设计可能会有延误,从而延迟了编码阶段的开始时间,压缩了编码实现的时间。而在编码阶段,通常会发现很多设计时没有考虑清楚的问题,或者遇到需求变更,导致编码阶段即使加班加点也会大大延期,最后留给测试阶段的时间就不够多了。鉴于瀑布模型存在的这些问题,后来又有很多人提出了其他的软件生命周期模型,比如快速原型开发模型、增量模型、迭代模型,以期保留瀑布模型的这些优点,克服瀑布模型中存在的问题。

 

 

 

二、快速开发快速改模型

快速原型模型(解决需求多变)

我刚毕业时参加了一个项目的开发,项目经理跟我说,这个项目怎么快就怎么写,不要在意代码质量、架构、性能这些,当时我表示很不能理解,哪有这样做项目的?我还偷摸着花了很多时间想把代码写好,结果发现,这个快速做好的简单版本,主要目的就是为了给客户演示,跟客户确认需求,然后把客户的反馈记录下来,再去优化。

这样几个小版本下来,基本上就把需求确定了,而我当时写的好多代码根本就用不上。

后来我才知道,这就是快速原型模型。

快速原型模型,就是为了要解决客户的需求不明确和需求多变的问题。

先迅速建造一个可以运行的软件原型,然后收集用户反馈,再反复修改确认,使开发出的软件能真正反映用户需求,这种开发模型就叫快速原型模型,也叫原型模型。

这就好比客户想要盖房子,但是他没想好要盖成什么样子,于是施工方就先搭了一栋彩钢房(就像工地里面搭的临时房子),让客户先用起来,然后再给反馈调整。因为彩钢房搭建简单快速,改起来也相对容易。

等到客户确定好需求,再在已经搭好的彩钢房的基础上完善,或者直接重新按照确定好的需求造房子。不过,这样做也有一个问题,用彩钢房这种方式盖房子虽然快,但是房子质量不会太好,住的不算舒服,想有点个性化的风格也难。

同样的道理,也适用于软件项目。

彩钢房就像是软件原型,重点是反映软件核心功能和交互,功能可以是不完整的,可靠性和性能要求不高,但开发速度可以很快。

原型模型因为能快速修改,所以能快速对用户的反馈和变更作出响应,同时原型模型注重和客户的沟通,所以最终开发出来的软件能够真正反映用户的需求。

但这种快速原型开发往往是以牺牲质量为代价的。

在原型开发过程中,没有经过严谨的系统设计和规划,可靠性和性能都难以保障。所以在实际的软件项目中,针对原型模型的这种快速、低质量的特点,通常有两种处理策略:抛弃策略和附加策略。

抛弃策略将原型只应用于需求分析阶段,在确认完需求后,原型会被抛弃,实际开发时,将重新开发所有功能。类似于用彩钢房盖房子,确认完客户需求后,拆掉重新建。

附加策略是将原型应用于整个开发过程,原型一直在完善,不断增加新功能新需求,直到满足客户所有需求,最终将原型变成交付客户的软件。类似于用彩钢房盖房子,最后还要做一番精装修,交付客户。

采用哪种策略来应用原型模型,还是要看项目特点,包括所采用原型开发工具和技术的成熟度。举例来说,如果客户对可靠性、性能要求高,那么就最好是抛弃策略,如果客户对质量要求不高,有简单功能就够了,那么可以试试附加策略。

 

快速原型模型即使到现在还一直有在用,用于低成本快速的确认需求。

另外,原型制作并不一定要像传统代码一样进行设计编码,有很多原型工具,像 Axure、墨刀等,简单的拖拽就可以实现简单的界面和交互,同样可以达到确认需求的目的。现在原型设计已经成为产品经理确认需求的一个非常重要手段。

 

大瀑布拆小瀑布(缩短周期)

瀑布模型的很多问题,根源都是周期太长。

周期长所以中间难以响应变更,周期长所以客户很久才能看到结果,周期太长所以风险不好控制。如果能将周期变短,那么很多问题就迎刃而解了。

基于这种思路,产生了很多开发模型,比较典型的主要是:增量模型迭代模型

 

增量模型——按模块分批次交付

增量模型是把待开发的软件系统模块化,然后在每个小模块的开发过程中,应用一个小瀑布模型,对这个模块进行需求分析、设计、编码和测试

相对瀑布模型而言,增量模型周期更短,不需要一次性把整个软件产品交付给客户,而是分批次交付。

如果拿盖房子来比喻的话,就是先盖卫生间,然后盖厨房,再是卧室。

盖卫生间的时候,也要先分析需求,然后设计,再实施,最后验收。有时候也可以多模块并行,例如同时盖卫生间和厨房,前提是模块之间不能有依赖关系,比如,你不可能先盖二楼再盖一楼。

你会发现,增量模型将整个系统进行模块化处理,所以你可以分批次交付软件产品,使用户及时了解软件项目进展。如果一个模块有问题,或者需要做需求变更,对整体影响也有限。在开发的时候,也可以灵活地按照模块来分工,多个模块并行开发提升效率。

因为增量模型的根基是模块化,所以,如果系统不能模块化,那么将很难采用增量模型的模式来开发。另外,对模块的划分很抽象,这本身对于系统架构的水平是要求很高的。

基于这样的特点,增量模型主要适用于:需求比较清楚,能模块化的软件系统,并且可以按模块分批次交付。

 

迭代模型——每次迭代都有一个可用的版本

迭代模型每次只设计和实现产品的一部分,然后逐步完成更多功能。每次设计和实现一个阶段叫做一个迭代。

我们还是继续拿盖房子来举例:如果用迭代模型的方式盖房子,第一个迭代要先盖一个茅草屋,快速满足客户对房子的核心需求;第二个迭代再盖一个小木屋,比茅草房更大更舒适;第三个迭代再盖成一个豪华别墅,满足客户所有需求。

你要注意,无论是造小木屋还是大别墅,整个过程都会像一个完整的项目一样,包括需求分析、设计、实现与测试验收。

在迭代模型中,整个项目被拆分成一系列小的迭代。通常一个迭代的时间都是固定的,不会太长,例如 2~4 周。每次迭代只实现一部分功能,做能在这个周期内完成的功能。

在一个迭代中都会包括需求分析、设计、实现和测试,类似于一个小瀑布模型。迭代结束时要完成一个可以运行的交付版本

迭代模型和增量模型很容易混淆,因为都是把大瀑布拆成小瀑布。

这两种模型的主要差别在于如何拆分项目功能上。增量模型是按照功能模块来拆分;而迭代模型则是按照时间来拆分,看单位时间内能完成多少功能。

还是用盖房子来理解,增量模型则是先盖厨房,再是卧室,这样一个个模块来完成。而迭代模型则是先盖一个简单的茅草房,有简易的土灶和土床,然后再升级成小木屋,有更好的灶和更好的卧室,这样一步步迭代成最终的房子。

我原来参与过的瀑布模型开发的项目,因为要很长时间才能看到最终结果,而且结果通常跟最初描述的结果相差较多,客户看到后多少会有些心理落差。

而后来改用迭代模型后,因为每次迭代完成后都有可以运行的版本,这样客户可以直观感受软件的进展,及时调整心理预期。尤其是当客户见证了一个软件从简陋到完善的过程,往往满意度是比较高的。

迭代模型最难的部分,在于规划每次迭代的内容和要达到的目标。多了可能完不成,少了可能造成每次迭代工作量不饱和,这需要在实践中去摸索,一个迭代一个迭代的去调整。

迭代模型由于在初始迭代时,只清楚当前迭代的需求,而不知道后续需求,设计可能会考虑不周全。这样的话,迭代一多,系统会有不少冗余,一段时间后就需要对系统进行重构。

另外每次迭代,用户可能会增加新的需求和对现有需求进行更改,因此开发时间上可能会比预期要长。如果你做的是小项目的话,并不建议使用迭代模型来开发。

 

 

三、常见的项目场景及模型选择

场景一:外包项目,需要阶段验收(V字模型)

假如你现在是一家外包公司,你可以采用瀑布模型开发,但是甲方需要对你项目的每个阶段进行验收测试,以确认你是不是达到要求。

针对从需求定义一直到编码阶段,每个阶段都有对应的测试验收。如果画成图,就是下面这个样子的。

这个模型就是 V 模型,本质上它还是瀑布模型,只不过它是更重视对每个阶段验收测试的过程模型。

 

场景二:项目风险高,随时可能会中断(增量模型或者迭代模型)

如果你现在要做一个风险很高的项目,客户可能随时不给你钱了。这种情况下,如果采用传统瀑布模型,无疑风险很高,可能做完的时候才发现客户给不了钱,损失就很大了!

这种情况,基于增量模型或者迭代模型进行开发,就可以有效降低风险。你需要注意的是,在每次交付的时候,要同时做一个风险评估,如果风险过大就不继续后续开发了,及时止损。

这种强调风险,以风险驱动的方式完善项目的开发模型就是螺旋模型。

 

场景三:山寨一款软件产品,希望能快速上线发布(增量模型)

其实软件行业山寨的案例不少,山寨项目的特点是,项目需求是明确的,不会有什么变化,这时候就可以选择增量模型,划分好模块,先实现核心模块,发布可运行版本,再增量发布其他模块。多模块可以同步开发。

 

场景四:客户都没想清楚想要什么,但是个大单子很多项目,客户一开始都没想清楚想要的是什么,需要花很长时间去分析定义需求,但是单子很大,值得认真去做好。

分四个阶段:

1. 初始阶段主要是确定需求边界和主要风险,几乎没有什么开发工作。

2. 细化阶段这个阶段主要是确定需求,可以采用快速原型模型开发,和客户对需求反复确认,需要辅助一定量的开发和测试工作。对代码质量可以要求比较低,重点是确认需求。可能需要一个或多个版本迭代。

3. 构造阶段在需求确认清楚后,现在可以使用迭代模型来开发,逐步交付产品。这个阶段的重点是开发和测试。如果迭代中,有新的需求加入或者需求变更,也可以在新的迭代中加入。

4. 交付阶段在开发和测试完成后,产品可以交付客户,根据线上运行情况还需要修复一些 Bug。这个阶段重点是测试和部署。也会有多个迭代。

 

场景五:我的产品已经上线,但是需要持续更新维护

很多产品在上线后,还在保持不停的更新维护,修复 Bug、增加新功能,每个月甚至每周更新。

在这种情况下,迭代模型是比较合适的。固定时间周期,在固定的周期内选择适合的需求开发任务和 Bug 修复任务去完成,按时发布。

另外还可以尝试敏捷开发,也是基于迭代的开发模型,它也强调快速交付,每次交付系统的部分功能,来保证客户满意度。

在敏捷开发中,系统交付的周期称之为冲刺(Sprint)。严格来说,敏捷开发并不算是一种开发模型,更像是框架或指南。有各种开发模型来实现敏捷开发,比如说极限编程(Extreme programming),看板(Kanban)和 Scrum。有关敏捷开发,我将在下一篇中向你详细讲解。

 

 

总结

稳定、可靠、一步到位的瀑布模型,不太适用于违约风险大、需求不明确、快速见效的场景。

快速原型模型:不见兔子不撒鹰。期初不考虑质量、架构,用最快的速度见效,并向用户确认需求。经过几轮直观、快速的反馈,把需求确定下来。接下来,既可以抛弃原型用瀑布精密重构,也可以在模型基础上完善。优点是快速有效的确认需求。不足难以有效应对后续的需求变更。

增量模型:分而治之。将大系统横向拆分成相对独立的若干小模块,每个模块采用瀑布模式分批次交付。优点是较快见到成果,且能够及时了解项目进展。不足是存在需求明确、系统可拆分、交付可分批等适用条件。

迭代模型:罗马不是一天建成。把软件项目纵向划分成若干阶段,从核心功能入手,逐渐深化、细化,直到满足用户的全部需求。每个阶段都是一个瀑布,都要在前一阶段成果基础上加工、打磨。优点是快速满足基本需要,并体会软件演进的快感。不足是需求演化具有不确定性,会导致代码冗余、系统重构风险、项目周期不可控。

我做甲方管过不少外包项目,大V模型再熟悉不过了。整个过程冗长繁琐,走流程比建软件更累心。而且等项目结束的时候,需求早就变得面目全非了。乙方只能硬着头皮做,不然连业绩都没有,真是血本无归。在增量或迭代模型的每次交付后都做一次风险评估,演进为螺旋模型,可以及时止损。

0 88

什么是工程方法?

有目的、有计划、有步骤地解决问题的方法就是工程方法。工程方法不是软件工程独有的,几乎所有工程类别都可能会应用,例如建筑工程、电子工程等,只不过步骤可能略有不同

工程方法通常会分成六个阶段:想法、概念、计划、设计、开发和发布

  • 想法:想法阶段通常是想要解决问题。最开始问题通常是模糊的,所以需要清晰地定义好问题,研究其可行性,检查是否有可行的解决方案。
  • 概念:概念阶段就是用图纸、草图、模型等方式,提出一些概念性的解决方案。这些方案可能有多个,最终会确定一个解决方案。
  • 计划:计划阶段是关于如何实施的计划,通常会包含人员、任务、任务持续时间、任务的依赖关系,以及完成项目所需要的预算。
  • 设计:设计阶段就是要针对产品需求,将解决方案进一步细化,设计整体架构和划分功能模块,作为分工合作和开发实施的一个依据和参考。
  • 开发:开发阶段就是根据设计方案,将解决方案构建实施。开发阶段通常是一个迭代的过程,这个阶段通常会有构建、测试、调试和重新设计的迭代。
  • 发布:将最终结果包括文档发布。

如果你用这六个或者其中几个阶段对照日常工作和生活中遇到的问题,会发现绝大部分问题都可以看成一个项目,并且拆分成几个阶段,按照计划一步步完成。

站在整体而非局部去看问题

可能会有人说:“我不用这种工程方法去做事,一样可以做成呀,并没有什么区别。”确实,做一件事有很多种方式,但用工程方法去处理事情,有两点好处:

  1. 有一个被有效论证过的方法论指导你,可以帮助你提高成功概率,也可以提高效率。
  2. 当你用工程方法去思考的时候,你会更多的站在整体而非局部去思考,更有大局观。

我们在日常处理事务时,天然地会选择自己感兴趣的、擅长的那部分,而容易无视整体和其他部分。所以问题的核心并不在于是不是用工程方法,而是有没有把这件事当作一个项目,是不是能看到这件事的全貌,而不是只看到局部。

 

工程思维,本质上是一种思考问题的方式,在解决日常遇到的问题时,尝试从一个项目的角度去看待问题、尝试用工程方法去解决问题、站在一个整体而不是局部的角度去看问题。

 

总结

学习本章之后的收获主要有两点:

  1. 无论是日常生活还是工作,都应该应用工程思维,将一个事情分成几个阶段,然后指定相应的计划
  2. 站在整体而非局部去看待问题,更多的关注项目的质量,进度,成本等大方向,对项目有利,对自己也有利

 

实际场景:

以下这些工作场景,估计你不会陌生。

  • 产品经理提出一些天马行空、不切实际的需求,而技术上不可行或者实现成本很高,导致最后返工,造成资源浪费和进度延迟;
  • 架构师为了满足开发上的成就感,更愿意自己“造轮子”,而不愿意采用现有开源程序或者购买合适的组件;
  • 开发工程师喜欢在代码中使用各种设计模式或者最新技术,导致项目进度延迟,代码难以维护;
  • 测试工程师不愿意学习自动化测试技术,导致测试周期较长,且容易出现疏漏;除非产品经理特别注明,开发工程师和测试工程师不会注意用户体验上的细节。

这样的场景问题还有很多,为什么会出现这种情况呢?事实上,这在很大程度上都归因于大家只是站在自己岗位的角度来看问题,没有站在项目的整体角度来看。

如果能站在项目整体来看问题,你就会去关注项目的质量、项目的进度、项目的成本、项目的最终用户,那么上面这些场景将变成:

  • 为了项目整体的效率和避免返工浪费,产品经理会及早和开发人员确认技术可行性,并对产品设计先行验证;
  • 为了节约项目开发成本,提高开发效率,架构师选择成熟的架构,合理购买商业组件和使用开源程序;
  • 为了提升开发效率,不影响项目开发进度,开发工程师尽可能采用成熟的技术,高效简洁地落实项目;
  • 为了项目质量和效率,测试工程师学习自动化测试技术,将大部分测试变成自动化运行,极大地提高了测试效率和质量;
  • 为了让用户有好的体验,不仅产品经理,每个人都会仔细体验用户界面,对于不合理的地方提出改进意见。

0 70

有人参与、有计划、有步骤地造一件产品,我们通常称为“工程”。

所有工程的本质,就是要做出有用的产品,比如造房子的建筑工程、造火箭的航天工程。像网红“手工耿”一样专搞无用发明的情况,我们是不能称为“工程”的。在软件领域,对应的就是“软件工程”,这些我们日常使用的软件背后,都是基于软件工程的方法在开发、运行和维护的。

 

一、什么是软件危机?

也许有人会认为,不用软件工程,我一样可以开发软件出来。这确实没有错,因为如果一个人没有学过建筑工程,他也是可以造一个房子出来,只是造出来大概会是这个样子:

我们知道,不按照建筑工程造房子,是会出事故甚至死人的。

而在软件工程的历史上,也是真的有造成过很大损失、甚至还有人为之丧命的事件存在。OS/360 操作系统是上世纪 60 年代最复杂的软件系统之一,也是第一个超大型的软件项目,一共有 1000 名左右的程序员参与了项目的研发,花费了 5000 个人年,最终无法运行。项目负责人佛瑞德·布鲁克斯后来写了一本软件工程的经典书籍《人月神话》,承认在他管理这个项目的时候,犯了很多错误,造成了价值数百万美元的损失。如果是说 OS/360 还只是造成了经济损失的话,Therac-25 事件就是真的导致了人员死亡。Therac-25 是加拿大原子能有限公司(AECL)所生产的放射线疗法机器,在 1985 年到 1987 年之间,在美国及加拿大,至少有六起和 Therac-25 相关的医疗事故是因为程序 bug,导致部分病患受到比正常剂量高一百倍的辐射,因而造成患者重伤甚至死亡。

发生这些惨痛的事,原因却并不难理解。

在计算机刚发明出来的时候,计算机的能力非常有限,只能接收简单的指令和运算,不需要软件工程也可以开发出简单的软件。但是,当软件的规模越来越大,复杂度不断增加,软件项目开发维护过程中的问题就逐步暴露出来:软件产品质量低劣、软件维护工作量大、成本不断上升、进度不可控、程序人员无限度地增加。所以在 60 年代,“软件危机”的概念被提出来。

 

二、应对软件危机的办法—软件工程的概念被提出

为了解决“软件危机”,1968年北大西洋公约组织提出了“软件工程”这个概念。软件工程,它是为研究和克服软件危机而生。软件工程,就是要用工程化方法去规范软件开发,让项目可以按时完成、成本可控、质量有保证。

 

三、软件工程的演化史

对比传统的工程学科,和软件工程最接近的就是建筑工程了。设想一下建一座房子:首先要先立项、设定预算,然后画设计图,再是施工,施工完成后,由专业人士进行质量检查,质检合格后入住。开发软件本质上也是像盖房子一样,是从无到有创造的过程。工程化的方式,就是你分步骤(过程),采用科学的方法,借助工具来做产品。于是参考建筑工程,整个软件开发过程也被分成了几个阶段:需求定义与分析、设计、实现、测试、交付和维护,这也就是我们常说的软件项目生命周期。

当然,各个阶段都会有人的参与,于是产生了软件项目里的各种角色:项目经理、产品经理、架构师、程序员、测试工程师、运维工程师。

而对这整个过程的管理,我们通常称之为“项目管理”。同时,也很自然就衍生出一套最基础的过程模型:瀑布模型。

 

瀑布模型:

瀑布模型的详解:

用瀑布模型做项目就像古代匠雕刻玉石,先有完整的设计图,然后按部就班往前推进,中间不能出一点差错,追求的是“一次成型”。

这就是瀑布模型,最基本也最常用的一种项目管理模型,又称线性模型

采用瀑布模型的项目依照该模型选定的阶段顺序进行,每一个阶段的工作产品都是下一个阶段工作的输入,每一个阶段只有在上一个阶段通过检查,确认完成后才开始新的阶段工作。

▲ 瀑布模型的思想示意图

瀑布模型的突出特征是文档驱动。从需求分析到系统维护,每一项活动的工作成果就是此项活动所产生的工作文档,以及在此基础上形成的产品。

瀑布模型最大的优点有两个:

1、每个阶段的开发质量都有保证,减少了返工。2、是文档细致,降低了沟通成本,有利于及早发现问题。

这就是开头说的雕刻玉石的步骤,有精细的设计图纸,每一步都不可行差踏错,因为一旦雕坏了,就得摔了玉重来。

这也正是瀑布模型的缺点:周期长,不易变更。

用户直到项目开发晚期才能了解产品的真实面貌和质量。这时候提出变更,成本会非常大。

适合采用瀑布模型的项目类型,通常是对用户需求非常明确的项目。同时还要求项目预算充足,人员齐备。

链接:https://zhuanlan.zhihu.com/p/116754890

瀑布模型的作用:

瀑布模型的诞生,在当时是有非常重大的意义的,让软件开发从无序到有序,让大家更好的分工协作,同时每个阶段又衍生出各自的方法学和工具,例如需求分析、软件测试等等。

瀑布模型的缺陷:

然而瀑布的特性决定了它只能从上往下流,而且从上到下走完整个周期很长,所以一旦出现了需求的变更,将会非常痛苦,很多事情需要重头再来。

瀑布模型的衍生:

于是基于瀑布模型,又衍生出 V 模型、原型设计、增量模型、螺旋模型等模型,试图改善瀑布模型存在的一些缺陷。这些改进模型的发展趋势上就是缩短项目周期,快速迭代。

敏捷联盟的出现:

这样到了 90 年代,各种轻量级开发方法例如 Scrum、极限编程等也不断被提出。到了 2001 年,这些轻量级开发方法一起组成了敏捷联盟,其后敏捷开发如同星星之火,逐渐形成燎原之势。

近些年,云计算、微服务这些新技术的产生,也对软件工程产生了影响。云服务让分工更细,很多企业可以将运维、服务器维护、DBA、甚至某些独立服务交给云服务商;微服务让大团队变成小团队,每个小团队可以更专注于细分领域,减少相互之间的依赖。

 

​一个公式

当你大致了解整个软件工程的演变发展史,你会发现,软件工程的知识,都是建立在软件项目的过程,或者说软件项目生命周期之上的。基于软件过程,我们有了角色分工,有了对过程的管理和工具,对过程中每个阶段细分的方法学和工具。

现在,如果再回头看看我们的问题“什么是软件工程?”其实可以总结为:软件工程就是用工程化的方法来开发维护软件。

也可以说软件工程就是用一定的过程,采用科学的方法,借助工具来开发软件。如果用一个简单的公式表达,那就是:软件工程 = 过程 + 方法 + 工具。

 

0 65

软件工程知识架构全景图(三要素)

首先你要明确,当我们谈软件工程学时,究竟在讲些什么呢?

在《软件工程——实践者的研究方法》这本经典软件工程教材中,作者 Roger S.Pressman 画了一张图,高度概括了整个软件工程的核心知识。

由图可见,“质量焦点”在最底层,这不难理解软件工程是为了应对软件危机诞生的学科,其目标就是为了要聚焦于质量,构建和维护高质量的软件。可以说,聚焦于质量就是软件工程的基石。

那“过程”指的是什么呢?

要构建高质量软件,则要解决软件过程中的混乱,将软件开发过程中的沟通、计划、建模、构建和部署等活动有效地组织起来。而软件过程,就是在软件项目的生命周期内,也就是软件从诞生到结束这期间,在开发与构建系统时要遵循的步骤。有两种过程框架你一定经常听到,那就是瀑布模型和敏捷开发。这是在软件工程多年的发展中,逐步形成的两种主流的软件过程指导框架。

那么,何为“方法”?

方法是指在整个过程中,如何构建系统的方法学。比如说,如何分析用户需求;如何对产品进行测试验收;如何进行系统架构设计等。

知道了过程,掌握了方法,那么具体落到操作层面,就会涉及到工具的使用。

我们需要工具来辅助方法的执行,提高效率。通过工具,可以把一些手动的工作自动化,比如自动化测试工具,自动构建部署工具;通过工具,可以帮助把一些流程规范起来,比如 Bug 跟踪、源代码管理;还可以通过工具,帮助提高编码效率,比如各种编辑器 IDE、各种高级语言。

如果现在再回头总结一下,软件工程的核心知识点,就是围绕软件开发过程,产生的方法学和工具。

你可以用一个简单的公式来理解软件工程,那就是软件工程 = 工具 + 方法 + 过程。

根据这个公式,我将软件工程的知识结构做成了思维导图,方便你对知识点有更好地理解,高效学习。

 

如何学习软件工程?

我给了你软件工程学的公式,也对软件工程有了更为全面的了解,看起来软件工程学很简单,但这些内容一下子要吃透也不容易。在开篇词中,我介绍了会从“道、术和器”三个维度去讲这个专栏,这其实对应了学习软件工程的四重境界。

学习软件工程的四重境界

第一重:用器

“器”就是工具,工具规则简单,上手就可以用,也很快就能看到效果。比如,原型设计工具可以帮助你确定需求,持续集成工具可以帮助你简化测试和部署的流程。对工具的学习是最为简单的,也是最基础的。

第二重:学术

“术”就是方法,学会方法,你就能应用方法去完成一个任务,例如用需求分析的方法,你去搞清楚用户想要什么,用 Scrum 去组织项目开发过程。掌握了术,甚至是可以脱离器的,例如你没用原型设计工具,你用纸和笔,用白板,一样可以去沟通确认需求。

第三重:悟道

“道”就是本源,软件工程知识的核心思想和本质规律。就像敏捷开发,本身并不是一种方法,而是一套价值观和原则,领悟了这个道,就可以成为你在处理项目过程中各种问题决策的依据。道是可以产生术的,你掌握了敏捷开发的道,你就可以领悟出 Scrum、极限编程这样的术。

第四重: 传道当你能把复杂的知识通过浅显易懂的方式传授给别人,那就说明你对知识的领悟已经到了更高的境界。同时,教学也是最好的学习方式,通过传授别人知识,可以让你对知识本身有更深入的理解。

做中学和教中学

你可能会问,怎样学,才能到达以上这四重境界?我在做技术管理的工作中,经常要做一些培训的工作,在这过程中我总结了两套行之有效的方法:“做中学”和“教中学”。

“做中学”,是一种自下而上的学习方法,通过实践,从使用工具到学习方法,再从方法中提炼出道。

在学习本专栏的时候,你可以采用“做中学”的方式,把专栏中的知识应用起来,在实践的过程中去巩固你学到的知识,去思考背后的道。把已经积累的项目经验和软件工程的知识点关联起来,这样才能加深你的理解,学以致用,把经验和知识转化为能力。

“教中学”,是一种自上而下的学习方法,通过教学,去进一步深入领会别人总结出来的道,去模仿推导方法,去学习如何使用工具。比如,你学习完一篇专栏文章后,把学到的知识进行输出,写成微博或博客分享出去;在公司内部讲给你的同事们听等。在教学分享的过程中,去进一步深化吸收知识内容,构建你的知识体系。

“做中学”和“教中学”,这两种方法你可以配合起来使用。

 

总结

软件工程知识架构为:以工具,方法,过程三要素,力求构建出高质量的软件。

三要素的关系可以概括为:软件过程,就是在软件项目的生命周期内,也就是软件从诞生到结束这期间,在开发与构建系统时要遵循的步骤,有了步骤就要有方法去实现,方法是指在整个过程中,如何构建系统的方法学,而工具就是为了提高方法的实现效率的工具。

学习软件工程的四部曲:

  1. 掌握工具的使用(比如使用栈类,队列类)
  2. 脱离工具也可以达到目的(比如不用现成的,自己实现一个栈,队列)
  3. 思考软件开发过程的本源(比如创建一个新的数据结构)
  4. 传授给别人。

也就是说 先设计出过程—>再得出实现过程的方法—>构建工具实现方法

0 55

引言

按理论上来说,我已经系统的 学习过软件工程这门课了。

但实际上,我一点也不理解 软件工程 这个标题的含义,甚至无法准确的描述软件,或者是工程的含义;我相信很多的同学跟我一样,仍然犯迷糊,因此我试图通过分享学习宝玉前辈的《软件工程之美》的一点心得,来帮助所有看到本篇文章的朋友。(或者是自己学习用,因为我只是个小菜鸡)

 

一、没有学习软件工程而出现的问题

花费较多的时间去学习各种技术栈,我称之为 下沉

在下沉的过程中,我们不断点亮新的技能点,这是一个很愉快的过程,但同时也是很危险的,正如潜水员不断下潜,也在离海平面越来越远,离海平面越远,就越容易失去对方向和计划的把握。

学习是为工作而服务,点亮新的技能点也是为了解决所接手的开发任务,那为什么,我们在工作的时候,会产生   明明我很努力,很认真,很有激情的,花200%的心血去完成开发任务,却收效甚微,或者频频出错,从而导致自己加班加点,信心受挫,给公司造成损失 的情况?

我们在实际工作中,常常遇到很多问题,比如:

  • 开发时没有分析没有设计,上手就写,后期难维护,加班熬夜去填“坑”;(开发前不分析思考)
  • 缺少理论指导,遇到新项目不能举一反三,工作很平庸;(开发时不能融会贯通)
  • 遇到需求变更这种事,除了抱怨两句客户,只能闷头做,无力反抗;(无法良好的应对需求变更)
  • 做项目没计划性,想到哪做到哪,总是延期,比其他同事做的慢;(无计划,无组织,无效率)
  • 不知道如何与团队协作,职业发展遇到瓶颈,无法得到晋升。(职业生涯上升遭遇阻塞)

那么,科班出身的程序员是否与我有同样问题?像微软、阿里等这些大厂的程序员,他们又是怎样协调完成好那么庞大的项目?我这个“野路子”程序员面临的问题,他们又是怎么分工协作解决的?

软件工程可以解开这些困惑。

 

二、软件工程

软件工程:软件项目的开发其实是一个工程,整个开发过程是可以有效组织起来的;对于开发过程的各个阶段,已经有很多解决问题的最佳实践,有很多方法来帮助我们高效完成任务;我们还可以借助工具来协助管理,提升开发效率。

于我而言,学习软件工程,使我区分出了 术 与 道 的概念。

  • 术:各种技术栈;
  • 道:站在工程,项目的角度去思考问题的出现,解决,本源。

软件工程将应用于软件开发的整个历史。(即以前,现在,未来都需要软件工程)。

你会发现,无论你是什么岗位,只要你从事软件开发相关领域,都绕不开“软件工程”,因为现代软件项目开发,多多少少都离不开软件工程知识的应用。想象下在日常工作中,不管你用什么开发语言,不管是前端和后端:

  • 你接到一个开发任务,如果想开发出客户想要的功能,你是不是先要做需求分析;
  • 你接手一个复杂的、大的功能模块,是不是先要做设计,才能把复杂的拆成简单的,才能让大家一起分工去开发;
  • 你完成一个功能模块,如果要保证质量,是不是需要写一些测试代码,还要做一些功能测试;
  • 还有日常用的那些工具,像源代码管理、Bug 跟踪。

而这些内容,都是软件工程相关的知识,和你用什么语言无关。

换言之,这就是经典的价值,为什么说我们要学经典,因为经典就是这个行业最为本质的东西。你顺着这个逻辑想,就知道为什么大学的计算机专业要设计数据结构、算法、操作系统、软件工程这样的课程了。

技术更新迭代速度确实很快,难以把握,更难以预测,但是软件开发背后的逻辑却万变不离其宗。你只有掌握了这些逻辑,才能步步为营,不被快速发展的软件开发行业所淘汰。因为你脑袋里装有软件开发的战略,相对于赤手空拳、盲打莽撞的人来说,你更能在未来获得先机。