#drools #rules #rule-engine #business-rules
Вопрос:
мне было интересно, могу ли я выполнить операцию contains с левой стороны (LHS) по правилу drools. Что-то в этом роде:
global java.util.List myGlobalList;
dialect "mvel"
rule "checker"
when
Task() from myGlobalList
then
System.out.println(myGlobalList);
end
Приведенный выше пример не является рабочим, и я не совсем уверен, как заставить его работать. Я открыт для предложений с другими ключевыми словами от drools (содержит, существует, в)!
Ответ №1:
Только если вы хотите проверить начальное состояние глобального. Как правило, глобальные значения выходят за рамки того, о чем известно правилу. Ваши правила не будут знать о каких-либо изменениях в глобальном.
Вместо этого вы должны поместить свою серию задач в список в рабочей памяти, как это:
rule "checker"
when
$myTasks: List() // suggest not a raw list in working memory, but this "works"
Task() from $myTasks
then
System.out.println($myTasks);
end
Ваше правило как есть будет работать только в том случае, если Task
оно присутствует в вашем глобальном списке в момент запуска правил. Если правило впоследствии удалит задачу, она не будет видна. Есть также некоторые дополнительные странности в отношении видимости, которые я сам не до конца понимаю, потому что в любом случае вам не следует писать правила против глобалов.
Теоретически, если вы понимаете жизненный цикл Dool-особенно то, как работает фаза сопоставления и как вы можете повторно запустить эту фазу на основе действий в ваших правилах ( update
, insert
и т. Д.), — вы должны теоретически написать правила, подобные этим, которые отключают ключ от глобального. Но поскольку глобальный не является частью рабочей памяти, он не может участвовать в тех же действиях (например, вы не можете позвонить update(myGlobalList)
). Это также добавляет много сложностей, потому что будущим разработчикам ваших правил потребуется такое же понимание жизненного цикла … по сути, это превратится в кошмар технического обслуживания.
В конце концов, вам действительно не следует вообще использовать глобалы. Обычно они больше всего пахнут кодом, это то, как мы извлекали данные из правил в «старые времена» (более 10 лет назад), потому что на самом деле не было лучших способов, и мы не знали ничего лучшего. Они действительно аналогичны «статическим» переменным в Java-если у вас несколько потоков, вы не можете полагаться на значение статической энергонезависимой переменной в условиях «если».
Итак, ответ на ваш вопрос-технически да, но практически нет. Не делай этого. Разработайте свои правила получше.
Обратите внимание, что документация Drools предупреждает вас также не делать этого:
Не используйте глобальные переменные для установления условий в правилах, если глобальная переменная не имеет постоянного неизменяемого значения. Глобальные переменные не вставляются в рабочую память механизма Drools, поэтому механизм Drools не может отслеживать изменения значений переменных.
Не используйте глобальные переменные для обмена данными между правилами. Правила всегда рассуждают и реагируют на состояние рабочей памяти, поэтому, если вы хотите передавать данные из правила в правило, утверждайте данные как факты в рабочей памяти механизма Drools.
По сути, единственный раз, когда вы когда-либо ссылаетесь на глобальный слева («когда»), — это когда глобальный действует как константа. Так что что-то вроде этого:
global Float freeShippingMinimum;
rule "Free shipping if minimum met"
when
$c: Cart( subtotal >= freeShippingMinimum,
shippingFee > 0.0 )
then
modify( $c ) {
setShippingFee( 0.0 )
}
end
В этом примере вы получаете бесплатную доставку, если ваш промежуточный итог соответствует минимальному пороговому значению. Этот порог передается в правила, потому что он является константой и поступает из какого-то внешнего источника данных. Он передан в правила как глобальный, потому что он является константой; поскольку он является константой, мы можем ссылаться на него слева / «когда».
Комментарии:
1. Спасибо за обширную информацию по этой теме, однако теперь, когда я выполняю правило, у меня есть 10 элементов в списке и одна задача, равная одному из этих 10 элементов, однако она выполняется 10 раз, потому что оператор печати присутствует 10 раз.
2. Да? Это начальное состояние, вот как это работает. Не используйте глобальные значения с левой стороны.