Onit App Builder provides many different tools and methods for solving business problems. When faced with a specific use case, our platform may present you with dozens of different ways to solve the same problem. Inevitably, though, some solutions will be better than others, and usually, one solution trumps them all.
When building a new Onit App or workflow, you should always aim for performance, user-friendly, safe, readable by others, and testable solutions. Of course, designing a solution that checks all of these boxes can be challenging.
In this tutorial, we’ll cover commonly accepted best practices used by Level 4 certified App Builder Developers. While following these best practices won’t 100% guarantee success, it will put you on the right path.
- Always Require Comments
- Enable Test Mode
- Watch Out for Expensive Liquid
- Do Not Use Ampersands (&) in App Names
- Avoid Excess Configuration
- Do Not Make REST Calls into Onit
- Background Conditional Compound Actions When Appropriate
- Know When to Create a Child App
- Always Aim for a DRY Solution
- Don't Hardcode
- Use Roles Appropriately
- Think of Security Design Early, Not Late
- Avoid Giving End-Users Unnecessary Access
- Alert Onit to Any Infinite Loops
- Think About Your End-User Experience
- Make Your Configuration Reader Friendly
- Prevent Users from Accessing the /apps Page
- Button Best Practices
- Don't Assume You Know How Configuration Works
- Optimizing Calculated Fields
- Use Initial Values Instead of Calculated Fields for Simple Field Populations
- Use Numeric Calculation When Appropriate
- Always Assign an Initial Value to Checkbox Fields
- Background Actions In Email Received Business Rule
- Don't fire direct Action badges from Direct Action badges
- Don't create a corporation-wide auditing app
- Questions to Ask if You Are Experiencing Poor Performance
Always Require Comments
Always require comments from your App Builder Developers (including yourself). Requiring comments for changes will make troubleshooting and tracking changes to your App much easier. For example, when changing your environment, you find a broken Action. If all App builders left comments when they changed configuration it would be easy to go back and change what had been broken.
To require comments in an environment:
- Navigate to your environment’s Administration page.
- Under the Edit Corporation tab, check the Require Comments on App Changes
Enable Test Mode
Note: Environments with gold-ab (e.g., www.onit.gold-ab.com) in the URL cannot send external emails by default.
Turn on Test Mode to avoid spamming users with emails while developing a solution. For example, let’s say you’re building a new workflow involving a Send Notification Action. You would like to test this notification before you send it to system users. Enabling Test Mode allows you to be sure that you will not notify users when testing your new Send Notification Action.
Test Mode can be enabled at three levels: the environment, the app, and the Action.
To turn on Test Mode in the whole environment, navigate to the Administration page, then the Edit Corporation Tab, and choose Notification Tab Mode. Enabling test mode at the environment level will prevent any notifications from being sent by the entire environment.
Test mode can also be enabled at the App level. Enabling it will prevent an entire App from sending notifications. To enable it, navigate to the Advanced Designer and choose the Settings node. At the bottom of the page, select Notification Test Mode.
The most granular way to enable test mode is at the Action level. Choose Test Mode on the appropriate Action configuration page. Test mode can be enabled for Send Comment Notification, Send External Notification, Send Notification, and Send Report Actions.
Watch Out for Expensive Liquid
Some Liquid expressions are very memory intensive and should be avoided whenever possible. This includes Liquid for loops
, and list lookups, as well as calling .size
, .first
, and .last
.
Additionally, calculated Fields can be expensive. When using calculated Fields in your App, turn them off at the environment level and specify when Onit should recalculate them using the Recalc Single Transaction Action. The Recalc Single Transaction Action should be utilized in Business Rules to run calculated Fields only when necessary (e.g., on a Record update).
For example, your App has a calculated Field named total. Total should update only when a user enters different amounts and prices in the Record. However, because the total is a Calculated Field, Onit will recalculate the total every time the Record is loaded. To prevent unnecessary recalculation, you can turn off calculated Fields at the App level and create a Recalc Single Transaction Action to update the total only when a Transaction Updated Business Rule fires. Recalculating the total in this way prevents expensive Liquid calculations on Record load.
For a more detailed explanation of Record Recalculations, see this section.
Do Not Use Ampersands (&) in App Names
This causes errors when attempting to export and whenever parsing is involved. Avoid ampersands and use the word and instead for best results.
Avoid Excess Configuration
Remember that every Field, button, App panel, and widget you add to your App will impact page load time. Every time a Launch or View Screen is loaded, Onit must individually load each item on the page, including hidden Fields. The more fields in an App, the slower its Records will load.
This doesn’t mean you should not create enough configuration in your App to satisfy the business problems. Instead, you should be careful not to create unnecessary configuration elements.
Do Not Make REST Calls into Onit
Onit’s API should not be called from within the Onit application. The REST Request Action makes it possible to perform API calls from within Onit. This Action might be used to call an external API to update a business Record. However, making API calls to Onit from Onit is expensive and can cause locking errors. For example, you might want to make a REST call from Onit to Onit to retrieve multiple Records from an App that meet certain criteria.
Background Conditional Compound Actions (CCAs) When Appropriate
Backgrounding a Conditional Compound Action (CCA) allows Onit to run it while the user is performing other tasks. This helps speed up perceived performance because the user can navigate away from the page while the Action is being processed. For example, you could background a CCA that changes phases on a related Record, adds participants, or creates a child Record.
Backgrounding a CCA is not always the appropriate course of Action. For example, if a backgrounded CCA fails, the user may never see the error or know of the failure if they’ve browsed away from Onit before the Action has completed processing.
Do not background a CCA that must work synchronously with other Actions. For example, a Change Phase Action should happen after a backgrounded CCA is completed. However, the CCA silently failed, and the Change Phase Action never happened. The end-user would not see any errors, and the Record would be in an incorrect phase.
Know When to Create a Child App
If an App collects a variable amount of data from end-users, then think about creating a child App to collect this data. Collecting this data from one launch form may become unwieldy for end-users.
For example, you are building an App that needs to collect documents from end-users. You might be tempted to create ten different Attachment Fields to accommodate a variable number of uploads. However, this will make the launch form clunky for users. Instead, you should aim to create a new child App that will collect as many documents as the user needs to upload in an organized manner.
Always Aim for a DRY Solution
When configuring your App, always aim for a DRY solution. The acronym DRY stands for Don’t Repeat Yourself. For example, you are building an App with five different Change Phase Actions to accommodate various workflows in your App, one for each phase that could be encountered in the workflow. However, by adhering to DRY, you can condense your Change Phase Actions using Liquid to variablize the phase.
Don't Hardcode
When building, make your Actions and Business Rules as flexible as possible (e.g., don’t hardcode names or email addresses when you can use a list lookup). Additionally, use list combos or transaction list providers instead of plain combo Fields wherever possible to avoid hardcoded values.
For example, when building a new workflow, it might be tempting to enter the Financial Supervisor’s email address into the Approver role; after all, the Financial Supervisor will always be the same, right? Well, if the Financial Supervisor changes, you will have to sign up for many app changes. Instead, you should abstract users from their Roles in Apps. One way to do this is to use a global_roles list. The global_roles list lists every position in your company and the employee’s corresponding email. If any employee changes, you can edit the list, and the new email will be reflected across the whole environment.
Use Roles Appropriately
When building, use Roles appropriately in your App. For example, you can only assign an Approver role to a user who needs to click the approve or reject buttons on a Record. When assigning a user to an Approver role, the role has reporting and UI implications.
Think of Security Design Early Not Late
Before starting your project, spend time thinking about the security of your environment. Some security requirements are possible in other platforms that are not possible in Onit, such as read-only security. Often, security will fall by the wayside, and a very brittle ad-hoc security system will develop over time. For example, Company A decides that simply restricting Record access to participants will be enough security to keep their Records safe. However, when employees leave Company A, they will have a participant who should no longer have access to sensitive Records. The old user must be manually removed from hundreds of Records and replaced with another user. Counteract this by planning your security strategy beforehand. An excellent place to start is our Crash Course on Security tutorial.
Avoid Giving End-Users Unnecessary Access
End users should not be given access to the development environment. This environment is meant for building configurations and is not production-ready. In our experience, giving end-users access to a development environment can confuse them with partially built solutions and may even lead to losing confidence in App builders. Generally, end users should only have access to UAT and Production environments. Additionally, avoid granting end-users a System Admin role. Instead, compromise with an App Admin, List Admin, or App Creator Role.
Alert Onit to Any Infinite Loops
If you accidentally create an infinite loop in your environment, immediately alert Onit. Onit tries to detect and kill all infinite loops; however, they can still happen. A hallmark of an unintentional infinite loop is an App running much slower than it usually does or large amounts of unexpected data being created. If you are unsure if you have created an infinite loop, contact Onit just in case. Infinite loops are easy to create accidentally. For example, you have created a loop to run a couple of Actions for every user in your environment; however, when specifying the stop condition, you accidentally used a greater than sign when you should have used a less than sign, so the loop never terminates.
If you suspect an infinite loop in your environment, run a debugger/logger. To access the debugger/logger tool, navigate to your environment's better-advanced designer page and click Debugger/Logger.
Think About Your End-User Experience
When building, consider the UX of your App. For example, consider ordering Fields on your launch page or using empty text (e.g., placeholder text) in Fields to help end-users understand what to enter. Additionally, consider using validators in Fields, auto-populating Fields when appropriate, strategically ordering Fields in launch forms, and not cluttering launch forms with too many Fields.
Make Your Configuration Reader Friendly
When configuring your App, make it as reader-friendly as possible. Include comments in your Liquid script, and name your Business Rules, Actions, and conditions appropriately. Keeping your configuration clean will help you and Onit understand it. For example, a new App builder is trying to learn your configuration, but when they access the environment, they see twenty Change Phase Actions named “Change Phase.” How are they supposed to know what’s going on? The Change Phase Actions should each have descriptive names like “Change Phase from Discovery to Planning.” This way, the configuration can be easily followed.
Below are some quick tips for keeping your configuration reader-friendly:
- When many Actions work together to solve a business problem, insert something similar in their names. For example, you have a couple of Actions handling phase changes and notifications when a user rejects a Record, so you name all of the Actions “Rejection – Action name.”
- When you have disabled a Business Rule, add “Disabled” to the beginning of its name. This way, other App builders can tell if the Business Rule has been disabled at a glance.
- Create a stand-alone document and ERDs that outline how the configuration has been built and how it works together. For example, this is an ERD of our ELM product:
Prevent Users from Accessing the /apps Page
Always prevent end-users from accessing the /app page. End-users should navigate around your environment through the navigation items in a dashboard.
- To prevent users from accessing the /apps page, navigate to your environment's Administration page.
- In the Edit Corporation node, click the Security tab.
- Scroll to the bottom of the page and check the Restrict to System Admin and App Creators box.
Button Best Practices
When configuring your environment, be mindful of how many buttons you create and what business problems they solve. Creating too many buttons could be a sign of a brittle workflow configuration. For example, you create six buttons to move through each Phase in your App when you could create just one button that moves the Record to the next phase. Additionally, delete any testing or troubleshooting buttons you create during development.
You should also use hide/show conditions to display buttons only when appropriate. This will minimize page clutter and prevent users from clicking the wrong button. To further organize pages, use secondary buttons that only show when expanded.
Don't Assume You Know How Configuration Works
If you inherit a large amount of pre-existing configuration, don't assume you know how the configuration works. When in doubt, consult other App builders and read our documentation!
Optimizing Calculated Fields
Heads up: The information below assumes you know how calculated Fields work in general. For a detailed explanation on configuring calculated Fields see our tutorials on Liquid calculations and Numeric calculations.
When recalculating Records, a certain amount of judgment is required to determine the best configuration for your environment. Suppose you simply mark a Field as “calculated” in an App’s wizard and do nothing else. In that case, Onit will be responsible for determining when and how many times to recalculate the Field whenever a Record is created or changed. This approach is simple to set up and works well until you notice a drop in the App’s performance (e.g., Records take a long time to create and update). This commonly occurs if you have many calculated Fields in an App and/or the Field calculation logic is complex and expensive. When this happens, switching to an alternate configuration approach is often advisable, which relies on firing the Recalculate Single Transaction Action to recalculate Records.
So, what’s the difference between the default recalculation approach and the approach that relies on the Recalculate Single Transaction Action?
When you rely on the default recalculation approach, a calculated Field automatically recalculates whenever a Record is updated, even if the update that a user made has nothing to do with the value being recalculated. In addition, using this approach, when a Record is created or updated on the backend, Onit tells each of the App’s calculated Fields to re-run their calculations multiple times. In other words, if you have five calculated Fields in the App when a Record is updated, each calculated Field doesn’t just re-calculate once. Instead, to ensure that each Field has up-to-date data, Onit recalculates each Field multiple times, just in case one of the calculated Fields relies on the completed calculation of another calculated Field. For these reasons, performance can be affected.
Alternatively, moving away from the default approach and instead using the Recalculate Single Transaction Action approach gives you much more control over specifying exactly when and how many times a Record should re-run Field calculations.
Tip: No one-size-fits-all number exists for the number of calculated Fields an App must have before changing its configuration approach. This threshold differs depending on various factors, most notably the type of calculations being performed. Generally, if your App’s performance seems poor when creating and updating Records, this is one area to investigate from a performance-tuning standpoint.
For example, a Budget Record contains a calculated Field that displays the total dollar amount on the Record. If you change the name of the Budget Record, under the default approach, the calculated Field will also recalculate, even though this field isn’t affected by the name change. Alternatively, use the Recalculate Single Transaction Action (and you disable the default Field calculation approach in the App). You can specify exactly when the Record should recalculate and how often. So, suppose the Record should only recalculate once when a relevant Field is updated. In that case, you can create a Business Rule that checks which Field has been updated and then recalculate the Record accordingly.
The steps below explain how to take the alternative calculation approach via the Recalculate Single Transaction Action.
- Navigate to the App’s Advanced Designer Page.
- Under the Actions node, click Add and choose Recalculate Single Transaction.
- Provide a name for your Action.
- Click Ok to save your configuration.
- Create a Business Rule to fire your Recalculate Single Transaction Action. The Business Rule you select depends on when you want this Action to fire. Often, you’ll create two Business Rules: Transaction Created and Transaction Updated.
Only performing the steps above is not sufficient. Your Fields will recalculate every time the Recalculate Single Transaction Action fires because the App still has the default method of calculating Fields enabled. The App will continue recalculating the Fields using the default, less performant approach.
You'll also need to disable the default method of calculating Fields in your App to prevent this from happening. To do so, follow the steps below:
- Navigate to your Apps' Settings page.
- Uncheck the Evaluate Calculated Fields checkbox.
- Click Save to save your changes.
Use Initial Values Instead of Calculated Fields for Simple Field Populations
Did you know you can use a Field’s initial value to perform simple Liquid calculations? This approach can be more performant in certain situations than marking a Field as being “calculated.”
You’ll often want to assign a static identifier to a Record programmatically. For example, a Matter Number or a Contract Number. Since this number should never change, it would be bad to set this value by making the Field “calculated.” If you did so, you’d ask Onit to recalculate and repopulate this Field every time the Record was modified, which would add needless processing time to your App (since the calculated value would always remain the same). Instead of making this Field “calculated,” you should set the value of this Field once (and only once) by inserting Liquid into the Field’s Initial Value property (in the App’s Wizard).
In the screenshot example below, a Matter Number field is set by concatenating together the following values: the four-digit year when the created was created, a hardcoded dash, and the Record’s Onit Atom Number.
Use Numeric Calculation When Appropriate
When performing math calculations across related Records, Numeric calculations are often better than Liquid calculations.
For example, let’s say that you have an App named Matter that is the parent of an App named Invoices. In Matter, you want to create a field showing the total of all child Invoices (all totaled for that parent Matter). While you could technically construct a Liquid calculation that would perform this math, that would be a bad idea for two reasons:
- Compared to a Numeric calculation, using Liquid would be vastly less performant in this situation.
- The Field in the parent App would likely get stale as child records were created and updated. One significant advantage of Numeric calculated Fields is that, without you having to add any extra configuration, Onit will perform the necessary recalculations to re-run Numeric calculations whenever needed. This is not true for Liquid calculations, which will only re-run when a Record is modified or when a recalculation-related Action (that you must create) runs.
Numeric Field calculations allow you to calculate the sum, average, minimum, or maximum from a Currency, Integer, or Decimal Field across related Records. Additionally, Numeric calculations offer a filter that Liquid calculations do not, letting you perform calculations on Records that match specified parameters.
For more information on Numeric calculations, see our tutorial on this topic.
Always assign an initial value to Checkbox Fields
Checkbox Fields that do not have an initial value and are not interacted with by the user have a value of Null, not false. To avoid throwing off reporting or configuration, always give Checkbox Fields an initial true or false value.
Background Actions in Email Received Business Rules
Any action tied to an Email Received Business Rule should always be placed in a Conditional Compound Action (CCA) and backgrounded to run asynchronously.
The email service that Onit uses to facilitate receiving emails expects all of the Actions fired by Email Received to be short-running (i.e., to collectively start and end relatively quickly). If you do not fire an async action off of an Email Received Business Rules, you may run into unintended and unexpected behavior if your Actions take a long time to complete. For example, Onit may abandon your Actions before they are complete and start the process over again.
To background a Conditional Compound Action, check the Run in Background box while configuring the Action.
Don't Fire Direct Action Badges from Direct Action Badges
When using a badge configured as Direct Action, be careful that your configuration does not fire off another Direct Action badge. This could cause two processes to try to affect the same Record simultaneously. Result: inconsistent behavior and errors.
Don't Create a Corporation-Wide Auditing App
Clients with heavy auditing requirements have sometimes asked for a single app that captures all events in the corporation, consolidating them into a single place. But this creates an app with millions of records, which causes a heavy load on the system and can slow down the system for everyone. Onit has native auditing capabilities and reporting; if a client requires audit reports, work with them to develop a solution using these.
Questions to Ask if You are Experiencing Poor Performance
- Are Fields being calculated in the settings?
- Are there any unused phases causing extra phase change rules to fire? (E.g., Auto Open MV on Create in VATM.)
- Is the Pending phase used, or can it be removed?
- Can any notifications be backgrounded?
- Can any Conditional Compound Actions be backgrounded?
- Can any set-related actions (update-related, set-related phases, etc.) be backgrounded or avoided?
- Can any find/create Actions be changed to relate-to-transaction?
- Are there any unnecessary Update Transactions running? Can we combine any? (E.g., set Legal Entity BelongsTo)
- Are there any Update Related Transactions that can be changed into Run Action on Transactions?
- Are there any duplicate loops (especially endorsements) that can be combined or set as a Field?
- Are there any list lookups on Field calculations that we can set with a UI action?
- Are there any list lookups that we can optimize using list_lookup_atom?
- Are there any loops in field calculations that we can optimize or remove?
- Is MM being replaced on initial create (in Matter)? We can prevent this with a flag Field.
- Are there any manual sums in Update Transaction Actions that we can get with a numeric calc?
- Are there any conditions with loops in their logic?
- Are there any buttons with conditions that have loops in their logic?
- Can we set conditions to prevent unnecessary actions from running?