首页 > 代码库 > 关于Django Web应用架构设计开发的几个问题
关于Django Web应用架构设计开发的几个问题
1、关于分层,做过传统JEE应用的同学肯定知道JEE应用会分很多个设计层。根据传统Web应用架构设计一般从上到下分这么几个层(太懒了,不画图了):Web前端层、Web后端交互层、业务层、基础数据设施层,Web前端层在浏览器里面由JavaScript来做,暂时不表,数据设施层,Django的数据操作接近Active Record模式,相当完善,基本不用再做封装加工,重点谈谈交互层和业务层,交互层主要接受请求数据,调用业务逻辑完成用户交互.
2、关于业务层的独立存在问题,Django中业务层独立有没有必要,说实话,我刚开始用它做互联网应用的时候,一是互联网场景都是弱业务弱事务环境:业务逻辑比较简单,二是Django的的数据设施层非常完善,用来直接做交互层,代码量也很小,但是在产品系统不断发胀的过程中,系统的规模和结构不断复杂化的过程中,对系统结构管理的要求就会逐渐浮现出来,这个时候对业务层独立实现的设计要求就会逐渐明显。产品是变化的,系统是变化的,业务层独立化重构的要求是在变化的场景下逐渐出现的,当然有的系统一步到位的要求比较高,也许从刚开始就得做独立的业务层。
3、业务层的设计实现问题,Django中的业务层以什么样的方式存在,首先企业应用架构模式中说Active Record模式下的业务层应该和Models放在一起.其次Django其实提供了一种标准的业务层实现方式,就是对models.Manager做扩展,然后把其实例传给Model类的objects对象.这种方式的好处是,直接从Model类的引用可以调用到业务逻辑方法,缺点是,它和具体Model类的连接有点过于紧密,对于涉及多Model类的业务逻辑,其实也可以在Models模块中直接以函数的方式来定义.
4、交互层做了什么,首先Django中的输入验证是在表单类定义代码中完成,简单的CreateUpdate操作也可以用表单的save直接完成,那么之前讲到交互层要调用业务层的问题,其实都是业务逻辑相对复杂情况下的行为,关于调用,方法调用自然要传参,在交互层实现Form表单对象的初始化和输入验证通过后,把表单对象传给业务层是比较适合的,1是表单的数据是经过清洗过滤处理的,2是传递一个表单对象,这样的效果类似的JEE中的DTO,传参处理比较干净。
5、事务层放在哪儿,在业务逻辑涉及到多次数据读写的时候,事务特性还是很重要的,首先Django提供的事务特性使用方式比较多样化,首先用事务装饰view函数是一个一劳永逸比较懒的做法,其次事务的本质其实是和业务有关系的,在业务层方法上添加事务装饰,是一种更严格的设计实现。这种嵌套的多级事务在Django事务特性中完美支持。
6、关于异常处理,首先Django本身提供500错误页面机制,也就是说异常出错以后的转向页面显示我们不用管,我们需要管的异常处理是什么?就是这些异常和正常的业务逻辑相关的那些异常:它们发生的时候,业务逻辑转向了另外的一个正常处理分支.
7、Django Signals的一个应用场景,Django的Signals机制并不是异步消息机制,他基本接近装饰器,是一种同步挂钩模式,同步就限制了它的业务设计场景,但是在实现设计角度还是有用的:Python的import会有死锁循环问题,Linux的执行环境比较严格,像字符串编码和import循环的问题会比windows更容易发生,import循环这个问题,从设计的角度讲就需要严格的架构分层设计,同层之间调用要尽量限制,跨层反向要绝对禁止,但是任何模块调用是复杂的,不可能绝对满足约束,singals的挂钩机制,隔离le 调用方,应该可以解决跨层反向调用的Import问题.(此方案未经实际应用测试)
8、再谈循环Import的架构层解决,在Django中跨App的Model依赖有可能比较平常,这种同层依赖甚至逆架构层方向的反向依赖都有可能导致import循环,对于逆架构层反向依赖这种现象应该是尽量避免,对于同层之间的数据依赖,应该尽量坚持view和所有的model属于同一个app之内,那么跨App依赖怎么解决?1、前端异步依赖,可以在前端再加载依赖的数据,异步数据提供接口当然放在Model所在App内,2、模板标签,正常的标签肯定不会在其它py文件里面被依赖,它正常情况下只被最顶端的模板代码所依赖,这种情况下肯定不可能循环。3、model类之间的外键依赖循环,这个比较致命,不过解决办法也很简单,用字符串形式引用model会直接避免import,就没有执行依赖了,不过这种方式要求必须把引用model所在的app加到settings的INSTALLED_APPS设置里。
9、Django Session里面如果放置列表此类的引用数据,在修改操作时,应该是赋值取出来,修改操作完,再赋值放回去,原处操作可能无效。后台技术原因可能是因为Session串行化的原因
10、前端表单里面没有的model字段一定要在Form定义里面Exclude掉,只在Model里面定义blank和null只能做到验证规则的定义,不能防止恶意用户构造假表单填充这些model字段。后补:用fields meta信息定义要比exclude要好一点。
11、Django 代码封装的一个特殊优势:当封装代码片段的操作对象是一个Model实例对象时,这个时候应该考虑借鉴Active Record的封装设计,把这个代码封装成Model类的实例方法,这种封装方式比Manager方法封装要更Nice,应该说这是大多数业务逻辑可以优先考虑的封装方式,起码调用方式更Nice。
关于Django Web应用架构设计开发的几个问题