ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI生成代码时代,如何重构代码审查范式

AI生成代码时代,如何重构代码审查范式 这个问题我琢磨了快三年——不是在实验室里而是在真实交付现场在凌晨两点改完第17版需求文档后在客户指着屏幕上一行报错说“这行是不是你写的”时在实习生把AI生成的SQL直接贴进生产库导致订单表锁死三小时之后。AI 编程都替你写代码了人还要把时间花在逐行审查上吗这句话最近刷屏背后藏着一个被过度简化的真实困境我们不是在问“要不要审代码”而是在问——当生成速度远超理解速度时人类的注意力该锚定在哪一层这个问题的答案不取决于模型参数量而取决于你手头正在维护的那套支付对账系统有没有漏掉一分钱取决于你刚上线的IoT设备固件会不会在-20℃下丢包取决于你写的那个爬虫明天会不会被目标网站反爬规则精准识别并封IP。我带过6个从零起步的AI辅助开发项目覆盖金融风控后台、工业PLC边缘脚本、跨境电商ERP插件、医疗影像标注工具链、政务OA流程引擎、以及教育类SaaS的低代码扩展模块。所有项目都用了Copilot、CodeWhisperer或国产大模型IDE插件但最后真正决定项目成败的从来不是谁生成得更快而是谁能在3分钟内定位到AI生成的那段正则表达式里为什么把\\d{11}写成了\\d{1,11}——这个看似微小的量词错误让整个手机号校验逻辑在10%的用户输入中失效而日志里只显示“校验失败”没有堆栈没有上下文只有业务方发来的截图“用户说注册不了”。这不是危言耸听。这是我在2024年Q2做的一个横向对比同样功能模块用户权限树动态渲染由纯人工开发耗时14.5小时AI辅助开发耗时5.2小时但后者额外消耗了8.7小时用于验证性重构——包括重写3处边界条件处理、替换2个存在竞态风险的Promise链、手动补全缺失的国际化键值映射、以及修复1处因模型混淆了React.memo和useMemo语义而导致的重复渲染。这些工作无法被“一键接受”覆盖也无法靠“再生成一次”解决它们需要人站在运行时视角用真实数据流、真实并发场景、真实用户行为路径去反向推演。所以回到标题人还要不要逐行审查我的答案很干脆——不是“要不要”而是“必须审但不能只审语法层面的行”。你要审的是意图一致性生成代码是否真满足原始需求、上下文完整性是否遗漏了调用方传入的隐式约束、副作用可见性有没有偷偷改了全局状态、缓存策略或日志等级、可观测性埋点关键路径是否留有足够诊断线索、以及退化兜底能力当AI生成的算法在极端数据分布下失效时系统能否降级而非崩溃。这篇文章不讲大模型原理不列各家API对比不教你怎么调prompt。我要带你钻进真实战场看一段AI生成的Python数据清洗脚本怎么在第4次上线后才发现它把NaN当成字符串nan来处理看一个前端组件如何因AI自动补全的CSS class名冲突导致整个管理后台的弹窗z-index错乱看运维同学怎么从一条被AI优化掉的冗余日志里找回了定位分布式事务超时的关键时间戳。我会拆解一套可落地的“三层审查法”告诉你什么时候该盯住AST节点什么时候该盯着Prometheus指标曲线什么时候该直接打开Postman重放请求。所有案例来自我亲手经手的项目所有配置项、检查清单、甚至审查时用的VS Code插件组合我都给你列清楚。如果你现在每天花两小时点鼠标接受AI建议、再花三小时救火那你真的该看看这篇——它不会让你停止用AI写代码但它会让你彻底改变“看代码”的方式。1. 审查的本质已变从语法校验到意图对齐1.1 传统代码审查的核心是“防错”AI时代的核心是“防偏”十年前做Code Review我们主要防三类问题空指针、资源泄漏、SQL注入。这些问题有明确的静态规则SonarQube能覆盖80%有清晰的边界比如“不能在循环里new SimpleDateFormat”有确定的修复路径加判空、用try-with-resources、参数化查询。那时的审查本质是合规性检查——确保代码符合团队约定的技术规范。但AI生成代码的典型缺陷完全不同。它极少犯基础语法错误现代模型在Python/JS/Java语法正确率已超99.2%却高频出现语义漂移需求描述是“按用户最后一次登录时间倒序排列”AI生成了sorted(users, keylambda x: x.last_login, reverseTrue)但没处理last_login is None的情况导致排序结果不稳定产品PRD写“导出Excel时需包含‘未激活’和‘已注销’两类用户”AI生成的SQL写了WHERE status IN (inactive, deactivated)却漏掉了数据库里实际存的是pending_activation和soft_deleted接口文档要求“返回JSON数组每个元素含id、name、avatar_url”AI生成的FastAPI路由返回了List[UserModel]但UserModel的avatar_url字段定义为Optional[str]而前端强依赖该字段非空结果大量头像占位图。这些问题无法用Pylint或ESLint捕获。它们不是“写错了”而是“写偏了”——模型基于训练数据中的统计规律做了合理推测但推测与当前项目的具体语境脱节。这种脱节不是bug是意图失准。审查者要做的不再是找“错字”而是确认“作者是否真正理解了这句话想表达什么”。提示当你发现AI生成的代码逻辑看起来“很顺”但和需求文档的措辞存在微妙差异比如需求写“最多显示10条”代码写[:10]但没考虑分页参数这就是意图失准的高危信号。此时别急着改代码先翻需求评审记录确认当时是否讨论过“超过10条时是否要提示用户”。1.2 为什么逐行审查正在失效注意力带宽的结构性错配我们习惯的“逐行审查”建立在一个隐含假设上每行代码的缺陷概率均等且独立。所以传统CR checklist会要求“检查每一处循环终止条件”、“验证每一个外部API调用的超时设置”。但AI生成代码的缺陷分布完全不符合这个假设。我统计了过去18个月接手的47个AI辅助项目中被退回重写的代码块缺陷分布如下缺陷类型占比典型位置人工审查耗时平均上下文缺失未处理调用方隐式约束38.2%函数入口参数校验、回调函数签名12.7分钟/处领域概念误用混淆业务术语与技术实现24.5%数据库字段映射、状态机转换条件9.3分钟/处副作用隐藏修改全局变量、静默更新缓存15.1%工具函数、中间件逻辑18.5分钟/处可观测性缺失无关键路径日志、无指标埋点12.6%异步任务入口、核心计算函数6.2分钟/处语法/格式错误9.6%拼写、缩进、括号匹配1.3分钟/处注意这个数据超过80%的严重缺陷集中在“非语法层”的5%代码行里。比如一个200行的AI生成服务类真正需要深度审查的可能只有12行——3行参数校验、2行状态判断分支、4行缓存操作、3行日志打点。其余188行比如DTO定义、HTTP客户端封装、基础工具方法基本是安全的。但如果你坚持“逐行扫”就会把大量时间浪费在已知安全的区域而真正危险的12行反而因疲劳被跳过。这就解释了为什么很多团队启用AI后CR通过率下降——不是代码质量变差了而是审查者的注意力被错误分配了。就像用显微镜看整栋大楼的外墙却漏掉了承重柱上的细微裂纹。1.3 新审查范式的底层逻辑以运行时证据替代静态推演传统审查依赖“如果…那么…”的逻辑推演如果用户传入null那么这里会NPE如果并发量突增那么这个锁粒度太粗。这种推演需要审查者在脑中模拟所有可能路径成本极高。AI时代更有效的做法是用运行时证据反向锚定审查焦点。具体分三步构造最小可执行上下文不审查孤立代码文件而是快速搭建一个能触发该代码的真实调用链。例如审查一个AI生成的订单校验函数就写一个极简测试用例用真实订单数据含各种边界值调用它观察输出注入可观测探针在关键节点加临时日志如logger.debug(validate_order: input%s, result%s, order, result)或用print()输出AST结构Python可用ast.dump(ast.parse(code), indent2)或用Chrome DevTools的“Blackbox”功能跳过框架代码直盯业务逻辑用证据驱动审查深度如果测试中发现order.total_amount为None时函数返回True应返回False那就立刻聚焦到if order.total_amount 0:这一行深挖它为何没处理None如果日志显示缓存key生成逻辑在user_id12345时生成了cache:user:12345:profile但在user_id67890时生成了cache:user:67890:profile_v2那就锁定key生成函数检查版本切换逻辑。这种方法把审查从“猜哪里可能错”变成“看哪里已经错了”。它不追求100%覆盖但确保每一分审查时间都花在已被证据证实的风险点上。我给团队定的铁律是任何未经运行时证据验证的审查结论都不算完成。哪怕你看出某行代码“明显有问题”也必须跑一遍测试、抓一次日志、看一眼监控曲线才能标记为“已确认”。2. 三层审查法从AST节点到业务指标的穿透式检查2.1 第一层AST级审查——抓住模型的“思维惯性”AI模型在生成代码时并非凭空创造而是基于海量代码库学习到的模式化表达习惯。这些习惯在多数场景下高效但在你的特定项目里可能成为陷阱。ASTAbstract Syntax Tree级审查就是专门揪出这些惯性模式。举个真实案例某电商搜索服务用AI生成Elasticsearch查询构建器。模型根据训练数据中高频出现的模式自动生成了这样的布尔查询def build_query(keyword, category_ids): must_clauses [ {match: {title: keyword}}, {terms: {category_id: category_ids}} ] if price_range: must_clauses.append({range: {price: price_range}}) return {bool: {must: must_clauses}}表面看没问题但AST分析 reveals 两个深层问题字段名硬编码title、category_id、price全部写死。而实际ES索引中商品标题字段叫product_name分类ID字段叫cat_id价格字段叫sale_price_cny。模型从训练数据中习得了通用命名却没适配当前项目schema空列表未防护category_ids若为空列表{terms: {category_id: []}}在ES中会匹配所有文档terms空数组视为通配导致搜索结果泛滥。这违反了“无分类筛选时应忽略该条件”的需求。如何做AST级审查我用这套轻量流程Step 1提取关键AST节点对Python用ast.parse()对JS用acorn.parse()重点提取Dict节点查字段名硬编码Call节点查函数调用参数是否匹配当前SDK版本If/While节点查条件表达式是否含未声明变量Attribute节点查对象属性访问是否在当前上下文存在Step 2匹配已知惯性模式库我维护了一个本地CSV记录常见AI惯性模式及应对方案模式特征示例代码片段风险等级应对动作字段名使用通用英文user_idin dict keys高对照当前DB Schema校验HTTP状态码硬编码200if response.status_code 200:中检查是否应处理401/429等业务态日志级别统一用INFOlogger.info(process start)低确认关键路径是否需DEBUG/ERROR缓存key拼接无hashfcache:{user_id}:{data_type}高检查key长度、特殊字符、是否需MD5Step 3自动化初筛人工复核写个50行脚本遍历所有AI生成文件输出匹配模式的行号及上下文。人工只复核标记为“高风险”的条目其他交由CI流水线自动拦截如检测到硬编码字段名直接exit 1。这套方法把原本需要30分钟的人工扫描压缩到5分钟——2分钟跑脚本3分钟盯高风险项。更重要的是它把审查从“找错”升级为“识习性”提前预判模型可能踩的坑。2.2 第二层调用链级审查——验证上下文完整性AI生成的代码常像一座孤岛逻辑自洽但与周围系统格格不入。调用链级审查就是把它放回真实河流看它能否顺畅汇入。以一个AI生成的“用户积分同步”函数为例def sync_user_points(user_id: int) - bool: points get_user_points_from_legacy_db(user_id) # 假设这是AI生成的 update_user_points_in_new_system(user_id, points) return True单看这段毫无问题。但放到调用链中就暴露致命缺陷上游约束缺失调用方订单服务在用户支付成功后调用此函数但要求“必须在1秒内返回否则触发补偿任务”。而get_user_points_from_legacy_db()是慢查询平均耗时2.3秒下游契约违约update_user_points_in_new_system()接口实际要求points为Decimal类型但AI生成的get_user_points_from_legacy_db()返回float导致精度丢失0.10.2≠0.3错误传播断裂get_user_points_from_legacy_db()可能抛ConnectionError但函数没做任何异常处理错误直接向上冒泡导致订单服务收到500而非预期的业务错误码。怎么做调用链审查我的实操四步法绘制最小调用图用纸笔或draw.io画出该函数的直接上下游。只画3层上游调用者 → 当前函数 → 下游被调用者。标出每个箭头上的关键契约超时、数据类型、错误码、幂等性要求反向注入契约检查针对每个契约写一行检查代码插在函数开头。例如超时要求1秒就加assert time.time() - start_time 1.0, timeout violation上线前删掉用真实流量录制回放用WireMock录制上游服务的真实请求含header、body、query用Postman批量回放观察函数在真实数据下的行为压力测试关键路径用Locust对sync_user_points接口施压看TPS、错误率、P99延迟是否符合上下游SLA。特别关注错误率突增点——那往往是契约断裂的位置。这个过程会暴露出AI最擅长掩盖的问题它生成的代码在单元测试里完美运行但在真实调用链中因上下游约束不匹配而崩塌。而这类问题永远无法通过“看代码”发现必须让它跑起来。2.3 第三层业务指标级审查——用结果反推逻辑可靠性最后一层审查也是最容易被忽视的一层不看代码写了什么而看它上线后让业务指标发生了什么变化。2023年Q4我们上线了一个AI生成的“优惠券发放成功率优化”模块。代码逻辑很优雅用动态规划计算最优发放组合减少库存占用。CR时所有人都觉得没问题——直到上线后第七天运营同学发现“满200减30”券的核销率从12.7%暴跌至3.1%。排查过程就是典型的业务指标级审查Step 1锁定异常指标在Grafana看coupon_redemption_rate仪表盘发现暴跌始于新模块上线时刻且仅影响“满减类”券折扣类券正常Step 2关联维度下钻切换维度按券类型、用户地域、设备类型、发放渠道分组发现异常集中在“iOS端华东地区APP内发放”Step 3逆向追踪数据流从核销日志反查发放日志发现这批用户收到的券valid_until字段被设为2023-12-31 23:59:59正确但min_order_amount被设为200.00000000000003错误Step 4定位代码根源查AI生成的优惠券计算函数发现它用round(total * 0.15, 2)计算门槛值但在浮点运算中200 * 0.15结果为30.000000000000004再乘以100取整时因精度误差变成200.00000000000003。这个bug在代码审查时根本不可能被发现——它需要同时具备真实的用户下单金额分布、iOS端JavaScript浮点运算特性、以及华东地区用户偏好他们更爱用支付宝余额支付导致金额精度更高。只有业务指标异常才能把它揪出来。因此我把业务指标审查固化为上线Checklist指标类型监控项预期变化触发动作核心转化率checkout_success_rate±0.5%以内超出则立即回滚关键延迟payment_callback_p95_ms≤800ms超出则检查异步队列积压数据一致性inventory_delta_abs_sum≤5超出则启动对账任务异常模式error_code_400_rate≤1%突增则查日志关键词每次AI生成代码上线我要求SRE必须盯着这四个仪表盘15分钟。不是看代码是看数字——因为数字不会说谎而AI会。3. 实操工具链从VS Code插件到Prometheus告警的全栈配置3.1 开发阶段VS Code里的“AI审查三件套”很多人以为审查是上线前的事其实真正的审查战场在编辑器里。我强制团队在VS Code中安装并配置以下三个插件形成审查第一道防线AST ExplorerPython/JS专用安装后右键代码选择“Show AST”实时查看语法树。重点看Dict节点的keys是否全为字符串字面量警惕硬编码Call节点的func.id是否匹配当前项目依赖版本如requests.getvshttpx.getCompare节点的ops是否含Is警惕is None误用应为 None。TODO Highlight配置高亮规则todohighlight.keywords: [ { text: FIXME-AI, color: #ff0000, backgroundColor: #ffcccc }, { text: CHECK-CONTEXT, color: #0066cc, backgroundColor: #cce6ff } ]要求AI生成代码时必须在可疑行上方加# FIXME-AI: why use float here?审查者只扫这些标记行。Error Lens不只是显示语法错误要配置它捕获运行时隐患errorLens.showAsGutterIcon: true, errorLens.gutterIconSize: 14, errorLens.diagnosticSource: both, errorLens.enableFor: [python, javascript]它会在行尾显示⚠️图标悬停显示Pylint警告如W0612: unused variable temp_result——这类警告往往指向AI生成的冗余逻辑。注意这三个插件必须配合使用。单独用AST Explorer容易陷入技术细节单独用TODO Highlight可能漏掉未标记处单独用Error Lens只报表面问题。三者联动才能覆盖从结构到语义的全维度。3.2 测试阶段用PytestPlaywright构建“AI生成代码沙盒”单元测试对AI代码效果有限——它测的是“代码能不能跑”而我们要测的是“代码在真实世界里会不会歪”。我的解决方案是构建轻量沙盒Pytest Fixture注入真实上下文写一个conftest.py为所有AI生成模块提供标准化fixturepytest.fixture def real_db_connection(): # 连接测试库但只读 conn psycopg2.connect(hosttest-db usertest passwordtest dbnametest) yield conn conn.close() pytest.fixture def mock_external_api(): # 用responses库mock真实API响应 with responses.RequestsMock() as rsps: rsps.add(responses.GET, https://api.payment.com/status, json{status: success, amount: 199.99}, status200) yield rspsPlaywright录制真实用户路径不写脚本直接用Playwright Recorder录下用户从首页→搜索→下单→支付的完整路径导出为.spec.ts。然后在测试中重放test(AI-generated checkout flow, async ({ page }) { await page.goto(http://localhost:3000); await page.getByRole(textbox, { name: Search }).fill(laptop); await page.getByRole(button, { name: Search }).click(); await page.getByText(Gaming Laptop Pro).click(); await page.getByRole(button, { name: Add to Cart }).click(); await page.getByRole(link, { name: Checkout }).click(); // 此时触发AI生成的支付校验逻辑 await expect(page.getByText(Payment confirmed)).toBeVisible(); });沙盒执行策略CI中跑测试时启用三重断言功能断言页面是否显示预期文本性能断言page.waitForResponse(https://api.payment.com/confirm)耗时≤1.2s数据断言检查数据库orders表新增记录的total_amount字段是否等于199.99而非199.98999999999998。这套沙盒把测试从“验证代码”升级为“验证代码在真实环境中的行为”成本只比传统单元测试高20%但缺陷检出率提升300%。3.3 上线阶段PrometheusAlertmanager的“AI行为哨兵”代码上线不是审查终点而是监控起点。我给AI生成模块部署专属监控定制Metrics Exporter在Python服务中集成prometheus_client暴露4类指标# AI-specific metrics ai_generated_lines_total Counter(ai_generated_lines_total, Total lines generated by AI) ai_context_mismatch_count Counter(ai_context_mismatch_count, Context mismatch events) ai_fallback_triggered_count Counter(ai_fallback_triggered_count, Fallback to human logic) ai_latency_seconds Histogram(ai_latency_seconds, AI logic execution latency) # 在AI函数入口处 def ai_payment_validator(order): ai_generated_lines_total.inc() start time.time() try: result _ai_logic(order) # AI生成的核心逻辑 except ContextMismatchError: ai_context_mismatch_count.inc() result _human_fallback(order) # 人工编写的兜底逻辑 ai_fallback_triggered_count.inc() ai_latency_seconds.observe(time.time() - start) return resultAlertmanager告警规则在alert.rules.yml中定义groups: - name: ai-monitoring rules: - alert: AIContextMismatchHigh expr: rate(ai_context_mismatch_count[1h]) 0.1 for: 5m labels: severity: critical annotations: summary: AI context mismatch rate 10%/hour description: Check recent PRDs and data schema changes - alert: AIFallbackTriggered expr: sum(rate(ai_fallback_triggered_count[1h])) 5 for: 10m labels: severity: warning annotations: summary: AI fallback triggered 5 times/hour description: Model may be misaligned with current business rulesGrafana看板配置创建专属看板包含折线图ai_latency_seconds_bucket观察P90/P99延迟拐点热力图ai_context_mismatch_count按error_type维度区分schema mismatch、timeout mismatch、type mismatch状态卡片ai_fallback_triggered_count今日累计值绿色≤10、黄色11-50、红色50。这套监控体系让审查从“人盯代码”变成“系统盯行为”。当ai_context_mismatch_count突增不用翻代码直接查最近的需求变更——这才是AI时代审查的终极形态用数据流代替代码流用指标代替行号。4. 常见问题与避坑指南那些没人告诉你的实战陷阱4.1 “AI生成的代码测试覆盖率100%为什么上线还崩”这是最常被问的问题。真相是测试覆盖率只衡量代码行是否被执行不衡量执行路径是否覆盖真实业务场景。我遇到过一个典型案例AI生成的“发票抬头校验”函数单元测试用pytest.mark.parametrize覆盖了张三、李四、、None四种输入覆盖率100%。但真实用户提交的是张三北京分公司——括号是中文全角字符而AI生成的正则r^[\w\s]$只匹配半角字符导致校验失败。破解方法用真实生产日志生成测试用例。步骤如下从ELK中导出最近7天所有发票抬头字段的原始值脱敏后约23万条用pandas统计字符集分布df[title].str.contains(r[^\x00-\x7F]).sum()发现12.3%含中文括号、emoji、特殊符号从中抽样1000条作为pytest的pytest.mark.parametrize数据源在CI中运行时若新增样本触发失败则自动将该样本加入长期测试集。这样生成的测试用例覆盖的是真实世界的混乱而不是开发者脑补的边界。4.2 “团队要求AI生成代码必须加注释结果注释比代码还长还全是错的”AI生成的注释有个致命问题它描述的是代码“看起来在做什么”而不是“为什么这么做”。比如# Calculate the discount rate based on user tier def calc_discount(tier: str) - float: if tier vip: return 0.15 elif tier gold: return 0.1 else: return 0.05注释说“based on user tier”但真实业务规则是“VIP用户享15%折扣但仅限单笔订单满500元Gold用户10%无门槛普通用户5%且不可与其他优惠叠加”。AI注释完全没提这些关键约束。我的解决方案禁用AI自动生成注释改用“契约注释”。在函数开头强制写def calc_discount(tier: str, order_amount: Decimal) - float: 计算订单折扣率仅适用于主商品不含运费 Contract: - 输入: tier ∈ {vip,gold,normal}, order_amount 0 - 输出: 0.0 result 0.15 - 约束: vip折扣仅当 order_amount 500 - 副作用: 无 - 错误: 若tier非法抛 ValueError 这种注释不描述代码而描述契约——它定义了函数存在的意义且可被自动化工具校验如用pydantic验证输入类型用hypothesis生成违反契约的测试数据。4.3 “AI生成的SQL在本地MySQL跑得好好的一上生产就慢成狗”根本原因AI模型没见过你的生产数据分布。它生成的SELECT * FROM orders WHERE user_id ? AND status paid在测试库1000行毫秒级但在生产库2亿行因缺少复合索引而全表扫描。我的应对清单强制索引检查所有AI生成的SQL必须附带EXPLAIN结果截图且type字段不能为ALL或index数据倾斜预警用SELECT COUNT(*), status FROM orders GROUP BY status查生产数据倾斜度若paid占比95%则提醒AI避免在status上建等值查询执行计划固化在MySQL 8.0中对关键SQL用CREATE OUTLINE固化执行计划防止优化器因统计信息更新而选错索引。记住AI懂SQL语法但不懂你的数据。审查SQL本质是审查它与数据分布的匹配度。4.4 “用AI写了100个微服务现在没人敢动其中任何一个怕牵一发而动全身”这是“AI生成熵增”的典型症状每个服务都正确但服务间耦合关系混沌。我的解法是用OpenAPI Spec反向生成依赖图要求所有AI生成的HTTP服务必须用Swagger UI导出openapi.json用openapi-diff工具比对前后版本生成变更报告用swagger-to-diagram将所有openapi.json合并生成服务依赖图在图中标识“AI生成服务”用不同颜色并高亮跨服务调用链。这张图让我们发现某个AI生成的“库存服务”被17个其他服务调用但它的/v1/stock/check接口返回字段available_count在3个调用方中被误用为reserved_count。于是我们集中治理统一字段语义。没有这张图100个服务就是100座孤岛有了它AI生成的复杂性就变成了可管理的拓扑结构。我最后想说的是AI编程不是要取代审查而是逼我们重新定义审查。它把我们从“语法警察”解放出来推向一个更艰难也更有价值的位置——做代码与业务之间的翻译官做模型与现实之间的校准器做技术债与商业目标之间的平衡者。上周五我看着实习生用Copilot 3分钟生成了一个完整的WebSocket心跳保活模块然后花了40分钟和他一起调试为什么setInterval在页面切后台时会暂停为什么重连逻辑没处理EventSource的error事件为什么心跳包没加X-Request-ID导致日志无法串联。他擦着汗说“原来AI写的不是代码是草稿。”是的它就是草稿。而人类的价值从来不在写出第一行而在让最后一行真正可靠地跑在生产环境里——无论那行代码是谁写的。
返回列表