# 编程规范

# Flag

UUID(Universally Unique Identifier)/GUID (Globally Unique Identifier)

  • Version 1: 基于时间戳和MAC地址,结合当前的时间戳(从格里高利历的1582年10月15日零点算起,100纳秒为单位)和计算机的MAC地址(或伪随机节点ID)。还包含一个“时钟序列”以处理时钟回拨和生成重复MAC地址的情况。
  • Version 2: 类似 Version 1,但将时间戳的高位替换为“DCE Security”域(如用户ID或组ID)。
  • Version 3: 基于命名空间和MD5散列,将一个“命名空间UUID”和一个“名称”(任意字符串)作为输入,然后通过MD5散列算法计算出。
  • Version 4: 基于随机数,大部分位由高质量的伪随机数生成器 (PRNG) 填充。只有几个位用于表示版本号和变体。
  • Version 5: 基于命名空间和SHA-1散列,类似 Version 3,但使用SHA-1散列算法代替MD5。

ULID(Universidally Unique Lexicographically Sortable Identifier)是一种设计用于解决传统 UUID 在数据库索引和可排序性方面缺点的新型标识符。ULID 结合了 UUID 的全球唯一性和时间戳的可排序性。

编程语言提供的随机数,是伪随机数,所谓伪随机数,并非真的随机,而是算法得到的。只要初始的种子值相同,算法会给出一样的结果。 一般来说,只有通过硬件,才能得到真随机数,单纯的软件算法做不到。真随机数需要满足三个条件。

  1. 无法预测。 随机数不能被猜到,所以必须非常大,否则会被暴力破解。
  2. 不能重复。 每次生成的随机数,不能是一样的。
  3. 均匀分布。 随机数必须平均散布在所有区间,不能集中在某些区间。

boolean

bool表示布尔型变量,bai也du就是逻辑型变量的定义符,zhi以英国数学家、布尔代数的奠基人乔dao治·布尔(George Boole)命名。

布尔型变量bool的取值只有false和true,0为false,非0为true。(例如-1和1都是true)

# 代码风格指南

naming conventions 约定大于配置

可读性:程序是供人类阅读和理解的,计算机的执行只是附带的事情。

展开查看思维导图

# 命名规范

  • 匈牙利命名法(Hungarian):变量类型缩写+大驼峰,如int iMyAge,Windows编程常用
  • 驼峰命名法(camelCase/lowerCamelCase,小驼峰): 首字母小写,后续每个单词首字母都大写。面向对象语言(如Java、C#)变量、方法常用
  • 帕斯卡命名法(CamelCase/PascalCase,大驼峰): 首字母大写,后续每个单词首字母都大写。常被面向对象语言(如Java、C#)类常用
  • 下划线命名法(under_score_case/snake_case,Snake蛇形):C、Python变量、数据库命名常用
  • 短横线命名法(kebab-case):Web前端语言(如CSS)变量常用,HTML 特性是不区分大小写的,无法使用驼峰命名
  • 不区分大小写(case-insensitive):Canonical 格式,一般用于HTTP Headers、URL Path

布尔变量尤其难起名。怎样才能贴切地表达,这个变量是表示"真"(true)和"伪"(false)的布尔值呢?

  1. is-:描述事物的状态,后面跟形容词,比如 isActive,isDeleted,isEmpty。
  2. has-:描述事物的所有权或包含关系,后面跟名词,比如 hasAccess,hasChildren,hasValidationErrors。
  3. can-:描述事物的能力或权限,比如 canEdit,canDelete,canRetry。
  4. should-:描述事物的意图或逻辑,比如 shouldRetry,shouldCacheResponse。

除了这四个前缀,起名还有另一条规则:永远不在布尔变量名中使用否定词。比如,不使用 isDisabled,而要用 isEnabled = false

Java

大小写敏感的,且只能以 字母$_ 开头,首字母随后的字符可以是字母数字$_

  • 项目名:全部小写,可使用-_连接符以分割单词,且不能有空格、中文和其他特殊字符
  • 包名:全部小写,单词不需分割,且不能有空格、中文和其他特殊字符
  • 常量:全部大写,可使用_连接符以分割单词
  • 变量:小驼峰式命名法,前缀应当是名词。尽量在变量名字中体现所属类型,如:length、count表示数字类型;name、title表示字符串类型
  • 函数:小驼峰式命名法,前缀应当为动词。
  • 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
  • 代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。注意,即使纯拼音命名方式也要避免采用。
  • 类名使用大驼峰风格,但以下情形例外:DO / BO / DTO / VO / AO / PO等。
  • 方法名、参数名、成员变量、局部变量都统一使用小驼峰风格,必须遵从小驼峰形式。
  • 常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
  • 抽象类命名使用Abstract或Base开头。
  • 异常类命名使用Exception结尾。
  • 测试类命名以它要测试的类名开始,以Test结尾。
  • 类型与中括号紧挨相连来定义数组。
  • POJO类中布尔类型的变量,都不要加is前缀,否则部分框架解析会引起序列化错误。
  • 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。
  • 杜绝完全不规范的缩写,避免望文不知义。
  • 最好逐一声明每个变量而不是写在一行。
  • Java的变量声明尽量靠近变量第一次使用的地方。

# Golang

可见性(访问控制)取决于其第一个字符是否为大写

  • 包名称:其他字母应该为小写单词,不要使用下划线或者混合大小写
  • 文件命名:尽量采取有意义的文件名,简短,有意义,应该为小写单词,使用下划线分隔各个单词
  • 结构体、接口、变量:使用驼峰命名法
  • 常量:全部大写字母组成,并使用下划线分词
  • 单元测试:文件名命名规范为_test结尾,测试用例的函数名称必须以Test开头

# Python

  • 文件名、包名、模块名、局部变量名、函数&方法名:全小写+下划线式驼峰
  • 类:首字母大写式驼峰。内部类可以使用额外的前导下划线
  • 函数和方法的参数
    • 类实例方法第一个参数使用self, 类方法第一个参数使用cls
    • 如果一个函数的参数名称和保留的关键字冲突,通常使用一个后缀下划线好于使用缩写或奇怪的拼写
  • 全局变量
    • 对于from M import *导入语句,如果想阻止导入模块内的全局变量可以使用旧有的规范,在全局变量上加一个前导的下划线。
    • 全大写+下划线式驼峰,应避免使用全局变量
  • 变量
    • 不论是类成员变量还是全局变量,均不使用 m 或 g 前缀。
    • 私有类成员使用单一下划线前缀标识,多定义公开成员,少定义私有成员。
    • 变量名不应带有类型信息,因为Python是动态类型语言,在解释的时候才确定类型
  • 常量
    • 所有字母大写,由下划线连接各个单词
  • 异常
    • 因为异常也是一个类,所以遵守类的命名规则。此外,如果异常实际上指代一个错误的话,应该使用Error做后缀
  • 缩写命名应当尽量使用全拼写的单词,缩写的情况有如下两种:
    • 常用的缩写,如XML、ID等,在命名时也应只大写首字母,如XmlParser。
    • 命名中含有长单词,对某个单词进行缩写。这时应使用约定成俗的缩写方式。
    function 缩写为 fn
    text 缩写为 txt
    object 缩写为 obj
    count 缩写为 cnt
    number 缩写为 num
    

关于下划线

  • 一个前导下划线:表示私有。
  • 一个后缀下划线:避免关键字冲突。
  • 以单下划线开头,是弱内部使用标识,from M import * 时,将不会导入该对象(python 一切皆对象)。
  • 两个前导下划线:当命名一个类属性引起名称冲突时使用。
  • 两个前导和后缀下划线:有特殊用途的对象或者属性,例如init或者file。绝对不要创造这样的名字,而只是使用它们。
  • 以双下划线开头的变量名,主要用于类内部标识类私有,不能直接访问。
  • 双下划线开头且双下划线截尾的命名方法尽量不要用,这是标识

# GNU风格版本规则

  • MAJOR.MINOR.PATCH即: 主版本号.次版本号.修正版本号
  • Major.Minor.Revision即: 主版本号.次版本号.修正版本号
  1. Major 主版本号:表示当前APR的主版本号,它的变化通常意味着APR的巨大的变化,比如体系结构的重新设计、API的重新设计、 重大的重构、重大的feature改动、重大的不兼容性的变化等等,而且这种变化通常会导致APR版本的向前不兼容。

  2. Minor 次版本号:发布较大的新feature功能,或者较大的重构或者模块变化,或者出现不兼容性改动,会增加子版本号; 子版本的发布会伴随着完整的change log,算是一个较大的版本发布,有仪式感

  3. Revision/PATCH 修正版本号:往往是bug fix,或者增加较小的feature,较小的功能改进或者模块变化, 在保证完整向后兼容的前提下,会增加修正版本号

  4. 当主版本号增加时,子版本号及修正版本号置0

  5. 当子版本号增加时,修正版本号置0

按照测试过程标识

  1. Alpha版:预览版或内部测试版,一般不向外部发布,会有很多Bug。
  2. Beta版:公测版。
  3. RC版:Release Candidate候选版本。也叫做Gamma版本。

# Commit提交规范

通常采用业界标准的 Conventional Commits(约定式提交)

Type 含义 适用场景
feat / feature 新功能 新增业务功能、接口、页面
fix / bugfix / fixed 修复缺陷 修复Bug、异常、数据错误
docs 文档变更 README、接口文档、注释、Wiki
style 代码格式 缩进、空格、分号、lint修复(不影响逻辑)
refactor / update / mod / changed 重构 不改变外部行为的代码结构调整、优化
perf 性能优化 提升响应速度、降低内存/CPU占用、缓存优化
test 测试相关 新增/修改单元测试、集成测试用例
build 构建系统 依赖升级、Webpack/Vite配置、Dockerfile、打包脚本
ci CI/CD Jenkins/GitLab CI 脚本、流水线配置
chore / add / delete / rem 杂项 工具脚本、配置文件、非业务代码维护
revert 回滚提交 撤销某次提交,格式:revert: <原提交subject>

# switch

  • 在Python中没有switch语法
  • JavaScript的switch语法跟Java一样
  • 在Java中

如果default不是switch代码块中最后一个case,请记得用break;结束默认case

switch ("A".toLowerCase()) {
case "a":
    System.out.println("a");
    // 注意:此处如果条件满足但没有添加break,则代码会继续执行,
    // 会无条件执行后面的语句,直到遇到break
    //break;
    // fall thorugh
case "b":
    System.out.println("b");
    break;
default:
    // 如果default写在最前面,会先执行,
    // 但是如果没有写break;还是会无条件执行后面的语句
    System.out.println("default");
    break;
}
  • 在Go中
  1. 左花括号{必须与switch处于同一行;
  2. 条件表达式不限制为常量或者整数;
  3. 单个case中,可以出现多个结果选项,以,分割;
  4. 与C语言等规则相反,Go语言不需要用break来明确退出一个case
  5. 只有在case中明确添加fallthrough关键字,才会继续执行紧跟的下一个case
  6. 可以不设定switch之后的条件表达式,在此种情况下,整个switch结构与多个if...else...的逻辑作用等同。
switch strings.ToLower("A") {
case "a":
    fmt.Println("a")
case "b":
    fmt.Println("b")
default:
    fmt.Println("default")
}

# 日期时间历法体系

  • 周编号系统 (Week Numbering System):指代决定“每周第一天是哪天”以及“第一周如何定义”的一整套规则体系。
  • 周日历 / 星期纪日法 (Week Date System):特指用“年-周数-星期几”来表示日期的历法系统。例如 ISO 8601 中将 2026年8月19日 记作 2026-W34-3,这就属于一种“周日历”表达法。
  • 区域设置 / 语境 (Locale):这是计算机科学中最核心的词。一个 Locale(如 en-US 代表美国英语,zh-CN 代表中国大陆中文)不仅仅包含语言,还硬性绑定了该地区的日期流派(大端序还是中端序)、年周流派(周日还是周一作为起始日)、甚至数字和货币格式。
  • CLDR (Common Locale Data Repository,通用区域数据仓库):这是 Unicode 联盟维护的一个全球标准数据库。如果你问“世界上那么多流派,计算机是怎么记住的?”,答案就是 CLDR。它被内置在 Java, Python, 操作系统和各大浏览器中,是所有日期时间“流派”的统一字典。
  • 国际化与本地化 (i18n & L10n / Internationalization and Localization):处理这些不同历法和时间流派的技术工程学名称。
  • 时间纪元 / 历元 (Epoch):特指上文提到的“计算机时间的起点流派”(如 1970年1月1日)。
  • 数据交换格式 (Data Interchange Format):ISO 8601 甚至 RFC 3339 的官方分类就是“信息交换的日期和时间表示法”。
  • 时间戳 (Timestamp):独立于时区和历法的绝对时间点表示法。
  • 时间标准 / 时间标尺 (Time Standard / Time Scale):用来区分原子时(物理流派)、世界时(天文流派)和协调世界时(妥协流派)。
  • 历法系统 (Calendar System):用来区分公历、农历、伊斯兰历等不同的人类纪年法则。

年周(Week of the Year)的规格与流派

流派 代表地区/领域 每周第一天 第一周规则 断裂周 典型特征
ISO 8601 欧洲、中国、国际商务、现代编程 周一 包含 1月4日(或第一个周四) ❌ 不允许 每周绝对是7天,年初/年末几天可能算作跨年
北美/格里高利惯例 美国、加拿大、拉美、日本 周日 包含 1月1日 的那一周 ✅ 允许 第1周可能只有1~6天,年底最后一周同理
美国商业周 美国企业内部、部分旧版办公软件 周一 包含 1月1日 的那一周 ✅ 允许 工作周从周一计,但仍以1月1日粗暴切分第1周
伊斯兰/中东惯例 沙特、迪拜等中东国家 周六 因地而异(通常含 1月1日) ✅ 允许 周末通常是周五,以适应伊斯兰聚礼日
简单除法周 某些特定的统计/报表算法 任意 当年的第几天 ÷ 7 向上取整 ✅ 允许 不考虑“星期几”,单纯把每年的前7天算作第1周
首个完整周 某些特定的薪酬结算系统 周一周日 新一年中首个完整的 7 天所在周 ❌ 不允许 1月1日若不在每周的起始日,则前几天算作上一年
广播日历 电视和广播行业的广告计费 周一 包含 1月1日 的那一周 ❌ 不允许 以周为绝对单位;每月必定由完整的 4周 或 5周 组成

日期与时间相关标准

流派 / 标准 核心特征 / 定义 主要适用领域 / 代表者 典型示例 / 备注
ISO 8601 最严谨的国际标准,严格规定分隔符 国际标准、数据库、系统底层 2026-08-19T19:48:00Z
T分界,Z表UTC)
RFC 3339 互联网工程任务组标准(ISO的子集) 现代 Web 开发、API 接口 允许用空格代替T,强制定时区:
2026-08-19 19:48:00 -07:00
RFC 2822 / 5322 互联网邮件时间格式,全文本表示 电子邮件、HTTP Header Wed, 19 Aug 2026 19:48:00 -0700
大端序 (Big-endian) 年-月-日 (YYYY-MM-DD) 中国、日韩、所有ISO规范系统 单位由大到小,最利于计算机文本排序
小端序 (Little-endian) 日-月-年 (DD-MM-YYYY) 多数欧洲国家、南美、大洋洲 单位由小到大,全球日常使用人数最多
中端序 (Middle-endian) 月-日-年 (MM-DD-YYYY) 美国 顺应英语口语,极易引起跨国歧义(如 05/04)
Unix / POSIX 起点:1970-01-01 UTC Java, Python, C/C++, Web 前后端 最泛用的时间戳,单位多为秒/毫秒
Windows / NTFS 起点:1601-01-01 UTC Windows 操作系统底层 1601年是格里高利历首个400年周期的开始
Apple / Cocoa 起点:2001-01-01 UTC macOS, iOS, Swift 苹果生态的独立纪元
NTP (网络时间) 起点:1900-01-01 UTC 网络时间同步协议 (NTP) 用于服务器之间的时间校准
GPS 时间 起点:1980-01-06 UTC 卫星导航定位系统 不计闰秒,不受地球自转变慢影响
UTC (协调世界时) 节拍等同原子钟,必要时插“闰秒” 现代社会的绝对时间基准 妥协了物理与天文的“完美流派”
TAI (国际原子时) 极度均匀的铯原子震荡频率 物理学、高精度科研 绝对均匀,从不妥协
UT1 (世界时) 基于地球自转的天文观测 天文学 不均匀,因为地球自转在逐渐变慢
GMT (格林尼治) 基于本初子午线的天文观测时间 日常沟通、英国本土 在严谨科学中已过时,常被当做 UTC 的俗称
格里高利历 (公历) 标准太阳历,设置闰年补差 全球通用的现代日历 平年365天,闰年366天
儒略历 (Julian) 公历的前身,因闰年规则粗糙有误差 东正教教会 导致东正教圣诞节落在公历的 1月7日
阴阳合历 (Lunisolar) 兼顾太阳周期与月相周期,设闰月 中国农历、希伯来历(犹太历) 既能反映月相,又不会脱离春夏秋冬
纯阴历 (Lunar) 仅按月相计月,不设闰月修正补差 伊斯兰教历法 (Hijri) 一年仅约354天,节日会在四季中循环游走