Skip to main content

Comprender el contexto de ejecución

Objetivos de aprendizaje

Después de completar esta unidad, podrá:

  • Saber qué métodos utilizar para invocar Apex
  • Escribir un desencadenador para un objeto de Salesforce
  • Observar cómo funciona el contexto de ejecución ejecutando código en la Developer Console
  • Comprender cómo los límites regulados afectan a los patrones de diseño
  • Comprender la importancia de trabajar con operaciones masivas
Nota

Nota

El reto práctico para esta insignia está localizado al japonés, español (LATAM) y portugués (Brasil). Para cambiar el idioma de su Trailhead Playground, siga estas instrucciones. Puede que la localización esté desactualizada. Si no aprueba el reto con las instrucciones localizadas, cambie el idioma a inglés y la configuración local a Estados Unidos, y vuelva a intentarlo.

Consulte la insignia Trailhead en su idioma para obtener más información sobre cómo aprovechar la experiencia de Trailhead en otros idiomas.

Siga el proceso con Trail Together

¿Desea seguir el proceso con un experto a medida que realiza este paso? Mire este video que forma parte de la serie Trail Together.

(Este video comienza en el minuto 16:36, en caso de que desee rebobinar y mirar el comienzo del paso nuevamente).

¿Qué es el contexto de ejecución?

Para aplicaciones ASP.NET, el código se ejecuta en el contexto de un dominio de aplicación. En el mundo de la plataforma Lightning, el código se ejecuta dentro de un contexto de ejecución. En pocas palabras, este contexto representa el tiempo entre el momento en que se ejecuta el código y cuando termina. Lo importante para usted es comprender que el código Apex que redacta no siempre es el único código que se está ejecutando.

Para comprender cómo funciona esto, necesita saber todas las formas con las que se puede ejecutar el código Apex en la plataforma.

Métodos para invocar Apex

reinstateDeleteRowWithRequest: Descripción
Desencadenador de base de datos Se invoca para un evento específico en un objeto personalizado o estándar.
Apex anónimo Miniprogramas de código ejecutados directamente en la Developer Console y otras herramientas.
Apex asíncrono Se produce cuando se ejecuta Apex futuro o colocable en cola, al ejecutar un trabajo por lotes o al programar Apex para que se ejecute en un intervalo especificado.
Servicios web El código se expone a través de servicios web SOAP o REST.
Servicios de email El código que se establece para procesar el email entrante.
Páginas de Visualforce o Lightning Los controladores de Visualforce y los componentes Lightning pueden ejecutar código Apex de forma automática o cuando un usuario inicia una acción, como al hacer clic en un botón. Los componentes Lightning también pueden ejecutarse a través de procesos y flujos Lightning.

Aparte de invocar código Apex, las acciones, como crear una nueva tarea, enviar un mensaje de email, realizar una actualización de campo o enviar un mensaje saliente, pueden desencadenarse todas por una de las funciones declarativas de la plataforma. Estas acciones también se ejecutan dentro de un contexto de ejecución.

Otra consideración importante es el contexto del usuario que ejecuta el código Apex. Apex se ejecuta en un contexto del sistema de forma predeterminada. El código Apex tiene acceso a todos los objetos y campos. Los permisos de objetos, la seguridad a nivel de campo y las reglas de colaboración no se aplican para el usuario vigente. Puede utilizar la palabra clave with sharing para especificar que las reglas de colaboración para el usuario vigente deben tenerse en cuenta para una case. Este tema es importante, de modo que eche un vistazo a Uso de las palabras clave with sharing o without sharing.

Fundamentos de desencadenadores

Antes de aprender más sobre el contexto de ejecución, retrocedamos un paso para introducirle en el mundo de los desencadenadores de bases de datos. Similares a los desencadenadores en SQL Server, los desencadenadores de bases de datos de Apex ejecutan lógica de programación antes o después de eventos en registros de Salesforce. Cuando se define el desencadenador, puede especificar más de uno de los siguientes eventos:

  • before insert
  • before update
  • before delete
  • after insert
  • after update
  • after delete
  • after undelete

La sintaxis básica de un desencadenador tiene el siguiente aspecto:

trigger TriggerName on ObjectName (trigger_events) {
   // code_block
}

Ahora sabemos lo mucho que les gusta a los desarrolladores .NET solucionar problemas con código, pero le ofrecemos una gran sugerencia de productividad. Solo tiene que recurrir al uso de un desencadenador cuando está completamente seguro de que la misma cosa no puede realizarse con una de nuestras herramientas de automatización con función de apuntar y hacer clic.

Para facilitarle las cosas, la plataforma de Salesforce incluye una herramienta de automatización eficaz, Flow Builder, para gestionar la lógica de negocios sin redactar código. En la mayoría de los casos, las tareas que hace mucho tiempo solo podían realizarse con un desencadenador ahora se hacen mejor con una de las herramientas de automatización.

Nota

Nota

Si es un desarrollador nuevo en la plataforma, no dude en dedicar tiempo al módulo Aprobar registros con procesos de aprobación en la ruta Desarrollador principiante antes de crear un desencadenador. Estamos bastante seguros de que no quiere ser la persona que aportó un montón de carga técnica innecesaria a la organización de Salesforce.

Marcar el contexto de ejecución

Para comprender mejor el contexto de ejecución, pasemos por la creación de un desencadenador de base de datos de Apex que crea una oportunidad cuando se ingresa una nueva cuenta. Este desencadenador llama a un método desde una clase de controlador, de modo que primero hay que crear eso.

  1. En Configuración, seleccione Su nombre > Developer Console para abrir Developer Console.
  2. En Developer Console, seleccione File (Archivo) > New (Nuevo) > Apex Class (Clase de Apex).
  3. Ingrese AccountHandler como nombre de la clase y haga clic en OK (Aceptar).
  4. Elimine el código existente e inserte el siguiente fragmento de código:
    public with sharing class AccountHandler {
        public static void CreateNewOpportunity(List<Account> accts) {
            for (Account a :accts) {
                Opportunity opp = new Opportunity();
                opp.Name = a.Name + ' Opportunity';
                opp.AccountId = a.Id;
                opp.StageName = 'Prospecting';
                opp.CloseDate = System.Today().addMonths(1);
                insert opp;
            }
        }
    }
    
  5. Pulse Ctrl+S para guardar la clase.
Nota

Nota

Se considera una mejor práctica utilizar únicamente un desencadenador por objeto, que verá en el siguiente ejemplo. Luego puede utilizar métodos de controlador específicos de contexto dentro de desencadenadores para crear desencadenadores sin lógica. Al adoptar esta práctica, puede evitar los escollos habituales con los que se encuentran los nuevos desarrolladores. Para aprender más sobre estas técnicas, eche un vistazo a Marcos de trabajo de desencadenadores y Mejores prácticas de desencadenadores de Apex.

De modo que ahora que tenemos la clase de controlador, crearemos el desencadenador de Cuenta.

  1. En Developer Console, seleccione File (Archivo) > New (Nuevo) > Apex Trigger (Desencadenador de Apex).
  2. Ingrese AccountTrigger como nombre y, a continuación, seleccione Account (Cuenta) para el sObject.
  3. Haga clic en Enviar.
  4. Elimine el código existente e inserte el siguiente fragmento de código:
    trigger AccountTrigger on Account (before insert, before update, before
        delete, after insert, after update, after delete,  after undelete) {
        if (Trigger.isAfter && Trigger.isInsert) {
            AccountHandler.CreateNewOpportunity(Trigger.New);
        }
    }
    
  5. Pulse Ctrl+S para guardar su desencadenador.

Para completar la presentación, ejecutamos código anónimo para simular un usuario que ingresa una nueva cuenta utilizando la interfaz de Salesforce. Recuerde, el código Apex puede ejecutarse de diversas formas.

  1. En Configuración, seleccione Su nombre > Developer Console para abrir Developer Console.
  2. Seleccione Debug (Depurar) > Open Execute Anonymous Window (Abrir ventana de ejecución anónima).
  3. Elimine el código existente e inserte el siguiente fragmento de código:
    Account acct = new Account(
        Name='Test Account 2',
        Phone='(415)555-8989',
        NumberOfEmployees=50,
        BillingCity='San Francisco');
    insert acct;
    
  4. Asegúrese de que la opción Open Log (Abrir registro) está seleccionada y haga clic en Execute (Ejecutar). Una nueva ficha muestra el registro de ejecución. Manténgala abierta de modo que puede examinarla detenidamente.

Examen del registro de ejecución

Observe que la primera línea del registro de ejecución marca el evento EXECUTION_STARTED (Ejecución iniciada) y que la última línea es el evento EXECUTION_FINISHED (Ejecución finalizada). Todo lo que hay dentro de estos eventos es el contexto de ejecución.

Echemos un vistazo más de cerca a lo que ocurre. Un evento CODE_UNIT_STARTED marca el momento en que el código de la ventana Execute Anonymous comenzó. Esta línea está resaltada en rojo en la imagen siguiente.

Captura de pantalla del registro de depuración en Developer Console, resaltando los eventos code_unit_started

La segunda línea CODE_UNIT_STARTED que está resaltada representa el momento en que se ejecutó el evento BeforeInsert.

No puede ver esto en la imagen, pero si está siguiendo su propia instancia de Developer Console, avance más en los resultados y busque otras instancias de CODE_UNIT_STARTED. Debería ver al menos una instancia más que representa el momento en que se ejecutó el evento AfterInsert. Si creó reglas de flujo de trabajo que se desencadenan cuando se crea una nueva cuenta, también se mostrarán en el registro de ejecución. Todo este código funciona bajo el mismo contexto de ejecución, y como tal, está sujeto al mismo conjunto de límites regulados.

Puede que se esté preguntando por qué es tan importante comprender esto. Bien, debido a que Salesforce es un entorno multiusuario, esos límites regulados son vitales para evitar que cada instancia de una organización de Salesforce consuma demasiados recursos. Básicamente, evitan que todo el sistema se colapse.

Trabajar con límites

Esto nos lleva de nuevo al asunto del trabajo con límites. Los dos límites que probablemente le afecten más es el número de consultas SOQL o declaraciones DML. Estos suelen hacer tropezar a los desarrolladores nuevos en la plataforma, de modo que queremos dedicar tiempo adicional centrándonos en cómo evitarlos.

Nota

Nota

Existen gran cantidad de límites que hay que tener en cuenta, y tienden a cambiar con cada versión principal. Además, no es poco habitual que los límites se relajen en vez de incrementarse, de modo que no olvide consultar los más recientes consultando el vínculo Límites regulados de ejecución en los Recursos.

Trabajo con operaciones masivas

Muchos desarrolladores caen en la trampa habitual de diseñar su código para que funcione con un único registro. Pronto aprenden que en la plataforma Lightning esto puede ser un gran error.

Los desencadenadores de Apex pueden recibir hasta 200 registros al mismo tiempo. En estos momentos, el límite síncrono para el número total de consultas SOQL es de 100, y 150 para el número total de declaraciones DML emitidas, de modo que, si tiene un desencadenador que realiza una consulta SOQL o una declaración DML dentro de un bucle y ese desencadenador se ejecutó para una operación masiva, adivine:

¡¡¡Buuum!!!

Correcto, va a aparecer un error de límites. Es posible implementar código y hacer que se ejecute bien durante un tiempo antes de descubrir el límite. En ese momento el desarrollador tiene que volver y determinar cómo “masivizar” el código. No es poco frecuente que este segundo intento tarde más que el diseño inicial. Para evitar esta situación, diseñe su código Apex para controlar operaciones masivas desde el comienzo. Aprenda formas de hacer esto en el módulo Desencadenadores de Apex masivos.

Probablemente se habrá dado cuenta, quizá no, que el código del controlador del desencadenador que creamos anteriormente no utilizaba un patrón masivo, así que es proclive a los errores de límites. Para recordárselo, a continuación aparece cómo era el código original.

public with sharing class AccountHandler {
    public static void CreateNewOpportunity(List<Account> accts) {
        for (Account a :accts) {
            Opportunity opp = new Opportunity();
            opp.Name = a.Name + ' Opportunity';
            opp.AccountId = a.Id;
            opp.StageName = 'Prospecting';
            opp.CloseDate = System.Today().addMonths(1);
            insert opp;
        }
    }
}

Observe que la operación DML de inserción está dentro del bucle for. Esto está mal, muy mal, y es algo que hay que evitar siempre.

Afortunadamente para nosotros, podemos arreglar este código cambiándolo para que escriba en una variable de lista dentro del bucle y luego insertar el contenido de la lista en un paso.

  1. En Configuración, seleccione Su nombre > Developer Console para abrir Developer Console.
  2. En Developer Console, seleccione File (Archivo) > Open (Abrir).
  3. Para el tipo de entidad, seleccione Classes (Clases). Seleccione AccountHandler como la entidad.
  4. Haga clic en Abrir.
  5. Elimine el código existente e inserte el siguiente fragmento de código:
    public with sharing class AccountHandler {
        public static void CreateNewOpportunity(List<Account> accts) {
            List<Opportunity> opps = new List<Opportunity>();
            for (Account a :accts) {
                Opportunity opp = new Opportunity();
                opp.Name = a.Name + ' Opportunity';
                opp.AccountId = a.Id;
                opp.StageName = 'Prospecting';
                opp.CloseDate = System.Today().addMonths(1);
                opps.add(opp);
            }
            if (opps.size() > 0) {
                insert opps;
            }
        }
    }
    
  6. Pulse Ctrl+S para guardar la clase.

Ahora que arreglamos el código del controlador del desencadenador, asegurémonos de que el desencadenador puede controlar una carga de 200 registros. Estamos seguros de que sabe que la redacción de pruebas de unidades para garantizar que el código funciona es una mejor práctica.

  1. En Developer Console, seleccione File (Archivo) > New (Nuevo) > Apex Class (Clase de Apex).
  2. Ingrese AccountTrigger_Test como nombre de la clase y haga clic en OK (Aceptar).
  3. Elimine el código existente e inserte el siguiente fragmento de código:
    @isTest
    private class AccountTrigger_Test {
        @isTest static void TestCreateNewAccountInBulk() {
            // Test Setup data
            // Create 200 new Accounts
            List<Account> accts = new List<Account>();
            for(Integer i=0; i < 200; i++) {
                Account acct = new Account(Name='Test Account ' + i);
                accts.add(acct);
            }              
            // Perform Test
            Test.startTest();
            insert accts;                               
            Test.stopTest();
            // Verify that 200 new Accounts were inserted
            List<Account> verifyAccts = [SELECT Id FROM Account];
            System.assertEquals(200, verifyAccts.size());    
            // Also verify that 200 new Opportunities were inserted
            List<Opportunity> verifyOpps = [SELECT Id FROM Opportunity];                              
            System.assertEquals(200, verifyOpps.size());                             
        }
    }
    
  4. Pulse Ctrl+S para guardar la clase.
  5. Seleccione Test (Prueba) > New Run (Nueva ejecución).
  6. Seleccione AccountTrigger_Test como TestClass, y TestCreateNewAccountInBulk como el método de prueba.
  7. Haga clic en Ejecutar.
  8. Seleccione la ficha Test (Prueba) y verifique que la prueba se ejecute hasta el final sin fallos, según indica una marca de verificación de color verde en la columna Status (Estado).
Nota

Nota

Aunque aún no hablamos sobre las pruebas de unidades, no se preocupe. Funcionan casi del mismo modo en la plataforma Lightning que en .NET, con solo algunas palabras clave diferentes. Podrá ponerse al día rápidamente sobre cómo están estructuradas. Conozca más detalles sobre la prueba de desencadenadores de Apex consultando los vínculos en Recursos.

Más información

Apex utiliza un bloque probar-capturar-finalizar familiar para gestionar las excepciones. Pero su declaración de captura y posible reversión podría ser diferente dependiendo de dónde se ejecute el código Apex. Consulte el vínculo en Recursos sobre las mejores prácticas en lo referente a probar, capturar y revertir en Apex.

No hay nada parecido a una variable de aplicación o sesión en la plataforma Lightning. Si necesita que los datos persistan entre clases, hay variables estáticas, pero tenga en cuenta que las variables estáticas en la plataforma Lightning no funcionan del mismo modo que en .NET. En el mundo de la plataforma Lightning, una variable estática solo puede hacer persistir información dentro del contexto de una única ejecución, aunque hay otras opciones disponibles para mantener datos entre invocaciones de desencadenadores. Consulte los vínculos de Apex avanzado en los Recursos de Internet para conocer más detalles.

Cuando se trabaja con límites, existen muchas concesiones a tener en cuenta, especialmente para desarrolladores de paquetes gestionados. Por cierto, los socios de Salesforce normalmente utilizan paquetes gestionados para distribuir y vender aplicaciones. En este módulo solo arañamos la superficie de lo que necesita saber. Si va en serio sobre el desarrollo en Apex, consulte los vínculos de Apex avanzado en los Recursos de Internet.

Recursos

¡Siga aprendiendo gratis!
Regístrese para obtener una cuenta y continuar.
¿Qué hay para usted?
  • Consiga recomendaciones personalizadas para sus objetivos profesionales
  • Practique sus aptitudes con retos prácticos y pruebas
  • Siga y comparta su progreso con empleadores
  • Póngase en contacto para recibir asesoramiento y oportunidades laborales