跳转到内容

常量与枚举管理规范

常量定义、枚举使用、魔法值治理


[Requirement] 常量必须使用 UPPER_SNAKE_CASE 命名,禁止在业务逻辑中直接硬编码字面量。

[Standard] 常量使用语言提供的不可变机制定义:Python 用模块级变量(约定大写),Java 用 static final,TypeScript 用 as const。

[Caution] 不要把”会随环境变化的值”(如数据库地址、API Key)当作常量,应走配置中心或环境变量。

示例:

# 正确
DEFAULT_PAGE_SIZE = 20
MAX_RETRY_COUNT = 3
HTTP_STATUS_OK = 200
 
def fetch_users(page: int = DEFAULT_PAGE_SIZE) -> list[User]:
    ...
类型说明示例
业务常量业务规则中的固定值ORDER_STATUS_PAID = 2
技术常量框架/协议相关固定值HTTP_TIMEOUT = 30
魔法值替换原本散落在代码中的字面量MAX_FILE_SIZE = 10 * 1024 * 1024

[Standard] 当一组值具有明确的固定集合且彼此互斥时,必须使用枚举而非字符串常量。

[Requirement] 状态机、类型标识、分类标签等场景优先使用枚举。

示例:

from enum import Enum
 
class OrderStatus(Enum):
    PENDING = "pending"
    PAID = "paid"
    SHIPPED = "shipped"
    CANCELLED = "cancelled"
 
def can_cancel(status: OrderStatus) -> bool:
    return status in (OrderStatus.PENDING, OrderStatus.PAID)

[Standard] 枚举值优先使用字符串(便于日志和调试),涉及存储或性能时使用整数。

[Caution] 枚举值一旦发布不应随意修改;如需变更,新增枚举项而非修改已有项的值。

[Suggestion] 为枚举添加业务语义方法,而不是在外部写 if/elif 链:

class OrderStatus(Enum):
    PENDING = "pending"
    PAID = "paid"
    SHIPPED = "shipped"
 
    @property
    def can_cancel(self) -> bool:
        return self in (OrderStatus.PENDING, OrderStatus.PAID)
 
    @property
    def display_name(self) -> str:
        names = {"pending": "待支付", "paid": "已支付", "shipped": "已发货"}
        return names[self.value]

魔法值是指代码中直接出现的、缺乏语义说明的字面量(数字、字符串)。

[Requirement] 以下情况禁止出现魔法值:

  • 业务状态码(如 status == 2)
  • 超时、重试、限制等配置值(如 timeout = 30)
  • 文件大小、数量限制等阈值

[Default] 0、1、-1、空字符串等极少数通用值可豁免,但建议加注释说明用途。

  1. 发现:代码扫描(如 ruff 的 PLR2004 规则)找出所有魔法值。
  2. 提取:替换为命名常量或枚举。
  3. 归类:按业务领域放入对应常量模块。

示例:

# 错误:魔法值
if order.status == 2:
    cancel(order)
 
# 正确:使用枚举
if order.status == OrderStatus.PAID:
    cancel(order)
# 错误:魔法值
if len(content) > 10485760:
    raise TooLargeError()
 
# 正确:命名常量
MAX_CONTENT_SIZE = 10 * 1024 * 1024  # 10 MB
if len(content) > MAX_CONTENT_SIZE:
    raise TooLargeError()

[Standard] 常量和枚举必须集中管理,不允许在业务文件中零散定义。

src/
constants/
__init__.py
common.py # 通用常量(HTTP 状态码、超时等)
business.py # 业务常量
enums/
__init__.py
order.py # 订单相关枚举
user.py # 用户相关枚举

[Caution] 避免创建一个”万能常量文件”(如 constants.py 放所有东西),应按领域拆分。

[Suggestion] 跨服务共享的常量应抽取到独立的公共包,各服务通过依赖引入,避免复制。


反模式示例问题
魔法数字if status == 3无法理解 3 的含义
魔法字符串if role == "admin"拼写错误不会被编译器发现
常量散落每个文件都定义 MAX_SIZE = 1024修改时容易遗漏
枚举当常量字典用STATUS_MAP = {1: "a", 2: "b"}没有类型安全,调用方可能传入非法值
硬编码配置db.connect("localhost", 3306)环境切换需改代码
枚举值随意变更把 PAID = 2 改成 PAID = 3历史数据与新枚举值不兼容