如何理解软件工程

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

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

  • 软件工程定义的本质:就是要用工程化方法去规范软件开发,让项目可以按时完成、成本可控、质量有保证。

  • 开发软件本质上也是像盖房子一样,是从无到有创造的过程。工程化的方式,就是你分步骤(过程),采用科学的方法,借助工具来做产品。如果质量不达标终会造成严重后果。

  • 整个软件开发过程也被分成了几个阶段:需求定义与分析、设计、实现、测试、交付和维护,这也就是我们常说的软件项目生命周期。

  • 各个阶段都会有人的参与,于是产生了软件项目里的各种角色:项目经理、产品经理、架构师、程序员、测试工程师、运维工程师。而对这整个过程的管理,我们通常称之为“项目管理”

  • 很自然就衍生出一套最基础的过程模型:瀑布模型。
    图片说明

  • 瀑布的特性决定了它只能从上往下流,而且从上到下走完整个周期很长,所以一旦出现了需求的变更,将会非常痛苦,很多事情需要重头再来。于是基于瀑布模型,又衍生出 V 模型、原型设计、增量模型、螺旋模型等模型,试图改善瀑布模型存在的一些缺陷。这些改进模型的发展趋势上就是缩短项目周期,快速迭代。

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

  • 软件工程的知识,都是建立在软件项目的过程,或者说软件项目生命周期之上的。基于软件过程,我们有了角色分工,有了对过程的管理和工具对过程中每个阶段细分的方法学和工具。

  • 软件工程就是用工程化的方法来开发维护软件。也可以说软件工程就是用一定的过程,采用科学的方法,借助工具来开发软件。

  • 软件工程 = 过程 + 方法 + 工具

  • 而软件工程的核心,就是围绕软件项目开发,对开发过程的组织,对方法的运用,对工具的使用。

    掌握工程思维

  • 软件工程是一门用工程化方法解决软件项目问题的学科,其本质也是一门工程学科,这门课的知识在学完后,不仅可以应用在软件项目中,还可以应用于日常生活中遇到的一些问题,Everything is a project。

  • 解决这些问题的方式,就是参考软件生命周期和瀑布模型,把一件事情分成几个阶段:分析、设计、实施、测试、完成,然后制定相应的计划。这种方法不仅非常有效,让我的做事效率大幅提高,而且让我在看待事情上,能够更全面地、站在更高的角度去思考。

  • 站在整体而非局部去看问题。确实,做一件事有很多种方式,但用工程方法去处理事情,有两点好处:

  1. 有一个被有效论证过的方法论指导你,可以帮助你提高成功概率,也可以提高效率。
  2. 当你用工程方法去思考的时候,你会更多的站在整体而非局部去思考,更有大局观。
  • 所以问题的核心并不在于是不是用工程方法,而是有没有把这件事当作一个项目,是不是能看到这件事的全貌,而不是只看到局部

  • 如果能站在项目整体来看问题,你就会去关注项目的质量、项目的进度、项目的成本、项目的最终用户。每个项目成员,如果能多站在项目的角度去考虑,那么这样不仅对项目有利,更对自己有好处。工程思维,本质上是一种思考问题的方式,在解决日常遇到的问题时,尝试从一个项目的角度去看待问题、尝试用工程方法去解决问题、站在一个整体而不是局部的角度去看问题。

  • 改变,最有效的是方式是改变思想,这往往也是最难的部分

瀑布模型

  • 瀑布模型,像工厂流水线一样把软件开发分层化。瀑布模型算是现代软件工程的起源,软件工程的发展,很大部分都是构建于瀑布模型的基础之上的。指出软件开发应有完整之周期,并将软件开发过程分成了若干阶段。像瀑布一样,从上往下,完成一个阶段继续下一个阶段。
    图片说明
    瀑布模型把整个项目过程分成了六个主要阶段:
    一、问题的定义及规划
    这个阶段是需求方和开发方共同确定软件开发目标,同时还要做可行性研究,以确定项目可行。这个阶段会产生需求文档和可行性研究报告。
    二、需求分析
    对需求方提出的所有需求,进行详细的分析。这个阶段一般需要和客户反复确认,以保证能充分理解客户需求。最终会形成需求分析文档。
    三、软件设计
    根据需求分析的结果,对整个软件系统进行抽象和设计,如系统框架设计,数据库设计等等。最后会形成架构设计文档。
    四、程序编码
    将架构设计和界面设计的结果转换成计算机能运行的程序代码。
    五、软件测试
    在编码完成后,对可运行的结果对照需求分析文档进行严密的测试。如果测试发现问题,需要修复。最终测试完成后,形成测试报告。
    六、运行维护
    在软件开发完成,正式运行投入使用。后续需要继续维护,修复错误和增加功能。交付时需要提供使用说明文档

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

  • 因为不管什么软件项目,不管采用什么开发模式,有四种活动是必不可少的,那就是需求、设计、编码和测试。而这四项活动,都是起源自瀑布模型,也是瀑布模型中核心的部分

  • 每个阶段都有侧重的事情,就像需求阶段专注于搞清楚需求,编码阶段专注于实现。最重要的是,这种编码前先设计、编码后测试、整个过程重视文档的方式,开发出来的产
    品,质量相对是有保障的。

  • 瀑布模型最大的问题就是不能及时响应需求变更,越到后期变更代价越大。另外,通常要到最后阶段才能看到结果是什么样子。
    图片说明

  • 瀑布模型简单易行,对于软件质量是有比较高保障的。但是瀑布模型对于前期需求不明确的项目,很难开展需求分析,后续如果有需求变更,瀑布模型便很难响应。

    瀑布模型的衍生模型

快速开发快速改

  • 快速原型模型,就是为了要解决客户的需求不明确和需求多变的问题。先迅速建造一个可以运行的软件原型,然后收集用户反馈,再反复修改确认,使开发出的软件能真正反映用户需求,这种开发模型就叫快速原型模型,也叫原型模型。
  • 原型模型因为能快速修改,所以能快速对用户的反馈和变更作出响应,同时原型模型注重和客户的沟通,所以最终开发出来的软件能够真正反映用户的需求。但这种快速原型开发往往是以牺牲质量为代价的。
  • 在原型开发过程中,没有经过严谨的系统设计和规划,可靠性和性能都难以保障。所以在实际的软件项目中,针对原型模型的这种快速、低质量的特点,通常有两种处理策略:抛弃策略和附加策略。
  • 抛弃策略是将原型只应用于需求分析阶段,在确认完需求后,原型会被抛弃,实际开发时,将重新开发所有功能。类似于用彩钢房盖房子,确认完客户需求后,拆掉重新建。附加策略则是将原型应用于整个开发过程,原型一直在完善,不断增加新功能新需求,直到满足客户所有需求,最终将原型变成交付客户的软件。类似于用彩钢房盖房子,最后还要做一番精装修,交付客户。采用哪种策略来应用原型模型,还是要看项目特点,包括所采用原型开发工具和技术的成熟度。举例来说,如果客户对可靠性、性能要求高,那么就最好是抛弃策略,如果客户对质量要求不高,有简单功能就够了,那么可以试试附加策略。
  • 快速原型模型即使到现在还一直有在用,用于低成本快速的确认需求。如果你将来遇到这种项目,就没必要花太长时间在代码质量上,赶紧做出来才是王道。另外,原型制作并不一定要像传统代码一样进行设计编码,有很多原型工具,像** Axure、墨刀等,简单的拖拽就可以实现简单的界面和交互,同样可以达到确认需求的目的**。现在原型设计已经成为产品经理确认需求的一个非常重要手段。

大瀑布拆小瀑布

  • 瀑布模型的很多问题,根源都是周期太长。周期长所以中间难以响应变更,周期长所以客户很久才能看到结果,周期太长所以风险不好控制。
    如果能将周期变短,那么很多问题就迎刃而解了。基于这种思路,产生了很多开发模型,比较典型的主要是:增量模型 和 迭代模型

    增量模型

  • 增量模型:按模块分批次交付。增量模型是把待开发的软件系统模块化,然后在每个小模块的开发过程中,应用一个小瀑布模型,对这个模块进行需求分析、设计、编码和测试。相对瀑布模型而言,增量模型周期更短,不需要一次性把整个软件产品交付给客户,而是分批次交付。如果拿盖房子来比喻的话,就是先盖卫生间,然后盖厨房,再是卧室。盖卫生间的时候,也要先分析需求,然后设计,再实施,最后验收。

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

  • 因为增量模型的根基是模块化,所以,如果系统不能模块化,那么将很难采用增量模型的模式来开发。另外,对模块的划分很抽象,这本身对于系统架构的水平是要求很高的。基于这样的特点,增量模型主要适用于:需求比较清楚,能模块化的软件系统,并且可以按模块分批次交付。

    迭代模型

  • 迭代模型——每次迭代都有一个可用的版本
    迭代模型每次只设计和实现产品的一部分,然后逐步完成更多功能。每次设计和实现一个阶段叫做一个迭代。我们还是继续拿盖房子来举例:如果用迭代模型的方式盖房子,第一个迭代要先盖一个茅草屋,快速满足客户对房子的核心需求;第二个迭代再盖一个小木屋,比茅草房更大更舒适;第三个迭代再盖成一个豪华别墅,满足客户所有需求。迭代模型更像是从一个毛坯房到室内装修再室外装修再加家具布
    置的精装过程
    图片说明

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

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

  • 增量模型是按照功能模块来拆分;而迭代模型则是按照时间来拆分,看单位时间内能完成多少功能。还是用盖房子来理解,增量模型则是先盖厨房,再是卧室,这样一个个模块来完成。而迭代模型则是先盖一个简单的茅草房,有简易的土灶和土床,然后再升级成小木屋,有更好的灶和更好的卧室,这样一步步迭代成最终的房子。

  • 瀑布模型开发的项目,因为要很长时间才能看到最终结果,而且结果通常跟初描述的结果相差较多,客户看到后多少会有些心理落差。用迭代模型后,因为每次迭代完成后都有可以运行的版本,这样客户可以直观感受软件的进展,及时调整心理预期。尤其是当客户见证了一个软件从简陋到完善的过程,往往满意度是比较高的。迭代模型最难的部分,在于规划每次迭代的内容和要达到的目标。多了可能完不成,少了可能造成每次迭代工作量不饱和,这需要在实践中去摸索,一个迭代一个迭代的去调整。迭代模型由于在初始迭代时,只清楚当前迭代的需求,而不知道后续需求,设计可能会考虑不周全。这样的话,迭代一多,系统会有不少冗余,一段时间后就需要对系统进行重构。另外每次迭代,用户可能会增加新的需求和对现有需求进行更改,因此开发时间上可能会比预期要长。如果你做的是小项目的话,并不建议使用迭代模型来开发

    如何选择合适的过程模型

  • 外包项目,需要阶段验收
    图片说明
    这个模型就是 V 模型,本质上它还是瀑布模型,只不过它是更重视对每个阶段验收测试的过程模型。

  • 项目风险高,随时可能会中断
    图片说明
    这种强调风险,以风险驱动的方式完善项目的开发模型就是螺旋模型。

  • 山寨一款软件产品,希望能快速上线发布
    山寨项目的特点是,项目需求是明确的,不会有什么变化,这时候就可以选择增量模型,划分好模块,先实现核心模块,发布可运行版本,再增量发布其他模块。多模块可以同步开发。

  • 客户都没想清楚想要什么,但是个大单子
    图片说明
    上面这种开发方式来源自统一软件开发过程(Rational Unified Process,RUP),适用于复杂和需求不明确的软件系统。

  • 我的产品已经上线,但是需要持续更新维护
    很多产品在上线后,还在保持不停的更新维护,修复 Bug、增加新功能,每个月甚至每周更新。在这种情况下,迭代模型是比较合适的。固定时间周期,在固定的周期内选择适合的需求开发任务和 Bug 修复任务去完成,按时发布。另外还可以尝试敏捷开发,也是基于迭代的开发模型,它也强调快速交付,每次交付系统的部分功能,来保证客户满意度。在敏捷开发中,系统交付的周期称之为冲刺(Sprint)。严格来说,敏捷开发并不算是一种开发模型,更像是框架或指南。有各种开发模型来实现敏捷开发,比如说极限编程(Extreme programming),看板(Kanban)和 Scrum。

总结

现在的软件项目,各种类型都有,根据项目特点,选择好合适的开发模型,可以让你事半功倍,降低项目风险,提高项目开发效率,控制项目成本

  1. 一个以确认需求为主要目的的项目,就可以不用花太多时间在代码质量上面,低成本、高效做出来才是最重要的;
  2. 一个高风险的项目,则可以采用螺旋模型,出现问题及时止损;
  3. 一个很长时间加班加点,却一直没法上线,导致士气低落的项目,可以改成增量模型,先上线一个小模块,让大家看到成绩提升士气,然后再迭代,逐步上线其他模块。
    当然也不拘泥与上述几种模型,可以借鉴其他模型做的好的地方,甚至创造自己的开发模型。