与 AI 同行。
出题
最直接使用 AI 的方法,就是出题。出题方式适用于写工具类。
如 “再谈函数式编程:释放编程创造力” 一文所示。
再给一例:
AI + 函数式 + 泛型编程,将能让你的编程效率成倍提升。
package util
import (
"runtime"
"sync"
)
/*
* 接收一个普通函数 plainFunc,返回一个可以并发调用 plainFunc 的函数,这个函数接收一个列表,返回另一个列表
* 这个结果列表由单个函数调用结果汇集而成
*/
func ConcurrentExecute[T any, R any](plainFunc func([]T) []R) func([]T) []R {
return func(list []T) []R {
ch := make(chan []R)
var wg sync.WaitGroup
subListSize := len(list) / runtime.NumCPU()
if subListSize == 0 {
subListSize = 1
}
for i := 0; i < len(list); i += subListSize {
end := i + subListSize
if end > len(list) {
end = len(list)
}
wg.Add(1)
go func(start, end int) {
defer wg.Done()
ch <- plainFunc(list[start:end])
}(i, end)
}
go func() {
wg.Wait()
close(ch)
}()
var finalResult []R
for resultPart := range ch {
finalResult = append(finalResult, resultPart...)
}
return finalResult
}
}
利用 AI 生成自动化工具
更复杂的出题,让 AI 生成自动化的完整实用工具。注意要详述要求。
比如,java 工程转 Go,需要把大量 Java 对象转成 Go 结构体。需要一个批量转换工具,不是手工编码。
写一个 java 程序,对于给定 java 对象,将其转成 Go 结构体。
比如
public class ScriptDTO {
@JsonProperty("pguid")
private String pguid;
/**
* 脚本类型
*/
@JsonProperty("type")
private String type;
@JsonProperty("rule")
private Rule rule;
@JsonProperty("sha256s")
private List<String> sha256s;
@JsonProperty("param")
private Map<String, Object> param;
@JsonProperty("create_time")
private Long createTime;
}
转成
type AgentScript struct {
Pguid string `json:"pguid"`
Type string `json:"type"`
Rule Rule `json:"rule"`
CreateTime int64 `json:"create_time"`
Sha256s []string `json:"sha256s"`
Param map[string]any `json:"param"`
}
要求满足如下条件:
- 类名、字段名、字段类型可以反射方式获取
- Java 字段类型要转换为 go 的对应字段类型
- go 结构体字段与 Java 类定义的字段顺序保持一致。
- Java 注释内容 /** comment */ 写在 结构体字段定义的后面,以 // 开始;如果没有则省略。
- 考虑字段没有 @JsonProperty("rule") 注解的空情形。
- 要求能够处理 java 里的各种原子类型,比如 int, Integer, String, Boolean, Long, long; 自定义类型按原样输出。
- go 结构体字段要首字母大写。
- 将 go 结构体写入用户主目录下 ~/ 的文件。文件名是类名的小写下划线形式,去掉最前面的下划线。
- 保持程序的模块化和易修改,做好错误处理。
- 请给出完整可用程序,不要伪代码。
写一个 java 完整程序,指定一个 java 包名,对这个包及其子包下的所有 后缀为 DTO.java ,或 DO.java 的 java 类,根据上述方法生成对应 go 结构体,并写入对应文件,写入用户主目录下 ~/ 的文件。文件名是类名的小写下划线形式,去掉最前面的下划线。 结构层级与包层级保持一致。
有时,AI 不能一次性生成完整程序,则需要出多道题把答案拼起来。
固定模式代码
比如设计模式代码。指定设计模式名称,则可直接生成对应代码。
例如:“Go 模板:用代码生成代码”一文中用 AI 生成生成器模式代码。
类似还有工厂、策略模式代码等。
提供样例
如果要生成的代码比较多但有固定样式,则可以提供样例。如下所示:
请记住如下样例:
给定一个 java 枚举:
public enum DetectionMethodEnum {
PROCESS_HASH("process_hash", "进程Hash检测"),
private final String type;
private final String desc;
}
生成对应的 go 枚举为:
type DetectionMethod string
type DetectionMethodInfo struct {
MethodType string
Desc string
}
const (
ProcessHash DetectionMethod = "PROCESS_HASH"
)
var DetectionMethodMap = map[DetectionMethod]DetectionMethodInfo{
ProcessHash: {
MethodType: "process_hash",
Desc: "进程Hash检测"
}
}
请严格按照样例,为下面的 java 枚举生成 go 枚举。
@Getter
@AllArgsConstructor
public enum ContainerTypeEnum {
DOCKER("docker", "docker_container"),
CONTAINERD("cri", "cri_containerd"),
CRIO("crio", "crio_container");
private final String type;
private final String name;
}
提供模板
与提供样例类似。模板通过若干变量生成。
请记住如下样例:
给定 do 类 DetectionDO, 生成:
type DetectionService interface {
service.BaseService[*models.DetectionDO]
}
type DetectionServiceImpl struct {
service.BaseService[*models.DetectionDO]
}
func NewDetectionService(repo repository.DetectionRepository) DetectionService {
return &DetectionServiceImpl{
BaseService: service.NewMongoService[*models.DetectionDO](repo),
}
}
func init() {
dow.ProvideGlobal[DetectionService](nil, func(injector *do.Injector) (DetectionService, error) {
repo, err := dow.InvokeGlobal[repository.DetectionRepository](nil)
if err != nil {
return nil, err
}
return NewDetectionService(repo), nil
})
}
type DetectionRepository interface {
repository.BaseRepository[*models.DetectionDO]
}
type DetectionRepositoryImpl struct {
repository.BaseRepository[*models.DetectionDO]
}
func NewDetectionRepository(db *mongox.Database) DetectionRepository {
return &DetectionRepositoryImpl{
BaseRepository: repository.NewMongoRepository[*models.DetectionDO](db.Collection(models.DetectionDO{}.TableName())),
}
}
func init() {
dow.ProvideGlobal[DetectionRepository](nil, func(injector *do.Injector) (DetectionRepository, error) {
database, err := mongox.TenantDatabase()
if err != nil {
return nil, err
}
return NewDetectionRepository(database), nil
})
}
请为 DO 类 IdsFileUploadTaskDO 生成 service 和 repository 代码。
语言翻译
将如下 Java 代码转换为 Go 代码:
public static String[] getCmdOutput(String cmd) throws InterruptedException, IOException {
long start = System.currentTimeMillis();
Process process = new ProcessBuilder().command("sh", "-c", cmd).start();
boolean ret = process.waitFor(3, TimeUnit.SECONDS);
String output = StringUtils.EMPTY;
String error = IOUtils.toString(process.getErrorStream(), StandardCharsets.UTF_8);
if (ret) {
output = IOUtils.toString(process.getInputStream(), StandardCharsets.UTF_8);
LOG.info("cmd: {} output: {}", cmd, output);
} else {
LOG.warn("cmd:{} ret is false", cmd);
process.destroyForcibly();
}
long end = System.currentTimeMillis();
LOG.info("exec cmd: {} cost: {} ms", cmd, (end-start));
return new String[] { output, error };
}
分离纯函数
很多业务方法,大部分都是纯逻辑(输入相同则输出也相同,具有引用透明性),只有少量是依赖外部服务的。
这时候,可以运用“分离纯函数”的技巧,将方法中的纯逻辑与依赖分离。AI 特别适合于生成无语境或无依赖的纯函数。
可参考 “改善代码可测性的若干技巧”和“使用Java函数接口及lambda表达式隔离和模拟外部依赖更容易滴单测”这两篇文章。
具体方法是: 先对方法进行拆解,把外部依赖部分抽取出来。外部依赖部分可以用函数参数替代,这样这个方法就变成了一个纯函数,可以用 AI 自动生成,并用 AI 生成测试用例和单测。
仔细再审视我们的工程代码,会发现,其实 80% 都是纯逻辑,真正的业务部分可能只占 20%。经过良好抽象之后,把纯逻辑提取出来,把业务部分做成配置,则理论上 80% 的代码可以用 AI 生成。
AI 代码纠错
定义
type ValueModifier[T any] func(T, ...any)
func DuplicateAndModifyElement[T any](list []*T, keyFunc funcs.IdKey[T], mFunc funcs.ValueModifier[*T], args ...any) []*T {
seen := make(map[string]bool)
result := make([]*T, 0, len(list))
for _, elem := range list {
key := keyFunc(*elem)
if !seen[key] {
seen[key] = true
mFunc(elem, args)
result = append(result, elem)
}
}
return result
}
为什么 这行报错,如何修复
pb := []*test.PersonBasicInfo{{Name: "qin", Age: 36}, {Name: "ni", Age: 28}, {Name: "qin", Age: 29}, {Name: "ni", Age: 28}}
undupAndModified := util.DuplicateAndModifyElement(pb, func(info test.PersonBasicInfo) string { return info.Name }, func(p *test.PersonBasicInfo, skills ...string) { p.Skills = skills }, "programming")
AI CodeReview
现在 gitlab 已经集成了 AI Code review 。这些 review 还是相对中肯的。
小结
对于高级程序员来说, AI 是一个强大的工具,真如虎添翼。
如何利用 AI 来提升效率和创造性,是一个很好的话题。
更多姿势还在解锁中。。。