徐昊 · AI 时代的软件工程
徐昊
Thoughtworks 全球技术策略顾问
2765 人已学习
新⼈⾸单¥98
徐昊 · AI 时代的软件工程
15
15
1.0x
00:00/00:00
登录|注册

15|使用LLM生成代码和测试

你好,我是徐昊,今天我们来继续学习 AI 时代的软件工程。
通过前面的学习,我们了解了如何使用大语言模型(Large Language Model,LLM)辅助进行业务知识管理。接下来,我们继续学习使用 LLM 辅助软件交付的整体流程,以及其中涉及到的知识管理。
从今天这节课开始,我们将进入如何使用 LLM 辅助软件开发的环节。让我们从一个例子开始。

命令行参数解析

我们所使用的例子源自 Robert C. Martin 的 Clean Code 第十四章,也是我的测试驱动专栏《TDD 项目实战 70 讲》讲过的第一个项目,需求描述如下:
我们中的大多数人都不得不时不时地解析一下命令行参数。如果我们没有一个方便的工具,那么我们就简单地处理一下传入 main 函数的字符串数组。有很多开源工具可以完成这个任务,但它们可能并不能完全满足我们的要求。所以我们再写一个吧。
 
传递给程序的参数由标志和值组成。标志应该是一个字符,前面有一个减号。每个标志都应该有零个或多个与之相关的值。例如:
 
-l -p 8080 -d /usr/logs
 
“l”(日志)没有相关的值,它是一个布尔标志,如果存在则为 true,不存在则为 false。“p”(端口)有一个整数值,“d”(目录)有一个字符串值。标志后面如果存在多个值,则该标志表示一个列表:
 
-g this is a list -d 1 2 -3 5
 
“g” 表示一个字符串列表[“this”, “is”, “a”, “list”],"d"标志表示一个整数列表[1, 2, -3, 5]。
 
如果参数中没有指定某个标志,那么解析器应该指定一个默认值。例如,false 代表布尔值,0 代表数字, "" 代表字符串,[]代表列表。如果给出的参数与模式不匹配,重要的是给出一个好的错误信息,准确地解释什么是错误的。
 
确保你的代码是可扩展的,即如何增加新的数值类型是直接和明显的。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

1. 使用大语言模型(LLM)辅助进行业务知识管理,学习使用LLM辅助软件交付的整体流程,以及其中涉及到的知识管理。 2. 强调了即使使用LLM生成了代码,仍需要进行测试来验证代码的正确性,以及使用LLM生成测试的过程。 3. 发现使用LLM生成的代码存在问题,需要进行调试和修改,以及提出错误信息来指导LLM修改代码的过程。 4. 展示了调试过程中对生成的代码进行修改,以及再次执行测试仍存在错误的情况。 5. 强调了测试的重要性,以及在调试过程中不断修正代码和测试的过程。 6. 展示了对生成的代码进行修改后再次执行测试,依然存在错误的情况。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《徐昊 · AI 时代的软件工程》
新⼈⾸单¥98
立即购买
登录 后留言

全部留言(5)

  • 最新
  • 精选
  • 穿靴子的加菲猫
    “l”(日志)没有相关的值,它是一个布尔标志,如果存在则为 true,不存在则为 false。“p”(端口)有一个整数值,“d”(目录)有一个字符串值。标志后面如果存在多个值,则该标志表示一个列表:   -g this is a list -d 1 2 -3 5   “g” 表示一个字符串列表[“this”, “is”, “a”, “list”],"d"标志表示一个整数列表[1, 2, -3, 5]。   这里第二个d是不是换个字母好点,后文第二次调试时d代表字符串,会增加理解成本

    作者回复: 原本需求就这样

    2024-04-10归属地:上海
  • 术子米德
    🤔☕️🤔☕️🤔 【Q】前面的课程,拉来认知模型,拉出LLM辅助建模和用户故事,做了这么多准备,怎么就跳跃到CleanCode的parseCmdLineArgs,这是出现幻觉了嘛?项目里,难道不是基于用户故事和建出来的模型,开始拆解到任务列表,让LLM浸泡在这个KnowledgeContext里持续辅助,然后用TDD的方法边验证、边实现、边详细设计、边螺旋迭代嘛? 忽然间切换KnowledgeContext,这个人也适用不了,更何况LLM怎么适应,这个跳跃真不懂。 — by 术子米德@2024年4月10日

    编辑回复: 因为在你说这的这些之前,需要把技术知识处理掉。比如你说拆任务这个 那需要把架构和测试策略 放到llm里才行。后续课程里这个例子还会再做一遍,到时可以仔细对比一下两种方式的不同。

    2024-04-10归属地:日本
  • 术子米德
    //BEGIN UT CODE GENERATED BY GITHUB COPILOT, EXCEPT FIRST LINE COMMENT //use gtest to test the function CC_parseCmdLineArgs defined in CC_parseCmdLineArgs.h #include "CC_parseCmdLineArgs.h" #include <gtest/gtest.h> TEST(CC_parseCmdLineArgs, NullCmdLineArgs) { CC_CmdLineArgs_T CmdLineArgs; EXPECT_EQ(CC_FAIL, CC_parseCmdLineArgs(0, NULL, &CmdLineArgs)); } TEST(CC_parseCmdLineArgs, NullCmdLineArgsPtr) { EXPECT_EQ(CC_FAIL, CC_parseCmdLineArgs(0, NULL, NULL)); } TEST(CC_parseCmdLineArgs, NoArgs) { CC_CmdLineArgs_T CmdLineArgs; char *argv[] = { (char *)"test" }; EXPECT_EQ(CC_SUCCESS, CC_parseCmdLineArgs(1, argv, &CmdLineArgs)); EXPECT_FALSE(CmdLineArgs.IsLoggingEnabled); EXPECT_EQ(0, CmdLineArgs.RecvPort); EXPECT_EQ(NULL, CmdLineArgs.pLogSavingDir); } ... TEST(CC_parseCmdLineArgs, RecvPort) { CC_CmdLineArgs_T CmdLineArgs; char *argv[] = { (char *)"test", (char *)"-p", (char *)"1234" }; EXPECT_EQ(CC_SUCCESS, CC_parseCmdLineArgs(3, argv, &CmdLineArgs)); EXPECT_FALSE(CmdLineArgs.IsLoggingEnabled); EXPECT_EQ(1234, CmdLineArgs.RecvPort); EXPECT_EQ(NULL, CmdLineArgs.pLogSavingDir); } TEST(CC_parseCmdLineArgs, LogSavingDir) { CC_CmdLineArgs_T CmdLineArgs; char *argv[] = { (char *)"test", (char *)"-d", (char *)"/tmp" }; EXPECT_EQ(CC_SUCCESS, CC_parseCmdLineArgs(3, argv, &CmdLineArgs)); EXPECT_FALSE(CmdLineArgs.IsLoggingEnabled); EXPECT_EQ(0, CmdLineArgs.RecvPort); EXPECT_STREQ("/tmp", CmdLineArgs.pLogSavingDir); } TEST(CC_parseCmdLineArgs, AllArgs) { CC_CmdLineArgs_T CmdLineArgs; char *argv[] = { (char *)"test", (char *)"-l", (char *)"-p", (char *)"1234", (char *)"-d", (char *)"/tmp" }; EXPECT_EQ(CC_SUCCESS, CC_parseCmdLineArgs(7, argv, &CmdLineArgs)); EXPECT_TRUE(CmdLineArgs.IsLoggingEnabled); EXPECT_EQ(1234, CmdLineArgs.RecvPort); EXPECT_STREQ("/tmp", CmdLineArgs.pLogSavingDir); } int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
    2024-04-10归属地:日本
  • 术子米德
    //BEGIN CODE&COMMENT BY ME typedef enum { CC_SUCCESS = 0, CC_FAIL = 1, } CC_Result_T; typedef struct { bool IsLoggingEnabled; //-l int RecvPort; //-p <port> char *pLogSavingDir; //-d <dir> } CC_CmdLineArgs_T; /** * @brief: Use CC_parseCmdLineArgs to parse command line arguments and save them in CC_CmdLingArgs_T. * * @param argc same as main * @param argv same as main * @param pCmdLineArgs pointer to CC_CmdLineArgs_T * @return CC_SUCCESS if successful, CC_FAIL otherwise in CC_Result_T */ CC_Result_T CC_parseCmdLineArgs(int argc, char *argv[], CC_CmdLineArgs_T *pCmdLineArgs);
    2024-04-10归属地:日本
  • aoe
    使用 AI 生成的测试通过 9 个,失败 7 个。在已有代码上修补,比自己从 0 到 1 实现快了非常多,这个只用了十几分钟! 主要步骤: 1. 15 课的例子扔给 coze 的 GPT4,得到的代码简单粗暴 2. 使用 Optimize 功能优化一下 prompt 3. 在优化的 prompt 上添加自己的想法 4. 因返回 token 限制,需要多次对话完成结果 4.1 请给出 CommandLineParser 的完整代码 4.2 请给出完整测试代码 4.3 补全测试代码:测试用例可以继续增加,包括各种边界情况和无效输入 5. 最终得到的代码虽然测试没跑通,但功能强大
    2024-04-10归属地:浙江
收起评论
显示
设置
留言
5
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部
文章页面操作
MAC
windows
作用
esc
esc
退出沉浸式阅读
shift + f
f11
进入/退出沉浸式
command + ⬆️
home
滚动到页面顶部
command + ⬇️
end
滚动到页面底部
⬅️ (仅针对订阅)
⬅️ (仅针对订阅)
上一篇
➡️ (仅针对订阅)
➡️ (仅针对订阅)
下一篇
command + j
page up
向下滚动一屏
command + k
page down
向上滚动一屏
p
p
音频播放/暂停
j
j
向下滚动一点
k
k
向上滚动一点
空格
空格
向下滚动一屏
播放器操作
MAC
windows
作用
esc
esc
退出全屏
⬅️
⬅️
快退
➡️
➡️
快进
空格
空格
视频播放/暂停(视频全屏时生效)