在电影片场,一个优秀的导演是如何工作的?
他会跟摄影指导说:"我希望这个镜头能传达出主角内心的孤独和绝望感,我们用冷色调,构图要空旷一些。" (这是顶层意图和艺术方向)
然后,摄影指导会把这个抽象的"意图"翻译成具体的执行方案,告诉灯光师:"我们需要一个顶光,用低色温的光源,把周围环境的亮度降下来,人物面部的阴影要硬一些。" (这是中层技术方案)
最后,灯光师会指挥工作人员:"把那盏2K的菲涅尔透镜灯吊起来,装上1/4的蓝色色纸,用黑旗把左边的光挡掉。" (这是底层具体操作)
这是一个权责清晰、沟通高效的体系。每一层的人都专注于自己该干的事。那么能够营造出最终成功的作品。

现在,想象一个糟糕的、爱抢活的导演。他会在片场大喊:
"我要孤独感!小王,去,把那盏2K的菲涅尔灯给我装上1/4的蓝色色纸!......不对,咱们这个镜头的构图是不是太空了?演员,你的情绪再绝望一点!"
当导演本人直接跳下去指挥灯光师助理"换色纸"时,会打乱了整个创作的"抽象层次"。他的思维在"最终艺术效果"和"具体灯具型号"之间来回跳跃,导致的结果就是:在场的所有人(包括他自己)都感到混乱,无法集中精力完成自己层级的本职工作,最终的艺术效果也必然大打折扣。
软件工程层面的抽象层次混乱
最近修改codebase中的一些代码,注意到有很多代码存在多个抽象层次混用的状况,需要修改的Bug正好和该问题有关,不贴原代码,通过AI,创造出风格类似的代码,如下:
def register_user(username, email, password, user_type):
# 第1层:业务逻辑层 - 业务规则判断
if user_type == 'premium':
if len(username) < 6:
return {'success': False, 'error': 'Premium用户名至少6位'}
# 业务规则:premium用户需要特殊验证
special_validation_needed = True
else:
special_validation_needed = False
# 第2层:数据处理层 - 数据验证和转换
# 邮箱格式验证
if not re.match(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', email):
return {'success': False, 'error': '邮箱格式不正确'}
# 密码强度检查
if len(password) < 8 or not re.search(r'[A-Z]', password) or not re.search(r'[0-9]', password):
return {'success': False, 'error': '密码必须至少8位且包含大写字母和数字'}
# 密码加密
password_hash = hashlib.sha256(password.encode()).hexdigest()
# 第3层:底层技术细节 - 数据库操作
try:
# 直接在业务函数中处理数据库连接
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
# 检查用户是否已存在
cursor.execute("SELECT id FROM users WHERE username = ? OR email = ?",
(username, email))
if cursor.fetchone():
conn.close()
return {'success': False, 'error': '用户名或邮箱已存在'}
# 插入用户数据
cursor.execute("""
INSERT INTO users (username, email, password_hash, user_type, created_at)
VALUES (?, ?, ?, ?, ?)
""", (username, email, password_hash, user_type, datetime.now()))
user_id = cursor.lastrowid
conn.commit()
conn.close()
except sqlite3.Error as e:
# 业务层被迫处理数据库技术细节
return {'success': False, 'error': f'数据库错误: {str(e)}'}
# 第3层:底层技术细节 - 邮件发送
try:
# 业务函数直接处理SMTP配置
smtp_server = smtplib.SMTP('smtp.gmail.com', 587)
smtp_server.starttls()
smtp_server.login('your_email@gmail.com', 'your_password')
# 根据用户类型发送不同邮件(业务逻辑与技术细节混杂)
if user_type == 'premium':
subject = "欢迎成为Premium用户!"
body = f"亲爱的 {username},感谢您成为我们的Premium用户..."
else:
subject = "欢迎注册!"
body = f"亲爱的 {username},感谢您的注册..."
msg = MIMEText(body)
msg['Subject'] = subject
msg['From'] = 'your_email@gmail.com'
msg['To'] = email
smtp_server.send_message(msg)
smtp_server.quit()
except smtplib.SMTPException as e:
# 业务层被迫处理邮件服务器技术细节
# 这里还要考虑:邮件发送失败了,要不要回滚数据库?
pass # 先忽略邮件发送失败
# 第1层:业务逻辑层 - 返回业务结果
return {
'success': True,
'user_id': user_id,
'message': f'{"Premium" if user_type == "premium" else "普通"}用户注册成功'
整个代码从抽象角度,可以看做是一个业务单元的完整操作,示例代码是一次用户注册:
- 输入验证与规则检查 - 根据用户类型执行不同的业务规则校验,对邮箱格式、密码强度等关键数据进行合法性验证。
- 数据转换与持久化 - 将原始密码转换为哈希值,检查用户唯一性约束,将用户信息存储到数据库中获取用户ID。
- 外部服务交互 - 根据用户类型构造相应的欢迎邮件内容,通过SMTP服务发送通知邮件完成用户体验闭环。
- 结果封装与返回 - 将操作结果、用户ID、状态信息统一封装成标准响应格式,为上层调用提供清晰的执行反馈。
可以看到,该函数的功能横跨了三个抽象层面,从最上层的注册用户业务逻辑,到对于用户对象的处,再到非常细节的服务交互,数据验证以及SQL处理,需要横跨多个抽象层级。
这种体感,在阅读该代码时,会感觉抽象层次非常混乱,考虑业务逻辑的同时,还需要看到密码长度规则的细节,如果这类代码读的多,很容易迷失在细节中,总结来看,会有下面问题:
- 代码可读性极差,难以理解("认知过载"):大脑必须在不同的抽象思维层面之间频繁切换,思维需要跨层次, 这种感觉很拧巴, 就像你想规划一个旅行,规划行程的过程中,同时考虑是不是要提前值机,选哪个座位,而不是更high level的去哪玩。
- 代码难以维护和修改:在一个混合了不同抽象层次的"大泥球"函数中,各个部分紧密地耦合在一起。任何微小的改动都可能引发意想不到的连锁反应。
- 代码难以测试:函数不仅圈复杂度高,同时又存在很多外部依赖,单元测试会非常困难。
- 代码复用性极低:整个代码仅适用于单一流程(用户注册),其他模块想要引用,就会陷入到香蕉大猩猩问题 :你想要一个香蕉,但你得到的是一个大猩猩拿着香蕉,以及整个丛林。
单一抽象层次原则 (Single Level of Abstraction Principle, SLAP)
如何解决?Uncle Bob在Clean Code中提出过一个SLAP原则,简单来说就是在一个函数(或者方法),所有代码语句都应该在同一个"抽象级别"上。在我看来类的也应该遵循该原则。
在开头的故事中,导演、摄影指导、灯光师所需要面对的问题分别位于三个层次,如下图:

每个角色仅考虑当前抽象层次的问题,使得分工协作效率大增。
题外话,软件工程还有一个说法,如果希望做好当前层级的事,需要对下一层级也有了解(例如,写SQL可以不懂优化器,但懂了优化器可以写出更好的SQL)。所以希望用AI写出好的代码,AI下层的软件工程理论变的更加重要,否则生成的代码对于大型项目可能是维护性灾难。
因此回到开头的函数register_user,按开头电影导演故事的抽象层次拆分,分为3部分
业务协调层 - 最高抽象层次
这一层是整个业务流程的"导演"或"总指挥"。它的核心职责是编排和协调,而非执行。就像导演告诉摄影指导"我需要孤独感",register_user函数通过调用User.create, user.save和_send_welcome_email等一系列高层次的指令,清晰地描述了"用户注册"这个业务故事的"What",而不是"How"。
# ============================================================================
# 第1层:业务协调层 - 最高抽象层次
# ============================================================================
def register_user(username: str, email: str, password: str, user_type: str) -> Dict[str, Any]:
"""用户注册主流程 - 业务协调,最高抽象层次"""
# 创建用户(内部会验证)
user_result = User.create(username, email, password, user_type)
if not user_result.success:
return {'success': False, 'error': user_result.error}
user = user_result.user
# 保存用户
save_result = user.save()
if not save_result.success:
return {'success': False, 'error': save_result.error}
# 发送欢迎邮件
_send_welcome_email(user)
# 返回成功结果
return _create_success_response(user)
def _send_welcome_email(user: 'User') -> None:
"""发送欢迎邮件 - 协调层职责"""
try:
email_content = _get_welcome_email_content(user)
email_sender = EmailSender()
email_sender.send(user.email, email_content)
except Exception:
# 邮件发送失败不影响注册
pass
def _get_welcome_email_content(user: 'User') -> Dict[str, str]:
"""获取欢迎邮件内容"""
return user.get_welcome_email_content()
def _create_success_response(user: 'User') -> Dict[str, Any]:
"""创建成功响应"""
user_type_display = "Premium" if user.user_type == "premium" else "普通"
return {
'success': True,
'user_id': user.user_id,
'message': f'{user_type_display}用户注册成功'
}
业务对象层 - 中抽象层次,健壮的业务对象
这一层是业务逻辑的"核心承载者",如同电影拍摄中的"摄影指导",负责将导演的抽象意图转化为具体可执行的"拍摄方案"。在这里,核心是User这个业务对象。
它不再是一个简单的贫血数据类,而是一个健壮的、自洽的实体。它封装了与"用户"相关的所有业务规则和数据操作:
# ============================================================================
# 第2层:业务对象层 - 中抽象层次,健壮的业务对象
# ============================================================================
@dataclass
class UserCreationResult:
"""用户创建结果"""
success: bool
user: Optional['User'] = None
error: Optional[str] = None
@dataclass
class SaveResult:
"""保存结果"""
success: bool
user_id: Optional[int] = None
error: Optional[str] = None
class User:
"""用户 - 核心业务对象,内部验证保证健壮性"""
def __init__(self, username: str, email: str, password_hash: str, user_type: str):
self.username = username
self.email = email
self.password_hash = password_hash
self.user_type = user_type
self.user_id = None
self.created_at = datetime.now()
@classmethod
def create(cls, username: str, email: str, password: str, user_type: str) -> UserCreationResult:
"""创建用户 - 内部验证保证健壮性"""
# 验证用户类型
if user_type not in ['regular', 'premium']:
return UserCreationResult(success=False, error='无效的用户类型')
# 验证用户名
username_error = cls._validate_username(username, user_type)
if username_error:
return UserCreationResult(success=False, error=username_error)
# 验证邮箱
email_error = cls._validate_email(email)
if email_error:
return UserCreationResult(success=False, error=email_error)
# 验证密码
password_error = cls._validate_password(password)
if password_error:
return UserCreationResult(success=False, error=password_error)
# 检查用户是否已存在
if UserRepository().exists(username, email):
return UserCreationResult(success=False, error='用户名或邮箱已存在')
# 创建用户对象
password_hash = cls._hash_password(password)
user = cls(username, email, password_hash, user_type)
return UserCreationResult(success=True, user=user)
def save(self) -> SaveResult:
"""保存用户到数据库"""
try:
repository = UserRepository()
self.user_id = repository.add(self)
return SaveResult(success=True, user_id=self.user_id)
except Exception as e:
return SaveResult(success=False, error=f'保存用户失败: {str(e)}')
@staticmethod
def _validate_username(username: str, user_type: str) -> Optional[str]:
"""验证用户名"""
if not username or not username.strip():
return '用户名不能为空'
if user_type == 'premium' and len(username) < 6:
return 'Premium用户名至少6位'
return None
@staticmethod
def _validate_email(email: str) -> Optional[str]:
"""验证邮箱"""
if not email or not email.strip():
return '邮箱不能为空'
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
if not re.match(pattern, email):
return '邮箱格式不正确'
return None
@staticmethod
def _validate_password(password: str) -> Optional[str]:
"""验证密码"""
if not password:
return '密码不能为空'
if len(password) < 8:
return '密码必须至少8位'
if not re.search(r'[A-Z]', password):
return '密码必须包含大写字母'
if not re.search(r'[0-9]', password):
return '密码必须包含数字'
return None
def get_welcome_email_content(self) -> Dict[str, str]:
"""获取欢迎邮件内容"""
if self.user_type == 'premium':
return {
'subject': '欢迎成为Premium用户!',
'body': f'亲爱的 {self.username},感谢您成为我们的Premium用户...'
}
else:
return {
'subject': '欢迎注册!',
'body': f'亲爱的 {self.username},感谢您的注册...'
}
@staticmethod
def _hash_password(password: str) -> str:
"""生成密码哈希"""
return hashlib.sha256(password.encode()).hexdigest()
基础设施层 - 最低抽象层次,纯技术实现
这一层是整个体系的"灯光师"和"场务",负责所有具体的"脏活累活"。它包含了与外部世界(如数据库、文件系统、邮件服务器等)打交道的所有技术实现。
============================================================================
# 第3层:基础设施层 - 最低抽象层次,纯技术实现
# ============================================================================
class UserRepository:
"""用户仓储 - 业务场景的数据访问"""
def __init__(self):
self.db_path = 'users.db'
def exists(self, username: str, email: str) -> bool:
"""检查用户是否存在"""
try:
with self._connect() as conn:
cursor = conn.cursor()
cursor.execute(
"SELECT id FROM users WHERE username = ? OR email = ?",
(username, email)
)
return cursor.fetchone() is not None
except Exception:
return False # 数据库错误时保守处理
def add(self, user: User) -> int:
"""添加用户记录"""
with self._connect() as conn:
cursor = conn.cursor()
cursor.execute("""
INSERT INTO users (username, email, password_hash, user_type, created_at)
VALUES (?, ?, ?, ?, ?)
""", (user.username, user.email, user.password_hash,
user.user_type, user.created_at))
return cursor.lastrowid
def _connect(self):
"""创建数据库连接"""
return sqlite3.connect(self.db_path)
class EmailSender:
"""邮件发送器 - 纯技术实现,不包含业务逻辑"""
def __init__(self):
self.smtp_host = 'smtp.gmail.com'
self.smtp_port = 587
self.username = 'your_email@gmail.com'
self.password = 'your_password'
self.from_email = 'your_email@gmail.com'
def send(self, to_email: str, content: Dict[str, str]) -> None:
"""发送邮件"""
if not to_email or not content:
raise ValueError("邮件地址和内容不能为空")
message = self._create_message(to_email, content)
with self._connect() as smtp:
smtp.send_message(message)
def _create_message(self, to_email: str, content: Dict[str, str]) -> MIMEText:
"""创建邮件消息"""
msg = MIMEText(content.get('body', ''))
msg['Subject'] = content.get('subject', '')
msg['From'] = self.from_email
msg['To'] = to_email
return msg
def _connect(self):
"""创建SMTP连接"""
smtp = smtplib.SMTP(self.smtp_host, self.smtp_port)
smtp.starttls()
smtp.login(self.username, self.password)
return smtp
整个实现的架构如图:

小结
就像一个好导演绝不会亲自去调灯光色纸一样,好的代码也应该各司其职、层次分明。当你的函数既要考虑"用户注册的业务逻辑",又要纠结"SMTP服务器配置"时,你就成了那个"爱抢活的导演"------看似很忙很全能,实际上把整个剧组都搞得一团糟。
这 个问题在AI时代变得更加微妙。AI擅长生成局部完美的代码片段,就像一个技艺精湛但缺乏大局观的"万能助理"------它能帮你写出完美的SMTP配置,也能生成漂亮的密码验证逻辑,但它不会主动告诉你"这些东西不应该混在一个函数里"。AI越强大,开发者的架构思维就越重要
在AI可以秒生代码的今天,真正的价值不在于写得多快,而在于想得多清楚------毕竟,没有人希望维护一个由AI生成的"意大利面条式巨无霸函数",那种感觉就像拿到了一个大猩猩、香蕉和整个丛林的打包组合...而你只是想吃个香蕉。