在入职的前6个月里,我有幸参与到室内3个任务的开发中。在完成任务时,我发现不同任务有着相似的开发流程,总结归纳这些相似点可以为以后的开发任务打基础。本文就系统设计思路与技术框架选型进行总结。
设计思路
需求内容抽象
虽然需求千变万化,但都是围绕数据的。例如,输入原始数据、进行某些操作、保存结果数据;只是录入数据;只是保存算法执行结果。抽象来看,对数据的操作只有4种:增加(Create)、查看(Retrieval)、更新(Update)、删除(Delete),简称CRUD。其实CRUD可以延伸为对很多事物的操作,例如,java的集合框架、页面表格、页面表单、资源(RESTful)、缓存(Redis)、数据库(SQL)。CRUD在不同事物中指代的内容如表 1所示。
表 1 CRUD在不同事物中的含义
操作含义 事物 | C | R | U | D |
Java中List | add | get | set | remove |
页面表格 | 新增一行数据 | 查看数据 | 更新选中数据 | 删除选中数据 |
页面表单 | 打开表单新增页面,让用户填写表单。 | 查看某条数据的表单详情 | 更新表单列表中某条数据 | 从表单列表中删除某行记录 |
RESTful | POST | GET | PUT | DELETE |
Redis中String | set | get | set | del |
SQL | INSERT | SELECT | UPDATE | DELETE |
CRUD不仅提供了分析需求内容的视角,而且连接了需求落地过程中的各个环节。以我参与的评估预测任务为例。该任务的在评估模块主要是计算并可视化一些指标的值,在分析需求时,我发现某些指标很容易获取,直接一条SELECT语句就搞定,就不需要考虑这些指标的新增、更新、删除等问题,就比较简单。而有些指标比较复杂与耗时,就需要将结果保存到数据库中,这时便要考虑更新等问题了。为了实现新增、更新、删除,需求文档中有哪些内容(例如,何时更新、何时创建、是否允许删除)还需明确?后端大概需要定义哪些数据结构?提供哪些接口?需要编写哪些SQL语句?前端还需要考虑新增、更新、删除吗(评估模块不需要)?
需求实现过程抽象
根据核心功能是否需要联网可以将软件划分为两大类:单机应用(stand-alone application,例如,office、记事本)和联网应用(web application),其中联网应用可进一步细分为C/S模型(客户端-服务器模型,Client/Server Model,例如,QQ、微信)和B/S模型(Browser/Server Model,例如,GitHub、所内日常使用的各种管理系统),从形式上可以将B/S模型理解为一种特殊的C/S模型,特殊之处在于其客户端为游览器。目前大部分应用或系统都属于联网应用,联网应用的总体结构如图 1所示。
图 1 联网应用结构
在图 1中,用户直接与客户端交互,客户端会将系统功能以网页(B/S模型)或页面(C/S模型)的形式展示给用户,实现网页或页面所用的技术称为前端技术,例如,HTML、CSS、JavaScript。客户端页面所需数据主要来自服务器,常见过程为:客户端发送请求,服务器接受请求、处理请求以及将处理结果作为响应返回给客户端。服务器接受处理请求所用的技术称为后端技术,例如:Java。
图 1同时抽象出了软件实现过程中的两部分,即前端与后端。前后端同时生效,才算真正实现了用户的需求。前后端的分工比较明确,前端负责呈现页面,页面内容便是需求文档中要求的功能点;后端负责实现这些功能点、访问数据库、校验用户操作权限、返回数据等。
Java Web 开发经过几十年的发展,已从开始的JSP,后来的模板引擎,发展到现在的前后分离。经过调研与编程实践,我发现前后分离不仅便于调试,更能彻底解放前端,分离开发人员,达到术业有专攻。因此我比较偏向于使用前后端分离这种技术架构去实现需求。我对前后端分离的现有认识是:前端做前端的事,后端干后端的事,互相不影响,独立推进。前后端通过接口(名称、入参、返回值)进行配合。例如,前端可以使用表单(POST)或查询参数(GET)向后端传递参数,后端将前端所需的数据作为接口返回值回馈给前端。在形式上,接口通常为一个URL,接口返回值的格式通常为JSON,这样的接口被称为RESTful接口,在实际中有较为广泛的应用。一个RESTful接口实例如图 2所示。
图 2 RESTful接口实例
技术框架
后端框架
随着技术的不断迭代与演进,后端开发框架也在不断变化。目前人们在使用Java 开发后端时最常使用的框架组合为Spring、Spring MVC、Mybatis,简称SSM,介绍如下。
在开始之前,需要先说明一下Spring、Spring MVC以及SpringBoot的关系。Spring是一个模块化的轻量级开源框架,由两个核心模块,即控制反转(Inversion of Control ,IoC)和面向切面编程(Aspect-Oriented Programming ,AOP)和一些企业开发常用的模块构成。这些企业开发常用模块就包括Web MVC,由于Web MVC包含在Spring中,故被称为Spring Web MVC,简称Spring MVC。而SpringBoot则是Spring的简化与拓展:摒弃了Spring中繁琐的XML配置,引入自动配置机制,全面采用注解编程模型。三者的关系可由图 3描述。
图 3 Spring家族中部分框架之间关系
鉴于图 3的关系,大家一般嘴上说的是Spring,但到了真正编程时,都使用的是SpringBoot。
好了,继续介绍SSM组合。在SSM中, Spring作为后端的基础,去实现具体的业务逻辑、集成其他框架(Redis、Kafka、Elasticsearch);Spring MVC的主要功能是实现URL到页面视图的映射;而Mybatis主要是便于访问数据库,Mybatis的帮助下,程序员只需专注于SQL语句,将SQL结果转换为java类(POJO类)的事情就交给Mybatis了。此外,Mybatis有完善的插件:使用PageHelper插件可以快速完成分页功能,Generator插件可以逆向生成常用代码,一个极简的SSM示例如图 4。
图 4 SSM示例
前端框架
Node.js(只用了解,不需要学)的出现极大地增强了JavaScript的能力,拓宽了前端的领域,使得前端不需要依赖后端便可运行。目前,只要涉及图形界面展示与交互,无论图形界面在哪种设备上,几乎都可以用前端去实现。网页展示就不用说了,前端的看家本领。借助Cordova框架,前端代码可以直接运行在移动端(IOS、Android)。借助Electron框架,前端可以编写桌面应用(Windows, Mac)。可见,前端已具有一次开发,多平台运行的特点,很有必要学习一门前端框架。
结合已有的开发经验,我偏向于选择Vue这个框架。Vue有着实用的双向绑定与组件化功能。同时Vue的组件化不仅在思想上和后端组件复用的思想一致,而且用法上同基本的HTML标签类似。Vue对于HTML标签中各部分的替代如图 5所示。
图 5 Vue的用法
Vue中组件的用法示例如图 6所示。
图 6 Vue组件用法示例
从图 6可以看到Vue组件的使用和基本组件用法很类似,同样有属性、事件以及内容,不同之处在于Vue组件的内容要放在<template>标签中。
Vue是一个JavaScript库,与其配合最好的UI库为element-ui。element-ui有很多封装库,比较常用的一个是Avue。使用Avue可以快速地完成表单的CRUD。同时GitHub上也有许多基于Vue的后台模板,比较受欢迎的一个是vue-element-admin。