实测 AI 写代码:从 Todo 小工具看效率、质量与源码落地
AI编程测评报告|附源码
摘要
过去一年,“AI 编程”已经从一个新鲜概念,快速变成了许多开发者日常工作流的一部分。从代码补全、单元测试生成、Bug 定位,到需求拆解、架构设计、文档编写,AI 编程工具正在不断拓展边界。本文将以一次相对完整的实测为基础,对 AI 编程在真实开发场景中的表现进行评估,并给出一个可运行的小项目源码示例,帮助读者理解 AI 在编码效率、代码质量、可维护性以及工程落地方面的实际价值。
本次测评不追求“AI 是否能够完全替代程序员”这类极端结论,而是重点关注一个更现实的问题:在当前阶段,AI 编程到底能帮开发者做到什么、做得怎么样、有哪些风险,以及如何更高效地使用它。
一、测评背景
随着大语言模型能力的提升,AI 编程工具已经不再只是简单的代码提示器。它们能够根据自然语言需求生成代码,解释已有代码逻辑,辅助重构复杂函数,甚至根据报错信息给出修复方案。
常见的 AI 编程使用方式包括:
-
代码补全
根据上下文自动补齐变量、函数、类、配置项等内容。 -
代码生成
根据需求描述生成接口、页面、脚本、算法、数据处理逻辑等。 -
代码解释
对已有代码进行逐行解释,帮助开发者理解陌生项目。 -
Bug 修复
根据错误日志、异常堆栈或测试失败信息提出修复建议。 -
单元测试生成
自动为函数、类或接口生成测试用例。 -
文档生成
根据代码生成 README、接口说明、注释或技术文档。 -
重构建议
发现重复代码、复杂逻辑、潜在异常,并提出优化方案。
从实际体验来看,AI 编程最显著的价值并不是“代替开发者写完整项目”,而是帮助开发者减少重复劳动、提升思考效率,并在一些边界清晰的问题上快速给出可用方案。
二、测评目标
本次测评主要围绕以下几个维度展开:
| 测评维度 | 说明 |
|---|---|
| 代码生成能力 | 是否能根据需求生成可运行代码 |
| 逻辑准确性 | 生成代码是否符合业务逻辑 |
| 可读性 | 命名、结构、注释是否清晰 |
| 可维护性 | 是否容易扩展和修改 |
| 错误处理 | 是否考虑异常输入和边界情况 |
| 测试能力 | 是否能够生成有效单元测试 |
| 工程化能力 | 是否具备模块化、配置化、文档化意识 |
| 开发效率 | 是否明显节省开发时间 |
为了避免测评过于空泛,本文选择一个小型但相对完整的案例:使用 Python 编写一个命令行待办事项管理工具。
这个案例看似简单,但实际包含了不少常见开发要素:
- 命令行参数解析;
- 数据持久化;
- 增删改查;
- 状态变更;
- 输入校验;
- JSON 文件读写;
- 基础异常处理;
- 可扩展代码结构;
- 单元测试思路。
三、测试需求描述
向 AI 提出的原始需求如下:
请使用 Python 编写一个命令行 Todo 工具,支持添加任务、查看任务列表、标记任务完成、删除任务。数据保存在本地 JSON 文件中。要求代码结构清晰,提供基础异常处理,并附带使用示例。
这个需求并不复杂,但也不是单个函数能够完成的任务。它要求 AI 能够将自然语言转化为合理的程序结构。
四、AI 生成代码整体表现
从结果来看,AI 通常可以较快生成一个可运行版本,核心功能基本完整。特别是在以下方面表现较好:
1. 能快速搭建基础结构
AI 往往会自动选择 argparse 作为命令行解析工具,使用 json 模块进行数据持久化,并将任务抽象成字典结构,例如:
{
"id": 1,
"title": "学习 AI 编程",
"done": False
}
这种结构简单直观,对于小型工具来说足够使用。
2. 能完成主要业务功能
在添加任务、查看任务、完成任务、删除任务方面,AI 生成代码通常能够覆盖主要流程:
- 添加任务时读取现有任务;
- 自动生成任务 ID;
- 将新任务写入 JSON 文件;
- 查询时展示所有任务;
- 根据 ID 找到对应任务;
- 修改任务状态或删除任务。
3. 代码可读性较好
AI 生成的代码一般会包含合理的函数拆分,例如:
load_tasks()save_tasks()add_task()list_tasks()complete_task()delete_task()
这类函数命名清楚,便于理解。
4. 边界处理存在不足
虽然 AI 会添加一些基础异常处理,但常常不够完善。例如:
- JSON 文件损坏时如何处理;
- ID 不存在时是否有明确提示;
- 任务标题为空时是否允许添加;
- 多次删除或完成同一任务时如何反馈;
- 文件权限异常是否被捕获;
- 并发写入是否可能造成数据丢失。
这些问题说明,AI 生成代码可以作为初稿,但仍然需要开发者进行审查和增强。
五、附源码:Python 命令行 Todo 工具
下面是经过整理和优化后的完整源码。该版本在 AI 生成代码基础上做了增强,包括输入校验、文件异常处理、JSON 解析异常处理,以及更清晰的命令行提示。
1. 项目结构
todo-ai-demo/
├── todo.py
└── tasks.json
其中:
todo.py是主程序;tasks.json用于保存任务数据,首次运行时会自动创建。
2. 完整源码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
一个简单的命令行 Todo 工具。
功能:
1. 添加任务
2. 查看任务列表
3. 标记任务完成
4. 删除任务
数据保存在本地 tasks.json 文件中。
"""
import argparse
import json
import os
from typing import List, Dict, Any
TASK_FILE = "tasks.json"
def load_tasks() -> List[Dict[str, Any]]:
"""
从 JSON 文件中加载任务列表。
如果文件不存在,则返回空列表。
如果文件内容损坏,则提示用户并返回空列表。
"""
if not os.path.exists(TASK_FILE):
return []
try:
with open(TASK_FILE, "r", encoding="utf-8") as file:
data = json.load(file)
if not isinstance(data, list):
print("警告:任务文件格式不正确,已使用空任务列表。")
return []
return data
except json.JSONDecodeError:
print("警告:tasks.json 内容不是合法 JSON,已使用空任务列表。")
return []
except OSError as error:
print(f"读取任务文件失败:{error}")
return []
def save_tasks(tasks: List[Dict[str, Any]]) -> None:
"""
将任务列表保存到 JSON 文件中。
"""
try:
with open(TASK_FILE, "w", encoding="utf-8") as file:
json.dump(tasks, file, ensure_ascii=False, indent=2)
except OSError as error:
print(f"保存任务文件失败:{error}")
def get_next_id(tasks: List[Dict[str, Any]]) -> int:
"""
获取下一个任务 ID。
"""
if not tasks:
return 1
return max(task.get("id", 0) for task in tasks) + 1
def add_task(title: str) -> None:
"""
添加新任务。
"""
title = title.strip()
if not title:
print("错误:任务标题不能为空。")
return
tasks = load_tasks()
new_task = {
"id": get_next_id(tasks),
"title": title,
"done": False
}
tasks.append(new_task)
save_tasks(tasks)
print(f"已添加任务:[{new_task['id']}] {new_task['title']}")
def list_tasks(show_all: bool = True) -> None:
"""
查看任务列表。
show_all 为 True 时展示全部任务。
"""
tasks = load_tasks()
if not tasks:
print("暂无任务。")
return
print("\n任务列表:")
print("-" * 40)
for task in tasks:
if not show_all and task.get("done"):
continue
status = "✓" if task.get("done") else " "
task_id = task.get("id", "?")
title = task.get("title", "")
print(f"[{status}] {task_id}. {title}")
print("-" * 40)
def complete_task(task_id: int) -> None:
"""
标记任务为完成。
"""
tasks = load_tasks()
for task in tasks:
if task.get("id") == task_id:
if task.get("done"):
print(f"任务 [{task_id}] 已经是完成状态。")
return
task["done"] = True
save_tasks(tasks)
print(f"已完成任务:[{task_id}] {task.get('title')}")
return
print(f"未找到 ID 为 {task_id} 的任务。")
def delete_task(task_id: int) -> None:
"""
删除指定任务。
"""
tasks = load_tasks()
new_tasks = [task for task in tasks if task.get("id") != task_id]
if len(new_tasks) == len(tasks):
print(f"未找到 ID 为 {task_id} 的任务。")
return
save_tasks(new_tasks)
print(f"已删除任务:[{task_id}]")
def build_parser() -> argparse.ArgumentParser:
"""
构建命令行参数解析器。
"""
parser = argparse.ArgumentParser(
description="一个简单的命令行 Todo 管理工具"
)
subparsers = parser.add_subparsers(
dest="command",
help="可用命令"
)
add_parser = subparsers.add_parser(
"add",
help="添加任务"
)
add_parser.add_argument(
"title",
type=str,
help="任务标题"
)
list_parser = subparsers.add_parser(
"list",
help="查看任务列表"
)
list_parser.add_argument(
"--todo",
action="store_true",
help="只查看未完成任务"
)
complete_parser = subparsers.add_parser(
"done",
help="标记任务完成"
)
complete_parser.add_argument(
"id",
type=int,
help="任务 ID"
)
delete_parser = subparsers.add_parser(
"delete",
help="删除任务"
)
delete_parser.add_argument(
"id",
type=int,
help="任务 ID"
)
return parser
def main() -> None:
"""
程序入口。
"""
parser = build_parser()
args = parser.parse_args()
if args.command == "add":
add_task(args.title)
elif args.command == "list":
list_tasks(show_all=not args.todo)
elif args.command == "done":
complete_task(args.id)
elif args.command == "delete":
delete_task(args.id)
else:
parser.print_help()
if __name__ == "__main__":
main()
六、使用示例
1. 添加任务
python todo.py add "学习 AI 编程"
python todo.py add "完成项目文档"
python todo.py add "阅读 Python 官方文档"
输出示例:
已添加任务:[1] 学习 AI 编程
已添加任务:[2] 完成项目文档
已添加任务:[3] 阅读 Python 官方文档
2. 查看全部任务
python todo.py list
输出示例:
任务列表:
----------------------------------------
[ ] 1. 学习 AI 编程
[ ] 2. 完成项目文档
[ ] 3. 阅读 Python 官方文档
----------------------------------------
3. 标记任务完成
python todo.py done 1
输出示例:
已完成任务:[1] 学习 AI 编程
再次查看:
python todo.py list
输出示例:
任务列表:
----------------------------------------
[✓] 1. 学习 AI 编程
[ ] 2. 完成项目文档
[ ] 3. 阅读 Python 官方文档
----------------------------------------
4. 只查看未完成任务
python todo.py list --todo
输出示例:
任务列表:
----------------------------------------
[ ] 2. 完成项目文档
[ ] 3. 阅读 Python 官方文档
----------------------------------------
5. 删除任务
python todo.py delete 2
输出示例:
已删除任务:[2]
七、源码评估
1. 功能完整性
该代码实现了 Todo 工具的核心功能,能够满足基础使用场景:
- 添加任务;
- 查看任务;
- 标记完成;
- 删除任务;
- 持久化保存。
对于一个命令行小工具而言,功能闭环已经成立。
评分:8/10
不足之处在于还没有支持任务编辑、优先级、截止日期、分类标签等扩展功能。
2. 代码可读性
代码结构较清晰,函数职责比较单一。例如 load_tasks() 只负责读取任务,save_tasks() 只负责保存任务,业务函数分别处理不同命令。
命名也比较直观,基本符合 Python 的编码习惯。
评分:8.5/10
如果继续优化,可以将任务抽象为 Task 类,或者使用 dataclass 提升结构化程度。
3. 异常处理能力
该版本已经处理了以下异常:
- 文件不存在;
- JSON 格式错误;
- 文件读取失败;
- 文件保存失败;
- 任务标题为空;
- 任务 ID 不存在;
- 重复完成任务。
评分:7.5/10
不过仍然存在一些可以增强的点,例如:
- 写文件时可以先写临时文件,再原子替换,避免写入中断导致文件损坏;
- 可以增加文件锁,减少并发执行时的数据竞争;
- 可以将错误输出到标准错误流;
- 可以增加日志记录。
4. 可维护性
目前代码集中在一个文件里,适合演示和小规模使用。如果项目继续增长,可以拆分为:
todo-ai-demo/
├── main.py
├── storage.py
├── service.py
├── cli.py
├── models.py
└── tests/
其中:
models.py存放任务数据结构;storage.py负责数据读写;service.py负责业务逻辑;cli.py负责命令行解析;tests/存放测试代码。
评分:7/10
当前版本适合入门,但还不算完整工程化项目。
八、AI 编程的实际优点
通过这个案例,可以明显看到 AI 编程工具在以下方面有较大价值。
1. 降低启动成本
对于很多开发任务来说,最耗费精力的并不一定是核心算法,而是“从零开始搭架子”。AI 可以快速生成初始项目结构,让开发者不必反复编写模板代码。
例如命令行工具中的参数解析、JSON 文件读写、基础函数拆分,这些都属于重复性较高的工作。AI 在这类任务上的表现通常比较稳定。
2. 提高编码速度
如果由人工从零编写上述 Todo 工具,可能需要 20 到 40 分钟,视熟练程度而定。使用 AI 生成初稿后,再进行人工审查和修改,整体时间可能缩短到 5 到 15 分钟。
当然,这并不意味着所有任务都能节省同样比例的时间。越是常规、边界清晰、资料丰富的任务,AI 越容易发挥作用。
3. 辅助学习新技术
当开发者不熟悉某个库、框架或语言特性时,AI 可以给出入门示例。例如开发者不熟悉 argparse,AI 不仅可以生成代码,还能解释每个参数的含义。
这对于学习阶段的开发者非常有帮助。相比单纯查文档,AI 可以根据上下文给出更贴近当前需求的示例。
4. 帮助发现思路盲区
AI 在生成代码时,常常会主动补充一些开发者没有明确提出的内容,例如:
- 参数校验;
- 文件不存在处理;
- 操作成功提示;
- 帮助文档;
- 函数注释。
虽然这些补充不一定完美,但可以提醒开发者考虑更完整的使用场景。
九、AI 编程的主要问题
AI 编程虽然有价值,但也存在明显限制,不能盲目信任。
1. 容易生成“看起来正确”的代码
AI 生成的代码通常语法规范、结构整齐,但这并不代表逻辑一定正确。尤其是在复杂业务中,代码可能表面合理,实际遗漏关键规则。
例如在订单系统、权限系统、财务系统中,一个看似微小的条件判断错误,可能造成严重后果。
2. 对隐含需求理解不足
真实业务需求中有大量隐含规则,而 AI 只能根据开发者提供的信息进行推断。如果需求描述不完整,AI 可能会自行补全假设。
例如 Todo 工具中,如果没有说明任务 ID 是否允许重复、删除后 ID 是否复用、是否需要排序,AI 可能选择一种默认方案,但未必符合实际需求。
3. 工程质量依赖提示词质量
同样的 AI 工具,输入不同提示词,输出质量差异很大。如果只是说“写一个 Todo 工具”,得到的代码可能比较粗糙;如果明确说明语言、结构、异常处理、测试要求,结果会好很多。
因此,AI 编程并不是简单地“让 AI 写代码”,而是需要开发者具备清晰表达需求和审查结果的能力。
4. 安全风险不可忽视
AI 可能生成存在安全隐患的代码,例如:
- SQL 拼接导致注入;
- 不安全的文件路径处理;
- 明文存储敏感信息;
- 缺少鉴权;
- 依赖过旧或存在漏洞;
- 错误地暴露环境变量。
因此,在生产环境中使用 AI 生成代码,必须经过代码审查、安全扫描和测试验证。
十、如何更高效地使用 AI 编程
1. 给出清晰的上下文
不要只说“帮我写一个接口”,而应该说明:
- 使用什么语言;
- 使用什么框架;
- 输入参数是什么;
- 输出格式是什么;
- 错误如何处理;
- 是否需要测试;
- 是否有性能要求;
- 是否有安全限制。
示例提示词:
请使用 Python 3.11 编写一个命令行 Todo 工具。
要求:
1. 使用 argparse 解析命令;
2. 数据保存到本地 JSON 文件;
3. 支持 add、list、done、delete 四个命令;
4. 对空标题、非法 ID、JSON 文件损坏进行处理;
5. 代码需要函数拆分清晰;
6. 请附带使用示例和简单测试思路。
这样的提示词明显比“写个 Todo 工具”更容易得到高质量结果。
2. 让 AI 先设计再编码
对于稍复杂的需求,不建议直接让 AI 写代码。更好的方式是先让 AI 输出设计方案:
请先不要写代码,先帮我设计模块结构、数据结构、主要函数和异常处理方案。
确认设计合理后,再让 AI 分模块生成代码。这种方式可以减少返工。
3. 要求 AI 解释关键代码
生成代码后,可以继续追问:
请解释 complete_task 函数的执行流程,并指出可能的边界问题。
通过解释,可以发现 AI 是否真的覆盖了关键逻辑,也方便开发者进行代码审查。
4. 使用测试约束 AI 输出
可以要求 AI 同时生成测试用例:
请使用 pytest 为 add_task、complete_task、delete_task 编写单元测试。
测试不一定完全正确,但可以帮助开发者发现遗漏场景。
5. 不要跳过人工审查
AI 生成代码必须经过人工确认,尤其是以下场景:
- 涉及用户隐私;
- 涉及支付、资金、订单;
- 涉及权限和安全;
- 涉及数据库写入;
- 涉及生产环境部署;
- 涉及复杂并发逻辑。
AI 可以提高效率,但责任仍然属于开发者和团队。
十一、可选扩展:单元测试示例
如果希望进一步提升项目质量,可以为核心逻辑添加测试。下面给出一个简单的测试思路示例。为了方便测试,实际项目中最好将 TASK_FILE 改造成可配置参数,避免测试污染真实数据。
示例测试代码:
import os
import json
import tempfile
import unittest
from unittest.mock import patch
import todo
class TestTodoApp(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.TemporaryDirectory()
self.task_file = os.path.join(self.temp_dir.name, "tasks.json")
def tearDown(self):
self.temp_dir.cleanup()
def test_add_task(self):
with patch.object(todo, "TASK_FILE", self.task_file):
todo.add_task("测试任务")
tasks = todo.load_tasks()
self.assertEqual(len(tasks), 1)
self.assertEqual(tasks[0]["title"], "测试任务")
self.assertFalse(tasks[0]["done"])
def test_complete_task(self):
with patch.object(todo, "TASK_FILE", self.task_file):
todo.add_task("测试完成任务")
todo.complete_task(1)
tasks = todo.load_tasks()
self.assertTrue(tasks[0]["done"])
def test_delete_task(self):
with patch.object(todo, "TASK_FILE", self.task_file):
todo.add_task("测试删除任务")
todo.delete_task(1)
tasks = todo.load_tasks()
self.assertEqual(len(tasks), 0)
if __name__ == "__main__":
unittest.main()
运行测试:
python -m unittest test_todo.py
这段测试代码主要验证三个核心功能:
- 添加任务后文件中是否存在数据;
- 标记完成后状态是否变为
True; - 删除任务后任务列表是否为空。
十二、综合评分
结合本次测评,可以给 AI 编程在该类任务中的表现一个综合评分:
| 指标 | 评分 |
|---|---|
| 需求理解 | 8/10 |
| 代码生成速度 | 9/10 |
| 基础功能实现 | 8/10 |
| 代码可读性 | 8.5/10 |
| 异常处理 | 7/10 |
| 工程化能力 | 7/10 |
| 安全意识 | 6.5/10 |
| 测试生成能力 | 7/10 |
| 综合表现 | 7.8/10 |
总体来看,AI 在小型工具、脚本、通用业务逻辑和模板代码方面表现良好,已经可以作为开发者的高效助手。但在复杂业务、严肃工程、安全场景中,它仍然需要人工把关。
十三、结论
AI 编程不是魔法,也不是噱头。它的真实价值在于:帮助开发者更快进入问题核心,减少重复劳动,提高迭代速度。
在本次 Todo 命令行工具测评中,AI 可以较好地完成基础代码生成,并提供清晰的程序结构。经过人工优化后,代码具备了较好的可读性和可用性。对于个人项目、原型验证、学习练习、内部工具开发,AI 编程已经具有很高的实用价值。
但与此同时,AI 生成代码仍然存在边界处理不足、隐含需求理解有限、安全意识不稳定等问题。开发者不能将 AI 输出直接视为最终答案,而应将其作为“高质量初稿”或“编程协作伙伴”。
更合理的使用方式是:
- 人类负责定义目标、约束和业务规则;
- AI 负责快速生成初稿、补全代码和提出建议;
- 人类负责审查、测试、优化和最终决策。
未来的开发模式很可能不是“AI 替代程序员”,而是“会使用 AI 的程序员替代不会使用 AI 的程序员”。对于开发者来说,掌握 AI 编程工具的使用方法,已经逐渐成为一项新的基础能力。