1.概论
开篇就讲到一个概念即:软件=程序+软件工程。
书中说到,程序指的是源程序,也就是基于数据结构上的实现算法,这是我们软件学生的基本功。程序员需要对代码不断编写,程序越来越庞大,就需要源代码管理。程序是要正确运行的,就需要软件测试。我们写的程序需要让别人的看得懂,就得运用程序理解。程序总会出现BUG,就需要软件维护。掌握一系列过程需要一个项目经理,称为项目管理。
所以,构建管理(数据结构+算法),源代码管理,软件测试,软件维护,项目管理,需求分析这些环节构成了软件工程。
我们在学校做一些小项目的时候,往往没有用到软件工程去进行开发,运营,维护。甚至有的不经过需求分析,就一边打代码一边构造需求,软件工程是把系统的,有序的,可量化的方法应用到软件的开发,运营,维护过程中。学习高软很难,难在哪里?我想有以下几点:1.软件复杂型,安卓开发项目中,定义了10个20个类我们都很好理解整个程序的运行过程,类与类之间的调用关系,但是一旦到了上百上千个类,模块之间的依赖几何级上升。2.不可见性,有些错误如JAVA运行时异常的BUG是很难调的。
2.个人技术和流程
现在的开发往往是很多人合作完成一款软件应用,不同的开发人员之间就存在依赖关系。我需要调用你写的代码模块,你也需要调用我写的代码模块,但是因为不了解模块的变化,模块没有达到高内聚低耦合造成了对其他模块的影响,往往会产生错误。在确定发布这个模块的时候,要经过完整的单元测试,为了达到事半功倍的效果,我们可以把规格说明说写得详细一些,详细到各项要求都可以表示为一个单元测试用例。
卡耐基梅隆有一套个人开发流程,很适用于我们做个人开发。接到项目之后我们可以按照以下几个步骤来进行,
估算时间--->需求分析--->生成设计文档--->设计复审--->代码规范--->具体设计--->编写代码--->代码复审--->代码测试--->记录用时--->测试报告--->计算工作量--->总结--->讨论改进。随着工作年限的增长,编码所占的比例会越来越小,因为开发不再是一味地编码,测试所占的比重会越来越高,保证质量要求。
3.软件工程师的成长
那么,我们为什么要用软件工程呢?因为软件工程把开发,运营,维护的过程中的技术,做法,习惯和思想结合到一起(软件开发流程)提高了软件开发,运营,维护的效率。同时,运用软件工程,也减轻了我们的工作量,避免不必要的返工。
怎么提高技能?通过不断的努力,把那些低层次的问题都解决了,变成不用经过大脑的自动操作,然后才有时间和脑力来解决较高层次的问题。我们要精通低层次问题(int[] arr还是int arr[],ArrayList 还是 Array<T>),中层次问题(使用何种架构),高层次问题(效能优化。。。。。。).
4.两人合作
现在的开发已经很少是单独完成的,最少也是两个人了。我们写代码不仅仅要让机器了解,更要让别人看得懂,让你的队友看得懂。这就需要代码规范。代码规范分为代码风格规范和代码设计规范。代码风格规范包括:缩进,行宽,{}的位置,分行,命名,大小写。其中我认为比较重要的有:每个语句只定义一个变量,做一个操作。即便IF和ELSE语句只有一句,也使用{}。在变量名中加入下划线表示作用域,如m_iAge。
代码设计规范不光是程序书写的问题了,而且牵涉到程序设计,模块之间的关系,设计模式等等。
一个函数只做一件事。
按照public,protected,private顺序来说明类中的成员。
在小型软件开发过程中,有一种模式叫做结对编程,在这种模式下,一对程序员一起完成设计,代码,测试,文档工作,由于每个工作都被两双眼睛看过,程序的初始质量取决于各方面水平较高的那一位程序员,在整个开发过程中不断地进行着潜移默化的复审。
5.团队和流程
什么是团队?团队有一致的集体目标,团队要一起完成这个目标。团队成员有各自的分工,互相依赖合作,共同完成任务。刚开始创业时,一些程序员聚在一起想写出好的程序,蜂拥而上一起解决问题,这是最简单的模式(一窝蜂模式)。逐渐地,团队就会过渡到以下模式。
主治医师模式:有一位首席程序员,负责处理主要模块的设计和编码,其他成员从各种角度支持他的工作。
社区模式:有一些志愿者参与自己感兴趣的项目,不拿报酬,如linux社区。
业余剧团模式:这样的团队在每一个项目中,不同的人会挑不同的角色。在下一个项目中,这些人也许会完成换成另外一个角色。团队有个老大指挥一切。
功能团队模式:具备不同能力的同事们平等协作,共同完成一个功能。
一起做软件,总要有一些开发方法,比如:
谢了再改模式:不需要太多的知识,直接上手写代码,一直改,直到发布。
瀑布模型:单向不可逆,最终产品直到最后才出来。按照需求分析-编码测试-发布一步步走下来。力求一次完成。
RUP统一过程:在大的尺度上像瀑布模型,在每个阶段内像迭代模型。初始阶段:分析系统大概的构成,和什么样的外部实体打交道,大致的成本和预算是多少。细化阶段:编制项目计划,确认主要的功能,性能。构造阶段:把所有的功能集测试并发布为Beta版。交付阶段:基于用户的反馈,不断进行修改。
6.敏捷流程
Scrum方法论是敏捷过程的一种,敏捷过程的精髓在于快速交付。第一步:找出完成产品需要做的事情,每一项工作用天为单位计算。第二步:把整个产品分为几个相互联系的冲刺,也就是sprint,团队成员主导任务的估计和分配,各取所长,能动性得到较大发挥。第三步:冲刺阶段各个团队相互独立,所有的问题都只能在这个冲刺完成之后进行交流。冲刺期间,每天需要开一个站立会议,告诉队友我昨天所做,今天将做,遇到问题。第四步:得到增量版本,交付。
敏捷方法用时间来管理,来驱动每一个冲刺,积少成多,最后形成不断迭代增量的版本。这种时间驱动彻底断除了我们延期完成工作任务的想法。
7.需求分析
我们开发软件是为了解决现实社会和生活中的各种问题。人们的需求各种各样,我们该如何找到需求呢?
1.获取和引导需求。需求是需要挖掘的,我们既可以引导客户,结合自身行业经验,得到需求,也可以分析技术的发展趋势和全球产业变化社会发展的大趋势分析需求,如大数据云计算移动互联网。
2.分析和定义需求。规整需求,定义需求的内涵,从各个角度量化需求。
3.验证需求。如果需求分析没有做好直接开工的话,容易做无用功,造成返工。软件团队要跟利益相关者沟通,通过分析报告,用户调查或演示等形式向他们验证软件团队对于这些需求的认知。
4.需求管理。如上所说,需求会不断变化,或者说解决需求有了新的捷径和方式,这些都要求我们因地制宜,跟着变化而变化。
5.需求的分类:功能性需求要求产品必须实现某些功能,开发过程需求要求开发流程必须产生哪些文档在什么时间交付,非功能性需求要求服务质量例如12306网站要做到实时响应。
那么,作为一个开发者,需不需要到需求中来呢,非常需要,因为软件的各种约束各种技术实现会影响到他们的工作过效率。我们一定要让相关角色在需求分析阶段有机会提出他们的需求和一件。
8.创新分析
创新可以使改良型的,在现有的软件中增加几个新的功能,把某个程序变得更快一点,把程序移植到新的平台。颠覆性的创新,一个新的产品导致就得产品或产业发生巨大的变化或消失。但是如何按部就班地分析需求,有条理地说服别人你的创新呢?有NABCD模型。
Need,你的创意解决了用户的什么需求。
Approach,找到了需求,就需要使用独特的作法来领先于其他软件了。独特的作法有技术上的,比如有人脸识别技术,有超大规模的数据处理能力。还有商业模式上的,第一个团购,地域上的,第一个苏州公交系统,行业上的,嘀嘀打车。
Benifit,这些实现可以给用户带来什么好处呢,为什么为了达到这个好处用户会花费时间金钱成本去迁移呢?
Competiors,看出处知己知彼的优势,博百家之长,扬长避短。
Dlivery,如何分发。
需求定义之后需要靠功能来实现。要把用户从竞争对手那里吸引过来,团队自己的产品要有一个差异化的焦点,在这个焦点上,我们的团队能做得比别人好10倍,高一个数量级,这样的功能叫做杀手级功能,其他功能则相对来叫做外围功能。
除此之外,我们的竞争对手和用户已经决定了一些此类产品必须要满足的需求,不能满足这些需求,产品就不会被用户青睐,所以把功能又划分为必需需求和辅助需求。
举例分析一个电子词典软件。杀手功能:屏幕取词技术。外围功能:良好的界面。必需需求:翻译的准确性。辅助需求:可以选择皮肤。
对于必须且杀手功能,应该全力以赴,以此为工作的重心。对于必需且外围功能,快速达到其他产品的水平就好了。对于辅助杀手功能,应该不做等待更好的时机或者空闲。对于辅助外围功能,建议采取维持的方法,以最低代价维持此功能。
9.典型用户
在软件设计的过程中,我们往往会以自己使用产品的习惯和对软件行业的熟悉程度出发设计,忘记了我们的软件是给千千万万个不那么会用电脑的人使用的,在这种情况下,就需要搞一个典型用户。
不要指望把产品的拓展性做得很好,从一般用户到超级用户都能搞定,且不论这样是否会覆盖所有的用户,这种方法肯定有其副作用。我们要从小部分人出发,明确定义谁是我们的用户。典型用户描述了谁(名字,年龄,收入,教育水平,代表比例)在什么地方(使用场景,使用环境)用了什么功能(动机,目的)。当创建完了一些典型用户之后,我们就要模拟典型用户的使用场景了,把自己(开发者)代入其中,在模拟的生活中一步一步走,就能深入理解用户的需求,及时地发现问题。
10.软件测试
测试设计有两种分类方法:黑箱和白箱。这是软件测试设计的方法,不是软件测试的方法。
黑箱:在设计测试的过程中,把软件系统当作一个无法了解或使用其内部结构,从软件的行为,而不是软件的内部结构出发。例如,程序行为的易用性测试。
白箱:在软件测试设计的过程中,设计者可以看到软件系统的内部结构,并使用软件系统的内部结构来选择测试数据和方法例如软件内部结构的流程模块化单元测试。
测试方法有很多,例如单元测试,代码覆盖率测试,构建验证测试,验收测试,探索式测试,回归测试,系统测试,伙伴测试,效能测试。
伙伴测试:在一个复杂系统的开发过程中,当一个新的模块加入系统中,往往会导致整个系统稳定性下降,影响了其他的模块,产生很多BUG。伙伴测试是指开发人员可以找一个测试人员作为或伙伴,在新代码签入之前,开发人员做一个私人构建,其中包括了新的模块,测试人员在本地做必要的回归测试,发现问题直接和开发人员沟通。也就是一个开发配一个测试,协调工作,避免BUG。
中国科学技术大学软件 + 刘艺凌 + 原创作品转载请注明出处