AI 代码生成的局限——有些代码 AI 就是写不好
AI 代码生成的局限——有些代码 AI 就是写不好
适读人群:使用 AI 辅助编程的工程师 | 阅读时长:约 10 分钟 | 核心价值:搞清楚 AI 代码生成的能力边界,用对地方
我有个习惯,每隔几个月会把同一批代码问题拿去问 Claude 和 GPT,看看它们的进步。
上个月做这个测试的时候,我在"擅长"这一侧发现了明显进步——特别是算法题,现在的模型比两年前强太多了。但在另一侧,有些问题两年前答得不好,现在还是答得不好,只是包装得更自信了。
这让我有点警惕。AI 写代码越来越流畅,但"流畅"不等于"正确"。区别是什么时候你能信任它,什么时候你必须自己动手——这个判断能力,才是现在工程师最核心的技能之一。
AI 写得好的代码类型
先说好消息。这些场景交给 AI,我基本不怎么改:
算法和数据结构实现
排序、搜索、图遍历、动态规划——这类问题有明确的正确答案,AI 训练数据里有大量例子,输出质量稳定。
# 让 AI 写一个 LRU Cache,质量很高
from collections import OrderedDict
class LRUCache:
def __init__(self, capacity: int):
self.capacity = capacity
self.cache = OrderedDict()
def get(self, key: int) -> int:
if key not in self.cache:
return -1
self.cache.move_to_end(key)
return self.cache[key]
def put(self, key: int, value: int) -> None:
if key in self.cache:
self.cache.move_to_end(key)
self.cache[key] = value
if len(self.cache) > self.capacity:
self.cache.popitem(last=False)这段代码 AI 写出来基本就是这样,我不需要改。
标准 CRUD 操作
给定 ORM 模型,让 AI 写增删改查,附带分页、过滤、排序——这类重复性工作 AI 做得又快又好。
# 告诉 AI:这是 User 模型,给我写 FastAPI 的 CRUD 接口
from fastapi import APIRouter, HTTPException, Query
from sqlalchemy.orm import Session
from typing import Optional
router = APIRouter(prefix="/users", tags=["users"])
@router.get("/")
def list_users(
page: int = Query(1, ge=1),
page_size: int = Query(20, ge=1, le=100),
search: Optional[str] = None,
db: Session = Depends(get_db)
):
query = db.query(User)
if search:
query = query.filter(User.name.ilike(f"%{search}%"))
total = query.count()
users = query.offset((page - 1) * page_size).limit(page_size).all()
return {
"total": total,
"page": page,
"data": users
}测试代码
单元测试和集成测试,AI 写得比大多数工程师还认真——它不会嫌麻烦,会老老实实覆盖边界条件。
# AI 写的测试代码,边界条件覆盖往往比人写的更全
import pytest
from unittest.mock import Mock, patch
class TestLRUCache:
def test_basic_get_put(self):
cache = LRUCache(2)
cache.put(1, 1)
cache.put(2, 2)
assert cache.get(1) == 1
def test_capacity_eviction(self):
cache = LRUCache(2)
cache.put(1, 1)
cache.put(2, 2)
cache.put(3, 3) # 应该驱逐 key=1
assert cache.get(1) == -1
assert cache.get(2) == 2
assert cache.get(3) == 3
def test_update_existing_key(self):
cache = LRUCache(2)
cache.put(1, 1)
cache.put(2, 2)
cache.put(1, 10) # 更新 key=1,它应该变成最近使用
cache.put(3, 3) # 应该驱逐 key=2,不是 key=1
assert cache.get(1) == 10
assert cache.get(2) == -1
def test_get_nonexistent_key(self):
cache = LRUCache(1)
assert cache.get(999) == -1
def test_single_capacity(self):
cache = LRUCache(1)
cache.put(1, 1)
cache.put(2, 2)
assert cache.get(1) == -1
assert cache.get(2) == 2格式转换和数据处理
JSON 转 CSV、XML 解析、正则表达式——这类有明确输入输出规范的代码,AI 信手拈来。
AI 容易出错的代码类型
现在说真正重要的部分。
复杂业务逻辑
这是最危险的地方。业务逻辑出错,AI 写的代码看起来完全合理,你不深看根本发现不了。
我给你看一个真实案例。我曾经让 AI 帮我写一段订单金额计算逻辑:
我的需求描述(过于简单):
计算订单总价,支持折扣码,VIP 用户打 9 折
AI 给出的代码:
def calculate_order_total(items: list, discount_code: str = None, is_vip: bool = False) -> float:
subtotal = sum(item['price'] * item['quantity'] for item in items)
discount = 0
if discount_code == "SAVE20":
discount = subtotal * 0.2
if is_vip:
subtotal = subtotal * 0.9
return subtotal - discount看起来没问题,对吧?但实际业务里有这些规则:
- VIP 折扣和折扣码不能叠加,取优惠更大的那个
- 折扣码有最低消费门槛(比如满 200 才能用)
- 某些商品类目不参与折扣
- 折扣计算后四舍五入到分
AI 写的代码把折扣叠加了,没有最低消费检查,没有品类过滤,四舍五入也没有。每一条都是真实的业务 Bug。
正确的代码应该是:
from decimal import Decimal, ROUND_HALF_UP
from dataclasses import dataclass
from typing import Optional
@dataclass
class OrderItem:
price: Decimal
quantity: int
category: str
discount_eligible: bool
DISCOUNT_CODES = {
"SAVE20": {"rate": Decimal("0.20"), "min_amount": Decimal("200"), "excludes": ["electronics"]}
}
def calculate_order_total(
items: list[OrderItem],
discount_code: Optional[str] = None,
is_vip: bool = False
) -> Decimal:
subtotal = sum(item.price * item.quantity for item in items)
# 计算各种可能的优惠
best_discount = Decimal("0")
# VIP 折扣:全场九折
if is_vip:
best_discount = subtotal * Decimal("0.10")
# 折扣码优惠(有门槛和品类限制)
if discount_code and discount_code in DISCOUNT_CODES:
code_config = DISCOUNT_CODES[discount_code]
# 检查最低消费
if subtotal >= code_config["min_amount"]:
# 只计算符合条件的商品
eligible_amount = sum(
item.price * item.quantity
for item in items
if item.discount_eligible and item.category not in code_config["excludes"]
)
code_discount = eligible_amount * code_config["rate"]
best_discount = max(best_discount, code_discount)
final_price = subtotal - best_discount
# 精确到分
return final_price.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)AI 没写错,但它不知道你的业务规则。你描述得越简单,它的代码就越危险。
性能敏感的代码
AI 能写出功能正确的代码,但它对性能的直觉很差。特别是在 Python 这类语言里,写法不同可能有 10-100 倍的性能差距。
# AI 很可能给你这个版本
def find_common_users(list1: list, list2: list) -> list:
result = []
for user in list1:
if user in list2: # 这里是 O(n) 的查找
result.append(user)
return result
# 整体 O(n²),数据量大了直接崩
# 正确版本
def find_common_users_fast(list1: list, list2: list) -> list:
set2 = set(list2) # O(n) 建 set
return [user for user in list1 if user in set2] # 每次查找 O(1)
# 整体 O(n)如果你的 list 只有几百条,AI 的版本没问题。如果有几十万条,AI 的版本直接挂掉。更麻烦的是,代码看起来完全正确,只有真正跑起来才发现问题。
数据库查询也一样。AI 生成的 ORM 代码经常产生 N+1 查询问题:
# AI 容易写出这种代码(N+1 问题)
def get_users_with_orders(db: Session) -> list:
users = db.query(User).all()
result = []
for user in users:
# 每个 user 都触发一次额外查询
orders = db.query(Order).filter(Order.user_id == user.id).all()
result.append({"user": user, "orders": orders})
return result
# 正确方式:JOIN 或 eager loading
def get_users_with_orders_correct(db: Session) -> list:
users = db.query(User).options(
joinedload(User.orders)
).all()
return [{"user": u, "orders": u.orders} for u in users]安全相关的代码
这是我最谨慎的地方。AI 写的安全相关代码,我会逐行 review,因为它的错误往往是隐蔽的。
常见问题:
SQL 注入风险(即使用了 ORM 也不是绝对安全):
# AI 有时候会给你这种"方便"的写法
def search_users(db: Session, query: str):
# 危险!直接插入用户输入
return db.execute(f"SELECT * FROM users WHERE name LIKE '%{query}%'")
# 正确的参数化查询
def search_users_safe(db: Session, query: str):
return db.execute(
text("SELECT * FROM users WHERE name LIKE :pattern"),
{"pattern": f"%{query}%"}
)时序攻击漏洞:
# AI 容易写的版本
def verify_token(user_token: str, stored_token: str) -> bool:
return user_token == stored_token # 字符串比较有时序漏洞
# 正确版本
import hmac
def verify_token_safe(user_token: str, stored_token: str) -> bool:
return hmac.compare_digest(user_token.encode(), stored_token.encode())JWT 验证不完整:
# AI 给的 JWT 验证经常遗漏关键检查
import jwt
# 错误:没有验证 algorithm,容易被 alg:none 攻击
def decode_token_wrong(token: str) -> dict:
return jwt.decode(token, SECRET_KEY, options={"verify_signature": True})
# 正确:明确指定允许的算法
def decode_token_correct(token: str) -> dict:
return jwt.decode(
token,
SECRET_KEY,
algorithms=["HS256"], # 明确限定算法
options={"require": ["exp", "iat"]} # 要求必要的 claim
)我实际怎么用 AI 写代码
整合下来,我现在的工作流是这样的:
- AI 负责: 样板代码、CRUD、测试用例、格式转换、算法实现
- 我负责: 业务逻辑设计、性能关键路径、安全敏感代码的最终 review
- AI 辅助我: 复杂业务逻辑的初稿(AI 写,我来逐行确认业务规则是否正确)
关键点不是"信任或不信任 AI",而是知道它在哪个维度可信。
算法正确性上,现在的 AI 相当可靠。业务规则上,它只知道你告诉它的。如果你的需求描述遗漏了一个条件,它的代码就会遗漏这个条件——而且代码跑起来完全没有报错。
这是 AI 代码生成现阶段最根本的局限:它不理解你的业务,它只能模式匹配你的描述。
