Skip to content
Good Practices

Good Practices

Overview & General Rules

To ensure effective implementation of Breezz in a Salesforce application, follow these guidelines:

  • Class Structure: For solutions implemented in Apex, every method invoked within Apex Triggers requires a dedicated class extending the forvendi.Step abstract class.
  • Trigger Context Guidelines:
    • Before Triggers: Should solely modify records from the trigger context. Asynchronous calls in before triggers are non-optimal and should be avoided.
    • After Triggers: Should solely modify records other than the trigger context.

Breezz Step Methods Guide

void Initialize()

Override this method when step-level initialization is required before processing records.

Boolean initRecordProcessing(Object record, Object optionalOldRecord)

Used to modify record fields when all necessary data is available upfront.

  • Restrictions: Neither DML, SOQL, nor SOSL are allowed in this method.
  • Modifying Related Records: Use ModificationContext via getContext().
  • Querying Data: Use DataStore via getStore() to request data asynchronously for subsequent processing.
  • Return Value (Boolean):
    • Return false if all record processing is completed using data already available in the trigger (no additional queries needed).
    • Return true if additional data was requested using DataStore. This signals Breezz to proceed to finishRecordProcessing.

DataStore Usage: Without custom Loaders, DataStore loads flat SObject records by ID using requestToLoad(List<Id> ids, Set<String> fields). Subqueries are also supported:

getStore().requestToLoad(
    accountRecord.Id,
    new Set<String>{ 'Id', 'OwnerId', '(SELECT Id FROM Public_Accounts__r)' }
);

For complex queries with distinct clauses, define a custom loader in the Breezz configuration and pass the storeKey parameter to requestToLoad.

ModificationContext Usage Warning:

  • addToUpdate(SObject record): Adds the given record to the update list. Replaces the whole record.
  • addModificationToUpdate(SObject record, SObjectField objectField, Object value): Appends a single field modification to the record. Use this when applying multiple sequential changes to avoid overwriting existing fields.

void finishRecordProcessing(Object record, Object optionalOldRecord)

Executed only for records where initRecordProcessing returned true.

  • Restrictions: Direct DML and SOQL/SOSL queries are not allowed.
  • Data Access: Data requested in initRecordProcessing is loaded between execution phases and can now be retrieved via getStore().getFromStore(recordId) (returns SObject or Map depending on loader usage).
  • Modifications: Record fields and related records can be updated or created via ModificationContext.

void finishSyncProcess(List records, List optionalOldRecords)

Finalizes the synchronous process.

  • Accesses records added via addToSyncFinish during previous steps.
  • Note: Runs automatically, even if no records were explicitly added to the sync context.

void executeAsyncProcess(Map<String, forvendi.AsyncJobInfo> asyncJobsByRecordKey)

Executes for records queued via addAsyncJob() (called in initRecordProcessing, finishRecordProcessing, or finishSyncProcess).


Advanced Concepts & Key Utilities

Flow Interviews

Flow Interviews can be skipped in Apex Steps and replaced with Flow Steps configured directly in Breezz, provided the target flow requires no input parameters originating from Apex logic.

Key ModificationContext Methods

  • Emails: Use getContext().addToSend(Messaging.SingleEmailMessage record).
  • Async Manipulations: addToAsyncInsert, addToAsyncUpdate, addToAsyncRemove.
  • Platform Events: Publish events using addEventToPublish.
  • Lead Conversion: Convert leads using addToConvert.
  • Inspect Context: Use getter methods (getRecordsToUpdate, getEventToPublish, getRecordsToConvert) to inspect queued records.

Breezz Logger

Use forvendi.BreezzApi.LOGGER.logError() to record warnings, catch errors, and gather execution metrics across your steps.

💡 Writing Custom Steps? For specific guidelines on writing clean, modular Apex Step classes, check out our dedicated Step Development Best Practices.