Django Web开发中控制层复杂的重构

Django是一个Python界的Web开发框架,符合MVC模式,只不过对应到Django是MTV(T为Template,即视图层,V为View,即控制层)。当使用类似vue框架来实现前端开发后,其实Web框架的视图层已经用不到了,只需要处理数据层和控制层。但往往随着业务的不断变化,业务功能上线时间紧迫,控制层容易变的越来越乱。下面介绍一些改进和避免复杂性的方法。

乱是怎么产生的?

我总结3点常见的原因:

抽象度不够

抽象是复用的基础,复用越多,代码量越少,代码也就越清晰。如果代码里充斥着 copy-paste 方式的复用,情况会在需求改动时变得糟糕,因为要改好多个地方,累且容易出错,但这也是很明显的重构信号。如果这时候还没有抽象,那么累的工作下次还需要做一遍。

代码冗长

假设控制层是基于CBV(Class-Base-View)来实现的,即每个Class的get、post方法处理对应的路由请求,把所有逻辑都写在get或post方法里,行数过百,代码很长。

代码冗长首先带来可读性差的问题。例如下面变量的含义得往上翻才能看出来,所以一般一个方法的行数不超过一个屏幕。另外代码冗长不容易看出此方法的整体逻辑的结构,容易被细节所迷惑。

代码实现不够简洁

这里指可能只需要5行代码就可实现的逻辑,写了10多行,虽然运行结果一样,但实现不优雅,难维护。通常会出现在有很多条件判断+循环的代码中。所以觉得代码复杂了,不清晰了,需要自己停下来思考。

一些优化方法

分解抽象

还以 CBV 模式举例,大概的代码结构如下:

Class RequestCheck(object):
    "请求参数校验"
    def is_valid(self, *args, **kwargs):
        pass
    
Class ResponseFormat(object):
    "响应码+数据格式化"
    def response(self, code, data={}, message):
        pass
    
Class Service(RequestCheck, ResponseFormat):
    "处理路由请求"
        
    def post(self, request, *args, **kwargs):
        # 参数验证,若有需要可以重写父类的 is_valid
        valid, argname = self.is_valid(args, kwargs)
        if not valid:
            self.response(1, message=f"参数{argname}错误")
            
        # 步骤1
        self.__action1()
        
        # 步骤2
        self.__action2()
        
        # 步骤3
        self.__action3()
        
        # 等等
        
        # 返回结果
        self.response(0, "xxxx")
        
    def __action1():
        pass
        
    def __action2():
        pass
        
    def __action3():
        pass

上面Service就是一个典型的接口路由处理类,参数校验和结果格式化继承通用的功能,若不满足可以重写方法。__action1、__action2、__action3 都是具体的业务逻辑代码,需要提前将业务逻辑的实现分为几个步骤,优化可读性的同时也帮助代码抽象。

上面的例子类似 Template design patten,针对复杂逻辑先定义好步骤然后对应实现。如果只有一个action,并且逻辑也简单,也可以直接写在 post 。但当发现逻辑不再简单或者逻辑内部有可复用的地方,需要及时抽象出独立方法。

action方法不一定是 Service 类的方法,也可以是调用其他Class的方法。

分层抽象

上面分解抽象做好后,Service 类相对就比较清晰了,但可能存在另一个问题,就是Service1 和 Service2 里的action功能类似,但却分布在不同的Service里,这时候就需要分层抽象,考虑从Service里抽象出相对稳定的逻辑实现,作为Service的下层,提供独立的服务。这样 MVC 里的控制层变成了2层。

这种方法可以继续使用,抽象出更稳定的独立服务作为第3层,形成倒金字塔型的依赖关系。上层依赖下层,减少同层之间的依赖,同层之间依赖太多也是乱的原因之一。

什么时候用继承来实现代码复用

一般有如下几种情况使用继承,其他情况选择调用、组合的方式来复用。
1、子类与父类有“是”的关系,例如毛笔是笔,钢笔是笔。
2、需要父类的全部功能;
3、除了使用父类的某些功能外还可能重写父类的方法;
4、实现多态的特性,即调用者只拿父类调用,不关心他实际是不是某个子类。

要不要对 ORM 层封装

如果只是对一个Model进行读写,没有其他业务逻辑,我觉得没必要封装。因为对于调用者来说没有更优。只是把 ModelName.objects.filter 换成了 query_obj 的名字而已,调用者还是需要对结果判断是否为空来继续后续逻辑。

如果对Model的读写包含了业务逻辑,或者是同时对多个Model进行读写,这就构成了一个功能了,有复用可能,这时候才有封装的必要。

代码扩展性

代码扩展性指应对需求变化的能力,当有新的需求出现时,系统不需要或者仅需要少量修改就可以支持。

提升可扩展性的一般方法:分层 + 设计模式。

分层通常有两种:一种是将变化封装在一个"变化层",将不变的部分封装在一个独立的"稳定层"。另一种是提炼一个"抽象层"和一个"实现层"。后一种在设计模式中经常见到。

Python中设计模式用的没Java重,因为Python的语言特性已经支持一些设计模式的效果(比如单例模式),而且Python语言讲究简单直接,不像Java弄很多抽象层。但设计模式相当于套路,掌握一些通用的套路以及对应解决的问题,能够提高写代码的敏感力,能及时发现需要重构的地方。

但太强调扩展性也不好,如果预测变化不准确可能导致过度设计,那种变化可能永远不会到来。过度设计的代码层次特别多,可读性差。所以扩展性适度就好,何为适度,就是在不影响整体架构和开发速度的情况下,方便就做下扩展,不方便就使用最简单的方式实现,后面如果有变化再根据变化持续迭代重构。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,042评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,996评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,674评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,340评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,404评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,749评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,902评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,662评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,110评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,577评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,258评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,848评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,726评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,952评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,271评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,452评论 2 348

推荐阅读更多精彩内容