2017年12月12日

Web应用系统开发简明流程和准则

作者 kevinwang

1         前言

1.1      目的

本文档为软件开发工程师(包括Web前端开发工程师、Web应用开发工程师)提供进行应用功能开发指导和准则。

1.2      内容和范围

本文档内定义了Web应用开发的简要过程,并定义页面代码、业务逻辑、异常处理、日志记录、参数定义等开发准则

本文档不能代替编码规范,不同语言(包括HTML、JavaScript、CSS、JSP、Java等)参考相关的编码规范文件。

1.3      依据

本文档依据大数据、物联网等项目的Web应用代码的评审建议,以及行业内国家级、省级平台性项目和软件产品对于开发规范的要求。

1.4      术语

生产环境:也称为生产系统,客户用于业务处理的IT系统,直接服务于客户日常管理、经营方面的业务。正式上线后,任何对于生产系统的修改和操作,均需要遵循严格的流程进行,切忌随意变动。生产系统的各个用户名和密码(特别是数据库)一般与测试环境区分开,以避免可能的误操作。

2         应用软件简明开发流程

应用软件一般是从项目开始,经过实践和提炼,形成可复制的产品。在开发过程中,一般分为需求、分析、设计、开发、测试发布、实施验收、运行维护,直到废弃(注意:本文未包括Bug处理流程)。

在需求之前,一般会与客户进行多次的沟通交流,形成会议纪要。建议在这个环节,同时开发着手编写需求说明书,再进一步形成原型界面(美工设计或通过Axure工具)。此时编写需求文档,是依据鲜活的信息(最新的交流内容),所增加的工作量在小时的量级,一般需要一名工程师负责编写即可(参与会议交流,熟悉客户行业业务的)。必要时,可设计主要功能的界面,以便于深入交流。通过这个过程,一方面能够深入了解客户需求,另一方面也有助于达成合同。

在需求调研阶段,依据前一阶段的需求文档,全面细致了解客户业务、流程单据、规章制度、岗位职责、业务活动、相关外部参与者(其他单位或系统)等信息,形成客户、用户和公司均能够理解的需求说明书。

在分析阶段,如果项目比较紧,须重点是做好需求分析,识别主要功能模块、参与者、业务逻辑、数据约束、数据模型。需求分析的重点是为公司内的开发设计工程师、软件测试工程师提供工作依据,并达成共识,开发设计工程师能够依据需求分析说明书进行软件功能的设计与开发,测试工程师能够依据需求分析说明书进行测试计划和用例编写,并完成测试工作。

在设计阶段,一般做好必要的概要设计内容即可,包括体系结构(物理结构和逻辑结构)、模块划分、接口设计、关键算法等内容,不再进行详细设计(不包括软件外包)。

在开发阶段,由软件工程师依据概要设计和需求分析(业务逻辑、业务约束、界面原型)进行开发,包括编码、单元测试、集成测试。

测试工作在需求分析之后即可开始,依据需求分析说明书编制测试计划和用例,在软件开发完成(标识是通过集成测试)后,进行系统测试,系统测试通过后,定义软件版本,进行软件发布,形成可安装部署的软件包或升级包。

在实施验收阶段,将发布的软件包在生产环境进行部署和配置,经过试运行后,和客户进行验收。

在运行维护阶段,定期或不定期的对系统进行维护,登记系统发现的Bug和客户提出的新功能,按照软件缺陷流程进行处理,并在生产系统进行升级。

3         Web应用简明体系结构

Web应用最简洁的体系结构是MVC架构,对于访问量高、并发高、数据量大的应用场景,需要进行适度的延伸和改造。从物理结构上,可采用Web集群、读写分离、缓冲集群、应用服务器集群等架构;从逻辑结构上,可进行VCSM的改造,表示从前往后分别经过视图(V)、控制器(C)、服务(S)、数据模型(M),在这种模式下,将应用通过服务的方式进行处理,能够实现应用与业务处理的解耦。

4         开发准则

4.1      总体原则

任何一个应用系统均能够通过多种不同的方式实现,而不影响客户的使用界面和操作习惯。在项目或产品开发过程中,须与选择适合项目和公司业务需求的模式,进行适度的分析和设计。一般来说,项目的合同额在项目验收交付后完成90%或以上,考虑到整个项目周期,仍然存在后续的投入。因此,在项目开始之初,就需要策划如何尽早把团队从项目中脱离出来,如何通过更少的成本去支撑验收后的运维工作(一般有1~3年的免费维护期)。

综上所述,无论项目周期如何紧张,从公司角度看,均需要做适度的开发原则要求,优先级从高到低分别是友好性、易维护、复用性、健壮性、可运维、扩展性和高可用性。

4.2      友好性

友好性是用户至上的表现之一,开发工程师一定明确,自己所开发的产品一方面是用户使用,而不是自己使用,另一方面是公司维护,而不是自己维护,因此,仅仅考虑自己开发方便是不够的。

友好性是指符合用户的使用习惯、审美、业务场景的需要,而不是工程师所认为的友好。友好性的本质是为用户提供好用、方便的软件,包括交互界面、使用习惯、图标大小、界面组件排列、系统维护、故障告警等内容。另外,友好性也需要考虑公司对于软件维护的工作(参见易维护部分)。

在项目开发过程中可考虑如下内容:

  1. 在需求调研中充分了解用户的特点、使用习惯、业务场景,以及用户最关注的内容,作为分析设计时优先考虑的内容;
  2. 在系统设计时,充分考虑在项目在行业中应用时可能发生变动的内容,并设计为配置项;
  3. 在系统发生错误或故障时,永远不要给应用软件用户提示一个一堆代码的界面,或者一个简单的404错误(404错误是Web上常见错误之一,表示找不到希望访问的页面)。

4.3      易维护

首先需要明确什么是易维护。一个项目的易维护性主要表现在如下方面:

  1. 发现问题后,能够迅速定位到发生问题的代码;
  2. 能够通过代码和日志,找到出现问题的原因;
  3. 解决问题后,能够方便部署到客户生产系统;
  4. 代码维护不依赖于某个人
  5. 代码易读性好
  6. 相同代码逻辑、数值在代码中只出现一次,其他需要的地方进行调用或应用;

 

针对上述表现,在开发过程中须遵循如下准则:

  1. 类和方法、关键算法、关键变量需要写注释;
  2. 有应用软件日志,且包括文件名和行号;
  3. 日志记录包括关键输入、输出、发送错误的场景信息;
  4. 代码所依据的文件鲜活、完整(一般是概要设计,以及需求分析);
  5. 同类产品一套代码,对于不同项目通过“变种”方式实现;

4.4      复用性

复用性是指类、方法、甚至页面等能够被重复使用。在项目开发过程中,对于项目范围内可复用的内容,封装为项目级的组件包,对于从项目中可提炼出来的公司其他项目通用的内容,封装为公司级别的组件包,并有专人负责维护。

4.5      健壮性

健壮性是指对于任何允许的输入,应用软件均能够进行处理,而不是被大量有意或恶意的访问造成服务器宕机。在系统处理达到峰值,不能处理新请求时,可考虑返回给用户“系统忙,请稍后”的信息。

  1. 在物理设计时,须估算系统容量,在必要的架构上使用集群或相关技术,以确保系统的健壮性;
  2. 在逻辑设计时,须考虑大量数据访问、异常数据请求的处理,至少确保记录日志(须设置级别,例如致命、告警、错误的日志类型);
  3. 在编码时,首先需要检查所有输入信息的合法性,特别对于Web应用,服务器不能依赖于在浏览器端进行数据合法性检查(仅仅适用于为用户提供友好性体验),必须对所有数据进行合法性校验;
  4. 在编码时,一般是以正确逻辑作为代码主线,对于所有错误、异常进行日志记录,并返回错误或者抛出异常;
  5. 在编码时,须处理所有分支(例如对于if、switch等分支);

4.6      可运维

应用软件的运维功能属于软件的非功能需求,是作为公司降低运维成本的一种方法,设计到软件功能中。最简单的可运维的表现就是开发一系列的运维工具脚本,包括软件安装脚本、升级脚本、自动定时监测系统健康状况的脚本,对于有特定服务的系统,一般通过watchdog或者系统脚本监测,当发现服务停止时,自动重启并记录告警。

在设计和编码时,需要考虑将应用软件自身的日志记录到独立的应用日志中,并设置合理的日志级别。对于日志文件的大小和个数进行限制,避免因为日志增加造成磁盘空间不足的系统宕机问题。

4.7      扩展性

扩展性是指在原软件基础之上,不修改或者扩展原有软件架构(而不是大量改变原软件架构),能够支撑更多的应用场景和业务功能。例如,对于VCSM架构下的系统,S层(服务层)是可扩展的一个体现,手机APP和Web应用均可通过同一个S实现同样的功能,在开发手机APP时,不再需要开发后台服务程序。

在设计时,遵循“高内聚、低耦合”原则进行设计。在行业项目的推进过程中,及时对项目架构、软件代码实现等进行调整,以适应市场需求。

4.8      高性能

高性能是指软件系统能够处理大批量、高并发的能力,例如支持并发在线用户10000万人,支持百亿级数据的智能搜索等。

对于大数据系统,可考虑增加查询响应时间作为性能的指标,例如十亿数量级的智能搜索时间<10秒,精确查询时间<5秒,等等。

高性能的实现包括需求、分析与设计、编码、测试工作。

4.9      高可用性

高可用性又称为HA(High Availability),是软件健壮性和高质量的重要指标,一般通过在线率指标识别,例如Web应用提供客户服务的时间,与总上线时间的比例,对于一个要求7×24小时在线的项目,上线1年(365天),由于软件升级或系统故障,累计停止服务10天,那么在线率=355/365≈97.26。

HA的实现涉及到小区、分析、设计和编码实现,难以通过测试进行验证,一般是通过采集在线生产系统的数据(自动采集)进行统计。公司可根据所处行业和应用特点设定高可用性的要求。

数据对比:电信级产品的HA表现是5个9甚至6个9(百万分之一,即100万天中由一天停止服务,或者11年半中有1秒停止服务)

4.10简明实践指导

4.10.1     视图(View)

视图端一般叫做Web前端,也就是通过浏览器展示的页面,包括页面代码(HTML或JSP,以HTML为主)、JavaScript代码、CSS代码。对于一个应用软件系统,一般还有总体页面布局定义,将通用的头部、尾部等公用页面使用独立的文件封装,从系统配置中读取用户名称、LOGO、底部信息等。

项目一般都是基于一套已有的框架进行开发,其中一般会包括页面布局、样式集(换肤)、Java Script脚本和函数、CSS样式代码和第三方引用的代码。但是在开发过程中,没有对工程师进行已有框架的培训和要求,会造成每个参与开发的工程师自己写一套代码(包括页面代码、CSS和Java Script)。

建议开发工程师遵循如下原则:

  1. 通用的头部、底部等页面,使用公共封装,当有特性化修改时(例如济宁项目放到德州),需要进行参数化改造,从配置中读取客户名称;
  2. Java Script脚本开发分为通用脚本和模块脚本,涉及到身份证格式检查、日期检查等通用功能,须统一放置到通用脚本中,特定业务模块自己所需要的脚本,放到业务模块的Java Script中;
  3. 整理现有项目的样式(字体、颜色、布局等),确定样式控制的技术风格(例如,全部使用class在CSS中进行定义),避免在后台代码、页面代码等再次编写个性化的显示样式;
  4. 对于使用的第三方脚本,例如jquery,须使用统一版本;(可在配置管理中管理)

4.10.2     控制器(Controller)

控制器是应用软件处理页面(或者其他通过HTTP协议的客户端)请求的第一个环节,是用户操作界面与应用软件之间的关键控制节点,是区分复杂业务处理与用户界面的控制点。由于应用软件一般基于已有框架进行开发(例如Struts、SpringMVC等),高级软件工程师需要深入理解该框架的机制,以确保在应用软件开发时能够进行正确的后续处理。

从本质上看,控制器的输入是http或者http是的协议,而不是用户操作的页面或者手机APP。因此,值得注意的是,开发工程师需要知道,控制器的请求来源不一定完全是用户通过浏览器的操作,也有可能是来自于工具软件模拟请求信息的自动发送的数据。

在编码时建议遵循如下原则:

  1. 记录应用软件独立的日志,并设置日志的级别、文件个数、文件大小等;
  2. 设计应用软件的基类控制器,并在此控制器中进行通用功能实现,例如,记录收到的请求原始信息等等;
  3. 检查所有输入信息的合法性;
  4. 检查访问权限的合法性;
  5. 在返回信息给前端前,通过日志记录处理结果;
  6. 检查所有调用的方法,捕捉返回结果或者异常,记录日志和上下文信息,包括输入参数、错误信息、关键变量等;
  7. 当发生错误时,返回给用户友好性信息,避免出现将工程师解决软件错误的代码、栈信息、打印信息返回给用户界面;
  8. 对于简单应用,一般将业务逻辑处理放到控制器中。在高并发情况下,需要考虑关键资源的使用。

 

4.10.3     模型(Model)

数据模型一般是对数据库的操作,根据请求对业务进行处理。对于目前大数据应用来说,更多的是使用数据,在数据模型方面很少涉及事务性处理。

控制器可以直接调用数据模型进行业务处理,也可以将业务处理请求发送给服务,由服务层调用业务模型进行处理。

4.10.4     异步通信

现代越来越多的Web应用使用异步通信技术(AJAX),在异步通信处理时,优秀的框架会对请求和应答的AJAX操作进行封装,主要步骤包括:

  1. 页面发出请求时,按照JSON格式发送请求数据;
  2. 服务器处理完毕返回应答时,返回信息包括操作状态、提示信息和结果集;
  3. 页面收到应答后,在页面上有固定的DIV展示返回信息,在业务功能模块中处理结果集;

在开发过程中,开发工程师须遵循AJAX异步通信的开发机制。

4.10.5     异常处理

异常处理是应用软件非常重要的部分,健壮系统中70~80%的代码用于处理异常请求。在实际开发中,服务器端代码须进行严格的异常处理,可参考如下处理原则:

  1. 在编码过程中,须有考虑错误输入的意识,考虑各种可能发生的错误情况,而不能假设所有输入信息都是正确的;
  2. 在开发一个方法或函数时,首先需要对输入产生进行合法性判断,对于非法情况记录日志,并返回错误或者抛出异常;
  3. 调用方法或函数时,根据返回值,判断执行结果是否正确,如果不正确,首先需要记录日志,并且返回给上一级调用者;
  4. 在需要返回给前端用户的模块时,捕捉到异常后,需要进行友好性的处理,返回给用户可读性好、体验好的界面和信息,尤其避免直接将开发者关注的代码信息返回给用户;
  5. 在调用方法或函数时,如果其抛出异常,需要捕捉异常;捕捉异常后,参考第3和4条原则进行处理;

4.10.6     日志记录

日志记录是帮助系统维护人员、开发工程师快速解决应用软件问题的重要 技术手段。由于日志记录需要写磁盘(涉及到磁盘的机械系统),占用存储资源,因此,在日志记录时须遵循如下原则:

  1. 日志文件大小可控:即无论写日志的级别是什么,系统运行多长时间,日志文件总计所占的磁盘是可控的,避免出现因为日志而占满磁盘的情况,更不能认为现在存储空间大,就可以不考虑日志占据磁盘的问题,很有可能1MB的日志成为压倒系统的最后一根稻草;
  2. 日志记录份级别:在代码中写日志时,区分调试日志和运行日志,其中运行日志由分为致命、严重、错误、警告、信息等级别,应根据开发需要和业务须与,编写合理的日志级别;
  3. 在系统运行初期,可以打开所有的日志级别,以便于跟踪和解决问题;
  4. 在系统稳定后,可关闭调试级别的日志,以降低些磁盘的频率,提高性能;

目前可采用的第三方日志记录组件均能够支持第1和2条。

5         附录

  • 《程序员修炼之道:从小工到专家》:作者:[美] 亨特(Andrew Hunt),[美] 托马斯(Daid Thomas)

文件下载:Web应用软件开发准则