[rules-users] Abstraction between rules and data model?

Wolfgang Laun wolfgang.laun at gmail.com
Mon Jun 2 12:08:04 EDT 2014


Perhaps  https://engage.redhat.com/forms/rule-design-patterns section
2.5 might be of interest to you.

Some of what you've posted seems to deviate towards what is called
"overengineering", but of course it may have to be as complicated as
it was
presented.

-W


On 02/06/2014, Horváth Péter Gergely <h.peter at mailbox.hu> wrote:
> Hi Davide,
>
> Thanks, I just wanted to get a grasp of the time frame we could expect
> (whether it is a month or half a year etc.) :)
>
> A bit more about our use case: we have a *massive* old system, with
> basically all of the logic embedded into Java. We are in the process of
> refactoring and moving up-to-date Java technologies. We would like to
> introduce a rule engine so as to extract logic from the core of the
> application. Since we need to re-structure the whole back-end and
> persistence layer, we face a challenge with rules: as the object model
> changes, the rules have to change also, which simply would not be
> manageable. (Imagine something really crazy/complex here: 6-8-... levels of
> object hierarchy, grown most of the time organically during the last 15
> years.) Deferring the introduction of the rule engine until the data model
> classes reach the final, ideal state is not something we can now afford,
> the rule engine and data model refactoring projects should be done in
> parallel, without the one paralyzing the other one...
>
> Take the following as an example (from the manual). Say, you have Applicant
> class, with age and name fields:
>
> public class Applicant {
>
>     private String name;
>     private int age;
>
> // getters/setters
> }
>
> Then, you could have a simple rule, requiring, that name must be supplied:
>
> rule "Supplied a proper name"
> when
>     Applicant( name == null)
>     $a : Application()
> then
>     output.println("### RULE MATCH: Invalid application: No name
> specified!");
>
>     $a.setValid( false );
>
> end
>
> But there is an issue: every single time you refactor / rename any field in
> your domain model, the rules are no longer valid. That is why we have a
> problem: we should start developing rules against a relatively fluid object
> model. Say Applicant.name is renamed to Applicant.fullName, then the
> existing rules are no longer valid. That is why I would like to have some
> sort of abstraction, since the rules do not really need to know the
> *exact *details
> of the underlying class.
>
> As a demonstration of my idea, I managed to hack together a custom
> parameterizable operator, that calls the method where the annotation
> contains the same parameter as in the rule. With this approach, changes to
> the field names would no longer affect the rules. Again, I have to
> highlight, I don't think this should necessarily be implemented in the core
> engine. *What I am looking for is some kind of extension point allowing us
> to hook into the expression evaluation part of Drools*. (Instead of a
> custom operator, something, where we can access the object and the
> expression being resolved so that we can implement our custom logic for
> returning the value of the expression)
>
> The rule now looks like this - note the custom satisfiesRule operation. The
> "Name of this Applicant" expression now abstracts away the name of the
> actual field (the second parameter is the operator for the test, please
> ignore it for now):
>
> rule "Supplied a proper name"
>     agenda-group "evaluate-application"
>     auto-focus true
> when
>     Applicant( this satisfiesRule[ "Name of this Applicant" ,  "is equal
> to" ] null )
>     $a : Application()
> then
>     output.println("### RULE MATCH: Invalid application: No name
> specified!");
>
>     $a.setValid( false );
>
> end
>
> The name is simply mapped by a custom annotation:
>
> public class Applicant {
>
>     private String name;
>     private int age;
>
>     @MyBusinessExpression("Name of this Applicant")
>     public String getName() {
>         return name;
>     }
> // getters/setters
> }
>
>
> I think having a level of abstraction between the rules and the data model
> would not only be useful for de-coupling, but also can make rule authoring
> easier for the business users. The custom operator (please see attachment)
> is a kind of hacky workaround, but demonstrates how something similar could
> be achieved at run time (without using DSL or any other rule
> transformation).
>
> Please let me know what you think. :)
>
> Cheers,
> Peter
>
>
>
>
>
>
>
>
>
>
> 2014-06-02 11:54 GMT+02:00 Davide Sottara <dsotty at gmail.com>:
>
>>  I can't guarantee a public date.. as a community member, I work on a
>> "best effort" basis...
>> I'll try to do it before the end of the month, though.
>> For now, as a workaround, I would create derived getter/setter pairs that
>> expose the desired
>> computations. A concrete example of what you are trying to do exactly
>> would also be helpful,
>> feel free to contact me privately if you can't share your code here
>> Best
>> Davide
>>
>>
>> On 05/28/2014 10:08 AM, Péter Gergely, Horváth wrote:
>>
>> Thanks for the explanation, I was a bit confused because of the
>> terminology; "virtual" is not mentioned in the docs. ;)
>>
>>  Is there any plan for the public release of Trait property binding to a
>> nested path? We would definitely need something like that in our
>> environment. Or do you see any way we could hook into the property
>> look-up
>> mechanism? Based on what I know, I don't see any official extension point
>> for that.
>>
>>  My only idea would be using some Java proxy voodoo-magic to wrap objects
>> before they are inserted to the session, but my gut feeling is that it
>> would be a way to debug hell...
>>
>>  What do you think?
>>
>>  Cheers,
>> Peter
>>
>>
>>
>> 2014-05-27 19:42 GMT+02:00 Davide Sottara <dsotty at gmail.com>:
>>
>>>  Consider that a trait is an interface applied to some class. In the
>>> context of the pair:
>>> A "hard" field is a property (get/set) exposed by the interface AND the
>>> underlying class
>>> A "soft" (or "virtual") field is a property exposed by the interface BUT
>>> NOT by the underlying class
>>> A "hidden" field is a field of the underlying class NOT exposed by the
>>> interface
>>>
>>> Hard and Soft fields can be accessed using the interface, hidden fields
>>> are accessible using the map-like
>>> construct fields[ "fieldName" ].
>>>
>>> This said,
>>> the mapping is by default done using the property name and (then) the
>>> property type.
>>> However, this mapping can be decoupled using the annotation @Alias() on
>>> either the class OR the trait.
>>> E.g.
>>> declare Core
>>>   name : String @Alias( "any-Id-or-even-an-IRI-here" )
>>> end
>>>
>>> declare trait SomeTrait
>>>     label : String @Alias( "..." )  // if two "aliases" match, this will
>>> be considered a hard field
>>> end
>>>
>>> The "accessor", i.e. the ability to bind a trait property to a (possibly
>>> deeply) nested path is what I'm working
>>> on these days, I have the same requirement from another urgent use case
>>>
>>> For the time being, you can probably create a "shortcut" accessor pair
>>> in
>>> your implementation class,
>>> to execute the complex expression, and @Alias it to the trait field.
>>>
>>> Please let me know if you find any issue/bugs and any feature request
>>> you
>>> may have!
>>> Best
>>> Davide
>>>
>>>
>>>
>>> On 05/27/2014 07:57 AM, Horváth Péter Gergely wrote:
>>>
>>> Hi Davide,
>>>
>>>  Drools trait functionality is one of the powerful concepts which makes
>>> Drools a good candidate for the project. So keep up the good work! :)
>>> However I'm not sure if its current level of flexibility would be
>>> sufficient for our use case. I've checked the documentation, but haven't
>>> really found the term virtual field -- could you please elaborate on
>>> this?
>>>
>>>  Do you think we could somehow hook into the evaluation of the aliases
>>> or the "fields" Map? Sometimes you would need slightly more than merely
>>> aliasing fields to something else; e.g. calculating values for the
>>> purpose
>>> of rule processing or extracting a value from a more complex object tree
>>> etc. Citing the example -- GoldenCustomer( fields[ "age" ] > 18 ) --
>>> being
>>> able to get a reference to the target object and the field map
>>> expression
>>> "age" would be quite close to what I imagined. Our custom code could
>>> then
>>> perform the appropriate translation and return the requested value,
>>> hiding
>>> the fact whether "age" is an actual field in the Customer object
>>> itself/retrieved from an encapsulated complex object e.g. replacing
>>> expression "customer.personalInformation.birthData.age"/calculated on
>>> the
>>> flight.
>>>
>>>  What do you think?
>>>
>>>  Cheers,
>>> Peter
>>>
>>>
>>>
>>> 2014-05-26 17:58 GMT+02:00 Davide Sottara <dsotty at gmail.com>:
>>>
>>>> We are working on the trait framework for cases like this. Essentially,
>>>> it allows to use
>>>> interfaces when writing rules AND to inject the interfaces dynamically
>>>> at runtime,
>>>> at the instance level. It relies on transparent proxies which wrap the
>>>> data classes
>>>> and implement the required interfaces. A simple field aliasing
>>>> mechanism
>>>> is provided
>>>> (work in progress). For more complex transformations, "virtual" fields
>>>> can be added.
>>>> See section 7.7.8 of the manual for more details and let me know if it
>>>> can help
>>>> with your use case.
>>>> Best,
>>>> Davide
>>>>
>>>> On 05/26/2014 09:55 AM, Wolfgang Laun wrote:
>>>> > Even a relatively sophisticated transformation would be easier to
>>>> implement
>>>> > and most certainly safer from changes in the unstable Drools API than
>>>> some
>>>> > hook-and-intercept mechanism built into Drools.
>>>> >
>>>> > Notice that violent structural departure of the model the BUs see
>>>> > from
>>>> what
>>>> > you call "persistence model" might make it impossible for the BUs to
>>>> come
>>>> > up with rules that can be transformed to match the other model at
>>>> > all;
>>>> > if it is possible, rules might still incur a heavy performance
>>>> > penalty.
>>>> >
>>>> > It is (IMHO) a myth that "Rules" is a foolproof way of establishing
>>>> > business logic
>>>> > independent from the data model and application environment with
>>>> > which
>>>> > this logic should be able to cooperate. As long as everything is kept
>>>> in the
>>>> > abstract (i.e., formulated in terms of mathematics) it will look
>>>>  good, but
>>>> > any implementation may throw a spanner in the works, or worse.
>>>> >
>>>> > -W
>>>> >
>>>> > On 26/05/2014, Péter Gergely, Horváth <h.peter at mailbox.hu> wrote:
>>>> >> Hi Wolfgang,
>>>> >>
>>>> >> Thank you for your input. You are right that some of the cases could
>>>> simply
>>>> >> be covered by regexp-replace, but I'm afraid, not all of them.
>>>> Interfaces
>>>> >> could also help, but we have a requirement that the business rules
>>>> should
>>>> >> not be tightly coupled to the underlying persistence model. (I
>>>> understand
>>>> >> that some might say this is not ideal, but that is our current
>>>> situation)
>>>> >>
>>>> >> I am wondering whether it is possible to hook into Drools engine and
>>>> >> intercept field value reference expression evaluations in run time
>>>> (e.g if
>>>> >> "foo.bars" is used in an expression, we could return "foo.barList")
>>>> >> ?
>>>> By
>>>> >> injecting some custom code, we could make the necessary decisions
>>>> >> and
>>>> >> extract the proper value from an object. Unfortunately these parts
>>>> >> of
>>>> >> Drools are pretty much undocumented.
>>>> >>
>>>> >> Regards,
>>>> >> Peter
>>>> >>
>>>> >>
>>>> >>
>>>> >> 2014-05-26 13:57 GMT+02:00 Wolfgang Laun <wolfgang.laun at gmail.com>:
>>>> >>
>>>> >>> What you describe can be done with /bin/sed.
>>>> >>>
>>>> >>> Notice that the DSL processor doesn't require you to translate
>>>> >>> entire
>>>> >>> patterns; there is a mechanism for translating "keywords", which is
>>>> >>> just arbitrary tokens to whatever replacement text.
>>>> >>>
>>>> >>> If a "bar" must be translated to a "barList" in the context of a
>>>> class
>>>> >>> "Foo" but not in any other context, a more sophisticated
>>>> >>> translation
>>>> >>> is required in any case (with /bin/sed still being sufficient if
>>>> >>> patterns aren't split across lines).
>>>> >>>
>>>> >>> Some say that good design makes use of Interfaces, which leaves
>>>> >>> room
>>>> >>> for actual implementations being changed as long as the interfaces
>>>> are
>>>> >>> implemented. Here, note that rules can be written against interface
>>>> >>> types.
>>>> >>>
>>>> >>> -W
>>>> >>>
>>>> >>>
>>>> >>> On 26/05/2014, Péter Gergely, Horváth <h.peter at mailbox.hu> wrote:
>>>> >>>> Hi All,
>>>> >>>>
>>>> >>>> We are evaluating Drools 6 for our use case, and face challenges
>>>> where
>>>> >>>> we
>>>> >>>> would need some ideas from more experienced users of Drools.
>>>> >>>>
>>>> >>>> We have an application with a massive code base and a large number
>>>> of
>>>> >>> model
>>>> >>>> (entity) classes. We are in the process of moving away from
>>>> inherited
>>>> >>>> legacy technologies and refactoring the old code base. As a part
>>>> >>>> of
>>>> >>>> this
>>>> >>>> work we would like extract some of the hard-coded business logic
>>>> >>>> to
>>>> >>>> external rules, that is why we are looking at Drools as a
>>>> >>>> potential
>>>> >>>> solution.
>>>> >>>>
>>>> >>>> What we would like to have is some kind of abstraction or mapping
>>>> >>>> between
>>>> >>>> actual entities and rules the business users can define so that
>>>> they do
>>>> >>> not
>>>> >>>> have to know the _exact_ details of the data model (field names,
>>>> >>>> precise
>>>> >>>> relations etc). This would be important for us so that we can
>>>> refactor
>>>> >>> the
>>>> >>>> old model classes without affecting business rules; also it would
>>>> make
>>>> >>> life
>>>> >>>> easier for the business users. While IDE support might make
>>>> refactoring
>>>> >>>> easier, we definitely want to have a separation between rules and
>>>> >>> entities.
>>>> >>>> Given our situation, writing and maintaining "stable"
>>>> wrapper/adapter
>>>> >>>> classes for the sole purpose of rule processing is out of
>>>> >>>> question.
>>>> I
>>>> >>> have
>>>> >>>> checked the documentation of Drools DSL support and for me it
>>>> >>>> seems
>>>> to
>>>> >>>> be
>>>> >>>> overkill for our use case: we do not really need a custom
>>>> >>>> language,
>>>> but
>>>> >>>> simply an abstraction between rules and the data model classes.
>>>> >>>>
>>>> >>>> What I could imagine is a piece of code, (a custom property
>>>> resolver? -
>>>> >>> no
>>>> >>>> sure how it is called) which maps property expressions to actual
>>>> >>> properties
>>>> >>>> based on a custom annotation on the entity class or something like
>>>> >>>> that,
>>>> >>> so
>>>> >>>> that a rule containing "Foo.bars" expression does not have to
>>>> >>>> change
>>>> >>>> even
>>>> >>>> if we decide to rename "Foo.bars" to "Foo.barList" in the model
>>>> >>>> classes.
>>>> >>>> (This was just a simple example of a potential use cases)
>>>> >>>>
>>>> >>>> Could you please share your thoughts on this topic and point me
>>>> >>>> into
>>>> >>>> the
>>>> >>>> right direction?
>>>> >>>>
>>>> >>>> Thanks,
>>>> >>>> Peter
>>>> >>>>
>>>> >>> _______________________________________________
>>>> >>> rules-users mailing list
>>>> >>> rules-users at lists.jboss.org
>>>> >>> https://lists.jboss.org/mailman/listinfo/rules-users
>>>> >>>
>>>> > _______________________________________________
>>>> > rules-users mailing list
>>>> > rules-users at lists.jboss.org
>>>> > https://lists.jboss.org/mailman/listinfo/rules-users
>>>> >
>>>>
>>>> _______________________________________________
>>>> rules-users mailing list
>>>> rules-users at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/rules-users
>>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> rules-users mailing
>>> listrules-users at lists.jboss.orghttps://lists.jboss.org/mailman/listinfo/rules-users
>>>
>>>
>>>
>>> _______________________________________________
>>> rules-users mailing list
>>> rules-users at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/rules-users
>>>
>>
>>
>>
>> _______________________________________________
>> rules-users mailing
>> listrules-users at lists.jboss.orghttps://lists.jboss.org/mailman/listinfo/rules-users
>>
>>
>>
>> _______________________________________________
>> rules-users mailing list
>> rules-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/rules-users
>>
>



More information about the rules-users mailing list