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

推荐订阅源

Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
博客园 - 【当耐特】
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
D
Docker
GbyAI
GbyAI
酷 壳 – CoolShell
酷 壳 – CoolShell
WordPress大学
WordPress大学
The Cloudflare Blog
雷峰网
雷峰网
A
About on SuperTechFans
小众软件
小众软件
博客园 - Franky
博客园 - 聂微东
F
Full Disclosure
大猫的无限游戏
大猫的无限游戏
C
Check Point Blog
MongoDB | Blog
MongoDB | Blog
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
V2EX
Engineering at Meta
Engineering at Meta
宝玉的分享
宝玉的分享
aimingoo的专栏
aimingoo的专栏
量子位
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
罗磊的独立博客
Martin Fowler
Martin Fowler
D
DataBreaches.Net
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Secure Thoughts
Project Zero
Project Zero
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tailwind CSS Blog
S
Schneier on Security
Blog — PlanetScale
Blog — PlanetScale
The Hacker News
The Hacker News
Spread Privacy
Spread Privacy
Security Latest
Security Latest
NISL@THU
NISL@THU
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
CXSECURITY Database RSS Feed - CXSecurity.com
J
Java Code Geeks

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参数优化 [分享]深度工作 你需要更多的思考时间 Django项目重构小结 工作七年小结: 学习,生活及其他 [分享]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 重新组织函数 [分享]关于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访问日志
Python 代码规范小结
2016-11-03 · via Posts on WKLKEN THINKING

code review中一些小结, 还没来得及加例子, 简要记录, 供参考

law

一: 一切都与复杂度有关 二: 代码应当易于理解

对人:

“好程序员”应当竭尽全力, 把程序写得让其他程序员(以及以后的自己)容易理解.

对代码:

  1. 代码被阅读的次数远多于编写和修改的次数
  2. E = mc2 (Error = more codes)

对项目:

公式: 可行性=(当前价值+未来价值)/(实现成本+维护成本). 即相比降低实现成本, 降低维护成本更加重要

基础: 风格

团队成员遵守统一的风格, 保持风格的一致性, 减少理解难度

遵循基础的编码风格:

请仔细阅读, 使用对应编辑器插件工具协助检查

  • 遵循 pep8 风格 利用pep8工具(编辑器相关插件)来解决这个问题, 在review之前处理. 以避免在review过程中出现此类问题.

  • 遵循 Google Code Style / 中文版

  • 不要吝啬空行, 把相关的代码行分组, 形成代码块. 声明按块组织起来, 并且把代码分成”段落”(按步骤/顺序/逻辑结构分), 排版合理

  • 每行只写一个语句, 每行只声明一个变量

注释

注释应该有很高的价值(传递信息/空间占用)

  • 代码本身应该尽力做到自说明

  • 注释, 记录了在写代码过程中的思考, 保持紧凑, 简单准确的描述

  • 不要使用尾注释. 容易被整行拷贝/不容易被编辑修改/逐渐腐烂

      x = 1  # bad comment
    
      # good comment
      x = 1
    
  • 不需要的代码, 维护到版本库后(写明commit info), 然后删除. 不要注释起来

  • 不要给不好的命名加注释, 应该去修改命名

  • 不要给那些从代码本身就能快速推断出来的事实写注释.(不要为了注释而注释)

  • 对于复杂的计算逻辑, 要给出注释, 可以通过列举例子, 简单的输入输出来描述

  • 对于大段的逻辑或模块, 需要给总结性注释

  • 注释代码时, 应注重-为何做, 而不是-怎么做

  • 每行注释前用一个空行分开. 注释缩进要和相应代码一致

命名

把信息装入名字中.(自说明)

  • 尽量短, 但是要包含足够的信息(刨掉其中毫无意义的词)
  • 命名一定要有意义, 尽量少使用单个字符作为命名, 除非短表达式(列表解析/lambda等)以及小的作用域范围
  • 常量大写, 变量小写, 类名驼峰, 函数名小写加下划线, 不要混用下划线和驼峰.
  • 不要使用关键字命名, 例如typedir
  • 避免使用容易混淆的命名, 防歧义
  • 慎用首字母缩略词和缩写, 除非团队成员都理解(不要妄图用注释来解决这个问题, 即, 不要注释不好的命名)
  • 不要使用大小写来区分不同对象
  • 同一个变量, 在多个地方, 前后端/数据库/不同函数/请求等, 尽量保持命名一致性
  • 不要害怕过长的命名, 保证易于理解和阅读(现代编辑器可以搞定自动补全和批量变更的问题)
  • 使用具体的名字, 而不是泛化的名字, 例如params/args等, 没有隐含任何信息
  • bool类型, 除非名字本身有True/False的含义, 否则建议统一使用is_前缀
  • 不要使用双重否定的命名: is_not_pass
  • for a in b, 注意 ab 的单复数区分

常量

  • 常量大写
  • 作用于同一个模块/逻辑的多个常量, 建议使用统一的前缀
  • 将常量统一组织到某个文件/某几个文件, 并写明注释.
  • 函数/循环中的正则, 请预先compile, 放入变量中.
  • 善用Enum, 对可读性提升很大
  • 同一个枚举变量中, 其包含类型应当一致

变量

  • 减少变量: 变量越多, 越难全部追踪其动向. a.减少没有价值的中间变量 b.减少中间结果(可以通过提前返回来消除) c.减少控制流变量
  • 缩小变量作用域: 避免全局变量(命名空间污染). 需要做到让你的变量对尽量少的代码行可见.
  • 变量定义尽量靠近其使用的地方, 或者, 在使用时定义.
  • 不要使用import *, 会出现各种突如其来的变量名, 可能导致名字空间污染, 造成诡异问题

数据结构

  • dict, 不要使用for key in d.keys(), 直接使用for key in d

表达式

原则: 保持简短, 易懂.(拆分超长表达式)

  • 抽取反复出现的长表达式到变量或者函数调用
  • 使用解释变量, 将超长表达式中的自表达式抽取城一个解释变量.(抽取, 然后使用变量, 而不是每次都重复表达式)
  • 总结变量: 一个表达式不需要解释, 但是装入一个新的变量中仍然有用. 短名字替代一大块代码. 例如: numbers[0]['obj'].name
  • 使用摩根定理: not a and not b to not (a or b)
  • 删除公共子表达式:如果发现某个表达式老是在你面前出现,就把它赋值给一个变量
  • 中文, 请统一使用u"中文"
  • 表达式中避免使用魔数, 使用常量/枚举替代之

控制流: 分支

  • if/else顺序: a. 先处理正逻辑而不是负逻辑. b. 先处理掉简单的情况, 还能保证if/else在同一个屏幕内都可见(否则到了else需要回头查) c.先处理有趣或可疑的逻辑
  • return early, 从函数中提前返回. 使用guard clause来实现. 某些情况返回后, 将不必要思考某个分支出口, 剩余注意力集中在为数不多的情况. 另一个好处是, 能有效减少代码缩进.
  • 减少嵌套: 嵌套很深的代码很难理解, 每个嵌套层次会在读者’思维栈’上又增加了一个条件. 使用return early来减少嵌套. 而循环中的减少嵌套方式, 可以使用if condition: continue/break来进行提早返回.
  • 减少嵌套: 当你对代码进行改动的时候, 从全新的角度审视它, 把它作为一个整体来看待.只关心局部, 不敢动旧有代码, 很容易一层层逻辑嵌套往里加导致深层嵌套
  • 使用is来判定是否是None, 而不是==
  • 条件语句中参数顺序: 左侧变量, 右侧字面值/常量
  • 默认情况都使用if...else, 三目运算只有在最简单的情况下才使用
  • if condition: return 则不需要else
  • 注意if/else的多层嵌套, 在某些情况下, 判断条件中恒真/恒假的情况

控制流: 循环

  • 善用enumerate而不是维护index变量( enumerate 还可以从1开始计数)
  • 除非必要(逻辑确实如此且带break), 否则不要使用for...else.(增加理解成本)
  • 不要使用for _ in l: _.x, 可读性太差
  • 减少循环内的if...else...嵌套层次, 可以使用if condition: continue

控制流: 异常处理

异常日志同注释, 应该有很高的价值(传递信息/空间占用)

  • 不要把所有代码放到try except中, 只捕获会出异常的代码片段. 注意粒度, 不要放入不必要的代码
  • 不要吞掉异常, 处理或抛出, 同时要打日志(使用logging而不是print打日志)
  • 谨慎使用except Exception捕获所有异常.
  • 不要在finally语句中使用return进行返回, 有坑.
  • 异常的错误信息要有用, 即足够明确, 对问题排查有帮助.
  • 不要使用异常控制程序的流程. 滥用异常, 异常不应该处理正常逻辑
  • 不要滥用异常, 底层被调用函数早已try...except处理了, 调用方不需要再次处理

函数

函数不要太大, 嵌套不要太深

  • 参数命名的一致性: 多个参数, 选择一个有意义的顺序, 并始终一致地使用它(可读性更好, 更容易发现问题)
  • 不要使用可变对象作为函数默认参数的值
  • 一次只做一件事, 注意函数大小, 注意抽象/拆分
  • 抽取不相关的子问题到独立的函数中, 例如纯工具代码, 通用代码, 项目专属代码
  • 抽取反复出现重复的代码到独立函数中
  • return 值不要使用0/1来代表True/False
  • 同一个函数可能存在多个return, 返回值要保持一致(个数/类型)
  • return early, 减少阅读代码时的逻辑堆积, 减少贯穿函数始终用于最终判断return的变量数量. 超过3个就变得有些难以维护了, 阅读过程中确定其值有困难
  • 如果函数调用链中, 参数或者return的值反复出现pack/unpack, 可以考虑用dict封装来进行传递.
  • 如果发现每次调用一个函数后, 还需要对返回值进行二次处理, 则是函数封装得不够导致的. 需重构函数, 将处理加进去. (防止某次调用忘了二次处理导致的bug)

  • 不要使用type进行类型检查, 用isinstance
  • 使用新式类, 驼峰命名
  • 假设类的某个属性, 每次取出来都需要进行处理(格式化, 转换等, 例如日期格式), 使用property封装这层处理, 同时处理异常情况.

模块

  • import顺序: 标准库/第三方库/本项目, 之间使用空行隔开
  • 多行import, 请使用from a import (b, c, d)而不是\来进行换行
  • 不要使用from A import *
  • 当相对独立的多个逻辑代码混杂放在一起, 或者发现constant文件超大包含了大量不同逻辑的产量, 可以考虑模块切分

抽象

  • 一定不要机械地复制粘贴代码(会出现大量的重复代码), 应该从全局考虑是否可以抽象
  • 多个函数之间, 如果仅有一两行代码不同, 则可以进行抽象提取
  • 当一段相似的代码出现两次以上, 需要考虑封装(注意粒度)

设计

软件设计三大误区: 1.编写不必要的代码 2.代码难以修改 3.过分追求通用

  • 思考足够充分, 减少过度设计

其他

  • 熟悉标准库, 减少土制轮子的概率, 可以少写代码
  • 熟悉框架/优秀第三方库提供的接口及特性, 原因同上
  • 项目发布前, 移除所有print语句
  • 文件/函数是否写明作者信息? 不, 版本记录中有作者信息. 容易形成领地, 他人不敢修改/不敢大改, 容易造成代码腐烂. 占用空间且没啥用.

参考书目

  • 编写可读代码的艺术
  • 简约之美—软件设计之道
  • 编写高质量代码—改善Python程序的91个建议