前言

这里的代码生成指的是模板代码生成,不是AI生成。模板代码生成是现代工程的核心基础设施,用户需要自己编写一个配置文件(文件内容当然要比生成的代码短得多),然后结合具体的模板生成相应代码。

解答困惑

我不知道会不会有人和我有同样的问题:

  1. 我们作为程序员不就是写代码的吗,为什么还要生成代码?

  2. AI发展这么快,为什么不让AI来生成代码,模板代码生成有什么不可替代性?

  3. 实际上手的时候,模板代码生成的技术该怎么用,用在哪?

在腾讯实习的这段时间,项目内的代码生成工具我用的很频繁,我来谈谈对上面几个问题的理解:

为什么要用代码生成

对于很多业务来说,服务器的工作其实是重复的,一个典型的例子就是数据库的CRUD,对于一个大型游戏来说,这种类型的业务非常多,程序员的精力应该投入到涉及逻辑操作、算法实现等较为复杂的需求中,而不是投入到大量的重复劳作中去,因此代码生成显得很有必要,对于我们来说,我们只需要编写一个合适的配置文件,剩下的CRUD操作就交给模板代码去生成,一方面保证了数据库操作相关代码的稳定性,另一方面极大地节省了程序员的精力,提高开发效率。

模板代码生成的不可替代性

我们不得不承认AI发展的迅猛,但AI生成代码还不能取代模板代码生成。

AI生成的代码终究是受随机数影响的,即使我们的需求会讲的很明确,但我们仍不能保证AI生成的代码的一致性,一个最简单的例子就是变量名,同样是“目标”,AI前一次可能叫target,后一次就可能叫成goal,前一次可能叫get_num(),后一次就可能叫成num_get(),这看着都是小事,但是在程序中,这种灵活性往往是个麻烦。

模板代码生成应该怎么用,用到哪?

就像前面说的一样,模板代码最终要解决的就是程序员的重复劳作问题,那些重复性的工作不应该交给程序员来费心,就像计算机诞生的最初目的就是解决重复运算一样。

因此我们大可以讲:“哪里有重复哪里就可以用模板代码生成。

了解模板代码生成的原理

既然模板代码生成这么好用,那它的原理一定很复杂吧?其实并不是,正相反,模板代码这个技术并不复杂,其实我们只需要了解他的原理就能实现个大概了。

组成结构

模板代码生成系统的构成其实非常简单,整个系统由配置文件、代码生成引擎、模板代码文件三个部分构成。

配置文件是模板代码生成中程序员操作最为频繁的部分,它包含了要生成的代码的关键信息,程序员在其中指定生成的类名,变量名,方法名等,并在其中指定相关的扩展选项,例如网络协议、游戏指令等内容。

模板代码文件则是模板代码生成是需要用的“地基”,它决定了要生成的代码的基本结构,包括模板类、模板变量、及包含简单逻辑的模板方法,使得生成的代码具有相关的基本功能,以供程序员使用。

代码生成引擎则是整套系统的核心,它负责把配置文件的语意进行解析,并结合模板代码文件生成目标代码。

实践

在实践部分我们会将配置文件命名为*.mcg (Mew gull framework Code Generator)模板代码文件命名为*.tpl(Template)文件也是代码生成中常见的模板代码扩展名,代码生成引擎则是提前编译好的可执行文件,这样能节省编译代码所用的时间,并将代码生成集成到项目编译的阶段,节省工作流程。

模板代码生成需要实现的功能:

用户提供一些.mcg配置文件,配置文件形似C++、Java等语言,使用注解来丰富特性,举例如下:

// Base.mgfg
struct Vector3{
    float x,y,z;
}

struct DateTime{
    int year;
    int month;
    int day;

    int hour;
    int minite;
    int second;

    Action<int> onYearChg;
    Action<int> onMonthChg;
    Action<int> onDayChg;
    Action<int> onHourChg;
    Action<int> onMiniteChg;
    Action<int> onSecondChg;
}
// SchoolSystem.mgfg
import Base.mgfg

class People{
    [key = true] string id;
    string name;
    int age;
    Vector3 pos;
}

class Student:People{
    [key = true] string studentId;
    string classRoomId;
    DateTime enterTime;
    DateTime guaduateTime;
}

class Teacher:People{
    [key = true] string teacherId;
    List<string> classRoomId;
    DateTime enterTime;
    [ExpressFunc]
    int #Speak{
        string knowledge;
    }
}

class ClassRoom{
    string classRoomId;
    List<string> teachers;
    List<string> students;

    [NetFunc]
    void #OnLesson{
        string lessonId;
        float duration;
        int status;
    }
}

class School{
    List<string> classRoomId;

    List<Teacher> teachers;
    List<Student> students;
}

就像上面的代码写的那样,我们使用自定义的语法去构建一个模板文件,并用它来表示若干代码中的类、方法等,并基于此来实现一些模板化的功能。我们要做的就是创建一个tpl模板,编辑模板,根据.mcg和.tpl文件来生成目标代码。