Using Declare Expressions with @when() to expose When Rule results as navigable properties in App Studio - scalability and maintenance concerns

Context

Hi all, we are implementing a fusion team delivery model where App Studio is the primary authoring environment for Business Architects. Our application architecture separates business entities into dedicated business modules (e.g., a Card module containing the data object Card) while Case Types are defined in consuming business applications (e.g., ReactivateCard in AccountServices).

We have identified a structural limitation: When Rules defined on embedded data objects (within modules) cannot be invoked from a Case Type in App Studio by navigating the data model. This applies specifically to single embedded page references (Page List navigation works).

Proposed pattern

To bridge this gap, we are considering the following approach:

  • For each ‘When Rule’ on the data object (e.g., IsCancelled on Card), create a corresponding Boolean property (e.g., .Card.IsCancelled)
  • Pair it with a Declare Expression using the @when() built-in function: Set Value = @when(“IsCancelled”)
  • Business users can then reference .Card.IsCancelled directly in App Studio conditions without needing to understand or access the underlying When Rule

The pattern works well in our prototype. The business team finds it intuitive: they navigate the data model, find a meaningful property name, and use it in conditions. The dev team retains control of the When Rule complexity.

Business reason

The goal is to maximize Business Architect autonomy in App Studio for condition authoring, reducing the dependency on professional developers for every new condition that references embedded data object logic. This is a key enabler for our fusion team operating model.

Questions for the community

  1. Has anyone deployed this Declare Expression + @when() wrapper pattern at scale? We are concerned about what happens when the number of such properties grows (e.g., 15-30 per data object across multiple modules). Any real-world feedback on maintainability?

  2. Are there known edge case where the @when() function inside a Declare Expression behaves unexpectedly (e.g., not recalculating when the underlying When Rule inputs change)?

  3. Alternative patterns. If this approach does not scale, has anyone found a better way to expose When Rule outcomes to App Studio business users without requiring Dev Studio intervention for each new condition?

Appreciate any feedback from teams who have gone through a similar exercise. Happy to share more details on our implementation.

Pega Infinity | App Studio | Constellation | Declare Expressions | When Rules | Fusion Teams

@MarcCheong @Kamil_Janeczek I am sure you’ve been through similar challenge and have found the best way to handle it !

As I understand that you want to maintain same value in .Card.IsCancelled and .IsCancelled scalar property using declare expressions - as a work around for your issue.

Kindly explore below approach as well. This is to avoid duplicate sets of data, as both properties would ultimately pointing to same memory location in this approach:

Use Property-Ref method in activity: As both properties refer to the same memory location, changing value of any one of them automatically changes value of the other property. The referenced property just refers to the address of the original property without saving the data twice (This relieves of edge cases where declare expressions might not fire and Cause mismatch in values)

Procedure:
In LHS, use a reference property
In RHS, use a non-reference property

Target property should be configured as reference property in the advanced tab.
Pega will maintain this link forever unless you change it manually. This reference will be maintained throughout the case life cycle.
Both point to the same memory location so if you change any one of them, automatically other reference will be changed. It is like ‘call by reference’.

There is also a public API called reset reference information that helps to reset/remove the linkage between reference and non-reference property (which you doesnt need in your use case)

Use: By doing a reference, data loaded at one place can be referred at other places without wasting memory.

@Jeremy_Sirour its an interesting problem! the when rule at your data class, in another app layer (module) belongs to that layer. So unless you allow them access to the view, and configuring visibility in those views at data- then you are stuck…

I did play with it a bit, and can’t find a way to do this even with the Reuse Library to create when rules from Case, using a Data- when rules :frowning:

In this case, as in others where I have hit this separation of concerns problem, I would be teaching my team how to create when rules in Dev Studio for this scenario. I know its not desirable but surely better than polluting the data model and concerns of number of declare expressions?

OR perhaps the module owners, I’m assuming system architects, can create the when rules in Dev Studio in the implementation app and mark them relevant for the BA’s/Citizen Devs to utilise? I know that breaks the separation of concerns again, but probably more desirable architecturally over the introduction of noise/performance issues.

@Jeremy_Sirour It is indeed unfortunate that it works with pagelists via "instances include” option, but that single page structures don’t have this option.

However, I agree with Marc for what approach to take right now. I would not create lots of declare expressions and evaluation-only boolean props for this purpose. I would, as Marc mentions, go into Dev Studio and create a when rule that contains the “call when rule using step page evaluates to true/false” option. A little less BA friendly, but much cleaner in the end.

Thank you @MarcCheong and @LantzAndreas for your thoughts and your time on the matter.

The challenge I see with “asking the developers to create the when rule” is that, in my example, checking whether a card is cancelled happens in many places and in many case types / applications.
That means that there is no way to define once for all that condition i.e., the case types ReactivateCard, CancelCard, InvestigateCard, ReplaceCard, etc etc (there are roughly 20 operations you can do on a card) will all have to define the same when rule over and over?

Technically speaking I thought about creating a when rule in Work- (within the module) but then I have to also create an embedded page .Card inside Work- and hope that people will use it.

Final thought : since App Studio and Constellation are an interesting exercise of challenging how we are used to do things for years…. I’ve tried to think about it twice… who said that a condition needs to be a when rule? I mean… I don’t expect to reference a paragraph rule when I need a long text, right? I simply store more text in a text property. So, the more I think about it, the more I think that this is the same for boolean fields. And, beyond that, the usage looks easy to me (and hopefully BAs) - one path only : looking for something on Card entity ? Navigate the model and check what you find on the Card object, simple as that.

Am I making some sense ?

Thanks for your reply @Bogga . However I am not looking for a technical solution or workaround to solve performance issues. My primary goal is to offer citizen dev experience but I am trying to be cautious about performance/maintenance implications.

@Jeremy_Sirour I get the reasoning. And for simple booleans it’s easy enough to expose that as your “proxy when rule” so to speak. I think the challenge comes when you want to base it on more than a simple boolean flag. Something like “is eligible?” that’s based on 5 different things in the card object. That’s where I personally would want to reference a when rule. The wrapping in concept is the same, a when rule in the work level that references either a bool prop from the object directly, or a when rule inside the card class. The unfortunate bit being that you can’t drill down into when rules, as discussed above.

Something else to look out for is whether the approach encourages custom conditions or not. In my mind, exposing individual “flags”, such as bool fields, encourages the usage of custom conditions, becasue you lay it more on the business app BA to use the fields directly to build the condition. Whereas if you are clear about that the module brings its own set of pre-packaged conditions in the form of when rules, you have 1 established way of interacting with said conditions > create a when rule in your case that embeds the predefined logic shipped with the module. Of course there will be situations where the business app might want to create their own conditions and so on, but at least you would have a baseline approach. And also the benefit, if the business app BA’s follow the model, that you don’t embed logic directly inside the views.

Regarding the commonality between casetypes: This is indeed a real consideration. But in my mind not strictly related to when rule/condition setup. If you do have common things between casetypes, it could make sense to define embedded props and subsequently some when rules etc. on YourApp-Work. But I would also not overthink it. As a baseline, I don’t actually care that much if I have .Card in 3 separate casetypes. Traditionally as LSA’s we would really not like this. But for me, the business/module level reuse of definitions and features is what matters. Getting card details, using the card data model, reusing “is eligible” when rule from the card module knowing I’m always up to date with the logic, those are things that matter to me. Creating a .Card and a when rule in the case type is for me not a huge hassle, and downright could be an obstruction of the development if the reuse discussions on this level is seen as a blocker because you need to anticipate the needs of 13 upcoming workflows.