Checkpoint del Módulo 6
Repaso del módulo, un trigger de escalado de casos que combina before, after y bulkificación, y tus primeros triggers de verdad en la Developer Org, incluida una recursión provocada a propósito.
✓ En esta sub-lección
- 01Combinar before y after en un mismo trigger, cada lógica en su momento.
- 02Escribir un trigger bulkificado que consulta una sola vez y guarda una sola vez.
- 03Crear, probar, leer el log y borrar un trigger en una Developer Org.
La nutria: ¿Te acuerdas? · Repaso de la lección 5
¿Por qué una guarda con un Boolean estático falla con 400 registros?
Con este módulo tu código ha dejado de esperar a que lo ejecutes. Todo lo anterior (SOQL, DML, bulkificación, clases, static) servía para llegar aquí: código que reacciona solo, a cualquier volumen, dentro de la misma transacción que tus flows y tus reglas.
Lo que has aprendido, sub-lección a sub-lección
1 · Qué es un trigger. trigger Nombre on Objeto (eventos). Siete eventos, de los que after delete y after undelete no existen en Flow. Siempre llega una lista, Trigger.new, de 1 a 200 registros: nunca Trigger.new[0]. Varios triggers en el mismo objeto no tienen orden garantizado.
2 · Contexto. Trigger.new y Trigger.old son $Record y $Record__Prior en plural; newMap y oldMap, lo mismo por Id. No existen en todos los eventos: no hay old al crear, no hay new al borrar, no hay newMap en before insert. Para saber si algo cambió: Trigger.oldMap.get(r.Id).
3 · before vs after. before es «Fast Field Updates»: cambias el propio registro, sin DML. after es «Actions and Related Records»: ya hay Id, tocas otros registros con un DML, y Trigger.new es de solo lectura.
4 · Orden de ejecución. Validación del sistema → flows before-save → triggers before → validation rules → duplicados → guardado → triggers after → asignación y workflow → flows after-save → roll-ups → commit → asíncrono. Un field update de workflow relanza los triggers de update.
5 · Recursión. Un DML sobre el propio objeto vuelve a disparar el trigger, hasta «Maximum trigger depth exceeded» en el nivel 16. Defensas: no provocarla (before), actuar solo si algo cambió, y una guarda static Set<Id>, nunca un Boolean.
EN FLOW HACÍAS… ·aciertos 0/0
En el elemento Start eliges el objeto Account.
Paso 1 de 8
¿Qué es eso en un trigger?
La nutria: ¿Flow o trigger?
La nutria: ¿Y por qué no un Flow? Porque es la regla que más va a crecer
Lo que viene: el Módulo 7
Los triggers de este módulo tienen la lógica dentro. Funciona, pero con tres o cuatro necesidades por objeto se vuelve un archivo enorme, difícil de probar y de ordenar. El Módulo 7 enseña el patrón que usan las orgs profesionales: un solo trigger por objeto, vacío de lógica, que delega en una clase handler. Todo lo que has escrito aquí se mudará a esa clase.
Ahora en tu Developer Org
- Developer Console → File → New → Apex Trigger. Nombre AccountOnboarding, objeto Account. Pega tu solución de la lección 3 y guarda.
- Crea una cuenta desde la interfaz sin Rating. Al guardar verás Rating = Warm y, en su related list de actividades, la tarea de bienvenida. Nadie ejecutó nada: lo hizo el trigger.
- Setup → Object Manager → Account → Triggers: ahí está. Justo al lado, Flow Triggers. Son los dos tipos de automatización del mismo objeto.
- Con la Developer Console abierta, edita la cuenta y abre el log que aparece. Busca CODE_UNIT_STARTED: verás tu trigger, las validaciones y los workflows en el orden de la lección 4.
- Provoca la recursión: crea el trigger OpportunityReview del ejercicio de la lección 5 en su versión sin guarda y edita una oportunidad. Lee el error: «Maximum trigger depth exceeded». La oportunidad no se guarda.
- Crea la clase OpportunityTriggerGuard (Setup → Apex Classes → New), cambia el trigger por tu solución con guarda y vuelve a editar la oportunidad: ahora se guarda.
- Limpieza: abre cada trigger en la Developer Console y usa File → Delete, para que no interfieran con los módulos siguientes.
El diccionario completo: de Flow a trigger
| En un Record-Triggered Flow | En un trigger |
|---|---|
| Objeto del elemento Start | trigger X on Account |
| «A record is created or updated» | (… insert, … update) |
| Fast Field Updates | before |
| Actions and Related Records | after |
| $Record | cada registro de Trigger.new |
| $Record__Prior | Trigger.oldMap.get(r.Id) |
| «Only when a record is updated to meet…» | comparar old y new |
| Trigger Order en Flow Trigger Explorer | no existe: un solo trigger por objeto (Módulo 7) |
| Get Records dentro de un Loop | consulta dentro de un bucle: el error del Módulo 4 |
La nutria: Lo que no se traduce: el volumen