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

推荐订阅源

T
The Blog of Author Tim Ferriss
S
Schneier on Security
H
Help Net Security
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MongoDB | Blog
MongoDB | Blog
云风的 BLOG
云风的 BLOG
H
Hacker News: Front Page
C
Check Point Blog
P
Privacy International News Feed
IT之家
IT之家
爱范儿
爱范儿
AWS News Blog
AWS News Blog
The Hacker News
The Hacker News
Stack Overflow Blog
Stack Overflow Blog
Project Zero
Project Zero
Microsoft Azure Blog
Microsoft Azure Blog
量子位
The Cloudflare Blog
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
C
Cybersecurity and Infrastructure Security Agency CISA
I
Intezer
Martin Fowler
Martin Fowler
Scott Helme
Scott Helme
酷 壳 – CoolShell
酷 壳 – CoolShell
A
Arctic Wolf
T
Threat Research - Cisco Blogs
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
The Exploit Database - CXSecurity.com
B
Blog
Simon Willison's Weblog
Simon Willison's Weblog
U
Unit 42
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Microsoft Security Blog
Microsoft Security Blog
博客园_首页
J
Java Code Geeks
K
Kaspersky official blog
Webroot Blog
Webroot Blog
C
CERT Recently Published Vulnerability Notes
H
Heimdal Security Blog
G
Google Developers Blog
T
Tor Project blog
W
WeLiveSecurity
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Blog — PlanetScale
Blog — PlanetScale
小众软件
小众软件
有赞技术团队
有赞技术团队

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
  • 自测
  • 测试
  • 灰度
  • 发布