免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 8066 | 回复: 13
打印 上一主题 下一主题

动词算子式代码生成器简介【理论随笔】 [复制链接]

论坛徽章:
1
天秤座
日期:2013-11-07 18:39:20
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2018-06-04 10:58 |只看该作者 |倒序浏览
本帖最后由 jerry_shen 于 2018-06-04 16:59 编辑

动词算子式代码生成器简介 【理论随笔】

    动词算子式代码生成器具体说来就是无垠式/和平之翼代码生成器阵列。是笔者所写的一系列易用的Java通用代码生成器。所有版本的动词算子式代码生成器都支持SGS(标准生成器脚本)语言。新版本的动词算子式代码生成器支持使用Excel模板生成Java项目。(包括无垠式代码代码生成器SimpleJEE 1.0.1版Ada,无垠式代码生成器JEEEU版1.5 Beta6 Ada,和平之翼代码生成器SMEU版 3.1 乌篷船)

    动词算子式生成器的主要概念是动词算子,域对象和棱柱。

    动词算子其实是功能的代名词,比如有一个动词算子称为ListAll,它会列出一个数据对象在数据库里的所有实例。所以ListAll动词算子和域对象Student的结合会产生一个具体的方法组ListAllStudents。它包括Dao,DaoImpl,Service, ServiceImpl, Facade和HTML5页面上的两个JS方法。这个方法组即是代码生成的目标。

    棱柱是围绕一个域对象的所有动词算子的功能的组合。如一个域对象Student,它对应的棱柱StudentPrism包含十余个动词如ListAll,Delete,SoftDelete,SearchByFieldsByPage等等,一个棱柱包含若干界面和驱动其所有界面的代码逻辑。

    动词算子式代码生成器生成是不需要数据库连接,它可以生成所有的数据库脚本,您可以将生成的zip包导入Eclipse JEE版进行进一步的功能代码开发。

    如此易用的Java代码生成器您值得一试。

    以下是主要的代码生成器的项目地址,敬请您的到来。

https://gitee.com/jerryshensjf/InfinityJEEEU

https://gitee.com/jerryshensjf/InfinitySimpleJEE

https://gitee.com/jerryshensjf/PeaceWingSMEU

https://gitee.com/jerryshensjf/InfinityGPGenerator

论坛徽章:
1
天秤座
日期:2013-11-07 18:39:20
2 [报告]
发表于 2018-06-04 10:58 |只看该作者
代码生成器技术乱弹一,多对多关系与双域动词

    在动词算子式代码生成器(无垠式代码生成器,和平之翼代码生成器)中的中心概念是如下三种,动词算子,域对象和棱柱。本文主要分析如下技术场景,使用上述概念分析和实现代码生成器中的多对多关系。

    我们知道,大多数代码生成器生成的功能大家都称之为单表操作,在动词算子式代码生成器中有一个对应的概念称为单域动词。在和平之翼代码生成器1.5实现多对多关系以前,所有的动词算子式代码生成器只支持单域动词,也就是说和现在大多数代码生成器是一样的。多对多关系为何不同?

    原因是多对多关系不是单表操作,而是一种双表操作。使用动词算子式代码生成器的术语,这是一种双域动词。描述了主域对象和从域对象之间的关系。具体说来为了实现两个对象之间的多对多关系,在和平之翼代码生成器1.5和以后的其它实现中,都实现了如下四个双域动词:ListMy,ListMyAvailable,Assign和Revoke,和单域动词不同,单域动词只属于其域对象的棱柱,而双域动词关系到两个棱柱。比如对域对象User而言,ListAll单域动词明显属于UserPrism棱柱。而User和Role之间的多对多关系应该属于User Prism还是RolePrism? 答案很简单,看谁是主域对象,谁是从域对象。如果User是主域对象,动词分别结合为ListMyRolesByUserId,ListMyAvailableRolesByUserId, AssginRolesToUser,RevokeRolesFromUser,这时很明显这些功能都从属于UserPrism。

    从理论上说,多对多关系意味者两个数据对象之间存在着一张联系表,其联合主键是两个对象的主键。在动词算子式代码生成器中,主键即所有域对象都有的domainid字段。所以很容易构造出两个域对象之间的多对多关系。

    对多对多的典型三栏式多对多单页式弹性界面如图所示,使用了一个单域动词和4个双域动词。

    如图:





     左侧的User列表框是User域对象的ListActive单域动词驱动的。中间的列表框,是ListMy双域动词。右侧的列表框是ListMyAvailable双域动词驱动的。中间和右侧列表框之间的两个按钮,是Assign和Revoke双域动词驱动的。一目了然,非常清晰,希望您可以理解。

论坛徽章:
1
天秤座
日期:2013-11-07 18:39:20
3 [报告]
发表于 2018-06-04 10:59 |只看该作者
代码生成器技术乱弹二,一对多关系的分析与实现

    类似多对多关系,其实一对多关系也是两个域对象之间的关系。一个域对象的Id记录在其他域对象中代表此域对象的所有信息。

    但是与多对多关系必须依赖双域动词不同,一对多关系可以使用两个单域动词来完成需要的功能。

    可以做如下分析。

   在我实现的动词算子式代码生成器中所有域对象都存在三个特殊字段:domainid,domainname,activefield即域对象的主键,域对象标准名字和域对象活跃字段(可以看作反置的软删除标志,如果此字段被命名为deleted或delete时,系统会自动使用软删除标志的语义)。一对多关系要解决的是如下两个问题:输入或查询字段时候变成下拉列表,在Grid字段里使用domainname代替数据库里实际保存的domainid值。

    解决这个问题有两种思路,使用联合查询或者使用两次查询。实际上在现有的动词算子式代码生成器的实现采用的是两次查询,把完整的动作拆成两部,采用单域动词实现。第一步是把主域对象查询出来,可以使用ListAll,ListActive,ListAllByPage或者是最新的主查询SearchByFieldsByPage。然后使用从域对象的ListActive单域动词将活跃的domainid翻译成domainname。下拉列表中的所有从域对象清单都是ListActive单域动词列出来的。

论坛徽章:
1
天秤座
日期:2013-11-07 18:39:20
4 [报告]
发表于 2018-06-04 10:59 |只看该作者
代码生成器技术乱弹三,所有字段搜索的主查询SearchByFieldsByPage

    对动词算子式代码生成器有所了解的同学都知道,动词算子式代码生成器有过两种界面,手写的蓝白两色的界面和后来的JQuery EasyUI界面。两者其实是不同的,支持的功能也并不完全一致。蓝白界面或者我们称之为经典界面支持如下的动词:ListAllByPage,SearchByName,Add,Update,Delete,SoftDelete,DeleteAll和SoftDeleteAll。而新的EasyUI界面支持更多的动词,如下SearchByFieldsByPage,Add,Update,Delete,SoftDelete,DeleteAll,SoftDeleteAll,Toggle和ToggleOne。

    很明显最大的不同是新的界面采用了所有字段的查询动词SearchByFieldsByPage,代替了原有实现中的ListAllByPage和SearchByName两个动词。这个动词是现有所有动词中最复杂和最难开发的动词。本文着重分析这个动词的实现。

    很直观,这个动词的场景如下:当页面加载时,相当于不加任何限制条件查询某域对象的数据库表,应该返回所有表中的数据,这种情况下,返回的数据其实和ListAllByPage是完全一致的。而如果查询domainname,这时返回的结果是和SearchByNameByPage是一致的。但是新的主查询支持对更多字段的查询。

    这个动词的难点是要生成正确的动态的查询语句,并以正确的顺序和数量设置查询键值并返回结果。在其MyBati实现和JDBC实现中都使用了类似技术。

    关键是要对字段逐一判断其是否为空,如果为空,就不生成相应字段的查询和设置键值的两段操作。值得注意的是这两段查询的位置顺序和判断空的条件必须完全匹配,否则会出现千奇百怪的错误。

    在我的实现中查询逻辑是和字段的类型绑定在一起的,是String类型进行like查询,其他字段进行相等查询。实现的结果您可以参考代码生成器的生成物或者代码生成器本身的源码。

论坛徽章:
1
天秤座
日期:2013-11-07 18:39:20
5 [报告]
发表于 2018-06-04 11:00 |只看该作者
代码生成器技术乱弹四,弹性万能界面

在代码生成器的实现中,有一个问题也是制约大家能否研发出代码生成器的关键之一。那就是界面。大家知道代码生成器是有一定灵活性的。如果一个代码生成器不能指定数据对象的字段,所有的关系都是僵死的,这样的代码生成器相信不会有太多用户,所以,代码生成器需要有一定的弹性。

        在动词算子式代码生成器中,解决这个问题的是使用了我称之为弹性万能界面的技术,或者更准确的说是单页式弹性万能界面。

        在动词算子式代码生成器中有三个特殊字段domainid,domainname和activefield。而弹性万能界面也有三个,主页模板基本上没有功能,单表操作的Grid单页式弹性万能界面和专用于多对多关系的三栏式多对多弹性万能界面。

        可以做如下分析,弹性万能界面最大的问题在于,如何处理不同对象的不同的字段。动词算子式代码生成器的解决方案是把变化集中于域对象。对域对象而言getDomainId返回主键,getDomainName返回域对象的标准名字,getFields返回所有字段,getFieldsWithoutId返回除了主键的所有其他字段。如此等等,有了这些方法,您就可以赋予界面以弹性。

        下图是Grid弹性万能界面的截图:





        下图是多对多弹性万能界面的截图:



论坛徽章:
1
天秤座
日期:2013-11-07 18:39:20
6 [报告]
发表于 2018-06-04 11:00 |只看该作者
代码生成器技术乱弹五,动词算子浅析

    无垠式和和平之翼代码生成器统称为动词算子式代码生成器。您是否知道为什么这类型的代码生成器称为动词算子式代码生成器?这里的主要问题是什么是动词算子。我们知道,所谓程序大师们给了一个公式:

程序=数据结构+算法

而我可以给一个公式,在动词算子式代码生成器中:

程序=域对象+动词算子

也就是说,动词算子在某种程度上是算法的等价物。

    那么,到底什么是动词算子,我的定义是动词算子是一组命名的函数级代码生成器堆栈。也就是说动词算子一旦和相应的域对象结合(如果是单域动词就是一个动词算子和一个域对象结合,如果是双域动词,是一个动词算子和两个域对象结合)。生成的结果是一个完整的方法堆栈包括了指定动词的Dao,DaoImpl,Service,ServiceImpl,Facade和JSButton和JSJsonAction的一系列方法。包括5个java方法和两个JavaScript方法。

    为何如此?答案是标准化,固定化以简化测试,降低通透测试需要的测试量。本质上,函数调用是一张网,一个函数可以调另一个函数。这是叫测试人员抓狂的测试工作量之网。不能这样干否则您的测试人员或者用户会把您吃了。所以我的解决方法是把某个函数固定搭配起来,比如ListAll的Facade方法只能调用LIstAll的ServiceImpl的方法,而ListAll的ServiceImpl也只能调用List All的DaoImpl方法,不知您编写过让人抓狂的方法调用Controller的DoGet方法调用ServiceImpl的listAllStudents方法,ServiceImpl的listAllStudents方法里调用queryAllPuple方法,而页面上的js方法叫另外一个古怪的方法。这是程序员的地狱。在动词算子式代码生成器中,命名是很有规律的。

    世界清静了?没这么简单,曾经,在无垠式代码生成器0.8以前。ListAll里面的方法永远是一致的,一个已经失落的程序员的天堂,为什么?因为有时和技术的绑定的关系。

    在和平之翼代码生成器中,动词算子SearchByFieldsByPage就是一个例子,比如它和student的结合在Facade层称为SearchStudentsByFieldsByPage,但是问题是分页查询,mysql里是limit ? offset ?,参数不对ByPage里是pagenum和pagesize不是这两个参数。所以需要把pagenum和pagesize换成limit和offset。我的解决方案是其dao和daoimpl的方法名是SearchStudentsByFieldsByLimit。一个动词算子的各层的名字不一致了。我也没办法,网状的调用模型在暗笑。

论坛徽章:
1
天秤座
日期:2013-11-07 18:39:20
7 [报告]
发表于 2018-06-04 11:01 |只看该作者
代码生成器技术乱弹六,编译器在拈花微笑

    到底什么是代码生成器,如何驱动代码生成器?这个问题不能一概而论,各家的做法也很不一致。有使用XML的,有使用JSON的,有使用SQL的,更多的,是采用图形界面操作的,定义数据对象,定义施加在这些操作对象上的各种操作,有时非常繁琐,有时非常易错。在我得到的唯一付费的代码生成器研发工作期间,我被授命开发一种"无码开发“的代码生成器。

    我的看法是,代码生成器是一种生成力很高,但是表现力受限的编译器。和大多数代码生成器一样。动词算子式代码生成器也是基于模板法的。但是如果您研究过这些代码生成器,您可以发现,它们是一种数据中心的代码生成器,不需要定义施加在数据即上的操作,只需要定义数据,也就是域对象,和域对象之间的关系,即可生成一个可以运作的系统。而且,不同的动词算子式代码生成器的架构很不相同,大概有近10种不同的架构。但是这些代码生成器支持的标准生成器脚本(SGS)却十分相似,在很多情况下,您只需要修改一下项目的technicalstack字段,比如从smeu改成jeeu。生成的代码就从Spring, Mybatis变成了html5,JDBC的了。

    为什么是这样?其实也很简单,这是编程的普遍规律。使用代码生成器的动机是什么,当然是省力。如何才能省力,当然是使用的工具高级。我有一比,在使用高级语言之前,程序员们使用的是汇编语言。工作量之艰巨叫现代人抓狂。据说,苏联人使用汇编语言编写了他们的巡洋舰的驱动代码110K,这是一个壮举,但也是成本高昂的。为啥汇编语言这么难写,易错,不易调试?我认为是其中的细节太多了,一种语言表现力越强,功能越强,其运用的难度,学习的难度,必然提高。就像一个雕塑家雕一座雕像,他必然是先用斧子,锤子等重工具把石头大致砍成基础的形状再使用刻刀的。在汇编语言时代,程序员就是面临着使用刻刀雕刻一尊雕像的烦恼。而代码生成器就是程序员的开山斧,是程序开发初期的利器。

    所以,代码生成器必须比高级语言生成力更高,否则,您为何要使用它呢?有没有办法?也很简单,约定优先于配置,简化关系的描述,最重要的,就是数据驱动,把程序对操作的描绘,尽可能省略掉。我对此的理解是,需要使用一种生产力比高级语言高10倍乃至于100倍的超级语言驱动代码生成器,代码生成器才有真正的意义。现在动词算子式代码生成器使用的是一种称为标准生成器脚本(SGS)的自定义语言,非常简略和高效,并有可以使用与此种语言等效的Excel模板来生成代码的选项。

    超级语言还是一种编程语言,还是跳不出编译器的五指山。所以,编译器在拈花微笑。

论坛徽章:
1
天秤座
日期:2013-11-07 18:39:20
8 [报告]
发表于 2018-06-04 11:36 |只看该作者
代码生成器技术乱弹三,所有字段搜索的主查询SearchByFieldsByPage

    对动词算子式代码生成器有所了解的同学都知道,动词算子式代码生成器有过两种界面,手写的蓝白两色的界面和后来的JQuery EasyUI界面。两者其实是不同的,支持的功能也并不完全一致。蓝白界面或者我们称之为经典界面支持如下的动词:ListAllByPage,SearchByName,Add,Update,Delete,SoftDelete,DeleteAll和SoftDeleteAll。而新的EasyUI界面支持更多的动词,如下SearchByFieldsByPage,Add,Update,Delete,SoftDelete,DeleteAll,SoftDeleteAll,Toggle和ToggleOne。

    很明显最大的不同是新的界面采用了所有字段的查询动词SearchByFieldsByPage,代替了原有实现中的ListAllByPage和SearchByName两个动词。这个动词是现有所有动词中最复杂和最难开发的动词。本文着重分析这个动词的实现。

    很直观,这个动词的场景如下:当页面加载时,相当于不加任何限制条件查询某域对象的数据库表,应该返回所有表中的数据,这种情况下,返回的数据其实和ListAllByPage是完全一致的。而如果查询domainname,这时返回的结果是和SearchByNameByPage是一致的。但是新的主查询支持对更多字段的查询。

    这个动词的难点是要生成正确的动态的查询语句,并以正确的顺序和数量设置查询键值并返回结果。在其MyBati实现和JDBC实现中都使用了类似技术。

    关键是要对字段逐一判断其是否为空,如果为空,就不生成相应字段的查询和设置键值的两段操作。值得注意的是这两段查询的位置顺序和判断空的条件必须完全匹配,否则会出现千奇百怪的错误。

    在我的实现中查询逻辑是和字段的类型绑定在一起的,是String类型进行like查询,其他字段进行相等查询。实现的结果您可以参考代码生成器的生成物或者代码生成器本身的源码。

论坛徽章:
1
天秤座
日期:2013-11-07 18:39:20
9 [报告]
发表于 2018-06-04 13:16 |只看该作者
本帖最后由 jerry_shen 于 2018-06-05 09:34 编辑

代码生成器技术乱弹七,动词算子式代码生成器的透明性

    动词算子式代码生成器的原理和人类手写编程一模一样。可以和任何框架搭配,只要你更新了生成器内部的动词和配置文件,就可以生成任意代码。您有兴趣可以仔细检查无垠式/和平之翼代码生成器阵列中的任何一个代码生成器,它们都不会添加任何笔者自己写的Jar包,您甚至可以手动移除代码生成物中的jar包,再手工添加,如果您添加的jar是兼容的,代码生成物即可运行,完全是透明的。

论坛徽章:
1
天秤座
日期:2013-11-07 18:39:20
10 [报告]
发表于 2018-06-05 09:37 |只看该作者
本帖最后由 jerry_shen 于 2018-06-07 09:05 编辑

代码生成器技术乱弹八,系统族与笛卡尔空间


大家认为代码生成器是一个神奇的东西,有些人认为它是一种类似于传说中的阿拉丁神灯之类的魔幻工具,您只需要对神灯下达命令,就会有一个灯神出来,为您写好您需要的程序,这种神奇东西是存在的,只是您光使用代码生成器还是不够的。一个写程序的神灯不是代码生成器,而是一个程序员配上一套很好的代码生成器软件。

   好了,玩笑说完,我们谈论一下真实的代码生成器,在代码生成器研发的历史上,有一本书叫做《产生式编程》是一组德国人写的,他们没有写出可用的代码生成器,但是却整出了代码生成器的理论。我2004年买过这本书,而无垠式代码生成器是2014年得到可用的系统的。在这期间,曾经浏览过这本厚厚的书。

    书中对工业化,流水线,自动化生产提供了很好的思路和史实。其中提到了系统组的思想。在代码生成器实现以后,我发现其中代码生成器的能力其实可以用系统族和系统族的迪卡儿空间表示,一个代码生成器可以产生的系统族的笛卡尔空间越大,其能力就越强。

    系统族是可以使用其动词算子的数量和域对象对字段限制的程度两个维度表示。在最新的无垠式代码生成器JEEEU版1.5中。共有ListAll, ListActive, SearchByFieldsByPage, SoftDelete, Delete, Add, Update, DeleteAll, SoftDeleteAll, Toggle, ToggleOne 11个单域动词和几个不完全的辅助性动词和ListMyActive, ListMyAvailableActive, Assign , Revoke四个双域动词组成。而域对象没有明确的字段限制只是要求每个域对象必须具有domainid,domainname,activefield 三个特殊字段。

    这约20个动词和域对象的可变性以及域对象之间的一对多和多对多关系。动词算子式代码生成器的变幻的笛卡尔空间是足够强大的。你只需要写下您的域对象清单和他们的规约,当然,不要忘了对它说一声call magic,你就可以得到系统族的馈赠,一个可以运行的一个子系统。

    代码生成器的生成空间就是代码生成器能生成的所有子系统的空间之和。也就是代码生成器的笛卡尔空间。根据上面的分析,无垠式代码生成器JEEEU版Ada 1.5的生成空间为(N-3)×20×3,我们可以简单记为60N,为字段,动词算子和关系三者的笛卡儿积。和平之翼代码生成器SMEU版3.1 乌篷船的生成空间为(N-3)×20×3×2,我们可以简记为120N,为字段,动词算子,关系和数据库类型四者的笛卡尔积。让我们群策群力,开发1000N级别(或者可以称之为1000倍率)的代码生成器吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP