Child rules can see a parent's rule inputs - is this expected behavior?

I was going through someone else's code at my company and found a puzzling thing.  There was a parent expression rule calling a child expression rule.  The child expression rule referenced a rule input that it did not have defined.  The parent rule did have that rule input defined, and the child rule was able to access the rule input defined only in the parent.

I want to make it clear that I believe the child rule *should* have had a rule input defined, and that the input should have been explicitly passed by the parent rule.  The situation I ran into is not something I would personally rely on or a best practice I would recommend.

Is this behavior intentional?  Just curious.

Below is a simple example:

The parent rule has one rule input of a CDT "Widget" which has field1, field2, field3.  ri!widget of type Widget is defined on expression rule "parentRule".

contents of parentRule

rule!childRule(

)

childRule has *no* rule inputs.

contents of childRule

{
ri!widget.field1,
ri!widget.field2,
ri!widget.field3
}   

When I execute parentRule, I get back the contents of the widget rule input.  If I tried to execute the childRule by itself, it complains that it does not recognize the ri!widget variable, but executing from the parent it all works.

  Discussion posts and replies are publicly visible

Parents
  • +1
    Certified Lead Developer

    This is expected, and how it's always worked, AFAIK.

    The way I think of it is: when Appian reads expression logic, you could imagine that it reads all of the code into one huge interface/expression, then interprets that.  That means that in a child rule, any ri! or local! variables that aren't explicitly overridden on that level, will simply "see" the values passed from the parent.  Back in the early days of SAIL, this was a common practice (unfortunately).

  • Thanks!  That makes sense. Glad it's not a common practice any more. Slight smile

  • Yea, this is a ding on any code reviews I give as it makes debugging a nightmare in many situations..  My best practice is to ALWAYS utilize rule inputs in child rules, NEVER reference any parent ri's or parent local variables directly.

    Plus, any rule that references a parent's variables directly is immediately stove-piped and cannot be easily reused as a common function.  

  • 0
    Certified Lead Developer
    in reply to Chris

    It becomes a bit of a savior when you need to set a complex-ish expression to determine the value of a column in a Portal Report (process report, task report, etc), since due to whatever weirdness still exists in those, you CAN'T actually pass in parameters using dictionary syntax to expression rules, but you CAN make the expression rule manually reference PVs that you expect to exist in the process model(s) in question. 

    Of course this is an extreme edge case, but very useful sometimes.  Now, if they actually fixed the expressionable values in Reports to not break when using dictionary syntax or non-primitive functions....

Reply
  • 0
    Certified Lead Developer
    in reply to Chris

    It becomes a bit of a savior when you need to set a complex-ish expression to determine the value of a column in a Portal Report (process report, task report, etc), since due to whatever weirdness still exists in those, you CAN'T actually pass in parameters using dictionary syntax to expression rules, but you CAN make the expression rule manually reference PVs that you expect to exist in the process model(s) in question. 

    Of course this is an extreme edge case, but very useful sometimes.  Now, if they actually fixed the expressionable values in Reports to not break when using dictionary syntax or non-primitive functions....

Children