惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
L
LangChain Blog
Jina AI
Jina AI
WordPress大学
WordPress大学
人人都是产品经理
人人都是产品经理
S
Secure Thoughts
T
The Exploit Database - CXSecurity.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 聂微东
小众软件
小众软件
Apple Machine Learning Research
Apple Machine Learning Research
C
Cyber Attacks, Cyber Crime and Cyber Security
Project Zero
Project Zero
T
Threat Research - Cisco Blogs
量子位
G
GRAHAM CLULEY
腾讯CDC
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
C
CERT Recently Published Vulnerability Notes
The Hacker News
The Hacker News
C
Cisco Blogs
Scott Helme
Scott Helme
Spread Privacy
Spread Privacy
宝玉的分享
宝玉的分享
V
V2EX
博客园 - 三生石上(FineUI控件)
T
Tor Project blog
P
Proofpoint News Feed
雷峰网
雷峰网
D
Darknet – Hacking Tools, Hacker News & Cyber Security
V
Vulnerabilities – Threatpost
PCI Perspectives
PCI Perspectives
博客园_首页
L
LINUX DO - 最新话题
IT之家
IT之家
有赞技术团队
有赞技术团队
博客园 - Franky
Hacker News: Ask HN
Hacker News: Ask HN
Last Week in AI
Last Week in AI
The Cloudflare Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
美团技术团队
博客园 - 【当耐特】
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Security Archives - TechRepublic
Security Archives - TechRepublic
L
LINUX DO - 热门话题
AWS News Blog
AWS News Blog
S
Security Affairs
T
Tailwind CSS Blog

Posts on WKLKEN THINKING

apisix 中的 lrucache apisix 中的服务发现机制 apisix 中的负载均衡 apisix etcd机制 聊聊框架 关于 k8s 的 zero downtime deployment 一些建议 apisix 遇到的一些问题 关于在除夕前一天换了一个洗衣机的故事 Django DRF 性能优化 DRF 的一些实践 Part1: Serializer DRF继承关系图 Better Code: 关于接口的灵活性 新的仓库: wklken/naming 缓存使用的一些经验 Better Code: 抽象: 可扩展性与可维护性的抉择 Better Code: 异常时, 该提示用户哪些信息? Better Code: 更好的异常日志打印 Go: some libs Go: go-redis/cache升级的坑 Go: logrus性能提升 Go: gin validation 远程办公的一点总结 Go: 开发过程中的一些bug 项目管理实践: 风险驱动开发 Go: 一种error wrap调用链处理方式 漫谈技术选型 Go: 基于 apitest 做handler层单元测试 Go: go-sql-driver interpolateparams参数优化 [分享]深度工作 你需要更多的思考时间 工作七年小结: 学习,生活及其他 [分享]bash日常: bash-utils 极客时间推广海报 2017总结: 予时光以意义 k8s APIServer源码: api注册详细细节 k8s APIServer源码: api注册主体流程 k8s APIServer源码: 服务启动 k8s APIServer源码: go-restful框架 重构 - 读书笔记(Python示例) 写给新人的沟通建议 vim 杂谈 - 关于快速编辑 vim 杂谈 - 关于移动 读书笔记-重构: 章11 处理概括关系 读书笔记-重构: 章10 简化函数调用 读书笔记-重构: 章9 简化表达式 读书笔记-重构: 章8 重新组织数据 读书笔记-重构: 章7 在对象之间搬移特性 读书笔记-重构: 章6 重新组织函数 Python 代码规范小结 [分享]关于vim ElasticSearch集群部署文档 Logstash+ElasticSearch处理mysql慢查询日志 [分享]关于代码调试DE那些事 Logstash+ElasticSearch+Kibana- 实现相对通用的数据收集分析 ELK维护的一些点(二) [分享]Python源码剖析-数据结构 一些Centos Python生产环境的部署命令 摘录<<6个月学会任何一种外语>> ELK 维护的一些点 也许是一个新的开始 一些vim的个性化配置 读书笔记-调试九法 这段时间的一些想法 Python 源码阅读 - 垃圾回收机制 我为什么要写博客 APUE笔记-第一章 UNIX基础知识 Python源码阅读-闭包的实现 Python源码阅读-内存管理机制(二) Python源码阅读-内存管理机制(一) Python-基础-数据结构小结 '活动'设计的一些trick 一些简单的Python测试题 我的tmux配置及说明【k-tmux】 Review and Restart 工作四周年小结 vim插件: surround & repeat[成对符号编辑] vim插件: gundo[时光机] vim插件: expand-region[区域选中] vim插件: quickrun[快速执行] vim插件: trailing-whitespace[行尾空格处理] vim插件: closetag[成对标签补全] vim插件: ctrlp[文件搜索] vim插件: airline[状态栏增强] vim插件: theme[主题] vim插件: tagbar[大纲式导航] vim插件: nerdcommenter[快速注释] vim插件: rainbow_parentheses[括号高亮] vim插件: syntastic[语法检查] vim插件: delimitmate[符号自动补全] vim插件: matchit[成对标签跳转] vim插件: easy-align[快速对齐] vim插件: multiple-cursors[多光标操作] vim插件: vim-signature[快速标记跳转] vim插件: easymotion[快速跳转] vim插件: vundle[管理插件] Elasticsearch几个问题的解决 分享一份 Vim 简介PPT k-vim 更新9.0版本 关于知识管理工具的思考 Logstash+ElasticSearch+Kibana处理nginx访问日志
Django项目重构小结
2018-12-06 · via Posts on WKLKEN THINKING

由于历史原因, 项目组中存在很多历史悠久的项目.

这类项目, 有着一些共同特征: 历史悠久, 几度经手, 缺乏文档, 维护困难, 模块不合理, 代码坏味道, 版本老旧等等.

总之, 维护困难.

如果维护需求不多, 基本不动, 这类项目可以保持现状, 稳定运行不出问题就行.

但是, 另一方面, 如果项目需求多, 需要频繁修改, 由于项目的原因导致变更困难/进度缓慢/问题频出, 那么就该考虑进行代码重构了.

梳理了一些django项目重构的事项, 供参考.

1. code review

将核心代码做个pr, 组织一次线上的code review.

  • 不要线下review, 此时代码可能非常庞大, 本身并不适合review
  • 要有本项目历史维护者参与, 也要有非项目维护者的外部人员参与

线上reivew一周, 收集大家的comment, 之后做个分类汇总

2. 升级django版本

如果是django1.3及以下, 可以考虑升级到 1.8

做升级, 并做相应的变更, 使得程序能正常运行

可以考虑升级到django2.x(python3)

3. use CBV or DRF

具体区别可以参考 Class-Based Views vs. Function-Based Views

老旧项目, 90%以上都是 FBV(Function-Based-View), 如果项目比较小, 使用FBV可以短平快地搞定需求.

但是如果项目变得比较大了, 可以考虑使用 CBV

对于大型项目, 建议使用 DRF(Django REST framework), 中小型项目不建议引入DRF的原因是, DRF有一定的学习门槛, 比较重, 可能引入不必要的复杂度.

  • 微型项目: FBV or CBV
  • 中小型项目: CBV
  • 大型项目: DRF

此时会涉及(以下均是django 1.8文档)

可以:

  1. 权限控制使用mixin, 去掉了原先的权限控制decorator
  2. 定义抽象出自己需要的view, 例如MakoTemplateView / JsonView
  3. 合并相关的view

流程: url不动, 将所有FBV改成CBV, 抽象及合并代码, 合并相关view

├── common
│   ├── __init__.py
│   ├── constants.py
│   ├── context_processors.py
│   ├── decorators.py
│   ├── exceptions.py
│   ├── http.py
│   ├── log.py
│   ├── middlewares
│   │   ├── __init__.py
│   │   └── exception.py
│   ├── mixins
│   │   ├── __init__.py
│   │   └── base.py
│   ├── responses.py
│   ├── tests.py
│   ├── utils.py
│   └── views
│       ├── __init__.py
│       └── mako.py

4. 分层及模块切分

严格的分层,使得每一层职责清晰;

thin views, fat models

  • 业务逻辑, 尽量瘦小简短
  • 将view中, 跟model具体对象相关的逻辑, 挪到model的方法中, 或者@property中, 补充一系列porperty/classmethod/staticmethod
  • 注意, 不包含{application}.objects.xxxx的ORM操作

 fat managers

  • 将view中, 跟ORM相关的复杂逻辑, 挪到manager中
  • [拆分出{application}/manager.py]
  • Django Manager

use form

  • 使用django form替换掉所有参数处理及校验相关的代码
  • 去除/合并原有的逻辑代码
  • [拆分出{application}/forms.py]

use enum

  • replace all the magic number and build the choices for model
  • [拆分出common/constants.py 和 {application}/constants.py]
  • common/constants.py 放项目全局常量
  • {application}/constants.py 放app局部使用常量

add utils helpers

  • 将工具类代码逻辑进行抽离, 减少代码容易
  • [拆分出common/utils.py 和 {applications}/utils.py]
├── app
│   ├── __init__.py
│   ├── admin.py
│   ├── constants.py
│   ├── forms.py
│   ├── manager.py
│   ├── migrations/
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   ├── utils.py
│   └── views.py

stupid template

5. 抽离第三方依赖api [拆分出components/xxx.py]

  • 重灾区: 可能每个地方都有拼url, 调用, 处理返回值, 可能前期就一两个地方, 但是随着时间推移, 会出现腐烂的趋势, 很多地方直接拷贝, 改改用. 需要全部抽出
  • 将原先散落在各处的依赖第三方系统的api调用, 全部抽出到同一个文件中
  • 减少代码冗余
  • 同时, 可以统一处理输入/输出/异常等
  • 后续接口协议变更, 可以做统一变更
├── components
│   ├── __init__.py
│   ├── engine.py
│   ├── login.py
│   └── tests.py

6. 统一

重灾区, 由于历史及人员的不同习惯, 往往一个项目会引入非常多的不同的做法去完成同一件事.

在重构的节点, 我们必须将其统一, 否则由于破窗理论, 整体项目会越来越混乱.

原则: 做同一件事,只存在一种方法; 不要存在重复的代码; 不能妥协.

 常量

  • 有时候, 同一个定义, 可能有几套常量, 每个人自己定义了一套

 utils

  • 重灾区, 不同模块下, 可能每个开发者自己将历史工具类/函数拷贝过来, 而不是使用公共的
  • 可能需求略有区别, 所以公共的工具模块/类, 需要重构支持

 错误码

  • 统一所有错误码

异常

  • 统一异常类
  • 统一异常处理方式/风格
  • 在同一层处理异常: 一种思路, 在middleware中统一处理所有类型异常, 而在view及其之下的调用链中可以减少try-except, 或者发现问题直接raise对应异常

 协议

  • 统一的返回值结构
  • 统一的http错误码/状态码
  • 可能涉及前端变更调用, 但是, 该改动必须改
  • 可以通过自定义view/mixin等方式处理, 也可以对django的Response/JsonResponse做一层封装

 unicode_literals

  • 如果使用python2, 可以from __future__ import unicode_literals
  • 不强求

7. 逐行重构

  • Python 代码规范小结

  • 重构 - 读书笔记(Python示例)

  • 删除无用的代码/注释/文档等

  • 命名: 对所有变量名/常量名/函数名/类名/模块名等等重新思考,改成更合适的名字(此时编辑器或IDE的批量查找替换发挥作用)

  • 归属问题: 函数/变量/方法等, 要思考是否属于这里, 不合适直接调整

  • 表达式

  • 控制流: return early / guard clauses….

  • 异常处理

  • 函数等

  • ……

  • 同时, 根据code review结果, 逐一修改

  • 该加注释加注释, 该加文档加文档

8. format the url

因为要动前端调用, 所以放靠后会更合适

  • 推荐使用restful风格
  • 格式化url
  • 涉及前端调用处一并修改
  • 如果被其他系统依赖, 可能需要兼容老的url/协议, 可用, 但标明deprecated, 并同时提供新版本的url/协议

9. fix all pep8 issues

flake8 --config=.flake8 .
  • 开始不忽略任何错误, 完整修一遍
  • 重构所有过于复杂的函数 C901 XXXX is too complex
  • 能不加# noqa就不加

10. unittest

  • 加单元测试, 优先核心模块的核心逻辑

11. 然后

  • code review again
  • 自测
  • 测试
  • 灰度
  • 发布