打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
什么是元编程?

临下班的紧急任务

时钟指向6点半,张大胖今天不太忙,想着今天终于可以早点儿下班了。

收拾好东西准备离开的时候,领导布置了一个新任务,张大胖很无奈,哀叹一声,老老实实地坐下来。

新任务看起来非常简单:从一个CSV文件中读取数据,形成Java对象,然后对外提供一个API,让别人调用。

这个CSV文件叫做employee.csv, 张大胖打开这个CSV文件,里边的内容一看就懂。

name,age,level

Andy,25,B7

Joe, 22, B6

张大胖的API就需要返回一个List,很自然,Employee类长这个样子:

class中的每个字段和csv文件的“表头”的“列名”保持一致。

这样简单的任务对张大胖来说是小菜一碟,他写了一个EmployeeParser,专门解析CSV文件,形成Employee对象,半个小时不到就收工了,赶紧下班!

还没来得及溜走,又被领导叫住了:“大胖,那个CSV文件新加了一个字段,叫做salary ,快把你的程序改一下啊!”

name,age,level,salary

Andy,25,B7,3000

Joe, 22, B6,2500

张大胖极不情愿地坐下来,给Employee类增加了一个salary的字段,又修改了EmployeeParser类,增加对这个字段的解析。

然后又听到领导在喊:“又加了一个字段,叫做tax !”

没辙,继续修改Employee类和EmployeeParser类吧。 这一次修改完,领导终于放他走了。

模板:用程序来生成程序

等了两趟车,终于在西二旗挤上了13号线,张大胖心里一直在想:明天保不齐还要增加字段,这真是让人厌烦的重复劳动啊。大家都说,Don't repeat yourself, 我这怎么才能减少重复呢?

关键点就在于,那个Java类的字段要和CSV的表头的列名做对应,CSV变化了,Java类的字段以及解析的方法都要做相应得修改才可以。

对了,能不能根据CSV的列名自动地生成那个Employee类啊,这样问题不就解决了吗? CSV变化, Employee类跟着变化,多好!

CSV的“列名”经过读取,可以变成一个Java 的List ,例如['name','age','level'], 如何写一段代码,把这个List变成一个Employee Class呢?

张大胖聚精会神,在地铁上想了一路,完全无视地铁上那拥挤的人群和污浊的空气。

快要下车时,他灵机一动,可以用模板技术嘛,比如velocity模板,定义一个employee.vm :

然后再写一个代码生成器,读取employee.csv的“表头”,形成List,把List传递给这个employee.vm模板,就可以输出Java类了:

写成具体的代码就是这个样子:

(友情提示:可左右滑动)

(码农翻身注:这里做了简化只关注了Empployee的字段,还需要处理getter/setter方法,尤其是也需要通过模板的方法生成EmployeeParser,用来形成Employee对象。此外还有数据类型的问题。)

在小区对面的田老师红烧肉吃了一份盖饭以后,张大胖立刻投入到程序的编写中来,一边写一边想:我这是用程序来生成程序啊!

元编程

第二天,领导果然要加新的字段了,张大胖心中暗自佩服自己的自知之明,调出昨晚写的“宝贝”执行了一下,不到一秒钟,新的Employee和EmployeeParser就生成了。

下午的时候,张大胖洋洋得意地给Bill展示自己的工作成果,Bill说:“不错啊,都开始元编程了!”

“元编程?”

“对啊,你不是用程序来生成程序嘛,这就是一种元编程。”

张大胖没想到的工作居然就是高大上的“元编程”,更高兴了。

“还有,如果把CSV文件看成数据库的表,代码生成器自动生成的EmployeeParser不就相当于DAO吗?Employeeb 不就是和数据表映射的Domain对象吗? 你的代码实现了Object-relational mapping !”

就是啊,我怎么没想到,虽然距离真正的O/R Mapping还很远,但思想是一致的,大神就是厉害,看透了本质,张大胖暗想。

可是Bill很快给它泼了一盆冷水:“不过这种用模板生成的方式还是有些‘低级’,每次CSV文件有变化,都需要运行一下代码生成器才可以。”

“那怎么办?”

“其实吧,这个Employee的类没有必要在编译期存在,如果能在运行时动态地生成就行了。”

运行期动态生成? 张大胖有点懵。

“对于Java语言来说,运行期在内存中动态生成一个Class,还是有难度的,你需要透彻理解Java Class的文件格式,还需要在底层需要用ASM这样的东西去操作Java字节码。”

“文件格式和字节码?就是那些0xCAFEBABE,iload ,iadd, putfield,invokespecial ? ” 张大胖看过虚拟机的书,知道有很多字节码,但是操作它们形成符合要求的类,实在是难以想象。

Bill 笑道:“你可以用动态语言,比如Ruby,元编程很强大,实现你这个功能简直是小菜一碟。”

Bill很快就写出了一段代码:

(友情提示:可左右滑动)

张大胖没有学过Ruby , 看到这里更懵了。

Bill看到张大胖发呆的样子,说道:”经过上述处理,内存中创建了一个类,如果把它的源码展示一下,你就明白了。”

(友情提示:可左右滑动)

(码农翻身注:对CSV文件内容的读取没有包括在其中。)

张大胖明白了,这个类是由数据驱动,动态生成的,CSV的header 中有多少字段,这个类就会生成多少个属性。

和自己的代码生成器比较了一下,Ruby写的这段代码更加精炼,不需要模板,没有所谓代码生成器,或者说,代码生成器和生成的类已经合二为一了。

即使是CSV文件发生了变化,也不需要额外运行代码生成器,只需要执行那段Ruby代码就行。

Bill问道:“怎么样,元编程不错吧?”

张大胖说道:“嗯, 这Ruby的元编程能力很强大啊,可惜的是,我们的项目都是Java的,这动态的脚本语言Ruby没法直接使用,如果是微服务,对外提供的是HTTP的API,我可以学学Ruby,单独写个Ruby项目。”

Bill说:“其实吧,编程语言中,元编程能力最强大的还属LISP,在LISP当中,程序和数据的表现形式是一致的,造就了它无以伦比的元编程能力,LISP程序可以像操作数据一样操作代码。 有人甚至说,LISP根本不是编程语言,它是编程元语言,专门为了生成程序而生。”

张大胖听得云里雾里,黯然道:“不知道你在说什么,太抽象了!等我学学LISP以后再回来和你讨论吧。”

(完)

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Ruby元编程构造简单优雅解决方案
跨越边界: Streamlined,第 2 部分
想快速成为编程高手?这个技巧必不可少!
31.5小时Ruby入门到精通 Learn to Code with Ruby
Python编程语言学习:在pandas中设置某字段为索引列,并在dataframe中指定该索引列
滚动条代码生成器
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服