Appearance
AI 能写代码之后,工程师还需要做什么?
现在使用 AI 开发功能,往往很快就能看到一批实现代码。过去需要自己编写的业务逻辑、数据转换、Controller、前端页面和单元测试,现在都可以交给 AI。
但使用一段时间后,我发现自己的开发时间反而增加了。
有些功能虽然很快生成了代码,后续却需要反复沟通、检查和修改。另一方面,AI 让一些原本需要较长时间的工作变得容易实现,我又开始尝试更多想法、开发更多功能。
以前,我通常一边设计、一边编码、一边调整,许多判断可以伴随着编码过程完成。现在,我更多地与 ChatGPT 讨论问题和方案,再将具体编码任务交给 Codex。
这种变化让我越来越重视四项工作:任务定义、方案判断、阶段与变更控制、结果验收。
一、任务定义:从弄清楚做什么,到把任务讲清楚
以前开发功能,通常是先有需求,再考虑如何实现。
现在我发现,AI 不仅可以帮助实现需求,还可以参与需求形成的过程。
我有一个用于研究 ETF 的系统,保存了历史日 K 数据,也记录了自己的交易数据。
最初,我对统计分析的理解比较有限,以为主要是平均数、众数、方差这些概念。后来通过与 AI 不断讨论,才逐渐了解滚动窗口、历史分布、偏离度等不同的分析方法。
例如,AI 曾提出研究某个品种下跌 20% 或 30% 后,未来 20、30、60 个交易日的涨跌表现。这个问题可以通过历史行情进行统计,而不必停留在主观判断上。
AI 还帮助我将研究过程划分为 Data、Analysis、Decision、Execution 四个层次。
历史日 K、交易记录属于 Data;CCI 分布、趋势统计属于 Analysis;依据研究结果形成交易假设属于 Decision;实际采取行动并记录结果才进入 Execution。
这套划分帮助我识别一项功能的职责:是在保存原始事实、计算分析结果,还是记录决策与执行情况?
例如,我曾研究过 CCI 处于低位时,能否在尾盘介入、尝试捕捉次日反弹。这项研究形成过统计结果和策略记录,但没有实际执行,属于研究与决策假设。
文中涉及的交易假设仅为个人研究记录,不构成投资建议;历史统计表现也不代表未来收益。
这是任务定义的一种情况:起初只有数据和疑问,需要先与 AI 讨论值得研究什么,再逐渐形成具体的功能需求。
另一种情况是,已经知道要解决什么问题,难点在于怎样把目标和边界讲清楚。
从 TXT 解析改为 Excel 解析
2023 年,我曾经开发过一个用于解析券商持仓文件的功能。
当时使用过多个券商,需要适配不同格式的文件,因此采用了 Processor + Factory 结构:由工厂选择对应的处理器,让不同券商的解析实现可以独立扩展。
早期主要解析类似 CSV 的 TXT 文件,但文件中的字段并不总是完整。
例如:
java
StringUtils.split("000001 100 10.5", " ");假如两个空格代表中间缺少一个字段,期望保留的结果是:
text
["000001", "", "100", "10.5"]但 StringUtils.split 会忽略连续分隔符形成的空字段,实际得到:
text
["000001", "100", "10.5"]缺失字段的位置没有保留下来,后续列就可能错位。旧代码需要根据不同情况提前过滤记录,或者按照不同数组长度进行特殊解析。
到了 2026 年,我主要使用一家券商,决定改用列结构更加明确的 Excel 文件。
过去自己编码,可以直接阅读旧代码,一边实现、一边修改。现在希望让 AI 完成具体实现,就需要把问题背景、目标和边界表达出来。
下面是根据实际讨论事后整理的一份任务说明示例,并非当时发送的原始 Prompt。其中部分设计要求也是在讨论中逐渐明确的。
背景
原有 TXT 解析存在字段缺失、列结构不稳定的问题,当前主要使用一家券商。
目标
解析该券商导出的 Excel 持仓文件,转换为系统内部对象。
约束
- 保留已有的
Processor + Factory扩展结构。- 解析、过滤、转换分别承担独立职责,作为内部组件。
- 对外提供统一的持仓导入处理器。
本次不做
不提前开发其他券商的解析器,也不在文件解析组件中执行数据库保存。
验收方式
分别验证 Excel 字段读取、无效记录过滤和对象转换结果。
过去自己实现时,很多细节可以随着编码逐渐明确。
交给 AI 后,任务定义包含两个方面:先弄清楚究竟要解决什么问题,再把目标、约束与完成标准表达清楚。
二、方案判断:理解依据,再决定采用什么
使用 AI 后,我越来越重视理解一个方案背后的原理,而不是直接接受结论。
例如,网上经常有人说,CCI 低于 -100 代表超卖,可以考虑买入。
但我在观察行情软件时发现,CCI 低于 -100 后还可能继续下降,股价也会进一步走低。我还注意到,不同品种的 CCI 历史分布并不相同。
这些实际观察让我产生了疑问:CCI 的公式是什么?它究竟衡量什么?能否从量价角度解释它的变化?
通过向 AI 追问,我了解到,标准 CCI 根据最高价、最低价和收盘价计算典型价格,再衡量价格相对于一定时期平均水平的偏离程度,并没有将成交量纳入计算。
理解公式后,我开始研究不同品种的 CCI 历史分布,并继续寻找能够衡量趋势方向、上涨和下跌强度的分析方法,希望避免在持续下跌过程中入场过早。
这是一个从实际行情观察出发,借助 AI 理解原理,再通过历史数据检验研究假设的过程。
网上流行的指标阈值可以作为研究起点,但是否适用于某个品种,需要结合它自身的历史分布和实际行情判断。
类似的取舍也出现在其他统计功能中。
例如,研究 ETF 成交量是否长期低迷时,我们曾讨论过使用“当前成交量相对于历史最大成交量下降了多少”来衡量。
我没有采用这个指标。
因为有些 ETF 在上市初期出现过异常大的成交量。即使后续交易并不冷清,与那个极端峰值相比,也可能表现为接近 99% 的衰减。
计算本身没有问题,但结果容易让人误解。
后来,我更倾向于使用历史成交量分位等方法,观察当前成交水平相对于历史分布所处的位置。
这让我认识到,一个指标即使能够计算,也需要判断它衡量的究竟是不是自己关心的问题。
让解析、过滤、转换各负其责
券商 Excel 解析的改造同样体现了方案判断。
早期 Parser 有一个类似这样的方法:
java
List<StockPosition> parse(String text);它能够直接返回持仓对象,但内部同时承担了原始文本解析、记录过滤和对象转换。
重新改造时,我认为这些职责过于耦合,应该分开。
经过与 AI 讨论,最终形成了三个内部组件:
Parser:读取 Excel,得到原始行数据。Filter:根据规则筛选记录。Transformer:将原始行转换为系统内部对象。
讨论中进一步明确了一个处理原则:Parser 尽量保留读取到的原始记录,不在解析阶段直接丢弃不需要的数据;由 Filter 判断记录是否应该保留,再由处理器组织整个流程。
例如,Excel 中的“持仓合计”行可以由 Parser 正常读取,再由 Filter 根据规则排除。
我还明确提出,三个类只作为内部实现,对外仍由统一的持仓导入处理器提供入口。
原有的 Processor + Factory 扩展结构继续保留。这并不是 AI 在本次改造中从零提出的新架构。
同时,考虑到现在主要使用一家券商,我没有要求 AI 提前开发其他券商的解析器。
后来重新检查代码时,我还发现旧的 AbstractBrokerParser 已经没有实际使用,可以进一步清理。
从统计指标到工程设计,我逐渐习惯先与 AI 讨论不同方案,再结合实际需求进行取舍。
AI 可以提供知识和新的思路,但最终还是需要判断:这个方案解决了什么问题,依据是否成立,又引入了哪些不必要的复杂性?
三、阶段与变更控制:让每次修改都有明确范围
在使用 AI 开发证券相关功能时,我曾经尝试让它连续完成多个任务。
例如,证券持仓相关功能涉及文件解析、记录过滤、数据保存、分页查询和图表展示。最初尝试让 AI 连续推进多个环节时,后续开发曾导致此前已经正常工作的功能出现回归。
遇到过两种情况:一是 AI 直接修改了已经完成的代码,二是新增逻辑间接影响了原有行为。
这些经历让我更加重视每次交给 AI 的任务范围。
后来,我将这类功能拆分为几个相对独立的阶段:
text
Excel 解析
↓
数据过滤
↓
数据保存
↓
分页查询
↓
折线图展示第一阶段先解决文件解析,确认原始数据能够正确读取。
第二阶段处理过滤规则,确保不需要的记录被排除。
之后再完成保存、查询和展示。
每个阶段都有相对明确的目标,完成并检查后,再推进下一项工作。
这种方式让我能够更清楚地知道当前修改了什么、需要验收什么。如果后续发生回归,也可以根据阶段边界缩小排查范围。
这与我原有的 Git 使用习惯也有关系。
几年前,公司电脑曾因为硬盘损坏导致本地代码丢失。从那以后,我养成了下班前执行 git commit 和 git push 的习惯。
即使在没有 AI 的时候,我也一直按照自己的开发节奏分批提交代码。
现在,每完成一个 AI 开发阶段,我更加关注本次修改涉及哪些文件,有没有超出任务范围,以及是否影响之前已经确认正常的功能。
如果后续出现问题,可以通过 Git 提交记录比较差异,必要时撤销相关变更。
过去,Git 主要帮助我保存成果、管理开发历史。现在,它也成为控制 AI 代码变更的重要工具。
四、结果验收:统计功能的错误不一定会报错
AI 生成代码并提示任务完成,只是开发过程中的一个节点。
我仍然需要确认功能是否符合需求,是否存在无关修改,以及有没有影响原有行为。
检查深度通常取决于任务的复杂度和风险。
| 任务类型 | 我的验收方式 |
|---|---|
| 简单修改 | 查看主要逻辑和代码格式,有时不专门执行人工测试 |
| 涉及业务规则 | 检查输入输出与边界条件,必要时运行单元测试 |
| 范围较大或可能影响旧功能 | 检查相关代码及 Git 差异,必要时调试和验证已有行为 |
在券商 Excel 解析功能中,职责拆分带来的一个好处,就是方便独立测试。
例如,一份 Excel 文件包含 27 条证券持仓和一行“持仓合计”。
Parser 的测试可以验证是否读取了全部 28 行;Filter 的测试可以检查汇总行是否被排除;Transformer 的测试则验证证券代码、持仓数量和价格转换是否正确。
但 ETF 统计分析还需要特别关注计算口径。
例如,研究历史下跌与后续收益时,我们共同确定采用逐日推进的滚动时间窗口,从历史数据的第一天开始逐步向后移动。后续观察数据不足的窗口,不纳入统计。
AI 可以根据规则编写计算逻辑、Controller 和前端页面。
但程序正常运行,图表能够显示,并不能证明计算口径一定正确。
我的验证方式之一,是打开对应 ETF 的历史日 K 线,对照日期与价格走势,检查统计结果是否符合实际行情。
这种核对能够帮助判断日期和价格是否对应。涉及精确收益率、样本数量等结果时,还需要进一步检查原始数据与计算过程。
口径之外,还有数据本身的问题。
在开发沪深两市融资余额统计图时,我曾发现 2026 年 9 月 30 日只有上交所的数据,缺少深交所对应记录。
如果程序直接按照日期汇总现有数据,即使正常返回结果,也会因为缺少一个市场的数据,让图表显示出融资余额突然大幅下降的假象。
这不是市场真的发生了相应幅度的变化,而是当天的数据不完整。
发现这个数据缺口后,我进一步明确了统计约束:只有沪深两市数据都存在,并且参与计算的必要字段均不为空时,该日期才能纳入合计统计。缺失值不能直接当作零。
这也说明,任务定义与结果验收不是相互孤立的两个环节。数据检查中发现的问题,还需要转化为新的计算约束,并落实到代码中。
对统计功能来说,即使公式、窗口或样本筛选规则存在问题,程序也可能正常运行,并生成一组看起来合理的结果。
要识别这些问题,开发人员仍然需要具备阅读、理解和必要时修改代码的能力。只有理解代码背后的业务规则与数学逻辑,才能判断结果是否真正回答了原来的问题。
五、代码实现更快了,我的时间去了哪里
开头提到,我使用 AI 后投入的开发时间反而增加了。
一部分时间花在了反复沟通、修改和验收上。另一部分,则投入了更多原本没有开展的工作。
以前,我想利用 ETF 历史日 K 开发一个统计功能,除了研究计算方法,还要自己编写纯计算类、Controller 和前端页面。
如果利用空闲时间开发,这类功能可能需要一周左右。
现在借助 AI,有些功能不到一天就能完成。例如 CCI 历史区间分布,以及不同历史时间窗口的涨跌表现统计。
因此,我把原来用于编写代码的一部分时间,投入了 ETF、统计学和研究方法的讨论中。
有时,是我从行情中观察到某种现象,希望借助 AI 理解原理并研究统计方法。
有时,是 AI 提出新的分析角度,我们再讨论它是否有意义,以及怎样利用已有数据实现。
研究问题逐渐变成开发任务,统计结果又可能带来新的疑问。
以前有些想法虽然存在,但受限于开发时间,不一定会真正动手验证。现在,很多想法可以更快地变成统计功能,我也可以更早地看到结果。
这正是我愿意继续使用 AI 的原因之一:把更多精力用在问题研究和知识学习上,而不仅是完成具体代码的编写。
结语
以前,我需要自己完成从需求理解、方案设计到代码实现的大部分工作,许多判断可以随着编码过程逐渐完成。
现在,AI 可以参与需求分析、知识学习、方案讨论、代码实现和测试编写。
对于熟悉的业务,例如券商文件解析,我可以基于已有工程经验,与 AI 讨论如何改造原来的设计,并控制实现范围。
对于相对陌生的统计分析,我则需要先理解公式、方法和统计口径,再决定哪些问题值得研究,怎样实现,以及如何验证结果。
对我来说,AI 能写代码之后,工程师需要做的,是更加清楚地理解问题、组织开发过程,并对实现结果作出判断和承担责任。
把工作交给 AI,并不意味着工作本身的复杂性消失了,而是有一部分复杂性转移到了任务定义、方案判断、阶段与变更控制以及结果验收上。