AI已经帮全球超过150万开发者写代码了。但奇怪的是,用了AI之后,一个新问题冒了出来:
代码变多了,质量变差了。
Copilot可以帮你写代码,但它写出来的代码——逻辑可能有漏洞、安全可能不过关、边界情况可能没处理。很多初级开发者看到代码"能跑",就以为代码"没问题",直接提交PR。
有一次,一位工程师看了一眼团队新人的Copilot生成代码,发现了整整三个隐藏的安全漏洞。
事后复盘,这位工程师说了一句让我印象很深的话:
"Copilot让写代码变快了,但它让审查代码这件事,变得比以前更重要了。"
这个故事说明了一个重要的真理:好的代码不是'能运行'的代码,而是'易维护'的代码。
而代码审查,就是发现这些隐藏问题的过程。
核心概念
代码审查(Code Review)是指由其他开发者检查代码的过程,目的是:
代码审查的六个维度:
生活化类比
想象你是一个建筑检查员,需要检查一栋新建的房子。
表面检查:房子看起来很漂亮,装修很豪华。
深度检查:
一个好的建筑检查员,不仅看表面,还要看内部。代码审查也是一样。
深度分析
代码审查实战检查清单
下面的清单浓缩了资深工程师审查代码时的核心思路,可直接复制到团队规范中使用:
✅ 检查清单一:功能正确性
def find_max(numbers): return numbers[0]def find_max(numbers): if not numbers: raise ValueError("列表不能为空") return max(numbers) # 用内置函数更简洁、更安全
✅ 检查清单二:安全性
def get_user_by_name(name): query = f"SELECT * FROM users WHERE name='{name}'" return db.execute(query)def get_user_by_name(name): query = "SELECT * FROM users WHERE name=?" return db.execute(query, (name,))def get_user_info(user): return { 'id': user.id, 'name': user.name, 'password_hash': user.password_hash, # 不应该暴露 'api_key': user.api_key # 不应该暴露 }def get_user_info(user): return { 'id': user.id, 'name': user.name, 'email': user.email }def read_file(filename): with open(filename, 'r') as f: # filename可能被注入 '../etc/passwd' return f.read()import osdef read_file(filename, allowed_dir='/safe/directory'): if '..' in filename or filename.startswith('/'): raise ValueError("非法文件名") full_path = os.path.join(allowed_dir, filename) if not os.path.abspath(full_path).startswith(os.path.abspath(allowed_dir)): raise ValueError("文件不在允许目录内") with open(full_path, 'r') as f: return f.read()
✅ 检查清单三:代码结构
def process_order(order_id):def process_order(order_id): order = fetch_order(order_id) validate_order(order) apply_discounts(order) send_notification(order) log_order(order) return orderdef calculate_price(qty, price): if qty > 100: return qty * price * 0.9 # 什么是0.9?打9折? elif qty > 50: return qty * price * 0.95BULK_DISCOUNT_THRESHOLD = 100BULK_DISCOUNT_RATE = 0.9MEDIUM_DISCOUNT_THRESHOLD = 50MEDIUM_DISCOUNT_RATE = 0.95def calculate_price(quantity, unit_price): if quantity > BULK_DISCOUNT_THRESHOLD: return quantity * unit_price * BULK_DISCOUNT_RATE elif quantity > MEDIUM_DISCOUNT_THRESHOLD: return quantity * unit_price * MEDIUM_DISCOUNT_RATE
✅ 检查清单四:性能
def get_users_with_posts(): users = db.query("SELECT * FROM users") result = [] for user in users: posts = db.query(f"SELECT * FROM posts WHERE user_id={user.id}") result.append({'user': user, 'posts': posts}) return resultdef get_users_with_posts(): return db.query(""" SELECT u.*, p.* FROM users u LEFT JOIN posts p ON u.id = p.user_id """)def calculate_stats(data): return { 'sum': sum(data), # 遍历1次 'mean': sum(data) / len(data), # 遍历2次 'max': max(data), # 遍历3次 'min': min(data), # 遍历4次 }def calculate_stats(data): if not data: raise ValueError("数据不能为空") total = max_val = data[0] min_val = data[0] for v in data[1:]: total += v if v > max_val: max_val = v if v < min_val: min_val = v return { 'sum': total, 'mean': total / len(data), 'max': max_val, 'min': min_val }
✅ 检查清单五:可维护性
def process(x): if x < 0: raise ValueError("参数错误") # 完全不知道哪里错def process(quantity): if quantity < 0: raise ValueError(f"数量不能为负数,当前值: {quantity}")
代码审查的最佳实践
class CodeReviewChecklist: """ 代码审查检查清单 建议在每次PR审查时,对照这份清单逐项检查 """ def __init__(self): self.checks = { '功能正确性': [ '代码是否实现了需求规格?', '是否处理了空值、零值、负数等边界情况?', '异常情况(网络超时/数据库断开)是否被捕获?', '是否有逻辑错误?' ], '代码结构': [ '函数是否遵循单一职责原则(<50行)?', '是否有重复代码(DRY原则)?', '变量名、函数名是否自解释?', '是否有不必要的复杂性?' ], '安全性': [ '是否存在SQL注入风险?', '用户输入是否经过验证和过滤?', '敏感信息(密码/Token)是否被暴露?', '文件操作是否有路径遍历风险?' ], '性能': [ '是否存在N+1查询问题?', '是否有不必要的循环或重复计算?', '网络/IO操作是否考虑异步?', '数据量大的场景是否做了分页或流式处理?' ], '可维护性': [ '注释是否解释了"为什么"而非"做什么"?', '错误信息是否清晰能定位问题?', '是否遵循团队编码规范?', '是否更新了相关文档?' ], '测试覆盖': [ '是否添加了单元测试?', '边界条件和异常分支是否被测试覆盖?', '测试是否可独立运行、互不依赖?' ] } def print_checklist(self): print("=" * 50) print(" 代码审查检查清单") print("=" * 50) for category, items in self.checks.items(): print(f"\n【{category}】") for i, item in enumerate(items, 1): print(f" □ {item}") print("\n" + "=" * 50)checklist = CodeReviewChecklist()checklist.print_checklist()
代码审查教会我们一个深刻的人生道理:没有人能写出完美的代码,但集体的智慧可以接近完美。
一个人的视角是有限的。你可能看不到自己代码中的问题,但别人能看到。这不是因为别人更聪明,而是因为不同的视角能发现不同的问题。
Copilot时代,这个道理更加深刻:AI生成的代码,AI自己不会审查,所以人的审查能力变得更加珍贵。
这和人生一样。我们都有自己的盲点。有时候,我们需要朋友、家人、甚至陌生人的意见,才能看清自己。
真正的成长,来自于接受批评和建议。
行动框架
五步建立你的代码审查流程
第一步:建立审查标准(今天就能做)
第二步:选择合适的工具(10分钟配置)
- GitHub → Settings → Branches → 开启Protected Branches
第三步:自动化部分审查(减少人工负担)
第四步:建立审查文化(最重要也最难)
第五步:定期回顾,持续改进