76

我正在审核一个使用所谓的规则引擎的项目。简而言之,这是一种从应用程序代码中外部化业务逻辑的方法。

这个概念对我来说是全新的,我对此持怀疑态度。在过去几年听到人们谈论贫血域模型后,我质疑规则引擎方法。对我来说,它们似乎是削弱域模型的好方法。例如说我正在做一个与规则引擎交互的java webapp。然后我决定我想要一个基于相同域的 Android 应用程序。除非我希望 Android 应用程序也与规则引擎交互,否则我将不得不错过已经编写的任何业务逻辑。

由于我还没有任何经验,只是好奇,我有兴趣了解使用规则引擎的利弊?我能想到的唯一优点是您不需要重建整个应用程序只是为了更改一些业务规则(但实际上,有多少应用程序真的有这么多的更改?)。但是使用规则引擎来解决这个问题对我来说听起来就像在猎枪伤口上贴创可贴一样。

更新 - 自从写了这篇文章之后,这位大神 Martin Fowler 在博客上写了一篇关于使用规则引擎的文章

4

12 回答 12

40

我见过的大多数规则引擎都被系统代码视为黑匣子。如果我要构建一个领域模型,我可能希望某些业务规则是领域模型固有的,例如告诉我对象何时具有无效值的业务规则。这允许多个系统共享域模型,而无需复制业务逻辑。我可以让每个系统使用相同的规则服务来验证我的域模型,但这似乎削弱了我的域模型(正如问题中所指出的那样)。为什么?因为我不是始终在所有系统中始终如一地执行我的业务规则,而是依靠系统程序员来确定何时应该执行业务规则(通过调用规则服务)。如果域模型完全填充给您,这可能不是问题,但如果您'

还有另一类业务规则:决策。例如,保险公司可能需要对承保申请人的风险进行分类并得出保费。您可以将这些类型的业务规则放置在您的域模型中,但是通常需要针对此类场景进行集中决策,并且实际上非常适合面向服务的架构。这确实引出了为什么是规则引擎而不是系统代码的问题。规则引擎可能是更好选择的地方是负责决策的业务规则随着时间的推移而变化(正如其他一些答案所指出的那样)。

规则引擎通常允许您在不重新启动系统或部署新的可执行代码的情况下更改规则(无论您从供应商那里收到什么承诺,请确保您在非生产环境中测试您的更改,因为即使规则引擎完美无瑕,人类仍在改变规则)。如果你在想,“我可以通过使用数据库来存储变化的值来做到这一点”,你是对的。规则引擎不是做新事物的神奇盒子。它旨在成为一种提供更高级别抽象的工具,因此您可以减少对重新发明轮子的关注。许多供应商更进一步,让您创建模板,以便业务用户可以填补空白,而不是学习规则语言。

关于模板的一个特别注意事项:模板永远不会比没有模板的情况下编写规则花费更少的时间,因为模板必须至少描述规则。计划更高的初始成本(就像您要构建一个系统,该系统使用数据库存储更改的值而不是直接在系统代码中编写规则) - 投资回报率是因为您节省了系统代码的未来维护.

于 2008-10-31T18:07:50.187 回答
29

我认为您对贫血域模型的担忧是正确的。

我已经看到了两个在我工作的生产环境中运行的著名商业 Rete 规则引擎的应用程序。我认为一个是成功的,另一个是失败的。

成功的应用程序是一个决策树应用程序,由约 10 棵树组成,每棵树约 30 个分支点。规则引擎有一个允许业务人员维护规则的 UI。

不太成功的应用程序有大约 3000 条规则被撞到规则数据库中。没有人知道添加新规则时是否存在冲突规则。对 Rete 算法的了解很少,产品的专业知识也离开了公司,所以它变成了一个不可触及、不可重构的黑匣子。部署周期仍然受到规则更改的影响——规则更改时必须进行完整的回归测试。记忆也是一个问题。

我会轻举妄动。当规则集大小适中时,很容易理解更改,例如上面给出的简单电子邮件示例。一旦规则的数量攀升至数百个,我认为您可能会遇到问题。

我还担心规则引擎会成为您应用程序中的单例瓶颈。

我认为使用对象作为划分规则引擎空间的一种方式没有任何问题。在我看来,在遵循私有规则引擎的对象中嵌入行为似乎没问题。当规则引擎需要不属于其对象一部分的状态才能正确触发时,问题就会出现。但这只是设计困难的另一个例子。

于 2008-12-29T19:20:29.270 回答
26

在某些情况下,规则引擎可以提供很多价值。

首先,许多规则引擎以更具声明性的方式工作。一个非常粗略的例子是 AWK,您可以在其中将正则表达式分配给代码块。当文件扫描器看到正则表达式时,代码块被执行。

你可以看到,在这种情况下,如果你有一个大的 AWK 文件,并且你想添加另一个“规则”,你可以很容易地转到文件底部,添加你的正则表达式和逻辑,然后完成它。具体来说,对于许多应用程序,您并不特别关心其他规则在做什么,并且这些规则并不真正相互操作。

因此,AWK 文件变得更像是“规则汤”。这种“规则汤”的性质让人们非常关注他们的领域,而很少关心系统中可能存在的所有其他规则。

例如,Frank 对总额超过 1000 美元的订单感兴趣,因此他将他感兴趣的规则系统放入其中。“如果 order.total > 1000 THEN 给 Frank 发送电子邮件”。

同时,Sally 想要来自西海岸的所有订单:“IF order.source == 'WEST_COAST' THEN email Sally”。

因此,您可以在这个微不足道的、人为的案例中看到,一个订单可以满足两个规则,但两个规则彼此独立。来自西海岸的 1200 美元订单通知了弗兰克和莎莉。当弗兰克不再担心时,他会简单地将他的排除从汤中剔除。

对于许多情况,这种灵活性非常强大。像这种情况一样,它也可以向最终用户公开以获取简单的规则。使用高级表达式和轻量级脚本。

现在,很明显,在一个复杂的系统中,可能会发生各种相互关系,这就是为什么整个系统没有“完成规则”的原因。某个地方的某个人将负责不失控的规则。但这并不一定会降低这样一个系统可以提供的价值。

请注意,这甚至不涉及专家系统之类的东西,其中规则触发规则可以创建的数据,而是更简单的规则系统。

无论如何,我希望这个例子展示了规则系统如何帮助增强更大的应用程序。

于 2008-10-30T15:03:41.527 回答
21

我见过的规则引擎最大的优点是它让业务规则所有者实现业务规则,而不是让程序员承担责任。即使您有一个敏捷流程,您不断从利益相关者那里获得反馈并经历快速迭代,它仍然无法达到通过让制定业务规则的人员也实施它们可以实现的效率水平。

此外,如果规则嵌入在代码中,您不能低估删除可能由简单规则更改导致的重新编译-重新测试-重新部署循环的价值。通常有几个团队参与为构建添加祝福,而使用规则引擎可以使很多事情变得不必要。

于 2008-10-30T14:57:25.533 回答
14

我为客户编写了一个规则引擎。最大的胜利是包括所有利益相关者。引擎可以运行(或重放)查询并以文本解释正在发生的事情。业务人员可以查看文本描述并快速指出规则、例外和其他特殊情况中的细微差别。一旦涉及到业务方面,验证就会变得更好,因为很容易获得他们的输入。此外,规则引擎可以独立于应用程序代码库的其他部分,因此您可以跨应用程序使用它。

缺点是一些程序员不喜欢学习太多。规则引擎和你放入其中的规则,以及实现它们的东西,可能有点麻烦。尽管一个好的系统可以轻松地处理病态和扭曲的逻辑网络(或者经常是不合逻辑的;),但它并不像编写一堆if语句那么简单(不管一些头脑简单的规则引擎做什么)。规则引擎为您提供了处理规则关系的工具,但您仍然必须能够在脑海中想象所有这些。有时就像生活在电影巴西一样。:)

于 2008-10-30T15:38:07.403 回答
8

它(与其他一切一样)取决于您的应用程序。对于某些应用程序(通常是那些永远不会改变的应用程序,或者规则最适合现实生活中的常数,即不会显着改变,例如物理属性和公式)使用规则引擎没有意义,它只是引入了额外的复杂性,并要求开发人员拥有更大的技能组合。

对于其他应用程序,这确实是一个好主意。以订单处理(从发票到处理货币交易的任何东西)为例,某些相关法律或法规(在司法意义上)时不时会发生微小的变化,要求您满足新的要求(例如销售税) ,经典)。与其试图强迫你的旧应用程序进入这种突然之间你必须考虑销售税的新情况,而以前你没有考虑,更容易调整你的规则集,而不是不得不干预潜在的大你的代码集。

然后,您当地政府的下一个修正案要求报告特定标准内的所有销售,而不是您也必须进入并添加。最后,您将得到非常复杂的代码,当您转身并想要恢复规则之一的效果而不影响所有其他规则时,这些代码将被证明非常难以管理......

于 2008-10-30T15:05:49.870 回答
6

到目前为止,每个人都对规则引擎非常积极,但我建议读者保持警惕。当问题变得有点复杂时,您可能会突然发现整个规则引擎变得不合适,或者比使用更强大的语言复杂得多。此外,对于许多问题,规则引擎将无法轻松检测到大大减少评估条件的运行时和内存占用的属性。在相对较少的情况下,我更喜欢规则引擎而不是依赖注入框架或更动态的编程语言。

于 2008-10-30T15:13:44.597 回答
3

“但说真的,有多少应用程序真的有这么多的变化?”

老实说,我开发的每个应用程序都经历了从概念到部署后的严格工作流程和/或逻辑变化。这是“维护”编程的第一大原因......

现实情况是,您无法预先考虑所有事情,这就是敏捷流程的原因。此外,在测试中发现之前,BA 似乎总是错过一些重要的东西。

规则引擎迫使您真正将业务逻辑与表示和存储分开。此外,如果使用正确的引擎,您的 BA 可以根据需要添加和删除逻辑。正如 Chris Marasti-Georg 所说,这让 BA 承担了责任。但更重要的是,它允许 BA 准确地得到他们所要求的。

于 2008-10-30T15:20:12.603 回答
2

规则引擎是可配置应用程序的胜利,如果可以避免,您不希望进行自定义构建。他们还擅长集中大量规则库,Rete等算法可以有效地快速匹配大型规则集。

于 2008-10-31T18:19:11.083 回答
2

已经有很多好的答案,但想补充几点:

  1. 在自动化任何复杂的决策时,关键的事情很快就变成了你管理而不是执行所涉及的逻辑的能力。规则引擎对此无济于事——您需要考虑业务规则管理系统具有的规则管理功能。大多数商业和开源规则引擎已经演变成具有存储库、报告规则使用情况、版本控制等的规则管理系统。规则存储库,结构化为可以编排以做出业务决策的连贯规则集,比任何一个都更容易管理数千行代码或规则汤。
  2. 有许多方法可以使用声明性的、基于规则的方法。使用规则来管理 UI 或作为定义流程的一部分可能非常有效。然而,规则方法最有价值的用途是自动化业务决策,并将其作为松散耦合的决策服务提供,这些服务接受输入、执行规则并返回答案——决策。这些服务可以回答其他服务的问题,例如“这个客户是否有良好的信用风险”或“我应该为这个订单给这个客户什么折扣或者”这个客户目前最好的交叉销售是什么。这些决策服务可以使用规则管理系统非常有效地构建,并允许随着时间的推移轻松集成分析,许多决策都可以从中受益。
于 2010-05-18T19:03:36.320 回答
1

我认为规则、流程和数据引擎(又名数据库)本质上是相似的。但是,出于某种原因,我们从不说对持久性子系统进行黑盒化是不好的。

其次,从我的 POV 来看,贫血模型不是行为执行轻的模型,而是行为本身轻的模型。描述域模型对象中可用行为的实际方法不必由对象本身完成。

于 2012-03-22T17:32:54.970 回答
0

根据我在规则引擎方面的经验,最大的复杂性在于:

  1. 从 OOP POV 来看,在重构影响规则的代码时重构和测试以声明性语言编写的规则是一件非常痛苦的事情。
  2. 通常我们应该总是考虑规则的执行顺序,当规则很多时会变得一团糟。
  3. 一些小的更改可能会触发规则的错误行为,从而导致生产错误。在实践中,并不总是可以通过预先测试来涵盖所有情况。
  4. 在其他对象中使用的规则变异对象也增加了复杂性,导致开发人员将它们分成多个阶段。
于 2014-06-10T06:18:55.997 回答