2013-12-10 5 views
4

Я новичок в слюнявостях, и я написал несколько правил, и они работают так, как ожидалось. Однако я не могу не думать, что существует более сжатый способ написания этих правил.правила слюни, требующие нескольких других правил.

Моей ситуацией является то, что многие правила имеют несколько аналогичных основных требований, которые я повторяю в каждом правиле. Так, например, предположим, что у меня есть следующие правила:

rule "Main Valid Message" 
    when Account (open && valid) 
    then myResults.add(new Message("Your account is valid")) 
end 

rule "The user owns something Message" 
    when Account (ownership.size() >= 1) 
    then myResults.add(new Message("You own something")) 
end 

rule "Eligibility Message" 
    when 
    Account (open && valid) 
    Account (ownership.size() >= 1) 
    then myResults.add(new Message("You are eligible")) 
end 

Есть ли способ переписать правила приемлемости, чтобы воспользоваться первыми двумя правилами, а не дублируя их содержание?

ОТВЕТ: Используя комбинацию ответов J Энди и Laune х ниже, я написал следующее:

declare IsValid 
    account : Account 
end 

declare OwnsSomething 
    account : Account 
end 

rule "Main Valid Message" 
    when $account : Account (open && valid) 
    then 
     myResults.add(new Message("Your account is valid")) 
     insertLogical(new IsValid($account)); 
end 

rule "The user owns something Message" 
    when $account : Account (ownership.sizeOwnsSomething() >= 1) 
    then 
     myResults.add(new Message("You own something")) 
     insertLogical(new OwnsSomething($account)); 
end 

rule "Eligibility Message" 
    when 
     IsValid() 
     OwnsSomething() 
    then myResults.add(new Message("You are eligible")) 
end 

ответ

1

Одним из вариантов было бы использовать (внутренние) факты для обработки состояния. Что-то вроде этого

declare AuthenticatedUser 
end 

rule "Authenticate user" 
    when 
    Account(open && valid) 
    then 
    insert(new AuthenticatedUser()); 
end 

rule "Eligibility Message" 
    when 
    AuthenticatedUser() 
    then 
    myResults.add(new Message("You are eligible")); 
end 

Я не уверен, что это ваш случай использования собственности счета, но я думаю, вы получите точку из приведенного выше примера кода.

Внутри файла DRL объявлен факт AuthenticatedUser. Это может быть обычный класс Java. Кроме того, в примере у него нет свойств вообще, но, как упоминалось ранее, он может даже содержать некоторое состояние, которое вы изменяете в правилах.

+0

@ большой ответ Laune в сделал кое-что отметить мой ответ не принимает во внимание: Там может быть несколько пользователей/счета в го рабочую память одновременно. Если вы все еще хотите использовать этот подход, вы можете украсить учетную запись/пользователя фактом «AuthenticatedUser», чтобы у вас все еще был доступ к свойствам учетной записи, таким как идентификатор. – kaskelotti

3

Тогда есть возможность расширения правила, которое позволяет наследовать условия одного правила к любому числу других правил:

rule "multiple account owners" 
when 
    $acc: Account(owners.size() > 1) 
then end 

rule "multiple and open and valid" 
extends "multiple account owners" 
when 
    Account(this == $acc, open && valid) 
then 

Если следовать идее Энди, рассмотреть вопрос об использовании insertLogical и ссылки на Счет в вопросе (если вы не расследует один факт счета в то время):

rule "multiple account owners" 
when 
    $acc: Account(owners.size() > 1) 
then 
    insertLogical(new Multiple($acc)); 
end 

Будьте осторожны с этим подходом, чтобы не иметь правил огонь преждевременно с отрицается формы собственности, представленной (!) вспомогательный факт, например,

rule "funny account" 
when 
    $acc : Account(balance > 10000000) # can have more than one owner 
    not Multiple(account == $acc) 
then ... end 

Это может срабатывать до того, как «несколько владельцев учетных записей» подтвердят множественность, если этому правилу не будет предоставлено более высокое значение. Кроме того, имейте в виду эффект оценки всех этих свойств путем вставки вспомогательных фактов: эти служебные данные создаются в любом случае, даже если определенной учетной записи не понадобятся все они для обработки.

Наконец, есть идея адаптера (или обертки) для учетной записи, обеспечивающей любое количество причудливых добытчиками для счета:

rule "wrap account" 
when $acc: Account() not Wrapper(account == $acc) 
then insert(new Wrapper($acc) end 

rule "multiple valid-open" 
when Wrapper(multiple && validOpen) 
then ... end 

И вы можете, конечно, прибегнуть к функциям ДРЛ:

function boolean multiOwners(Account account){ 
    return account.getOwners().size() > 1; 
} 

rule "multi valid open" 
when $acc: Account(eval(multiOwners($acc) && openValied($acc))) 
then ... end 

(я не уверен, нужна ли вам Eval в версии (ы) последние Drools.)

+0

Спасибо за информацию, laune.Я смотрел в правило расширения, но похоже, что это будет отношение к многим, и я ищу многих. Синтаксис и использование для Wrapping кажутся менее простыми, чем вставка - и это то, что мне нужно, чтобы это было принято. Ваш совет по insertLogical кажется мудрым, поэтому я внедрил его в свое решение. К сожалению, я не могу принять оба ответа. – Nixx

Смежные вопросы