目录
- 项目实现思路
- 项目路径展示
- 项目启动文件 bin/start.py
- 配置文件 conf/setting.py
- 展示层 core/src.py
- 逻辑层 interface/
- 数据层 db/db_handler.py
项目实现思路
ATM项目
ATM架构设计
三层架构
core目录下的src.py(浏览器) (展示层)
interface目录下的多个py文件(框架) (核心逻辑层)
db目录下db_handler.py(数据库服务) (数据处理层)
优先实现功能
在src.py的展示层写面条版的函数,先实现主题功能,暂时别想着优化
拆分函数
如下图是一个用户注册功能函数:
我们要做的是将其到interface、db构成三层架构
拆分到哪?
核心逻辑层 有user bank shop admin等文件,负责不同的功能, 将跟user相关的代码(登录、注册) 放入相应的user_innerface.py文件
然后如果在innerface层下需要进行数据操作,就调用db层的函数。
请注意:展示层只能访问逻辑层,不能访问数据层。
项目路径展示
项目启动文件 bin/start.py
项目启动文件start.py可以放在项目根路径,也可以放在bin文件夹下。
该文件首先要做的第一件事就是使用os.path.dirname获取将当前项目路径,并将其导入sys.path。
然后就是调用展示层文件src.py。
配置文件 conf/setting.py
配置文件应该存放的是一些不会变动的信息,如项目的根路径、数据库的路径、日志的存放位置。
配置文件也可以存放一个项目路径,这一点是跟start文件相同的。
日志模块
关于日志模块的配置信息,应该写在settings.py文件内,并且封装成函数方便调用:
在每个接口文件的开头都放一个logger,方便调用,下面拿bank接口文件举例:
所有这个文件内产生的日志,都是银行日志。
展示层 core/src.py
用户注册 register
1. 获取用户输入 展示层
获取用户输入包括 获取用户名和获取密码
可自行添加:退出、输入两次密码比对
这两个功能逻辑简单,可以放在展示层
2. md5加密 lib/common.py
使用hashlib对用户输入的密码进行md5加密,将密文保存到数据层,下次用户登录直接比对密文。
展示层只调用加密函数,加密函数应该存放于lib/common.py路径下:
3. 调user功能接口 interface/user_interface.py -->register_interface函数
将用户名、密文输入user接口函数:
接口函数在核心逻辑层,在user_interface.py文件内:
逻辑层调用数据层的select函数,检查用户是否注册。再建立用户信息字典,最后调用数据层的save函数,输入用户信息字典,保存数据
4. 调数据层的select函数
注意:当用户存在,返回用户信息的字典,当用户不存在,返回None。
5. 调数据层的save函数
ensure_ascii参数保证写入的时候不会把中文转成bytes类型,增强可读性。
用户登录 login
1.获取用户输入 展示层
2.md5加密 lib/common.py
1. 调user功能接口 interface/user_interface.py -->login_interface函数
调user功能接口:
这个接口返回两个值:登录状态,信息
将用户名和密文传入login_interface函数:
2. 登录成功修改全局字典
当登录成功后,会修改全局字典:
将全局字典'username'键的值从空改成当前用户。
这里需要注意的是,每次传入的参数,都需要进行校验,保证传入干净的数据。
登录校验装饰器 login_auth -->common.py
由于我们希望只有登录的用户,才能使用更多功能,所以要给其他函数添加装饰器。
只有当全局字典是有值的,才会执行被装饰函数。还记得吗,登录成功会将全局字典的值改为当前用户。
装饰器理论上应该放入common.py,因为登录检验的逻辑不是我们应该给用户展示的,但是放入common.py容易引起循环导入:
查看余额 check_account
1. 从全局字典获取当前用户名
2. 调bank功能接口 interface/bank_interface.py -->check_account_interface函数
这个功能比较简单,先调用bank接口(之前是user接口),再调用select函数得到用户信息字典,返回用户的余额数据即可。
余额提现 withdraw
1. 从全局字典获取当前用户名
2. 调bank功能接口 interface/bank_interface.py -->check_account_interface函数
传入用户名、提现金额两个参数。
接口函数在逻辑层:
参数进来了先校验数据是否正确,最后添加流水之后再保存到数据库。
账户充值 repay
与余额提现很相似,故省略。
repay:
repay_interface:
用户转账 transfer
转账相对来说,比前面复杂一点点,需要指名给谁转账:
需要注意的点
- 不能转账给自己
- 确认被转账的人存在
- 确认用户余额足够转账
- 确认转账之后当前用户金额减少
- 确认被转账用户金额增加
查看流水 check_flow
流水就是在充值、提现、转账,这种涉及到账户余额的变化时,将金额变动的信息加入用户信息字典:
所以应该在上述函数中,都添加一些代码,将流水信息添加到用户字典。
查看流水,就是将用户信息字典的流水信息拿出来展示,这个功能实现很简单,不再赘述。
日志也可以实现这个功能,下文再介绍日志的使用。
添加购物车 add_shopcar
展示商品
用户需要先查看商品,才能添加购物车。所以可以在逻辑层写一个展示商品的函数。商品数据也可以放在逻辑层。
使用临时字典(可选)
什么叫临时字典?在添加购物车时,我们运行用户循环添加,直到用户输入q则停止添加。如果不使用临时字典,则用户每次添加,都会进行一次数据层的文件写入。使用临时字典,则是将数据保存在字典中,等到用户输入q,再将字典中的数据一次性写入文件。总得来说就是减少了写入的次数。
展示临时字典
因为临时字典是在程序运行中临时存在的,所以无法通过查看文件中的用户信息,来看到临时字典里的东西。
只能及时展示,每次循环临时字典都会变动。
查看购物车 check_shopcar
清空购物车 clear_shopcar
管理员功能 admin_sys
逻辑层 interface/
对传入数据进行校验
逻辑层会接受到用户传入的数据,为了安全性,我们必须对传入数据进行校验。
数据层 db/db_handler.py
数据层的优化
数据层总是需要用到项目路径(base_path)、数据库路径(db_path),这两个路径都是不变的。
在每个函数内都写很麻烦,我们可以将其放入配置文件conf/setting.py
优化前:
放入配置文件:
在数据层(db_hander.py)导入即可form conf import setting
数据层只包含:
save方法:保存用户字典
select方法:判断用户是否存在,如果存在就返回用户字典,如果不存在返回None