业务规则引擎的设计与实现

在现代软件开发中,业务逻辑的复杂性不断增加,尤其是在金融、贸易等领域。为了应对这种复杂性,需要一种灵活且高效的机制来管理和执行业务规则。本文将介绍一种业务规则引擎的设计和实现,它能够处理复杂的业务逻辑,并在对象属性变更时触发相应的规则。

问题的提出

在实际的业务场景中,例如贸易处理系统,需要处理非常复杂的级联规则。这些规则通常涉及到对象图的多个属性,当一个属性发生变化时,可能会触发整个对象图中其他属性的级联变化。传统的处理方式,如在setter中直接触发业务规则,或者将业务规则编码到setter中,虽然看似简单,但长期维护起来却非常困难。

主要问题包括:

  • 业务规则与数据结构强耦合,无法根据不同的上下文应用不同的规则。
  • 业务规则分散在整个对象图中,长期维护变得非常困难。
  • 容易多次触发相同的规则,导致性能问题和调试困难。
  • 依赖多个输入的值的默认值,如果输入的顺序发生变化,代码的行为可能也会发生变化,这同样会导致调试和维护的困难。

解决方案

解决方案的灵感来自于ORM框架,它们需要拦截属性变化以生成SQL更新命令。在这种情况下,创建了一个透明的代理对象,它拦截变化并触发所需的规则。

以下是一些示例代码:

public class Abcd : IAbcd { public int A { get; set; } public int B { get; set; } public int C { get; set; } public int D { get; set; } } public class AbcdRules : MappingRules<IAbcd> { public AbcdRules() { Set(x => x.B) .With(x => x.A) .If(x => x.A < 100) .OnChanged(x => x.A); Set(x => x.C) .With(x => x.B) .If(x => x.C < 100) .OnChanged(x => x.B); Set(x => x.D) .With(x => x.C) .If(x => x.D < 100) .OnChanged(x => x.C); Set(x => x.A) .With(x => x.D + 1) .If(x => x.A < 100) .OnChanged(x => x.D); } }

要使用规则引擎,需要实例化一个“facade”。它接受一个对象实例和规则实例作为参数:

var instance = new Abcd(); var rules = new AbcdRules(); var abcd = new InterfaceWrapper<IAbcd>(instance, rules);

像操作业务对象一样设置facade的值:

abcd.Target.A = 1;

检查对象的状态:

Assert.AreEqual(100, instance.A);

拦截属性更新

要创建一个对象的类型代理,所有公共属性都需要是虚拟的(显式声明为virtual或从接口继承),并且类不应该被封闭。如果这些条件无法满足,可以使用动态代理作为替代方案。

以下是来自真实交易系统的一个示例。这次,创建了一个包含两个节点trade -> product的对象图的facade。设置一个对象的属性可能会改变另一个属性。

var trade = new CdsTrade { Product = new CreditDefaultSwap() }; var rules = new CdsRules(); dynamic p = new DynamicWrapper<CdsTrade>(trade, rules); p.CdsProduct.RefEntity = "AXA"; p.Counterparty = "CHASEOTC"; Assert.AreEqual("ICEURO", trade.ClearingHouse); Assert.AreEqual("MMR", trade.CdsProduct.Restructuring); Assert.AreEqual("SNR", trade.CdsProduct.Seniority);

实际建议

只有当属性的值发生变化时,规则才会被触发。对于值类型,为了区分一个属性是否具有其默认值,使用可空类型。

Set(v => v.DealWay) .With(v => "B") .If(v => v.BookOcCode == 9826 && v.Folder == "HEDGE_OA_HY") .OnChanged(v => v.BookOcCode) .Or(v => v.Folder) .Or(v => v.DealWay) .EndRule();
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485