Design Principles
One Handler per Concern
Each object has one trigger and one orchestrator. Each handler does one thing, so it is easy to name, test and switch off.
One Role per Context
A role says what a class does. Keep one role per class in each context: a class with two roles runs only as the first, and nothing warns you.
List Order Is the Dependency
Handlers run in list order. Each predicate runs at its handler's turn, so it sees what earlier handlers wrote.
No Loops, No SOQL per Record
The library loops over the records. Handlers declare the parents and related records they need, and the library loads them in bulk, never per record.
Before Contexts Populate, After Contexts Act
In before insert and before update, DML or an event publish fails the save. Change other records from a Writer in before delete or an after context.
Qualification Is Explicit
Every role declares which records it wants. An action never runs for a record its predicate rejected.
Library Errors Always Surface
ContinueOnError swallows a handler's own exception. It never swallows a TriggerTypes.TriggerLibException: a broken contract is a bug.
Safe by Default
In the update contexts, a Populator, Writer or Dispatcher acts on the same record at most three times per transaction by default.
No Required Metadata
The library works with zero custom metadata records. Metadata only switches an object or a handler off.
