让AI替代50%的工作 ——利用 AI 进行代码改写与依赖迁移
chinese AI
本文以及本专栏正在参加豆包 Marscode 专栏征文活动,如何喜欢欢迎投票支持,这将对我们意义非凡
投票链接
以下实战案例均使用豆包 MarsCode AI 工具,欢迎大家尝试!
在我们讨论使用 AI 进行代码改写和依赖迁移之前,先思考一个问题:从信息的角度来看,代码的描述力处于什么水平?
例如,当我有一个业务需求,不考虑书写描述的难度,仅考虑不同描述方式的“描述力”,是用文字描述这个业务描述力强,还是用代码描述力强?
这个问题没有统一的答案。如果是哲学问题,我相信文字的能力大于代码;但如果是逻辑问题,我认为代码的描述能力更强。许多追求“Code is Law”的朋友相信,一个详尽描述所有情况的代码就是法律,是比法律条文更可靠、更能避免二义性的描述方式。当然,这就有点扯远了。
我们回到描述力。在利用 AI 辅助编程时,我们的核心任务是使用各种方式让 AI 理解我们想做的事、提供足够的上下文。我认为这是 AI 辅助编程中人类的核心任务。如果从 AI 辅助编程扩展到设计 AI 应用,人类的任务就多了一个 给 AI 提供足以完成任务的外部能力。当然,我们这里仅限于 AI 编程,AI 应用的故事我们之后有机会聊。
所以,对于 AI 了解你的需求,没有什么比你的代码更具有信息量。在理解了这件事后,让我们开始这一章的学习。
依赖迁移
我们从我个人常用的技巧开始。就像前几章我们举过的 JS 生态中 moment.js 和 day.js 的例子,前者是一个几乎在现代开发中没有使用价值的老旧库,但依旧在许多遗留代码库中占据主流。因此,在公司内部安全要求和供应链安全的要求下,我们经常会做类似的迁移。
这里我们以 moment.js 迁移到 luxon.js 为例,因为 luxon.js 提供了完整的与 moment.js 对比的文档。
对不熟悉 JS 或相关背景的朋友,不需要理解代码(其实熟悉的朋友也不需要理解代码,这些并非真实代码),重点在于交互的过程。
首先,我们有一部分基于 moment.js 进行日期计算的 Node.js 代码:
const moment = require("moment");
// 获取当前日期和时间
const now = moment();
// 格式化日期
console.log(now.format("YYYY-MM-DD HH:mm:ss"));
// 解析日期字符串
const date = moment("2023-04-15", "YYYY-MM-DD");
// 日期加减
const nextWeek = date.add(7, "days");
// 获取星期几
console.log(nextWeek.format("dddd"));
然后,我们进行提示,要求 AI 进行迁移:
我有一段使用 moment.js 的 JavaScript 代码,需要将其迁移到使用 luxon.js。请帮助我改写以下代码,并确保功能保持不变:
<your-code>
请在改写后,解释每一处改动的原因和 luxon.js 中对应的方法。
这里有一个注意点。
因为 moment.js 和 luxon.js 都是非常流行的库,且 API 相对稳定,在 AI 训练数据库中有一定的比重,所以改写质量还可以。
但依赖库的 API 变化太快了,我们不应该依赖于此,而是应该手动提供有价值的信息。同样地,提供信息的原则是:给我同样的信息我可以顺利完成这个任务。熟练背诵最新的 API 显然不是我们具备的能力,也不应该是我们要求 AI 具备的能力。
所以,这就是我们应该提供的信息:luxon.js 文档:给 Moment 用户:
我有一段使用 moment.js 的 JavaScript 代码,需要将其迁移到使用 luxon.js。请帮助我改写以下代码,并确保功能保持不变:
<your-code>
这是相关的文档供你参考:<doc>
请在改写后,解释每一处改动的原因和 luxon.js 中对应的方法。
由于我们的改写任务不是一个特别复杂的程序,且 moment.js 和 luxon.js 比较流行,所以两次输出的结果是一致的。但对于内部库、小众库或者是最新的库,这种方法的效果会更好。
这个技巧也很适合对代码库进行依赖的升级,例如使用升级 Redux 5.0 到 RTK 2.0 的迁移文档作为上下文,来帮助升级 Redux 相关的依赖。
语言迁移
就像前文说的,代码是描述力更强的方式,能够让 AI 更深入理解我们的需求。在日常工作中,我们的很多工作并不是开创性的,甚至极少有开创性的工作,所以参照现有的代码是很常见的。
不同语言擅长和常见的工作领域不一样。例如,我之前在做关于 GIS(Geographic Information System,地理信息系统)的业务时,大量的相关代码是用 C++ 写的,而使用 TS(TypeScript)的参考代码就很少。之前在这种情况下,需要自己先理解 C++ 语法和这个程序,然后想到对应的 TS 写法,最后改写成 TS 版本。现在,这个任务用 AI 显然是非常方便的。
例如,我们现在有一段使用 C++ 编写的计算经纬度的代码:
#include<iostream>
#include "math.h"
using namespace std;
#define pi 3.1415926535897932384626433832795
#define EARTH_RADIUS 6378.137 //地球半径 KM
double rad(double d)
{
return d * pi /180.0;
}
double RealDistance(double lat1,double lng1,double lat2,double lng2)//lat1第一个点纬度,lng1第一个点经度,lat2第二个点纬度,lng2第二个点经度
{
double a;
double b;
double radLat1 = rad(lat1);
double radLat2 = rad(lat2);
a = radLat1 - radLat2;
b = rad(lng1) - rad(lng2);
double s = 2 * asin(sqrt(pow(sin(a/2),2) + cos(radLat1)*cos(radLat2)*pow(sin(b/2),2)));
s = s * EARTH_RADIUS;
s = s * 1000;
return s;
}
int main()
{
cout<<RealDistance(34.04640,-118.434,34.042,-118.429);
return 0;
}
我们使用 AI 将其转换成使用 JS 实现的代码:
这里是一段使用 C++ 编写的计算两个经纬度坐标点之间的距离的代码,帮我改写成 TS 版本,注意计算的准确度。
注意,代码风格符合 TS 的习惯。
<c++_code>
这里 AI 写的代码在一些细节上还有优化空间,就像我们前面章节提到的,AI 并不能解决所有问题。所以,这里是给我们提供了一个基础的实现,我们可以在此基础上进行修改,要比我们从零开始实现方便得多。
对大多数人来说,比起完整地写代码,更擅长在一定基础上修改代码。
在 prompt 中,我们强调了注意计算的准确度,这是因为 TS 不擅长做科学计算。这里可以根据自己的需求进行额外的强调,例如:
- 注意代码的简洁
- 使用 xxx 库去实现
- 注意复用现有的工具函数
<your-code>
- 使用 ES6 编码风格,不要使用 var
- …
应用这些额外的要求,来提高 AI 代码输出的质量。
代码风格改写
代码风格改写是指一些旧的写法、旧的风格,需要我们统一改成新的实现方式,但这过程中是繁琐的重复劳动,并不需要投入太多精力。例如在 JS 中,经典的把回调地狱改成 async/await 的方式,修改起来并不涉及复杂的逻辑,但又不是简单的字符替换,需要稍微花一些心思,就很适合 AI 来做。
原代码:
function getUserData(userId, callback) {
database.getUser(userId, function (err, user) {
if (err) return callback(err);
api.fetchProfile(user.profileId, function (err, profile) {
if (err) return callback(err);
cache.save(userId, profile, function (err) {
if (err) return callback(err);
callback(null, profile);
});
});
});
}
然后使用 AI 进行修改:
请将以下使用回调函数的代码改写为使用 `async/await` 的现代写法:
<your-code>
然后我们只需要做审核工作,验证 AI 的修改逻辑。