Skip to main contentMAF Configuration Practices

Applying Configurations

Overview

When customizing Maximo Mobile applications, the method you choose for applying configurations has significant implications for maintainability, upgrade compatibility, and long-term support. This guide explains the recommended approaches and why certain practices should be avoided.

There are three primary methods for applying configurations:

  1. Using AppCustomizations.js (✅ Recommended)
  2. Extending base JavaScript classes (✅ Recommended for complex scenarios)
  3. Directly modifying base controllers (❌ Not Recommended)

Understanding when and how to use each approach is critical for creating maintainable customizations that survive version upgrades.

Why This Matters:

The configuration approach you choose directly impacts:

  • Upgrade success - Whether your customizations survive version updates
  • Maintenance effort - How much work is required to maintain customizations
  • Technical debt - Long-term cost of supporting your customizations
  • Team productivity - How easily others can understand and modify your work

Method 1: Using AppCustomizations.js (Recommended)

Overview

The AppCustomizations.js file is the primary and recommended location for all application customizations. This file is specifically designed to persist through Maximo Mobile upgrades, making it the safest place for your custom logic.

The AppCustomizations.js file acts as a global controller for your entire application. Any event handler that can be defined in datasources, dialogs, pages, or the application itself can be implemented within AppCustomizations.js. This includes:

  • Application lifecycle events (applicationInitialized, applicationResumed)
  • Page lifecycle events (pageInitialized, pageResumed, pagePaused)
  • Dialog lifecycle events (dialogInitialized, dialogOpened, dialogClosed)
  • Datasource events (onDatasourceInitialized, onAfterLoadData, onBeforeLoadData)
  • Custom event handlers defined in your XML configuration

This centralized approach means you can intercept and customize any event in your application from a single, upgrade-safe location.

Why Use AppCustomizations.js

Benefits:

  • Upgrade-safe - This file carries over during version upgrades
  • Centralized - All customizations in one location for easy maintenance
  • Global scope - Can handle events from any component in the application
  • Clear separation - Distinguishes custom code from base framework code
  • Event interception - Can intercept any event before or after base controllers

Trade-offs:

  • ⚠️ May require adjustments when APIs are deprecated between versions
  • ⚠️ Developers need to monitor release notes for API changes
  • ⚠️ Functions may need refactoring if underlying framework behavior changes
  • ⚠️ Can grow quite large as a singular file, making readability and navigation challenging

Basic Structure

The AppCustomizations.js file follows a standard class-based structure with lifecycle methods:

/**
* Application customization file
* This file persists through upgrades - place all custom logic here
* Acts as a global controller for the entire application
*/
const TAG = 'AppCustomizations';
class AppCustomizations {

Common Customization Patterns

Pattern 1: Wrapping Existing Methods

When you need to add logic before or after an existing method without replacing it entirely:

/**
* Wrap an existing controller method to add custom logic
*/
pageInitialized(page, app) {
if (page.name === 'workDetail') {
const controller = page.findController((c) => c.constructor.name === 'WorkOrderDetailController');
if (!controller) {
this.app.log.w(TAG, 'WorkOrderDetailController not found');

Pattern 2: Event Handler Registration

Subscribe to application or datasource events:

/**
* Register custom event handlers
*/
applicationInitialized(app) {
this.app = app;
const methodTag = `${TAG}.applicationInitialized`;
// Listen for datasource events
this.app.on('onAfterLoadData', (event) => {

Pattern 3: Datasource Customization

Modify datasource behavior and queries:

/**
* Customize datasource when it initializes
*/
onDatasourceInitialized(datasource, owner, app) {
const methodTag = `${TAG}.onDatasourceInitialized`;
if (datasource.name === 'workorderDS') {
this.app.log.d(methodTag, 'Customizing work order datasource');

Pattern 4: Dialog Customization

Customize dialog behavior during initialization:

/**
* Called when a dialog is initialized
* @param {Object} dialog - The dialog instance
*/
dialogInitialized(dialog) {
const methodTag = `${TAG}.dialogInitialized`;
this.app.log.d(methodTag, `Dialog initialized: ${dialog.name}`);
if (dialog.name === 'woStatusChangeDialog') {

Pattern 5: Custom Event Handlers from XML

You can define custom event handlers in your XML and implement them in AppCustomizations.js:

In app.xml:

<button label="Custom Action"
on-click="handleCustomAction"
on-click-arg="{item}"
id="btn_001"/>

In AppCustomizations.js:

/**
* Handle custom action button click
* This method is called from the XML event handler
*/
handleCustomAction(item) {
const methodTag = `${TAG}.handleCustomAction`;
this.app.log.d(methodTag, `Custom action for item: ${item.wonum}`);
// Implement your custom logic

Best Practices

✅ Do:

  • Place all custom business logic in this file
  • Use clear, descriptive function names
  • Add comprehensive comments explaining the purpose of each customization
  • Use the TAG constant for consistent logging
  • Test customizations after each Maximo Mobile upgrade
  • Monitor release notes for deprecated APIs
  • Wrap original methods when extending functionality (preserve base behavior)
  • Use bind() when saving method references to preserve context
  • Implement event handlers for any component (datasource, dialog, page, app)

❌ Don’t:

  • Assume APIs will remain unchanged between versions
  • Skip testing after upgrades
  • Mix custom logic with base framework files
  • Ignore deprecation warnings in release notes
  • Modify the file structure or class name
  • Remove the export default statement

Handling API Changes During Upgrades

When upgrading Maximo Mobile versions, you may need to adjust your AppCustomizations.js code to accommodate API changes:

/**
* Example: Handling deprecated API
* Version 8.3: Used app.datasources.workorderDS
* Version 8.4: Changed to app.findDatasource('workorderDS')
*/
applicationInitialized(app) {
this.app = app;
const methodTag = `${TAG}.applicationInitialized`;

Real-World Example

Here’s a complete example showing multiple customization patterns:

/**
* Custom Application Logic for Technician App
* Adds validation, logging, and custom business rules
* Acts as global controller for all application events
*/
const TAG = 'TechnicianCustom';
class AppCustomizations {

Summary

The AppCustomizations.js file is your primary tool for customizing Maximo Mobile applications. It provides:

  • Upgrade safety - Your customizations persist through version updates
  • Global controller - Can handle events from any component in the application
  • Centralized management - All custom logic in one place
  • Flexibility - Can wrap, extend, or add new functionality
  • Maintainability - Clear separation from base framework code
  • Event interception - Can intercept and customize any application event

While you may need to adjust for API changes between versions, this approach is far superior to directly modifying base controllers, which would require complete reapplication after each upgrade.

Learn More:


Method 2: Extending Base JavaScript Classes (Recommended)

Overview

For more complex customizations, extending base JavaScript classes provides a structured, object-oriented approach that maintains separation between custom and base code while surviving upgrades. This method is particularly useful when AppCustomizations.js becomes too large or when you need to create reusable controller logic.

Why Extend Classes

Benefits:

  • No manual reapplication - Custom logic doesn’t need to be manually merged after upgrades
  • Object-oriented - Leverages inheritance for clean code organization
  • Override flexibility - Can selectively override specific methods
  • Maintains base functionality - Inherits all base class capabilities
  • Better organization - Separates concerns into focused class files

When to Use:

  • Complex controller customizations with many methods
  • Multiple related method overrides in a single controller
  • When AppCustomizations.js becomes too large and unwieldy
  • When you want better code organization and separation of concerns

Trade-offs:

  • ⚠️ Requires understanding of JavaScript inheritance
  • ⚠️ Must test after upgrades to ensure base class changes don’t break extensions
  • ⚠️ Need to track which base classes are extended
  • ⚠️ More complex than AppCustomizations.js for simple customizations
  • ⚠️ Requires XML configuration changes

Creating an Extended Controller Class

Step 1: Create the Extended Controller File

Create a new JavaScript file with a unique name. The file should import the base controller and the logging utility:

/**
* ExtendedSchedulePageController.js
* Extended controller for schedule page
* Location: /app/controllers/extended/ExtendedSchedulePageController.js
*/
import { log } from "@maximo/maximo-js-api";
import SchedulePageController from "../SchedulePageController";
const TAG = "ExtendedSchedulePageController";

Step 2: File Organization

Organize your extended controllers in a clear directory structure:

Recommended Structure:

app/
├── controllers/
│ ├── extended/ (Custom extended controllers)
│ │ ├── ExtendedSchedulePageController.js
│ │ ├── ExtendedWorkOrderController.js
│ │ └── README.md (Document what each does)
│ ├── SchedulePageController.js (Base controller)
│ ├── WorkOrderController.js (Base controller)
│ └── ...

Alternative Structure (Co-located):

app/
├── controllers/
│ ├── SchedulePageController.js (Base controller)
│ ├── ExtendedSchedulePageController.js (Extended controller)
│ ├── WorkOrderController.js (Base controller)
│ ├── ExtendedWorkOrderController.js (Extended controller)
│ └── ...

Note: While extended files can coexist in the same location as the original controller, we recommend creating a subfolder (e.g., extended/) for better readability and organization.

Step 3: Register in XML Configuration

Update your application’s XML file to reference the extended controller instead of the base controller:

Before (using base controller):

<page id="schedule"
controller="SchedulePageController">
<!-- Page configuration -->
</page>

After (using extended controller):

<page id="schedule"
controller="ExtendedSchedulePageController">
<!-- Page configuration -->
</page>

For dialogs:

<dialog id="statusChangeDialog"
controller="ExtendedStatusChangeController">
<!-- Dialog configuration -->
</dialog>

Best Practices for Extended Classes

✅ Do:

  • call super.methodName() when overriding methods to preserve base functionality
  • Use descriptive class and method names that clearly indicate purpose
  • Document what each override accomplishes and why it’s needed
  • Test thoroughly after upgrades to ensure base class changes don’t break your extensions
  • Add comprehensive comments explaining custom logic
  • Maintain a README documenting all extended classes

❌ Don’t:

  • Override methods without calling the parent implementation unless absolutely necessary
  • Modify the base class files directly
  • Create deep inheritance hierarchies (keep it simple - one level of extension)
  • Assume base class method signatures won’t change between versions
  • Forget to update XML configuration to reference the extended controller
  • Mix extended classes with direct controller modifications

Summary

Extending base JavaScript classes provides:

  • Upgrade safety - Extended classes can be carried over after upgrade
  • No manual reapplication - Custom logic survives upgrades automatically
  • Better organization - Separates complex logic into focused class files
  • Object-oriented design - Leverages inheritance for clean code structure
  • Flexibility - Can selectively override methods while preserving base functionality

Registration Process:

  1. Create extended controller file with unique name
  2. Import base controller and logging utility
  3. Extend base class and override methods as needed
  4. Update XML configuration to reference extended controller

When to Choose This Method:

  • Complex controller customizations with many methods
  • Need for better code organization
  • Reusable components across applications
  • AppCustomizations.js is becoming too large

When to Use AppCustomizations.js Instead:

  • Simple, straightforward customizations
  • One-off event handlers
  • Quick method wrapping
  • Application-wide event subscriptions

Method 3: Directly Modifying Base Controllers (Not Recommended)

Why This Approach Should Be Avoided

Directly modifying base controller files is strongly discouraged and should never be used in production environments. This section explains why this approach creates significant problems and what you should do instead.

The Problems with Direct Modification

Critical Issues:

  1. ❌ Upgrade Complications

    • Base files are completely overwritten during upgrades
    • All custom changes are lost and must be manually reapplied
    • High risk of introducing bugs when merging changes back in
  2. ❌ Maintenance Burden

    • Extremely difficult to track what was changed and why
    • Hard to distinguish custom code from framework code
    • Increases technical debt significantly
    • Other developers may not know which files contain customizations
  3. ❌ Version Compatibility

    • Base methods can change implementation details between versions
    • Your modifications may conflict with new framework behavior
    • Framework improvements may be incompatible with your changes
    • Debugging becomes extremely difficult
  4. ❌ Team Collaboration

    • Version control conflicts are more likely
    • Knowledge transfer is complicated
    • Code reviews become difficult
    • Onboarding new developers is harder
  5. ❌ Support Issues

    • IBM support cannot help with modified base files
    • Troubleshooting requires reverting to base files first
    • Cannot easily test if issues are framework bugs or custom code problems

Migration Path

If you’ve already modified base controllers, migrate immediately:

Step 1: Document All Modifications

Create a document listing every modified file:

# Modified Base Controllers
## WorkOrderDetailController.js
- Line 45-55: Added custom validation for completed work orders
- Line 78: Added custom logging
- Line 120: Modified error handling
## SchedulePageController.js
- Line 89: Added custom map initialization

Step 2: Choose Migration Approach

For each modification, decide:

  • Simple logic → Migrate to AppCustomizations.js
  • Complex logic → Create extended controller

Step 3: Implement in Recommended Approach

Move the custom code to AppCustomizations.js or extended controller.

Step 4: Test Thoroughly

  • Verify all custom functionality works
  • Test edge cases
  • Ensure no framework features are broken

Step 5: Restore Base Files

Replace modified base files with original framework files.

Summary

Why Direct Modification Fails:

  • ❌ Changes are lost during upgrades
  • ❌ Requires manual reapplication every upgrade
  • ❌ High risk of introducing bugs
  • ❌ Difficult to maintain and track
  • ❌ Breaks team collaboration
  • ❌ Voids support from IBM

What to Do Instead:

  • ✅ Use AppCustomizations.js for simple customizations
  • ✅ Use extended controllers for complex customizations
  • ✅ Both approaches survive upgrades
  • ✅ Both approaches are maintainable

Key Takeaway: Never modify base framework files. Always use AppCustomizations.js or extended controllers. The time saved by “quick” direct modifications is lost many times over during upgrades.


Comparison Matrix

Quick Reference Table

AspectAppCustomizations.jsExtended ClassesDirect Modification
Upgrade Safety✅ High - File persists✅ High - Files persist❌ Low - Changes lost
Maintenance✅ Easy - Centralized✅ Moderate - Organized❌ Difficult - Scattered
API Changes⚠️ May need updates⚠️ May need updates❌ Must manually merge
Complexity✅ Simple⚠️ Moderate❌ High risk
Setup Time✅ Quick⚠️ Moderate✅ Quick (but costly later)
Code Organization⚠️ Can become large✅ Well organized❌ Mixed with base code
Testing After Upgrade⚠️ Moderate⚠️ Moderate❌ Extensive
IBM Support✅ Supported⚠️ Limited support❌ Not supported
Recommended✅ Yes✅ Yes❌ Never
Best ForSimple to moderate customizationsComplex controller logicNever use

*IBM Support means the AppCustomization.js will automatically be caried over to the new version. This does not mean IBM will assist with the configurations.

Detailed Comparison

Upgrade Safety

AppCustomizations.js:

  • ✅ File is preserved during upgrades
  • ⚠️ May need to update for deprecated APIs
  • ✅ Framework changes don’t affect file location
  • ⚠️ Requires moderate testing after upgrade

Extended Classes:

  • ✅ Files are preserved during upgrades
  • ⚠️ May need to update for base class changes
  • ✅ Inherits new base class functionality automatically
  • ⚠️ Requires moderate testing after upgrade

Direct Modification:

  • ❌ Files are completely overwritten
  • ❌ All changes are lost
  • ❌ Must manually reapply every upgrade
  • ❌ Requires extensive testing and high risk of bugs

Maintenance Effort

AppCustomizations.js:

  • ✅ All customizations in one place
  • ✅ Easy to find and review
  • ⚠️ Can become large and unwieldy
  • ✅ Clear separation from framework

Extended Classes:

  • ✅ Organized into focused files
  • ✅ Clear inheritance structure
  • ✅ Easy to understand purpose
  • ✅ Scales well with complexity

Direct Modification:

  • ❌ Changes scattered across base files
  • ❌ Hard to identify what was customized
  • ❌ Difficult to review
  • ❌ Mixed with framework code

IBM Support

AppCustomizations.js:

  • ✅ Fully supported by IBM
  • ✅ Documented approach
  • ✅ Recommended by IBM

Extended Classes:

  • ⚠️ Limited support from IBM
  • ⚠️ Custom code responsibility
  • ⚠️ May need to isolate issues
  • ⚠️ Use at your own discretion

Direct Modification:

  • ❌ Not supported by IBM
  • ❌ Must revert to base files for support
  • ❌ Cannot troubleshoot with modifications
  • ❌ Voids support agreement

Development Time

AppCustomizations.js:

  • ✅ Quick to implement
  • ✅ No file structure changes needed
  • ✅ Immediate testing possible
  • ✅ Low learning curve

Extended Classes:

  • ⚠️ Requires file creation
  • ⚠️ Requires XML configuration update
  • ⚠️ Need to understand inheritance
  • ⚠️ Moderate learning curve

Direct Modification:

  • ✅ Appears quick initially
  • ❌ Costly during every upgrade
  • ❌ High long-term cost
  • ❌ Technical debt accumulates

Summary

Quick Decision:

  • Need IBM support? → AppCustomizations.js
  • Simple customization? → AppCustomizations.js
  • Complex controller logic? → Extended Class (limited support)
  • AppCustomizations.js too large? → Extended Class (limited support)
  • Need reusable components? → Extended Class (limited support)
  • Unsure? → Start with AppCustomizations.js

Never:

  • ❌ Directly modify base controllers
  • ❌ Mix custom code with framework code
  • ❌ Skip documentation of customizations

Support Considerations:

  • ✅ AppCustomizations.js is fully supported by IBM
  • ⚠️ Extended classes have limited IBM support
  • ❌ Direct modifications void IBM support

Upgrade Considerations

Overview

Maximo Mobile upgrades can introduce API changes, deprecated methods, and new framework features. Understanding how to prepare for and handle upgrades is critical for maintaining your customizations.

Pre-Upgrade Checklist

Complete these steps before upgrading Maximo Mobile:

1. Document All Customizations

For AppCustomizations.js:

# AppCustomizations.js Inventory
## Event Handlers
- applicationInitialized: Registers global event handlers
- pageInitialized (workDetail): Wraps saveWorkOrder method
- dialogInitialized (statusChangeDialog): Adds custom validation
## Custom Methods
- validateCustomRequirements: Validates completed work orders

For Extended Classes:

# Extended Controllers Inventory
## ExtendedWorkOrderController.js
- Extends: WorkOrderDetailController
- Overrides: pageInitialized, saveWorkOrder
- Custom Methods: validateByWorkType, validateByStatus
- XML Reference: workDetail page
## ExtendedScheduleController.js

2. Review Release Notes

Before upgrading, review the Maximo Mobile release notes for:

  • ✅ Deprecated APIs
  • ✅ Changed method signatures
  • ✅ New features that might replace custom code
  • ✅ Breaking changes
  • ✅ Performance improvements

Example Release Note Items to Watch:

Version 8.4 Release Notes:
- DEPRECATED: app.datasources.* - Use app.findDatasource() instead
- CHANGED: saveWorkOrder() now returns Promise<SaveResult> instead of Promise<boolean>
- NEW: Built-in validation framework - consider migrating custom validation
- BREAKING: Dialog lifecycle events now pass different parameters

3. Create Backup

Backup these files:

  • AppCustomizations.js
  • All extended controller files
  • Modified XML files
  • Custom configuration files
# Example backup structure
backup/
├── pre-upgrade-8.4/
│ ├── AppCustomizations.js
│ ├── controllers/
│ │ ├── extended/
│ │ │ ├── ExtendedWorkOrderController.js
│ │ │ └── ExtendedScheduleController.js
│ ├── app.xml

4. Test Current Functionality

Document expected behavior before upgrade:

# Pre-Upgrade Test Results
## Work Order Save Validation
- ✅ Completed WOs require actfinish
- ✅ Completed WOs require actlabcost
- ✅ Toast message displays for validation failures
- ✅ Save is prevented when validation fails
## Status Change Dialog

During Upgrade

1. Note Warnings and Errors

Pay attention to:

  • Deprecation warnings in console
  • Build errors
  • Runtime errors
  • Changed behavior

2. Review Framework Changes

Check if base classes you’ve extended have changed:

// Before upgrade - your extended class
class ExtendedWorkOrderController extends WorkOrderDetailController {
async saveWorkOrder() {
// Your custom logic
return await super.saveWorkOrder();
}
}
// After upgrade - check if base class signature changed

Upgrade Testing Strategy

1. Smoke Testing

Quick tests to verify basic functionality:

## Smoke Test Checklist (15 minutes)
- [ ] Application loads without errors
- [ ] Can navigate to main pages
- [ ] Can open dialogs
- [ ] Can save records
- [ ] No console errors
- [ ] Custom features visible

2. Functional Testing

Detailed testing of customizations:

## Functional Test Checklist (1-2 hours)
### AppCustomizations.js
- [ ] Test each lifecycle method
- [ ] Test each event handler
- [ ] Test each wrapped method
- [ ] Verify custom logic executes
- [ ] Verify original functionality preserved

3. Regression Testing

Ensure nothing broke:

## Regression Test Checklist (2-4 hours)
- [ ] All standard features work
- [ ] All custom features work
- [ ] No new errors in console
- [ ] Performance is acceptable
- [ ] Mobile functionality works
- [ ] Offline functionality works

Summary

Key Takeaways

Three Methods for Applying Configurations:

  1. AppCustomizations.js (Recommended)

    • ✅ Primary method for most customizations
    • ✅ Fully supported by IBM
    • ✅ Upgrade-safe - file persists
    • ✅ Centralized location
    • ⚠️ Can become large for complex projects
  2. Extended Classes (Recommended for Complex Scenarios)

    • ✅ Better organization for complex logic
    • ✅ Upgrade-safe - files persist
    • ✅ Object-oriented approach
    • ⚠️ Limited IBM support
    • ⚠️ Requires XML configuration
  3. Direct Modification (Never Recommended)

    • ❌ Changes lost during upgrades
    • ❌ No IBM support
    • ❌ High maintenance burden
    • ❌ Never use in production

Decision Framework

Choose AppCustomizations.js when:

  • Simple to moderate customizations
  • Need IBM support
  • Quick implementation required
  • Application-wide logic

Choose Extended Classes when:

  • Complex controller logic
  • AppCustomizations.js too large
  • Need better organization
  • Reusable components

Never choose Direct Modification:

  • Always use one of the recommended approaches

Critical Success Factors

For Upgrade Success:

  1. Document all customizations
  2. Review release notes before upgrading
  3. Test thoroughly after upgrading
  4. Use feature detection over version checking
  5. Implement defensive programming

For Maintainability:

  1. Use consistent logging with TAG constants
  2. Add comprehensive comments
  3. Keep customizations organized
  4. Document business logic
  5. Use descriptive names

For Team Collaboration:

  1. Centralize customizations in AppCustomizations.js or extended classes
  2. Never modify base controllers
  3. Document all extended classes
  4. Use version control
  5. Code review customizations

Quick Reference

AppCustomizations.js Template:

import { log } from "@maximo/maximo-js-api";
const TAG = "AppCustomizations";
class AppCustomizations {
applicationInitialized(app) {
this.app = app;
log.t(TAG, "Customizations initialized");
}

Extended Class Template:

import { log } from "@maximo/maximo-js-api";
import BaseController from "../BaseController";
const TAG = "ExtendedController";
class ExtendedController extends BaseController {
constructor() {
super();
log.t(TAG, "Extended controller initialized");

Prerequisites

Before implementing configurations, understand these concepts:

Simple Configurations:

Advanced Configurations:

Troubleshooting

  • Debugging UI - Tools and techniques for debugging
  • FAQ - Common questions and solutions

External Documentation


Additional Notes

Performance Considerations

AppCustomizations.js:

  • Keep methods lightweight
  • Avoid heavy processing in lifecycle events
  • Use async/await for I/O operations
  • Consider impact on mobile devices

Extended Classes:

  • Call super methods to preserve base functionality
  • Don’t override methods unnecessarily
  • Profile performance after customizations
  • Test on actual mobile devices

Security Considerations

Best Practices:

  • Validate all user input
  • Don’t expose sensitive data in logs
  • Follow principle of least privilege
  • Test security implications of customizations
  • Review custom code for vulnerabilities

Common Pitfalls:

  • Logging sensitive data (passwords, tokens)
  • Bypassing framework security checks
  • Exposing internal implementation details
  • Not validating data from external sources

Mobile-Specific Considerations

Offline Functionality:

  • Test customizations in offline mode
  • Ensure custom logic works without server connection
  • Handle sync conflicts appropriately
  • Consider data storage limitations

Performance:

  • Mobile devices have limited resources
  • Test on actual devices, not just emulators
  • Optimize for battery life
  • Consider network latency

User Experience:

  • Provide clear feedback for custom actions
  • Use appropriate loading indicators
  • Handle errors gracefully
  • Test on various screen sizes

Documentation Best Practices

Document Your Customizations:

Create a README.md in your customization directory:

# Application Customizations
## Overview
Brief description of what customizations exist and why.
## AppCustomizations.js
- **Purpose**: Centralized customization logic
- **Key Features**:
- Work order validation

Continuous Improvement

Regular Reviews:

  • Review customizations quarterly
  • Remove unused code
  • Refactor as complexity grows
  • Update documentation
  • Test with new framework versions

Code Quality:

  • Use consistent coding standards
  • Implement code reviews
  • Add unit tests where possible
  • Monitor performance
  • Track technical debt

Remember: The configuration approach you choose today will impact your ability to upgrade and maintain your application for years to come. Always prefer AppCustomizations.js or extended classes over direct modification of base controllers.

Page last updated: 30 April 2026