软件设计文档 (SD)
注:Mission Craft 任务工厂系统同时也是该小组成员在 2019 年春季学期中山大学系统分析与设计课程的大作业。按照本课程作业要求在 SD 文档开头点明。
文档变更记录
版本 | 日期 | 描述 | 作者 |
---|---|---|---|
V1.0 | 2019.4.20 | 初步制定开发计划 | 潘鉴 |
V1.1 | 2019.5.1 | 初步确定前后端框架 | 潘鉴 |
一、开发计划
开发人员
学号 | 姓名 | 身份 | 邮箱 | 专业方向 |
---|---|---|---|---|
16340173 | 欧穗新 | 后端开发工程师 | 1473595322@qq.com | 计应 |
16340176 | 潘鉴 | 后端开发工程师 | 903794757@qq.com | 计应 |
16340178 | 彭靖寒 | 后端开发工程师 | pengjh9@mail2.sysu.edu.cn | 计应 |
16340174 | 欧阳梓轩 | 前端开发工程师 | ouyzx5@mail2.sysu.edu.cn | 计应 |
163401 | 彭伟林 | 前端开发工程师 | 1622070923@qq.com | 计应 |
163401 | 彭流生 | 前端开发工程师 | 1728343423@qq.com | 计应 |
开发计划
需求调研阶段,我们将首先根据初期的会议内容考虑市场需求以及基本的市场现状,并根据以上的内容设计问卷来寻找痛点。我们准备使用第三方问卷工具,以电子问卷的方式来进行调查。初步预计会收到200份问卷。
在需求调查阶段,同时开展对同类型的网站的评估工作。进入初步的需求分析阶段。目标是取得现有任务挣钱网站或手应用的基本购票流程,并对其交互等方面作出评估。找出冗余的功能以及不必要的跳转等。
在需求调查阶段结束后,正式进入需求分析阶段。首先分析调查问卷的结果,并得出所需的结论。进一步确定用户的用例等等。结合前期进行的现有购票网站分析,确定最终的用例以及需求。
在需求分析结束之后,技术小组根据需求小组的分析结果(UML图,用例图等等)进行系统设计,包括架构设计、数据结构选择、确定数据库、确定代码风格、建立GitHub仓库等等。
完成设计工作之后,即开始初步的原型程序制作。按照初步的设计方案,进行原型程序的编码。在原型程序编码结束之后,立刻对此程序进行评估。主要的目标是确定需求设计是否有较大偏差,以及软件架构设计是否有不恰当的地方。
评审结束后需要对需求文档以及设计文档作出修订,形成最终版的需求文档以及设计文档。
确定了最终的需求以及软件设计架构之后,就进入了正式的编码阶段暨系统开发阶段。在编码的同时要求完成单元测试的内容。目标是,提交的每个子模块代码都在工程师的手中保证完成了单元测试。
在系统开发完成之后,由测试工程师以及质量保证工程师牵头进行集成测试。目标是核对系统是否有影响使用的bug。
在完成集成测试后,进入系统试运行阶段,此阶段的负责人是项目经理、客户经理、质量保证经理。在此阶段需要完成的目标是核对整个项目是否符合预期,在功能上是否能满足要求。
以上完成后即进入发布阶段,之后将进行运维工作。
开发环境和工具
- 终端支持:PC浏览器
- 开发语言框架:Vue,CSS,JavaScript
- 服务器端支持
- 语言:Python
- Web框架:Flask
- 关系数据库:SQLite3
- 负载均衡机制:Nginx
- 开发平台与工具
- IDE:VSCode
- 集成与测试:pytest
- 源代码管理:Github
- 项目管理与自动构建:maven
开发规范
- WEB前端
- 语言:JS
- 代码风格:
- 自动化检测工具
- WEB后端
- 语言:Python3
- 代码网络:
- 自动化检测工具
二、软件总体设计
1. Client
1.1 软件设计技术
1.1.1 MVC框架
MVC框架整个前端页面分成View,Controller,Modal,视图上发生变化,通过Controller(控件)将响应传入到Model(数据源),由数据源改变View上面的数据。
整个过程看起来是行云流水,业务逻辑放在Model当中,页面渲染逻辑放在View当中,但在实际运用上却存在一个问题:那就是MVC框架允许View和Model直接进行通信。当View和Model之间随着业务量的不断庞大,会出现蜘蛛网一样难以处理的依赖关系,完全背离了开发所应该遵循的“开放封闭原则”。面对此问题,MVVM框架出现。
1.1.2 MVVM框架
MVVM分别指Model,View,View-Model。与MVC框架主要有两点不同。
- 实现数据与视图的分离
- 通过数据来驱动视图,开发者只需要关心数据变化
View通过View-Model的DOM Listeners将事件绑定到Model上,而Model则通过Data Bindings来管理View中的数据,View-Model从中起到一个连接桥的作用。
我们使用的Vue.js就是基于MVVM的框架。
1.1.3 Object Oriented Programming
面向对象的基本思想是使用类, 对象, 继承, 封装, 消息等基本概念进行程序设计。 面向对象方法的三个基本特征:
- 封装性:将对象的实现细节隐藏起来, 通过一些公共的接口方法来供外部调用对象的功能
- 继承性:是面向对象实现的的重要手段,子类继承父类, 子类直接获得父类的非private属性和方法
- 多态性:子类对象可以赋值给父类对象引用, 但运行的时候仍然表现出子类的行为特征,同一个类型的对象在执行同一个方法时, 可能表现出不同的特征。
在项目中,对各对象、组件进行了封装,只留给外部接口,调用它的其他组件不用知道其内部的具体实现方式,每个组件拥有自己的方法与行为,在解决整个事务的某问题中行使具体职责。
1.2 技术选型及理由
- vue:一个类MVVM的渐进式JavaScript框架
- vue-router:单页应用前端路由
- vue-material:UI框架
- axios:ajax异步请求工具库
Vue.js框架
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架,是一个轻巧、高性能、可组件化的MVVM库。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。
- 当下前端开发中的前沿技术框架,Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合;
- 另一方面,当与单文件组件和 Vue 生态系统支持的库结合使用时,Vue 也完全能够为复杂的单页应用程序提供驱动;
- Vue 支持组件化开发,其独特的 .vue 文件可以将组件的HTML/CSS/JS代码整合在一个文件中,有利于进行代码管理;
- Vue 也支持响应式、双向数据绑定等 MVVM 特性,能够很好地支持丰富的用户交互体验。
基于以上理由,选择Vue.js作为前端框架对用户和开发者都十分友好。
vue-router
- vue-router 和 vuex 是官方提供的前端路由和数据状态管理的库,能够完美地结合 Vue 框架,实现前端路由和应用数据状态管理,代码结构清晰,程序复杂度降低。
vue-material
- Google material design 风格组件在 vue 框架下的实现,是一套优雅的 UI 框架;
- 该框架封装了多种 UI 组件,使用方便,支持按需加载,编程时可以只引用需要的组件,无需引入整个库,减少了前端代码体积。
webpack
- 当下前端最流行的构建打包工具,利用 webpack 搭配相应的 loader,可以在前端项目中使用 es6 进行开发,效率更高,开发完成后,webpack 还可以将代码编译到 es5 以兼容大部分浏览器;
- webpack 2优化了构建打包的算法,优化前端的模块加载,整合各个文件的代码、图片、字体、样式表等等,使得构建打包后的产品代码体积更小,也减少了这些资源在传输给用户时的时间损耗。
axios
- 基于 promise 的工具库,使用这个库可以给服务端发送 ajax 请求;
- 由于这个库基于 promise,使得在处理异步请求的时候不需要嵌套回调函数,代码架构上有了极大优化,可维护性更高;
- 简单、轻量,不会影响前端的加载速度。 总结起来,Vue.js有以下特性
1.3 模块划分
根据业务逻辑和UI设计图,将挣闲钱系统前端分为11个页面,按照vue开发要求的文件结构,每个vue页面包含html,js和css,分别处理布局、逻辑、样式;根据页面的划分,得到页面模块的细分:
十一个页面模块包括:
- 登录,获取用户的信息
- 注册,注册新用户
- 回答问卷,领取问卷任务后填写问卷
- 任务详情页,查看该任务详情
- 我的发布,查看我已经发布的任务
- 发布一般任务,发布除问卷以外的任务,包括取快递,借东西等等
- 发布问卷,发布问卷,提供文件编辑界面
- 我的领取,查看我领取的任务
- 任务广场,展示可领取的任务
- 数据统计,用于问卷的信息统计
- 用户信息,展示,修改用户信息
最后前端挣闲钱系统的结构如下:
2. Server
2.1 软件架构设计
2.1.1 Client Server Model
客户端-服务器模式(Client–server model)简称C/S结构,是一种网络架构,它把客户端 (Client) 与服务器 (Server) 区分开来。每一个客户端软件的实例都可以向一个服务器或应用程序服务器发出请求。服务器等待来自客户端的请求,处理请求并传回结果。
2.1.2 Browser Server Model
浏览器-服务器(Browser/Server)结构,简称B/S结构,它是随着Internet技术的兴起,对C/S结构的一种变化或者改进的结构。与C/S结构不同,其客户端不需要安装专门的软件,只需要浏览器即可,浏览器通过Web服务器与数据库进行交互,可以方便的在不同平台下工作;服务器端可采用高性能计算机,并安装Oracle、Sybase、Informix等大型数据库。B/S结构简化了客户端的工作,它是随着Internet技术兴起而产生的,对C/S技术的改进,但该结构下服务器端的工作较重,对服务器的性能要求更高。
B/S的优势:
- 极少部分事务逻辑在前端(Browser)实现,但是主要事务逻辑在服务器端(Server)实现。大大简化了客户端电脑载荷,减轻了系统维护与升级的成本和工作量,降低了用户的总体成本
- 局域网建立B/S结构的网络应用,并通过Internet/Intranet模式下数据库应用,相对易于把握、成本也是较低的。它是一次性到位的开发,能实现不同的人员,从不同的地点,以不同的接入方式(比如LAN, WAN, Internet/Intranet等)访问和操作共同的数据库。
- 它能有效地保护数据平台和管理访问权限,服务器数据库也很安全。
- 维护和升级方式简单。B/S架构的软件只需要管理服务器就行了,所有的客户端只是浏览器,根本不需要做任何的维护。无论用户的规模有多大,有多少分支机构都不会增加任何维护升级的工作量,所有的操作只需要针对服务器进行。
- 前后端人员能同时开发,更好地划分任务,节省时间。
Resful Web Services
REST 定义了一组体系架构原则,您可以根据这些原则设计以系统资源为中心的 Web 服务,包括使用不同语言编写的客户端如何通过 HTTP 处理和传输资源状态。REST 近年来已经成为最主要的 Web 服务设计模型。
其具体实现应该遵循四个基本设计原则:
- 显式地使用 HTTP 方法。
- 无状态。
- 公开目录结构式的 URI。
- 传输 XML、JavaScript Object Notation (JSON),或同时传输这两者。
显式地使用 HTTP 方法
这个基本 REST 设计原则建立了创建、读取、更新和删除(create, read, update, and delete,CRUD)操作与 HTTP 方法之间的一对一映射。 根据此映射:
- 若要在服务器上创建资源,应该使用 POST 方法。
- 若要检索某个资源,应该使用 GET 方法。
- 若要更改资源状态或对其进行更新,应该使用 PUT 方法。
- 若要删除某个资源,应该使用 DELETE 方法。
无状态
完整、独立的请求不要求服务器在处理请求时检索任何类型的应用程序上下文或状态。 REST Web 服务应用程序(或客户端)在 HTTP Header 和请求正文中包括服务器端组件生成响应所需要的所有参数、上下文和数据。 这种意义上的无状态可以改进 Web 服务性能,并简化服务器端组件的设计和实现,因为服务器上没有状态,从而消除了与外部应用程序同步会话数据的需要。
公开目录结构式的URI
从对资源寻址的客户端应用程序的角度看,URI 决定了 REST Web 服务将具有的直观程度,以及服务是否将以设计人员能够预测的方式被使用。
传输XML或者JSON
资源表示形式通常反映了在客户端应用程序请求资源时的资源当前状态及其属性。使用具有结构性的标记语言来传输数据,可以使得服务可由运行在不同平台和设备上并采用不同语言编写的各种各样的客户端所使用。
在本项目中,使用JSON进行客户端和服务端的数据通信。
- 与XML相比,JSON更加的简洁,我们可以一眼就看出其中的内容,方便检查排错
- SON更加轻量级,不管是编写,传输,还是解析都更加高效
- JSON在传输过程中采用了压缩技术,更加的节省宽带
- 众多的语言支持,如javascript,python,C,C++等主流语言都支持
2.2 技术选型及理由
后台主要技术栈是: Nginx + Python Flask + SQLite 完全 Docker 化。
2.2.1 Nginx
Nginx 是一个高性能的 Web 和反向代理服务器, 是如今业界较为受欢迎的服务器程序之一。它具有有很多非常优越的特性:
- 作为 Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应
- Nginx 安装非常的简单,配置文件 非常简洁(还能够支持perl语法),Bugs非常少的服务器: Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在 不间断服务的情况下进行软件版本的升级。
- 当网页应用部署到服务器上时,前后端使用不同的端口,会产生跨域问题。用nginx反向代理实现跨域,是最简单的跨域方式。只需要修改nginx的配置即可解决跨域问题,支持所有浏览器,支持session,不需要修改任何代码,并且不会影响服务器性能。
2.2.2 Python Flask
flask是一个使用 Python 编写的轻量级 Web 应用框架。Flask也被称为 “microframework” ,因为它使用简单的核心,用 extension 增加其他功能。利用扩展,Flask可以变成你任何想要的东西,一切恰到好处,便于我们实现。
- 和 Python 内部的服务器框架对比:相对比于 Django, Flask 框架更加轻量;相比于 tornado,Flask 处理异步消息更加友好;相比于 webpy, Flask 的社区维护更加持续。
- 有很多扩展的包来支持我们的功能,简单易用。
- 和 Java, C++ 语言相比较,动态编程语言对于开发这种小型的服务器的迭代速度更快。
- 和 nodejs 相比较,队伍中负责后台的同学接触python更多,学习成本更低。
2.2.3 SQLite
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它占用资源非常的低。Python就内置了SQLite3,所以,在Python中使用SQLite,不需要安装任何东西,直接使用。SQLite和C/S模式的数据库软件不同,它是进程内的数据库引擎,因此不存在数据库的客户端和服务器。使用SQLite一般只需要带上它的一个动态库,就可以享受它的全部功能。
考虑到SQLite在并发(包括多进程和多线程)读写方面的性能一直不太理想,当用户规模增大到一定规模时,数据库可能会被写操作独占,从而导致其它读写操作阻塞或出错。因此,在开发的后期,我们会改为使用MySQL或者PostgreSQL等更大型的数据库。
2.2.4 Redis
Redis是一个高性能的key-value数据库。出于安全考虑,我们把一些重要的信息保存在磁盘中,Redis是个不错的选择。
Redis 与其他 key - value 缓存产品有以下三个特点:
- Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
-
Redis支持数据的备份,即master-slave模式的数据备份。
- 作为缓冲 Cache, 因为点餐菜单信息需要频繁修改,同时为了实现多人点餐,数据交换速率需要有保证。所以引入一个 Cache 来进行临时数据交互。
- 为了增加后台的服务性能,需要扩充 python flask 容器的个数,此时每个容器都对一个 Redis 中的数据进行操作,可以保证数据的一致性。
2.2.5 pytest
应用写单元测试可以检查代码是否按预期执行。 Flask 提供了测试客户端, 可以模拟向应用发送请求并返回响应数据。应当尽可能多地进行测试。函数中的代码只有在函数被调用的情况下才会运行。 分支中的代码,如 if 块中的代码,只有在符合条件的情况下才会运行。测试 应当覆盖每个函数和每个分支。越接近 100% 的测试覆盖,越能够保证修改代码后不会出现意外。但是 100% 测试 覆盖不能保证应用没有错误。通常,测试不会覆盖用户如何在浏览器中与应用进行 交互。尽管如此,在开发过程中,测试覆盖仍然是非常重要的。
pytest是一个非常成熟的全功能的Python测试框架,主要特点有以下几点:
- 简单灵活,容易上手,文档丰富;
- 支持参数化,可以细粒度地控制要测试的测试用例;
- 能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests);
- pytest具有很多第三方插件,并且可以自定义扩展,比较好用的如pytest-selenium(集成selenium)、pytest-html(完美html测试报告生成)、pytest-rerunfailures(失败case重复执行)、pytest-xdist(多CPU分发)等;
2.3 模块划分
容器化各容器的文件组织结构
.
├── app
│ ├── app.py
│ ├── data
│ │ ├── menu_database.json
│ │ ├── recommendation.json
│ │ └── restaurant_database.json
│ ├── dbTools
│ │ ├── dbConfig.py
│ │ ├── dbInit.py
│ │ ├── dbOperators.py
│ │ ├── dbPool.py
│ │ ├── __init__.py
│ │ └── tools.py
│ ├── docker-entrypoint.sh
│ ├── Dockerfile
│ └── requirements.txt
├── client
│ └── dist
│ ├── index.html
│ └── static
├── db
│ ├── 01-my-script.sh
│ ├── Dockerfile
│ ├── TinyHippo.sql
│ └── TinyHippoTest.sql
├── docker-compose.yml
├── Makefile
├── nginx
│ ├── conf.d
│ │ └── web.conf
│ └── Dockerfile
├── README.md
|—— tests/
app.py
层级划分:
app.py
├─ Restaurant
├─/restaurant/recommendation
├─/restaurant/session
├─/restaurant/category
├─/restaurant/category/
├─/restaurant/category/<int:categoryId>
├─/restaurant/dish/<int:dishId>
├─/restaurant/getdish/<int:dish_id>
├─/restaurant/order
├─ Customer
├─/restaurant/customer/record
├─/restaurant/customer/edit
├─/restaurant/customer/read
├─/restaurant/table/read
├─/restaurant/table/payment
├─/restaurant/customer/history