Pega Infinity Development Best Practices
Pega Infinity Development Best Practices
|Description||Guidelines for Pega Platform developers to create efficient, sustainable, and guardrail-compliant applications|
|Version as of||8.5|
|Capability/Industry Area||Enterprise Application Development|
This document provides application development best practices for Pega Platform™ developers to create efficient, sustainable, and guardrail-compliant applications. We collated and consolidated the following list of best practices from the development experiences shared by lead system architects, consultants, and development teams.
The following list of Pega Infinity development best practices is sorted by impact category and then by severity if developers do not follow guidelines. You can click the table headers to sort the list by rule type or impact category. Note that this list excludes Cosmos development best practices. When new best practices are encountered, this list will be updated to capture the new information.
|Rule type||Impact Category||Best Practice||Severity|
|UI rules||Update||Pega Infinity has controls that support new features, such as offline capability, responsiveness, and cross-browser support. Deprecated or custom controls do not have these capabilities, so you should update to controls shipped with Pega Infinity. Replace custom or deprecated controls with the latest Pega Infinity controls. If no updated control is available, make custom controls cross-browser and responsive.||H|
|UI rules||Update||Pega Infinity recommends the skin rule for all styling needs in the application. This reduces maintenance cost and provides flexibility to style consistently, regardless of browser or device. Make applications cross-browser and cross-device-compliant. Inline styles and custom CSS must be re-engineered using Pega Infinity skin, mixins, and style formats.||H|
|Data pages||Update||Do not remove parameters for a data page. Never remove parameters from shipped data pages in the framework layer. The implementation layer might use your data pages with Key,Value; removing a parameter might make referenced rules invalid, causing exceptions in flows.||H|
|Reports||Update||Do not remove properties from report definitions when they are declared as available, especially in the framework layer. Never remove properties from report definitions that are shipped, even if those properties are not being used. If the implementation layer attempts to re-use a report definition for which properties have been removed, it will impact the referencing rules.||H|
|Data pages||Update||Avoid adding required parameters to old rules. Avoid adding new required parameters to shipped data pages in framework layer. The implemention layer might use these data pages, and adding new parameters might make their referenced rules invalid, causing exceptions in flows.||H|
|All rules||Update||Do not block the availability rules in the framework layer.||H|
|All rules||Update||Replace deprecated rules references with recommended/available rules. Do not use deprecated activity methods.||H|
|All rules||Update||Do not reference internal Pega rules in implementations.||H|
|All rules||Update||The use of locatable pages was deprecated in Pega Platform as of the 7.3.1 release. Locatable pages are a legacy feature that is not supported by the Internal Language (IL) assembly. Using locatable pages would require falling back to legacy assemblers that would not utilize the IL assembly optimizations.||H|
|All rules||Update||Use extensions wherever provided instead of overriding rules. Use Pega rules as-is and append new functionality in your application rules.||H|
|Ruleset||Update||Only application ruleset validation (ABV) is recommended for ruleset setting.||M|
|All rules||Update||Pega Infinity has been enhanced with more guardrails and validations and with better coding standards. Some legacy features are no longer supported and must be modified to Pega Infinity standards. Update references such as $ANY or $NONE with appropriate class references.||M|
|Data types||Update||Pega Infinity has updated Data Management/Modeling features that provide better design and runtime performance. Update these components to new features. There are no auto-update utilities for most of the features in this area. Update old data tables to the new local storage data types to comply with Pega Infinity standards.||M|
|Portal||Update||Legacy fixed or custom portals are no longer recommended in Pega Infinity, as they do not support cross-browser or responsive design. Debugging tools such as Live UI might not work for these legacy portals. Replace fixed or custom portals that lack responsiveness with Pega Infinity composite portals.||L|
|Delegated rules||Update||Delegated rules will continue to work after you update to Pega Infinity, but they might need updates to address changes to referencing rules and form changes. Skimming is recommended during update, which might require delegation re-mapping. Rule form changes require business retraining. Update delegated rules wherever required.||L|
|Reports||Performance||Fetch only the required columns and not all columns from the database.||H|
|Reports||Performance||Avoid unnecessary JOINS while fetching database records.||H|
|Activity||Performance||Use data pages backup by RD or Look up rather than using obj-browse. Do not use obj-browse for list of objects. If you use obj-browse, fetch only the column you need and not the entire BLOB. If some BLOB data is used frequently, consider exposing that column.||H|
|UI rules||Performance||Consider using pagination of records for Memory / Performance optimization based on your specific use case requirements. Pagination should be enabled when fetching records from the database.||H|
|All rules||Performance||Use Alert logs, PAL, and Log Usage to monitor performance during development, UAT, and performance testing. If you observe performance issues, collaborate with performance tuning experts to resolve those issues. Assess performance load and verify the capacity of your production system.||H|
|Clipboard viewer||Performance||Identify and remove unnecessary clipboard pages at the end of each process. Redundant pages use JVM memory.||H|
|Reports||Performance||Verify that the report definition filters load only necessary data to the clipboard. Configuring filters correctly is better than using row visibility conditions to hide rows in a grid.||H|
|Decision tables||Performance||To avoid slow performance, limit your decision table to no more than 300-500 rows.||H|
|Decision trees||Performance||To avoid slow performance, limit your decision tree to no more than 300-500 rows.||H|
|Map values||Performance||To avoid slow performance, limit your decision map rules to no more than 300-500 rows.||H|
|Class||Performance||Ensure classes are not mapped to more than one purpose database table, such as pr_data or pr_other. Maintenance of exposed properties for more than one type of data prevents appropriate indexes from being used.||H|
|Rule-Obj-Activity||Performance||Always use Obj methods (rather than RDB methods) to ensure the BLOB and columns are kept in sync. RDB methods should be used only for complex query processing/connecting to an external database.||M|
|Activity||Performance||Max Records is not automatically specified on the RDB-List method. If the Max Records value is left blank, it defaults to 10,000. Consider specifying a maximum limit for improved query performance.||M|
|All rules||Performance||Debug Log (oLog) should be implemented properly in activities to debug and write warnings/errors in log files if an exception occurs. When logging log information externally, verify that logged information provides sufficient detail to assist in debugging an issue. By default, the application logs class name, activity name, step, date/time, requestor, and error type. Additional log items might include case ID, case status, and operator. Make sure you do not log sensitive information. Specify appropriate log level settings so that production logs and PDC are not cluttered. System.out.print should be removed or commented after development.||M|
|UI rules||Performance||Records fetched in memory should be just-in-time rather than persisted throughout the user session. Use appropriate data page scoping.||M|
|Activity||Performance||If you use a parameter with the OBJ-BROWSE method (to/from/like), define a pre-condition on the step to verify that all required parameters exist before the OBJ- BROWSE method is invoked.||M|
|Agent||Performance||Use queue processors or job schedulers instead of agents for better performance, resiliency, fault tolerance, and flexibility.||M|
|Class||Performance||Consider not storing the history of classes in environments where changes will be frequent and you have no business reason to track updates.||M|
|All rules||Performance||Avoid using large text values in top-level pages. Elastic search indexes all top-level properties when it is enabled on a class. Consider keeping large text values in embed page properties.||M|
|All rules||Performance||Use wrapper activity to consolidate actions and reduce the number of requests to the server.||M|
|UI rules||Performance||Enable defer load for tabs/section for faster screen loads. Load data just in time when the end user needs it.||M|
|UI rules||Performance||JPEG/PNG images should be used only when the image size is greater than 100 x 100 px. For smaller images, consider using Icon font so you avoid time-consuming requests to the server.||M|
|Data pages||Performance||Load mechanism is executed on every interaction for data page can impact performance. Select this option only when the business use case requires the freshest information.||M|
|Activity||Performance||Do not use the Infoforced log. Remove unnecessary log messages before check-in. Change the logging level to prevent cluttering of log files and avoid potential performance impact.||L|
|Data transforms||Performance||Enable "call super-class data transform" checks only if you have a data transform with the same name in the class inheritance tree. Doing so avoids the overhead of looking up to parent classes.||L|
|Access roles||Security||Implement custom security roles to maintain security requirements. End-user access groups should not grant the PegaRULES:SysAdm4 security role. Roles should default to having least privileges to end-user access groups.||H|
|Reports||Security||Add appropriate privileges and restrictions to reports to control which user groups can execute a report.||H|
|Activity||Security||"Allow direct invocation from the client or a service" or "Allow invocation from browser" is unchecked by default. If you enable the "Allow direct invocation from the client or a service" checkbox, you must add a privilege to the activity.||H|
|Workbasket||Security||Add the appropriate roles to workbasket definitions to control who can process assignments in the workbasket||M|
|Data pages||Security||Select an appropriate user-level access group for all node-level data pages. Create an access group used specifically for batch processing (data page loading and agent activity processing).||M|
|All rules||Maintainability||Reduce or eliminate use of duplicate loops in rules such as activity or data transform, which can have significant performance impact.
1. When possible, do as much processing as possible in one pass to avoid looping over the same data multiple times. .
2. When looping over a data structure, be aware that the larger the list, the more times processing will occur. For example, you can use a report definition "Class Join" feature to gather data in one database call rather than making separate database call for every result returned. If services are called within a loop, use data pages to cache results to improve overall performance.
|Database||Maintainability||Do not use custom store procedures to accomplish a task.||H|
|Data transforms||Maintainability||Data transforms should not use the pxExecuteAnActivity function to call an activity. Evaluate whether the called activity can be transformed to a data transform.||H|
|Section||Maintainability||'Create work' action class input parameters should not be hard-coded. Consider using dynamic class referencing to improve maintenance and extensibility.||H|
|Flow||Maintainability||To create the implementation layer case type, select other option and use DCR to specify the class name rather than selecting the case type in create case smart shape.||H|
|All rules||Maintainability||Consider deprecating rules to post warnings on usage. Provide documentation on the deprecated rules.||H|
|All rules||Maintainability||Avoid creating custom-coded rules. If no better option is available, then ensure custom-coded rules, such as activities with java steps, non-autogenerated UI rules, and functions, are final.||H|
|Class||Maintainability||Consider enabling 'Propagate schema changes to child classes', for work classes to avoid explicit optimization at the customer end.||M|
|All rules||Maintainability||When creating a rule such as an activity or data transform, use parameters to clearly define the inputs and outputs so system architects understand how that activity is used. If the activity needs a specific value to process, rather than passing a complete page reference, pass a scalar parameter.||M|
|All rules||Maintainability||When creating a new rule that is similar to an existing rule, minimize duplicate code. If you are changing only values (but not changing the code) in a rule, refactor the rule to use parameters instead of creating multiple versions of the same rule. If the same code is used multiple times, create well-documented reusable assets that can be called from different places rather than copying that code. Determine the reusability of the rule, as this determines where the rule should be placed in the Class and RuleSet hierarchy.||M|
|All rules||Maintainability||Consider your rule's Applies-to class carefully. Put rules in a higher parent class if you anticipate reusing it across all children or if you want to avoid duplicate rules. If a rule is not reusable, put it in the class where it is used. Do not flood abstract classes with rules that can be used only in particular concrete classes. If a rule is needed in multiple concrete classes, do not copy the rule across to the sibling. Instead, promote the rule to the child class and withdraw the original rule to avoid duplicate code.||M|
|Activity||Maintainability||Do not use Page-New methods to create a page that you are planning to use as step page for Obj-Open/Obj-Browse/RDB-List/RDB-Open. These methods create the specified page by itself.||M|
|Activity||Maintainability||Do not use hard-coded reusable values in properties such as URL or classes (activity class etc) in activities. Rather, use data pages/decision tables/map values.||M|
|All rules||Maintainability||The name of a workbasket should clearly identify the purpose of the workbasket.||M|
|Flow||Maintainability||Business rule flow should be neat and readable, as it can be exposed to business users. Add annotation to improve readability.||M|
|Flow actions||Maintainability||Flow Action Name should describe the functions of the flow action. For example: AttachAFile, Notify External.||M|
|Flow||Maintainability||Utilities should serve a business purpose. Instead of adding one utility that does an entire step, separate the utility into separate smaller utilities, and use these smaller utilities as individual identity in the flows. This makes the flows descriptive and readable.||M|
|Flow||Maintainability||The number of Smart Shapes (excluding connectors) should not be more than 15 per work flow.||M|
|Flow||Maintainability||Flow implementation should be model-driven. For example, identify and use decision rules in a flow rather than an activity. This will make the logic of the flow clearer.||M|
|UI rules||Maintainability||When possible, set the label value for a control from the short description for its property rather than from inline labels, which increase maintenance costs.||M|
|Property||Maintainability||Do not duplicate properties if you can avoid it.
1. If multiple classes use a property, define the property once where it is accessible to all classes that need it.
2. If one of two classes that need to use the property do not share a parent (for instance, one is Embed- and the other is not), you can copy the property. Be sure to use the exact same name.
|Property||Maintainability||Avoid copying data.
1. During processing, data should exist in only one place. In Pega, that means in a single property.
2. If user input has a cascading effect (setting a value in one place creates defaults for a number of other values), then you can copy data if the effect is one-directional. In other words, you can copy data only when you can define it using something like a declare expression. Verify that you do not create circular dependencies when you copy data.
|Property||Maintainability||Property types should be selected from the type dropdown rather than specified in text.||M|
|All rules||Maintainability||Add test rules to a separate test application that is built on a target application.||M|
|All rules||Maintainability||Remove all unused rules before you move to production.||M|
|Activity||Maintainability||The Page-New method with an empty class initializes the page with the class defined in Pages and Classes. Consider using dynamic class referencing for easy maintenance and extensibility.||M|
|Flow actions||Maintainability||Use a validate rule to perform data validations, and invoke the same validate rule from the flow action. An activity doing the same in post processing using Obj-Validate or Property-Set-Messages does not support extensibility.||M|
|Navigation||Maintainability||Control action should not be configured using hard-coded class. Consider using dynamic class referencing for easy maintenance and extensibility.||M|
|Data transforms||Maintainability||Consider modularizing a data transform so that it does not require more than 20 steps. This improves reusability and unit-level quality.||M|
|UI rules||Maintainability||Use WHEN rules rather than expressions in section/layout/control visibility conditions if the same condition is used in multiple places for easy maintenance and extensibility.||M|
|Data transforms||Maintainability||Inline Java is always overhead in terms of maintenance. Consequently, consider using data page or data transform. RUF is recommended if unavoidable.||M|
|Section||Maintainability||When deciding whether to use a section or to nest a dynamic layout, minimize the number of sections that you create to improve performance and maintenance.
|Data transforms||Maintainability||Do not use more than five levels of nested steps in data transforms.||M|
|Declare-On Change||Maintainability||Do not use a Complex Java Expression under When condition in the Conditions field of the On Change Properties tab,||M|
|Activity||Maintainability||Use automation rules instead of activity rules when you create an API.||M|
|Activity||Maintainability||Give precedence to a local variable over a property if scope is defined only within the activity. If local variables are defined but are not being used in the activity, consider removing them.||L|
|Activity||Maintainability||Provide comments to describe the context of significant steps in an activity to improve readability and maintainability,||L|
|Activity||Maintainability||Comment out activity step lines to prevent them from executing at run time during testing. Commented lines should usually be removed before merging your rules. You may want to keep commented lines if they are helpful when debugging or if they help someone understand the activity,||L|
|All rules||Maintainability||Document your rules when the purpose or use of a rule is not clear to improve maintainability. Document what the rule does in the description and how the rule is used in Usage. The rule label should indicate the purpose of the rule in human-readable form.||L|
|Activity||Maintainability||Activity names should start with a verb/noun.||L|
|All rules||Maintainability||When defining parameters, select the appropriate data type and provide a meaningful description/purpose.||L|
|Activity||Maintainability||Activities should not exceed 20 steps.||L|
|Property||Maintainability||Property names should be based on nouns or noun phrases that describe the property.||L|
|Declare expressions||Maintainability||Adopt a naming convention for properties designed to be computed in Declare Expression rules. Create Declare Expression rules early, using stub or dummy expressions. By following naming conventions, developers can easily identify declare expression properties and can avoid setting values procedurally.
The use of reference properties in an expression's target or page context can result in unpredictable behavior. Consider using non-referenced properties instead.
|All rules||Maintainability||You must provide appropriate comments when checking in a rule after modification. Include a work item, such as a change request or error number, at the beginning of the description of the change. For example: "US-00001 – Removed pyWorkPage Page Delete Step from Activity."||L|
|Data transforms||Maintainability||Consider adding comments to the data transform for easier readability, maintenance, and potential reuse.||L|
|Data transforms||Maintainability||Data transforms should not have disabled steps under most circumstances. Review and remove disabled steps if they are not required.||L|
|Activity||Maintainability||If an Activity rule is required, set an appropriate 'Activity type’ in the Security tab to remove warnings. For example: "Utility (default), Validate, Load Data Page."||L|
|Data transforms||Maintainability||Avoid using (<APPEND>) (<CURRENT>) to improve readability. Consider using 'Append and map to'.||L|
|UI rules||Functionality||Do not use horizontal scrolling. Minimize vertical scrolling.||H|
|Property||Functionality||Use Date Time rather than Date or TimeOfDay types for properties that are part of persistent objects in your application. Avoid using Date property types in persistent objects, even if your application is used in only a single time zone, unless a time zone value is also stored in another property of the object.||H|
|Decision tree||Functionality||We cannot redirect a rule to itself under Circumstance Value in the Options field of the Results tab. Avoid creating a circular set of redirections (A to B and B to A) because this causes an exception at runtime.||H|
|Declare Trigger||Functionality||When there are multiple triggers on the same class(user defined/inherited), then the order in which the triggers fire is not guaranteed. Trigger activities should be implemented in a way where they are mutually exclusive and independent of each other in terms of functionality.||H|
|Map values||Functionality||We cannot redirect a rule to itself under Circumstance Value in the Options field of the Results tab. Avoid creating a circular set of redirections (A to B and B to A) because this causes an exception at runtime.||H|
|Activity||Functionality||When you use the History-Add method, use field values to support localizations.||M|
|Activity||Functionality||Use @equals functions instead of '==' for string comparisons.||M|
|Flow||Functionality||Always give the status of an assignment and the status of work in the assignment task parameters.||M|
|Flow||Functionality||Do not hardcode the workbasket/router user name In the routing unless it is important. Use a parameter page instead.||M|
|Flow||Functionality||Configure meaningful and readable audit information in a flow. For example, use a proper action description in the assignment task. Remember that whatever action comes in an assignment will be described in the work item history as “Assignment To” and the added text.||M|
|UI rules||Functionality||Don't use fixed widths. For table-style layouts such as grids or tree grids, always set the width to 100%. This allows the display to adapt to the device the viewer is using.||M|
|UI rules||Functionality||Make sure autogenerated controls have validation options.||M|
|UI rules||Functionality||Improve the user experience by removing unneeded clicks, especially for tasks that are simple or frequently repeated.||M|
|UI rules||Functionality||Use the field values for text displayed to users to support localization.||M|
|UI rules||Functionality||To ensure client validation is working, enable client validation on the harness.||M|
|UI rules||Functionality||'Localize' should be checked on Section rules.||M|
|Decision tables||Functionality||Specify the most likely outcome rows before you specify less likely outcome rows.||M|
|Declare-Index||Functionality||Do not create declarative indexes for top-level Single Value properties.||M|
|Rule-Utility-Function||Functionality||Use the String.Equals () or String.equalsIgnoreCase () Java method, not the == or != operators, to compare the value of a property to a literal string or to the value of another property.||M|
|Circumstance-Definition||Functionality||List the more likely outcomes in rows at the top of the table.||M|
|Circumstance-Definition||Maintainability||When circumstancing rules, use circumstance templates rather than circumstancing on properties to allow implementation layers to customize the templates.||M|
|Exception handling||Functionality||Database calls (and other integration calls) should be handled by incorporating preconditions and transitions related to errors and exceptions. “Jump To Later Step” / “Exit Activity” should be used effectively in activities to handle exceptions. Evaluate raising appropriate PDC alerts when errors occur.
Not handling an error may result in ungraceful errors.
|Exception handling||Functionality||Error Flow should be implemented in all critical use cases.||M|
|All rules||Functionality||Do not assume a clipboard page is available. Instead, perform appropriate verification checks before executing a data transform or activity.||M|
|Activity||Functionality||Do not use obj-save to save rules. Use "call pxUpdateRecord/pxCreateRecord" or "Call Save" instead.||M|
|Section||Functionality||Using Refresh When and Refresh Other Section.
Use Refresh When whenever possible, especially for read-only references that need to remain synchronized with data on the server, as it declares dependencies ("This section needs to be updated when .x changes"). When this is not possible (for example, if you have editable references that are updated based on other input or based on untrackable inputs such as button clicks), use a Refresh Other Section targeted refresh.
|Section||Functionality||Avoid Refresh section.
Refreshes interrupt the user experience. The user has to wait, the screen seems to hang until the section refreshes, and after the refresh is done, the user has lost focus and has to manually return to the original screen. Manage client-side interactions by using change tracker whenever possible. For example, instead of refreshing a section with a pre-processing data transform, call a data transform or use set value and set your visibility conditionals to evaluate on client.
Do refresh a section when:
Do not refresh a section when:
|Section||Functionality||Use set value to set flags. Use case: you have a property .pyIsThingVisible. Put the property in a hidden input field in the UI and use "set value 'pyIsThingVisible = true" (or false). This is lighter weight than using "Run data transform pzSetIsThingVisible" (and creating and maintaining the data transform).||M|
|All rules||Functionality||Add Pega units for all the supported rule types. Execute them during the development in branches and during the merge process. Look for 100% Unit Test passed before merging the branches.||M|
|Report-Definition||Functionality||Consider the use of the Smart Info capability to enrich the value of reports.||L|
|Data transform||Functionality||Avoid hardcoding pyWorkPage and pyWorkCover in data transforms and activities, as hard coding hampers the reuse of rules.||L|
|Activity||Functionality||In case of unavoidable scenarios, if Page-Change-Class Method is used, then you should use DCR pattern rather than a hard-coded class.||L|
|Flow||Functionality||As a best practice, use one of the following prefixes to support standard reports and maintain continuity in between your custom status and standard status values: New-, Open-, Pending-, or Resolved-||L|
|UI rules||Functionality||Avoid using icons for controls. Use link text or a button for clarity and ease of localization.||L|
|Section||Functionality||A general design/development approach should be that read-only display of a particular section is controlled outside of the section either through the harness in which it is included||L|
|UI rules||Functionality||Bundle your transactions in minimum calls (ex: call activity and refresh section can be bundled).||L|
|UI rules||Functionality||Input validation should happen on both the client and the server.||L|