with() declarations refresh on any user action regardless of connection

Hello:

I have noticed that anything declared in a with will get refreshed on any action the user takes on an interface, even if the with is unrelated to the action (such as a summary section at the top of the screen and a comments text box at the bottom, with no connection between the two).

Is this expected behavior for Appian?

It seems like with declared variables/rules/components should only refresh if one of the input variables changes.

If you see in the attached interface, changing the value in the textbox is refreshing the with variable, even though they are not related.

OriginalPostID-251823


example_interface.txt

  Discussion posts and replies are publicly visible

  • @marky, you can use queryEntities in with() and still avoid un-necessary DB calls. You can check if the queryentity should really be evaluated within if().

    an example: if(isnull(local!name), todatasubset({}), a!queryEntity() ). So, if the search criteria is not specified, the queryEntity will not evaluate.
    I agree that ideally it should evaluate only if it is needed. But with() is meant to be "re-active".
    To state a simplistic example:
    load(
    local!num1: 5,
    local!num2: 7,
    with(
    local!addition: local!num1 + local!num2,
    {/*..more code*/
    }
    )
    )
    now, in a "normal programming language", local!addition will not be updated even if values of local!num1 and local!num2 get updated. It will remain the same.
    But, in case of with(), if value of local!num1 or local!num2 get updated, local!addition gets updated. That's called "reactivity". Check this link: https://en.wikipedia.org/wiki/Reactive_programming

    Now, SAIL provides with() for reactive mechanism. In the example given, local!addition is dependent on local!num1 and local!num2, hence it need to be updated automatically if the values of its dependents change. This is sort of similar to event handlers in JavaScript. In this case , with() is "listening" for any changes to the values of any of the local!variables.

    Now, I saw the code that you attached. You have a variable in with() declared like this:
    local!refreshedVariable:1 + tointeger(rand() * (50)) . Now this variable is actually not dependent on any other local variable and hence ideally should not be re-evaluated - I see your point.
    Seems like with() just re-evaluates even if any of the local variables used inside the with() block are saved into - these variables may not have been declared inside with() and may not be affecting the variable which needs to be re-evaluated.
    I guess, determining if a local!variable should be re-evaluated or not is complicated. One reason I think is: even if such logic was developed, the SAIL interpreter would have to analyze the dependents of all local variables used in the UI, and would have run the same logic on each and every local variable and decide if it should be re-evaluated. It would slow down things on UI.. A UI needs to be re-active/having quick response time. Hence, its not worth implementing this complexity for with().. This is just my opinion.
  • In addition to what others have mentioned, if you want certain things to change only when the user does something specific, you should place that logic (query entities or whatever else it might be) within the saveIntos of the appropriate components.
  • I already know how to refactor the code, so thank you for the suggestions. The problem is that I doubt more than 10% of Appian developers actually understand the way with() scope works. So I ask which is more practical: a) All of the Appian developers in the world all become educated on how with works, and spend a lot of effort to refactor the code to improve performance. b) Appian fixes the way with works to improve the performance of all existing code without any effort or training by the developers.
  • 0
    Certified Lead Developer
    In regards to point a, developers should read the documentation of the functions they use so they understand the behavior and performance impact. I don't think it is a big ask for developers to understand how their code works. In regards to point b, if you change the functionality of with() you could negatively impact developers who used with() correctly. What happens when I have a with() variable that I want updated every time an action occurs but with no explicit connection to the object being updated? An update to the with() function would break my functionality forcing me to apply fixes to production code.
  • Agreed. C developers had to become educated to free() after malloc(). If they don't do it, that's their fault, not C's or Kernighan and Ritchie's. Using with() properly in Appian is no different.
  • Agree with Josh and Carlos. The with() function is incredibly useful when used properly, and Appian provides us with documentation and free training portals to enable us to use the tool as designed
  • Well i don't agree with Josh, Carlos, or Ashvin at all. Not using with() and instead using only saveInto makes the code many, many times more complex and increases the number of defects tremendously. If you have a SAIL form with 30 variables and 50 components, its nearly impossible to keep track of what components should update which variables using just the saveInto. This is just a generalization, but 30 variables/50 components is not a far stretch from most of the code I have seen others create. Not using with() is not a practical, good, or maintainable way to develop code. And what Josh mentioned makes no logical sense. Why would you have something get updated on every single interaction done on the screen, rather than only on actions related to that variable? Sounds like you need to re-think your implementation so that it is maintainable and logical, and regardless of whether with() is changed, you should change your approach to how you design SAIL forms.
  • Carlos - C developers having to free the allocated memory is a restriction built upon the programming language. It's also a simple and straightforward solution to a devastating problem (running out of memory). Appian doesn't offer an easy, simple, or straightforward way to avoid performance problems. This is no real alternative for enterprise development. You either write un-maintainable code not using with() and relying on only saveInto, or you use with() and have performance issues. If it was as easy as putting a few free() in the code, we wouldn't be having this discussion, would we?
  • Having with() re-evaluate its variables is also built on the programming language
  • Let us say, hypothetically, that you have a display label used in one part of the form that's based on performing arithmetic on two load() variables. You change one of the load variables with an integer field on the bottom of the form, and you would like to update the display label based on the arithmetic to reflect one of the load() variables being changed.

    Using with(), this automatically happens. However, when you use a completely different integer field, the logic for the with() still completes even though it's unrelated and very resource intensive logic that ultimately winds up with the label you already had. Wasted resources.

    Question: In order to implement your proposed solution, how do you inform the with() display label which integer fields are related to its reevaluation and which are unrelated using any means less complicated than a saveInto() and load() variable for the display label?