Robust Expression Design

Building applications using Appian is considered low-code. As low is more than no, we still have to apply some basic principles of software engineering and best practices to end up with code that …

  • can easily be read and understood by others
  • can easily be used by others
  • is tested
  • has no unknown edge cases
  • is fast
  • uses little memory

Well, that sounds like a general guideline for any kind of programming in any language. Right, and that’s great because then all we have to do is copy existing software risk management best practices and adapt them to the specifics of low-code and the Appian platform.

In the following paragraphs, I will explain which methods I apply in my projects.

Consistent Return Types

Appian Expressions do not support explicitly defining the data type of its output. But, to use an Expression Rule, I need to be able to rely on the consistency of its output. I have seen Expressions creating more than three differently typed outputs like: NULL, false, {“hello”, “world”}. When I want to use this expression, I need to implement some logic to be able to consume that output in a meaningful way.

Guideline: An Expression Rule creates output of ONE specific type in all situations!

Null Checks

I already wrote a post about the magic of null checks (https://appian.rocks/2022/10/17/the-magic-of-null-checking/), but here I would like to write about a different aspect. I divide Rule Inputs of Expressions into two categories. Some absolutely require valid input values, while others can be more relaxed and fall back to a default behaviour.

When implementing an Expression having strict requirements, implement some validations und use the error() function to make your fellow developers aware of missing parameters. This will make a process pause by exception or show that lovely red error boxes in interfaces.

I try to put almost all my Expressions into the second category, trying to implement a comprehensible default behaviour. When I build an Expression ACM_GetCaseById, then passing an ID is mandatory, but in case you forget the ID, then it will just return a type-casted NULL value.

I understand that this method might scare some die-hard pro-code developers, but in low-code with Appian I consider this very appropriate. After all, in Appian, we don’t build 10 layers of stacked abstractions that all have to be secure to the last.

Guideline: An Expression implements a comprehensive default behaviour for omitted Rule Inputs!

Test Cases

Do we really have to discuss this?

Guideline: An Expression has at least one test case and validates any edge cases!

Comment

The argument about how to write good comments is probably as old as comments in source code. I want to avoid getting too deep into this, but I advise using comments to give the reader an added value compared to the code itself. We work here with low-code which is very meaningful on its abstract level. This makes a huge part of the comments superfluous. As easy as the code is to read, it is sometimes not clear for what reason something is implemented that way.

Guideline: An Expression has value-adding comments that describe the “why” and not the “how”!

Naming

The naming of design objects and variables is a field full of misunderstandings. I can only strongly advise you to give your objects names that have a clear and unambiguous meaning.

You wonder what I mean by this? Well, an expression exists because it solves a specific problem or implements a specific requirement. And I require that this concrete purpose becomes clear just by reading the name. To achieve this, leave the functional context of your expression and look at it from the outside.

Added November 20th 2022: Check out this great video about naming patterns and anti-patterns. https://youtu.be/-J3wNP6u5YU

Guideline: An Expression has a name, that makes me understand its purpose!

Description

I do not require an Expression to have a description. A good name should tell me enough about its purpose and how to use it. But there are cases that require more details about specific behaviour that I add to the description. Again, it’s about adding value beyond the name.

Guideline: An Expression has a description if it adds value beyond the name!

Local Variables

As Appian uses a functional programming approach, using local variables to store an intermediary result is not necessary. And starting every line with a local variable, to make the code look familiar, just shows that you might still be stuck with your old procedural style.

In case the result of your first function call is not the final result, just wrap it into another function that gets you closer to your expected outcome.

I use local variables in expressions when I need an intermediate result more than once, or to make larger steps in the implemented logic more comprehensible.

Guideline: An Expression uses local variables only to store intermediate results used multiple times or to separate larger logic blocks!

Error Handling

There is no sophisticated way of error handling in Appian using exceptions and throw and try-catch. In my honest opinion, there is also no need for this. We do low-code, and the levels of nested Expressions typically does not exceed three.

We might need a new approach when thinking about error handling. In my experience, it is a good idea to shift perspective from technical to business. So, as long as my Expression technically works, I can just accept errors. But as soon as a business relevant error occurs, you need to immediately stop any further processing.

I have seen many clients struggling with a fragile network infrastructure or unreliable APIs. I want to avoid making this into a problem of my Appian application. Third-party systems and APIs need to be monitored by the OPs department. I just have to make sure that my application does not make any wrong decisions because of missing data.

Guideline: An Expression handles business errors and accepts technical errors!

Maintainability

Check out some Expressions you wrote a year ago. Do you still immediately understand what it is doing, how, and why? And how much time did it take? This happens to every person who has been looking at this code in the meantime! Reduce that time by half!

Guideline: An Expression can easily be understood and refactored!

Simplicity

When you have a pro-code background, like I do, you probably love to build abstractions. I mean, in pro-code, you typically spend more time in solving technical challenges than solving actual business problems your users care about. This is what low-code is about. It relieves us from this burden of having to make tech work.

This also means, that we can relax a bit and implement applications in an agile way. Keep things simple and concentrate on the requirements of today instead of trying to guess the requirements of tomorrow. No worries, things become complex soon enough.

Guideline: An Expression implements today’s requirements in the most simple way!

Summary

Please consider this article as an impetus to think about your own approaches. You have a different background and experience than I do, and your clients, projects and teams are different. Maybe some of this is new to you, or some of it is already known. In conversations with other Appian developers, I too always get new thoughts that put my supposedly great approaches to the test.

In any case, I’m excited about your feedback.

Leave a Reply