目录:
- web应用结构
- 模型与数据库,Code First
- OOP: ViewModel的意义
- 代码解释权反转
- ORM和原生SQL语句
- 数据库事务和其他
- Flask框架知识
- Python的知识
- 总结
web应用结构
可以抽象成两个点:Request 和 Response,请求和响应。
- 从这请求和响应两点展开看:
客户端按照HTTP协议格式发送请求到服务端。经过tcp三次握手,IP解析,到达服务端。然后服务端做出响应,返回HTTP协议格式的数据,经过tcp四次挥手,客户端收到数据。
- 再展开到服务端:
一个请求到达了服务端 -> 硬件防火墙 -> 从nginx代理服务器 -> 遵循WSGI协议的socket服务器 -> 基于web框架的应用 -> web框架原路返回请求需要的数据
- 再展开到基于web框架的应用:
路由分发,定位到相应路由下的具体函数 -> 全局验证器 -> 连接模型 -> 连接数据库 -> 根据业务得到最终数据 -> 创建Response对象,把数据放入,最后返回。
- 再到全局验证器:
特别提一下基于AOP思想的全局验证器,通过它验证数据是否有效。这是保障应用健壮的关键一步。
模型,数据库和Code First
Code First是指直接在模型类里编写表字段,关心怎么创建数据。(ORM关心的范围更广)
Code First可以让我们专注业务模型的设计,而不是专注数据库的设计。
数据库只是用来存储数据的,它的表关系应该由我们的业务来决定。
所以,表设计直接在Model模型类里完成,业务逻辑也可以直接写在模型方法里,达到复用效果。
ViewModel的意义
ViewModel 顾名思义,指对应一个页面的Model,即这个ViewModel能提供这个页面需要的数据。
ViewModel对应的概念:原始Model,是一个和数据库表字段一一对应的模型类。如果直接用原始Model的数据填充页面的话,会有大量冗余的数据用不上。
这时就可以创建一个专门对应页面数据的Model,它的数据和页面需要的数据是一一对应的。
这样做的好处:
- ViewModel可以更好的复用,包括在多个相同性质的页面中。
- 业务逻辑可以定义在ViewModel的方法中,也实现了业务逻辑的复用。
可以说很好的利用了面向对象编程的特性。
一般的经验是创建单体和集合两个viewModel类。
代码解释权反转
一段编写好的代码里,预留一个位置给调用者,调用者可以使用也可以不使用这个位置。如果调用者使用了,那么就称为“代码解释权反转”。
为什么叫反转?是因为本来这段代码直接由编写者定好,解释权在编写者手里。但如果调用者使用了这个预留的“位置”,那么解释权就到了调用者手里,也就相当于反转了。
本质是定义者把逻辑控制交给了调用者。
具体实现:
使用函数式编程。调用者通过传递一个函数,以此实现使用这个“预留位置”,获取解释权。
原生SQL语句和ORM
从数据库读取数据时,有两种方法:
- 直接写原生SQL语句,这种性能最优
- 写ORM对象关系映射语句,这种性能较差
还有一种取平衡的中间方法,基于原生SQL语句封装成和ORM语句相同的API。当然也支持原生SQL语法的写法。
在Python里有peewee,Java里有jood。
数据库事务和其他
数据库事务是指,在某种错误发生后,重置刚才被打断的数据库写入,防止数据混乱。
事务有两个功能或者说好处:
- 保证数据的正确性。因为有commit提交和rollback回滚,确保数据不出错。
- 数据库链接之间是隔离的。比如多个删除的请求,一个请求删了一半,另外的请求还是可以看到完整的数据,不会就只看到一半的数据了。具体到flask中,请求被flask接收后,都会通过flask sqlalchemy的数据库链接池分配一个数据库链接,请求结束后,会把这个数据库链接返回给flask sqlalchemy的数据库链接池。flask通过这样的方式实现了数据库的隔离和链接的复用。
其他的:
一般查一张表和关联表的数据,就会遇到n+1问题,先有一条复杂度为O(1)的数据,然后循环遍历找其相关联的数据为O(n^2),数据大了后无疑是很慢的。
这里就会用join来解决。这样就使用了数据库本身的优化,在数据上做了计算,而不是单纯地移动数据,然后自己再计算,只是这样的话会被大量IO拖慢,没有一个上下文,数据库也不能统一优化查询。
Flask框架知识
Flask核心机制:
- 存储上下文的栈结构
- AppContext,应用上下文
- RequestContext,请求上下文
- Flask中的线程隔离对象Local和隔离栈Local Stack
Python的知识
- 可调用对象:call
- 上下文管理器:context manager
- 各种魔法方法和运算符重载
- 属性描述符@property和@属性名.setter实现get和set
还有很多,一时想不起了……
总结
列举了一些我掌握到的编码和Web知识点。这些知识点很杂乱,不是很好总结在一起。或许以一个应用项目为单位来总结,不失为一个方法,反正杂乱无法理顺,索性见招拆招。