Action模型 -- 增强型UML建模和后台代码的自动生成工具

       无论是哪种软件开发的思路,代码的可重用都是所追求的主要目标之一(通俗地说,就是实现同一种功能不第二遍写代码)。无代码/低代码的实现也是基于代码的可重用,但是前台和后台采用的是不同的路径:

前台:
        前台代码重用的主要是大量的可视化构件,通过对这些构件的可视化组装来达成前台功能的实现。本系列文章的重点在于后台的无代码开发,同时,网上也已经有很多关于前台低代码\无代码开发的介绍,因此这里就不再进行讨论了。

后台:
        如果仅仅从源代码的角度来看两个功能类似的软件系统(例如ERP),我们会发现,即使是实现相同功能的方法,其实现代码也可能会存在很大差异。导致这种差异的最主要的原因就在于两个系统中相同功能的方法的输入参数都可能大不相同,例如,针对相同行业的不同企业的ERP,或者针对不同行业的不同企业的ERP。为解决这种代码的可重用性,就必须采用有针对性的办法:从直觉上看,我们都知道这是两个内容不同但是功能相同的方法,从逻辑上讲它们也是完全相同的,但就是内容不相同,因此如何进行代码重用呢?
        为解决这个问题,有两个方向相反的途径:
        具象化:将一个功能不断地进行分解,直到分解为多个具有相同或者相似签名的子功能,通过对这些子功能的重用来达成功能的重用。每写一个新系统,就可能需要对这些子功能进行重新组合,从而无法真正做到无代码,而最多只能是低代码。此途径的另一个缺点在于无法进行可视化构建。同时,其实现难度并不亚于下面的抽象化途径,甚至从某种角度看难度还要高一些。
        抽象化:抽象是软件科学最基本的思想之一。那么如何进行抽象呢?模板(Template)就是一种对实现代码的抽象。由于可以为实现相同功能的模板设定一组数量、类型都不固定的输入参数,而这些不固定的输入参数对应的就是具体系统中可能大不相同的输入参数,这样一来,模板就可以根据这些不同的输入参数值生成不同内容的代码,从而很好地解决了代码可重用的问题。
        模板的输入参数值可以通过UML模型编辑器生成,从而可以无代码地以可视化的方式实现后台代码的自动生成。
        做一下类比:模板就可以被看作是“工业母机”,它是生成代码的代码。只要这个模板没有Bug,就可以保证其生成的代码没有Bug;只要排除了模板中的一个Bug,其之后所生成的所有代码中相同的Bug也会完全消失。用一个专业术语描述就是:这些Bug都是“发现即摧毁”。
        抽象化的途径用一句话形容就是:照葫芦画瓢,只要我们能够造出葫芦,即模板,就可以高质量、低成本、快速地构建新系统,即瓢。这样就等于将拷贝的概念从物理层面提升到逻辑层面,从软件层面提升到系统层面。

        在开发了Action模型这个项目之后,但在进一步学习MDA相关标准之前,我一直认为使用MDA只能达成数据访问层(也就是业务层之下的那一层)的无代码实现,对于业务层则无能为力。原因主要在于:
        数据访问层只有四个操作:增删改查,而Action模型也只是增加了一个“替代追认”操作,也就是说,数据访问层所提供的方法掰着手指头都能算出来,因此实现其的无代码自动生成是完全可能的。
        实际上,数据访问层的无代码自动生成只是Action模型的副产品,Action模型最主要的贡献在于实现了如下几项堪称黑科技的技术:
        无需考虑并发的并发模型;
        无需时间输入的时间模型;
        N元关联也支持Qualifier的关联模型。
       下面分别介绍一下这三个模型:
        并发模型:应用了并发模型之后就使得IT人员在设计和编码Java后台系统时无需再考虑并发的问题。大家都知道,并发代码的设计即使不是软件设计中最具有难度的问题,也是相当具有难度的问题,但是现在在编写并发系统时不用再考虑并发的问题,这是不是很科幻?因此称之为黑科技乃是实至名归。这里我要强调一点,Action模型的并发模型所采用的技术既不完全是悲观锁、也不完全是乐观锁,而是一种全新的并发模型。这里可以做这样一种类比:悲观锁是垄断市场经济,乐观锁是以产定销的自由市场经济,Action模型是以销定产的自由市场经济。实际上,在我编写的一个测试用例中,在一台16线程的笔记本上同时开450个被称为Runnable链的事务,其中共包括三种类型的长短事务,可以确保在处理这450个事务的过程中既不会有死锁发生,也不会有竟态条件发生,这里的技术含量就无需赘述了。有兴趣的读者可以交流探讨。
        关联模型:包括UML三剑客在内的所有IT界大佬们都说N元关联不支持Qualifier,但是Action模型中的关联模型则支持带Qualifier的N元关联,这就是我说关联模型是黑科技的原因。更重要的是,关联模型不仅在概念上支持带Qualifier的N元关联,而且已经从建模阶段到代码自动生成阶段都实现了对带Qualifier的N元关联的支持。有兴趣的读者可以交流探讨。
        时间模型:共有三个时间参数:when、whentosee、whentocall;
        同时有三个时间阶段:过去、当前、未来;
        每个时间参数都可能有三种可能的取值范围,与三个时间阶段一一对应。
        这样一来三个时间参数组合在一起就总共有3x3x3共27种可能的取值范围的组合。
        同时,when、whentosee、whentocall这三者之间的前后关系也有3x2x1共6种可能。
        这就意味着所有的时间参数最少有27种可能,最多有27x6共162种可能。
        而Action模型中的时间模型可以很好地解决上述这个比较复杂的时间问题,实际上,在很多情况下,在后台采用Action模型的系统中,前台甚至无需输入任何时间参数值,或者仅输入很少的时间参数值,就好像后台没有时间模型一样。另外,Action模型在从底层开始就不支持对业务数据的非法篡改的同时,支持对业务数据进行追认操作,所谓追认,即对已经发生过的事务的补充(即覆盖追认)或者修正(即替代追认)。有兴趣的读者可以交流探讨。

        并且这些功能的实现都完全基于一个增强型的UML模型编辑器(将传统的三隔间改为多隔间,同时取消了方法隔间)来进行建模,从而真正做到了可视化的无代码编程。并且这种建模的难度要小于后面将要提到的业务层的领域建模的难度。
        业务层则完全不同,不同系统的业务可能都是千奇百怪,纷繁复杂,如果按照Action模型的思路,确实对业务层代码无法进行无代码的自动生成。
        但是,通过最近这一阶段时间对MDA相关标准和规范的研读,我发现业务层代码的无代码自动生成也是可能的。其主要途径就是上面提到的抽象化。举个例子,两个相同行业的企业,它们的ERP系统的功能必然会有很多类似的地方,但是也会有很多不同的地方。但是如果我们采用上面抽象化的思路,就会找到这些不同点中的相同点。可以这么说,对于不同的信息系统而言,抽象程度越高,它们的相似程度就越高。
        另一方面,一般而言,企业管理都有各种各样的规范和标准,如果一个企业的管理都严格按照标准来执行,则采用无代码方式自动生成管理系统就是可能的,因为我们可以将各种各样的管理标准都写到模板之中,这样就达成了无代码生成业务层代码的目的。当然,如果一个企业的管理并不十分规范,则这就需要对这个企业的一些业务方法进行定制,而这也不过就是由无代码状态进入了低代码状态,而这仍旧没有违反软件重用的基本原则,因为这些定制的方法都是第一次编写。

        读到这里,可能有些读者会说,我们公司已经有几套甚至几十套软件系统,足以满足市场的各种需求,没有必要通过MDA的方式再将系统重构一遍。

        这里我要声明一点,使用Action模型构建新系统和重构现有系统的能力都完全具备,应用Action模型构建新系统和重构现有系统的难点各不相同,为此本人还专门针对重构现有软件系统的方法进行了研究,有兴趣的读者可以交流探讨。
        通过MDA将现有软件系统重构一遍并非是简单地将系统重写,通过将现有软件系统转化为UML类图和模板,就使得现有系统有了模型驱动的能力,从而可以高质量、快速、低成本地为每个新客户都提供深度定制化的系统。从发展的角度看,耐用消费品市场都已经出现了定制化的发展趋势,作为难度要高出很多的软件系统而言,软件系统深度定制化的时代也必将到来。而到了那个时候,如果一个软件公司能够拥有采用MDA技术构建的软件系统,则必将形成对竞争对手的降维打击。
        通过MDA将现有软件系统重构一遍的难度并非高不可攀。虽然“MDA中国”已经关门多年,但这并不意味着MDA技术本身没有生命力,而只能说MDA在中国应用的不好罢了。本人通过长时间的不懈努力,终于找到了一条高效低成本的应用MDA的技术路线(即类图加模板),Action模型走的就是这条技术路线。我可以负责地说,如果没有MDA,Action模型是断然无法构建出来的。
        通过MDA将现有软件系统重构一遍的门槛并非能轻易跨过。Action模型就是一道技术门槛,Action模型包含多项核心技术,其中的关键核心技术完全可以在不影响业务代码调试的情况下不对外公开,这就使得即使参与重构项目的核心人员出现了流动,也不会导致关键核心技术的外流。可以这么说,没有Action模型,软件系统的MDA重构将是一件非常困难的事情;有了Action模型,软件系统的MDA重构才变得不那么高不可攀,但是这种情况仅针对拥有Action模型的公司成立。
        通过MDA将现有软件系统重构一遍的基础并非一穷二白。本人所构建的Action模型在数据访问层就实现了对并发、时间、关联的支持,从而大大降低了业务层代码编写和生成的难度。有了Action模型作为基础,所有有增删改查需求的软件系统就都有了使用MDA进行重新构造的坚实基础。
        通过MDA将现有软件系统重构一遍的费用并非不可想象。功能强大的Action模型是本人花费大约三年半的时间构建完毕的,其中百分之九十九的工作量都是本人一个人独立完成的,我是自己不给自己发工资,但是反过来说,即使给我发工资,我一个人一年又能发多少工资呢?
        现在正处在一个经济形势的低谷区间,但这也不正是埋头修炼内功的最佳时机吗?如果我们能在这个低谷区修炼好内功,则一旦经济形势全面恢复时期来到,那时就将是我们享受劳动成果的美好明天。

        业务层代码的无代码自动生成是一件很美好的事情,但这也是有门槛的,或者说是有技术难点的。除了上文所说的Action模型这一门槛之外,另一个门槛就是领域建模,或者更准确地说,是使用UML进行领域建模。虽然有了Action模型作为基础,导致领域建模的难度已经大为降低,使得使用UML对信息系统建模不再困难,但是如何将模型建的简洁、优雅、准确则仍旧不是那么容易的事情。

        基于上面的认识,我就动了撰写一个文章系列的心思,这就是即将推出的“如何理解UML2.5.1”这一系列文章。在这一个文章系列中,我将通过一些实例的讲解来使大家能够比较快速地提高对UML的理解程度,从而有助于大家提高自己的领域建模水平。
        欢迎大家对我的文章进行批评指正,谢谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,我们可以了解到Drools提供了一种模型来表示规则集和规则集的规范表示,并且可以使用流利的DSL方便地创建此模型的实例。此外,该模型本身完全独立于Drools,理论上可以被其他引擎重用。 因此,我们可以使用Drools提供的模型自动生成Drools代码。具体步骤如下: 1.创建一个Java类,该类将用于表示规则。例如: ```java public class Rule { private String name; private String condition; private String action; // getters and setters } ``` 2.使用Drools提供的模型来创建规则集和规则。例如: ```java KieServices ks = KieServices.Factory.get(); KieFileSystem kfs = ks.newKieFileSystem(); KieModuleModel kmm = ks.newKieModuleModel(); KieBaseModel kbm = kmm.newKieBaseModel("rules") .setDefault(true) .setEqualsBehavior(EqualityBehaviorOption.EQUALITY) .setEventProcessingMode(EventProcessingOption.STREAM); KieSessionModel ksm = kbm.newKieSessionModel("ksession-rules") .setDefault(true) .setType(KieSessionModel.KieSessionType.STATEFUL) .setClockType(ClockTypeOption.get("realtime")); kmm.newKieSessionModel("ksession-rules") .setDefault(false) .setType(KieSessionModel.KieSessionType.STATEFUL) .setClockType(ClockTypeOption.get("realtime")); kfs.writeKModuleXML(kmm.toXML()); KieBuilder kieBuilder = ks.newKieBuilder(kfs).buildAll(); KieContainer kieContainer = ks.newKieContainer(kieBuilder.getKieModule().getReleaseId()); KieSession kieSession = kieContainer.newKieSession("ksession-rules");``` 3.将规则添加到规则集中。例如: ```java Rule rule = new Rule(); rule.setName("rule1"); rule.setCondition("Person(age < 18)"); rule.setAction("System.out.println(\"Person is a minor\");"); kieSession.insert(rule); kieSession.fireAllRules(); ``` 以上代码将创建一个规则集,并将一个规则添加到该规则集中。在这个例子中,规则的条件是“Person(age < 18)”,意思是如果一个人的年龄小于18岁,则该规则将被触发,并且规则的动作是打印一条消息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值