1-3-2-命名哲学
1.3.2 命名哲学:命名是小型哲学思考
引言
Phil Karlton 有句名言:
"计算机科学中只有两件难事:缓存失效和命名。"
为什么命名这么难?
因为命名是一个哲学问题——你需要理解一个事物的本质,然后用一个词或短语精确地表达它。
好的命名不仅仅是"听起来不错",而是:
- 准确反映事物的本质
- 符合读者的心智模型
- 在系统中保持一致
- 随时间推移仍然有意义
命名的本质:抽象的具体化
命名是把抽象的概念变成具体的符号。
# 抽象概念:一个保存用户信息的数据结构
# 具体化1
x = {...}
# 具体化2
data = {...}
# 具体化3
user_info = {...}
# 具体化4
user_profile = {...}
每一层具体化都在传达更多信息。
x:没有传达任何信息
data:传达了"这是数据"
user_info:传达了"这是用户的信息"
user_profile:传达了"这是用户的档案资料"
命名的层次
层次1:描述是什么(What)
# 差
a = 25
# 一般
number = 25
# 好
age = 25
# 更好
user_age_in_years = 25
层次2:描述做什么(Do)
# 差
def process(data): ...
# 一般
def handle(data): ...
# 好
def validate_user_input(data): ...
# 更好
def validate_and_sanitize_user_input(data): ...
层次3:揭示意图(Intent)
# 描述"做什么"
def filter_items(items, status):
return [item for item in items if item.status == status]
# 揭示"为什么"
def get_active_items(items):
"""获取所有活跃的项目(用于展示给用户)"""
return [item for item in items if item.status == 'active']
常见的命名反模式
反模式1:无意义的前缀/后缀
# 不好:无意义的前缀
myVariable = 10
theUser = get_user()
aList = []
# 不好:匈牙利命名法(在现代语言中)
strName = "Alice"
intAge = 25
boolIsActive = True
# 好:直接用有意义的名字
name = "Alice"
age = 25
is_active = True
例外:在特定上下文中有意义的前缀是可以的
# 好:区分原始值和处理后的值
raw_text = " Hello World "
cleaned_text = raw_text.strip()
# 好:区分不同类型的ID
user_id = 123
order_id = 456
反模式2:过于通用的名字
# 不好
def process(data):
...
def handle(input):
...
def do_something(x, y):
...
# 好
def validate_email(email_address):
...
def send_welcome_notification(new_user):
...
def calculate_shipping_cost(weight, distance):
...
反模式3:缩写和简写
# 不好
def calc_tot_prc(itms):
tot = 0
for i in itms:
tot += i.prc * i.qty
return tot
# 好
def calculate_total_price(items):
total = 0
for item in items:
total += item.price * item.quantity
return total
例外:广为人知的缩写是可以的
# 可以接受的缩写
html = "<div>...</div>"
json = {"key": "value"}
url = "https://example.com"
id = 123
max_size = 1024
min_value = 0
反模式4:单词拼写错误
# 不好
def send_notifaction(user): # typo: notifaction
...
def get_usr_permisions(user): # typo: permisions
...
# 好
def send_notification(user):
...
def get_user_permissions(user):
...
注意:拼写错误会传播,6个月后你可能忘了是哪个错误拼写。
反模式5:名字说谎
# 不好:名字和实际行为不符
def get_user(user_id):
user = db.query(User).get(user_id)
if not user:
# 名字说"get",但实际上会"create"
user = create_default_user(user_id)
return user
# 好:名字如实反映行为
def get_or_create_user(user_id):
user = db.query(User).get(user_id)
if not user:
user = create_default_user(user_id)
return user
# 或者分成两个函数
def get_user(user_id):
return db.query(User).get(user_id)
def ensure_user_exists(user_id):
user = get_user(user_id)
if not user:
user = create_default_user(user_id)
return user
命名的规则和模式
规则1:布尔值用 is/has/can/should
# 不好
user_active = True
user_permissions = True
user_delete = True
# 好
is_active = True
has_permissions = True
can_delete = True
should_notify = True
规则2:集合用复数
# 不好
user_list = [user1, user2]
active_user = [user1, user2] # 看起来像单个用户
# 好
users = [user1, user2]
active_users = [user1, user2]
规则3:函数用动词开头
# 不好
user_email(user)
user_validation(data)
# 好
send_user_email(user)
validate_user_data(data)
常见动词:
get_*: 获取(不修改)set_*: 设置create_*: 创建新对象delete_*: 删除update_*: 更新现有对象find_*: 查找(可能找不到)calculate_*: 计算validate_*: 验证send_*: 发送process_*: 处理
规则4:对称命名
# 不好
def open_connection(): ...
def terminate(): ...
# 好
def open_connection(): ...
def close_connection(): ...
# 不好
def start_server(): ...
def kill(): ...
# 好
def start_server(): ...
def stop_server(): ...
常见对称词:
open/closestart/stopbegin/endcreate/deleteadd/removeinsert/deletelock/unlockacquire/release
规则5:保持作用域一致的详细程度
# 局部变量:可以简短
def calculate_total(items):
total = 0 # 作用域小,可以简短
for item in items: # 循环变量可以简短
total += item.price
return total
# 全局变量/常量:必须详细
DATABASE_CONNECTION_POOL_SIZE = 10 # 全局作用域,必须清楚
# 类属性:中等详细
class Order:
status = 'pending' # 在类的上下文中,status 就够了
created_at = datetime.now()
命名的文化差异
Python 风格
# Snake case for variables and functions
user_name = "Alice"
def get_user_profile(): ...
# Pascal case for classes
class UserProfile: ...
# UPPER_CASE for constants
MAX_UPLOAD_SIZE = 1024
JavaScript 风格
// Camel case for variables and functions
const userName = "Alice";
function getUserProfile() { ... }
// Pascal case for classes
class UserProfile { ... }
// UPPER_CASE for constants
const MAX_UPLOAD_SIZE = 1024;
Go 风格
// Public (exported): starts with uppercase
func GetUserProfile() { ... }
var UserName string
// Private: starts with lowercase
func validateEmail() { ... }
var internalState int
在团队中保持统一比个人偏好更重要。
领域驱动的命名
使用业务领域的术语
# 不好:技术术语
def process_transaction(data):
record = DatabaseRecord(**data)
record.save()
# 好:业务术语
def place_order(order_details):
order = Order(**order_details)
order.save()
避免技术泄漏
# 不好:暴露实现细节
def get_user_from_redis_cache(user_id): ...
def save_to_postgres_database(data): ...
# 好:隐藏实现细节
def get_cached_user(user_id): ...
def save_user(user): ...
如果未来从 Redis 切换到 Memcached,第一种命名就需要改,第二种不需要。
重命名的勇气
何时应该重命名
- 名字不能准确反映功能(需求变更导致)
- 发现更好的术语
- 团队达成新的命名共识
# 旧代码
def send_email(user):
# 后来需求变了,不仅发邮件,还发短信
email_service.send(user.email)
sms_service.send(user.phone)
# 应该重命名
def send_notification(user):
email_service.send(user.email)
sms_service.send(user.phone)
如何安全重命名
- 使用 IDE 的重构功能(不是手动查找替换)
- 先写测试确保重命名不破坏功能
- 批量重命名,不要留下新旧名字混用的状态
- 更新文档和注释
对使用 AI 的程序员的建议
AI 生成的命名往往是"安全的"但不一定是"最好的"。
AI 命名的常见问题
# AI 可能生成
def process_data(data):
result = do_something(data)
return result
# 应该改成
def validate_user_registration(registration_form):
validation_result = check_all_required_fields(registration_form)
return validation_result
如何改进 AI 生成的命名
- 检查所有
data、result、item等通用名字 - 用业务术语替换技术术语
- 确保动词准确描述行为
❌ 不好的提示:
"写一个函数处理用户数据"
✅ 好的提示:
"写一个函数 validate_user_registration_form,它接收注册表单数据,
验证所有必填字段,返回验证结果(包含 is_valid 和 errors 列表)"
命名检查清单
完成代码后,检查每个名字:
变量名
函数名
类名
真实案例
案例1:Ruby on Rails 的命名约定
Rails 有严格的命名约定,让代码高度一致:
# 模型(单数)
class User < ApplicationRecord
end
# 表名(复数)
# users
# 控制器(复数)
class UsersController < ApplicationController
def index # GET /users
def show # GET /users/:id
def create # POST /users
def update # PUT /users/:id
def destroy # DELETE /users/:id
end
这种一致性让新人能快速理解代码结构。
案例2:Stripe API 的命名
Stripe 的 API 命名清晰且一致:
# 创建
stripe.Customer.create(email="user@example.com")
stripe.Charge.create(amount=1000, currency="usd")
# 获取
stripe.Customer.retrieve("cus_123")
stripe.Charge.retrieve("ch_123")
# 更新
stripe.Customer.modify("cus_123", email="new@example.com")
# 删除
stripe.Customer.delete("cus_123")
每个资源都使用相同的动词,降低了学习成本。
总结
命名的哲学:
- 命名是理解的体现——好的命名来自对事物本质的深刻理解
- 准确比简短更重要——
user_age_in_years比age好(如果精度重要) - 一致性是关键——在整个项目中保持命名风格统一
- 使用领域术语——让业务人员也能读懂代码
- 不要害怕重命名——发现更好的名字时,立即改
- AI 生成的命名需要人工审查——改成更精确的业务术语
记住:
你今天多花 30 秒想一个好名字,能为未来的维护者(包括你自己)节省 30 分钟的理解时间。
命名不是小事,而是每天都在进行的小型哲学思考。
好的命名让代码自解释,差的命名让代码需要注释,糟糕的命名让代码无法理解。

浙公网安备 33010602011771号