这是我的第一篇博客,记录的是我在完成《软件工程(3)》中第一个四周单人 project 的感想。

先谈谈自己在这次的 project 里的收获吧。

  • 掌握了 django+uwsgi+nginx 的部署技术
  • 对使用第三方接口开发有了新的体会
  • 学习测试的使用方法,并在 pycharm 里进行单元测试

产品概述

这是一个依托微信公众号平台的活动抢票应用。活动管理员可以上传活动的相关信息,包括活动时间、订票时间、票量等。而普通用户可以在公众号里查询到活动的信息,已绑定的用户则可以在抢票时间内进行抢票等操作。

部署

环境

Ubuntu 16.04.1 LTS + python 3.5.2 + django 1.11.5 + uwsgi 2.0.15 + nginx 1.10.3-0

部署流程

首先我们需要对 django+uwsgi+nginx 有个大致的理解。外部的请求发来后首先被 nginx 处理,如果是静态资源则直接返回(当然其也负责负载均衡等功能),动态网页则通过端口或 socket 进一步转发给 uwsgi 进行处理,uwsgi 再调用 django 的服务。

因此成功部署主要需要下列操作

  • 编写 nginx 用到的 app.conf ,记录监听的端口,转发的 socket 以及静态文件的信息等
  • 编写 uwsgi 用到的 ini 文件,记录 nginx 发送的 socket ,项目路径,python 路径等信息,以便接受 nginx 传递的信息后启动 django 服务处理
  • 通过uwsgi --ini uwsgi.ini 拉起服务,同时(sudo) service nginx restart启动nginx

不出意外的话,经过上述过程已经可以正常运行django程序。

如果遇到问题

  • 可以在/var/log/nginx下查看日志。若 nginx 这一块没有 bug,再去项目目录的 log 里(写在 uwsgi.ini 里的daemonize)
  • 如果是服务启动失败,按照提示去systemctl service XXX查看失败的原因
  • 常见的坑: nginx 静态路径配置错误,uwsgi 的 python 路径配置错误,django 项目 settings 里没有注释掉 APP_DIR (Debug=false下)等
  • 善用 google,stackoverflow 以及相关软件的 documentaion

测试

单元测试用的 django testcase,功能测试采用 selenium + phantomJs 模拟浏览器。

这其实也是我第一次编写自动化测试单元,如果不算之前写 C/C++ 中写的一些很简单的 assert 的话。

由于时间的关系,测试的样例主要是覆盖在用户端,因为相对而言用户端的行为更加不可控。管理员的操作相对来说还是比较安全的。

同时,对于抢退票的相关操作,自然是需要更多更精细的单元测试,毕竟这是这一块的核心而且极其容易出错。

由于没有想到比较好的 mock 出微信端操作的方法,因此在抢退票方面主要是做了单元测试,保证抢退票操作的合理应对以及对数据库的正确更新。而对其他的像用户查看活动详情与票据详情,则在单元测试的基础上也进行了功能测试,保证相关页面不会出错。

项目缺点

  • 没有进行性能测试
  • 对抢退票可能存在的竞争关系没有特殊处理,高并发下可能出现问题
  • 微信的 reply_text 接口在 xml 化的过程中对一些特殊符号如 '<', '&' 等进行了转义,导致没有办法给出比较优雅的返回多个链接的形式,且对于有多个input的get操作,可能需要跳转两次才能访问到(因为 '&' 转义为 '&amp'),好像需要浏览器再进行处理才能正确访问到,导致用户体验不太好(需要再次点击)
  • 活动的key应当作为unique,并且保证不含空格,这样可以减少很多不必要的麻烦。但作为缩写的key成为unique又确实强人所难。目前想到的一个比较好的实现就是将过期活动的key修改为其他难以碰撞的词(比如加入当前时间信息然后哈希)

槽点

  • 接口文档有许多东西交代的不是特别清楚。比如在调整微信菜单的接口中

    我就对这个请求参数的正确打开方式思考了很久。当然我也知道编写文档中难免会出现交代不清楚的地方,但经过这次开发让我对文档的重要性有了进一步认识,也提醒自己以后编写文档要更加小心谨慎,避免跳过一些因为自己是开发者所以觉得很trivial的细节。

  • 我始终觉得这种项目形式,应该先介绍测试相关然后才编写代码。在这次project里等到课上介绍TDD的时候,基本上业务代码都已经完成了。在已经编写完业务代码,再让同一个人编写测试用例时其实效果是鞑靼折扣的。虽然也还是确实能发现一些之前没有注意到的逻辑漏洞,但更多的样例还是会有“为了踩坑而踩坑”之嫌。

感想

匆匆忙忙赶在 ddl 前将作业交上了,许多之前想做的优化也最后没有实现,测试单元也并不完全。作为一次作业的话,感觉还是挺失败的...但抛开作业,这次 project 也确实全方位锻炼了我,在开发、测试、部署的那段时间里也确实学习到了很多,包括部署的过程中遇到各种各样奇奇怪怪的坑然后一个一个填,这样的经历还是涨很多码力的。而测试单元的编写则是用更高的抽象去俯视去审视代码,在编写的过程中也会去不断反思自己当初写业务逻辑犯下的错误。总之,在这次的project里切身体会学习了许多新东西,也就对得起我在这上面花费的时间了。