Conhecer os princípios da camada de domínio
Objetivos de aprendizagem
Após concluir esta unidade, você estará apto a:
- Resumir as origens do padrão Domain usando padrões corporativos.
- Determinar o tipo de código do Apex que pertence à camada de domínio.
- Explicar como a camada de domínio se encaixa na arquitetura de seu aplicativo e na plataforma.
- Projetar uma camada de domínio para trabalhar com as melhores práticas da plataforma.
Pré-requisitos
Bem-vindo! Este módulo baseia-se nos princípios que você aprendeu no módulo Padrões empresariais do Apex: camada de serviço e nas etapas que você concluiu no seu Trailhead Playground durante os desafios práticos. Naquele módulo, falamos sobre a camada de serviço ser um meio de encapsular os processos comerciais de seu aplicativo e nos concentramos em como os serviços são expostos de forma consistente e relevante a outras partes do seu aplicativo, como controladores do Visualforce, Apex em lote e APIs voltadas ao público.
Se você ainda não concluiu o módulo Padrões empresariais do Apex: camada de serviço, conclua-o antes de continuar.
Camada de domínio
Domínio (engenharia de software): “ Um domínio é um campo de estudo que define um conjunto de requisitos, terminologia e funcionalidades comuns de um programa de software criado para resolver um problema na área da programação, conhecido como engenharia de domínio.” – Wikipédia, Domínio (engenharia de software)
Com os padrões empresariais da plataforma Salesforce, a camada de domínio é definida pelos objetos personalizados que você cria (projeto, fatura e outros), permitindo que você crie o armazenamento de dados do aplicativo rapidamente. Mas e o comportamento desses objetos, como validação, cálculo e a manipulação complexa dos dados? É possível expressar comportamento no Salesforce tanto declarativamente (apontar e clicar) quanto programaticamente (usando o Apex). O uso dessa combinação com eficiência é essencial como habilidade para o sucesso de um desenvolvedor na plataforma. E, honestamente, quem não quer ser um desenvolvedor de sucesso na plataforma?
Padrão Domain
Se a complexidade de determinados comportamentos para objetos no aplicativo requer código Apex, pense em estruturar e fatorar o código usando técnicas de programação voltada para objetos (ou OOP) e o padrão Modelo de domínio.
Modelo de domínio – “Um modelo de objeto do domínio que incorpora tanto o comportamento quanto os dados.” “Na pior hipótese, a lógica de negócios pode ser extremamente complexa. As regras e a lógica descrevem vários casos e comportamentos diferentes, e é para lidar com essa complexidade que os objetos foram criados.” – Fowler, Martin
Assim como a camada de serviço, o modelo de domínio oferece um nível mais granular de encapsulamento e reutilização de código no aplicativo, por exemplo, validação, predefinição e outras lógicas relativas a cálculos e manipulação complexos.
Esta unidade vê uma perspectiva específica do Apex sobre o padrão Modelo de domínio. Ela oferece diretrizes para associar claramente o código da camada de domínio a cada objeto personalizado, permitindo que você gerencie as camadas e a Separação de preocupações (SOC) com eficiência na base de código de seu aplicativo. Antes de vermos do que é feita a classe de domínio, vamos rever onde ela é usada.
- Acionadores do Apex: operações de criação, leitura, atualização e exclusão (CRUD), inclusive cancelamento de exclusão, ocorrem em seus objetos personalizados quando os usuários ou as ferramentas interagem por meio das interfaces do usuário do Salesforce padrão ou de uma das APIs da plataforma. As operações são encaminhadas para o código da classe de domínio pertinente que corresponde ao objeto e à operação.
- Serviços do Apex: o código da camada de serviço deve ser facilmente identificável e deve facilitar a reutilização de código relativo a um ou mais objetos com os quais cada uma de suas operações interage por meio das classes de domínio. Essa abordagem mantém o código na camada de serviço concentrado em organizar os processos comerciais ou as tarefas expostas.
A classe do Apex de domínio é consumida pelo manipulador do acionador do Apex e pela chamada do método de serviço do Apex apresentada no módulo Padrões empresariais do Apex: camada de serviço. Esta unidade aborda como essas duas áreas podem compartilhar lógica exposta por uma classe de domínio, seja explicitamente chamando seus métodos ou indiretamente pela lógica de um manipulador de acionador.
Importante: lembre-se de que o ideal é que o código relativo aos controladores do componente Web do Lightning, aos controladores do Visualforce, ao Apex em lote e às classes de API desenvolvidos devam usar funções expostas apenas pelas operações da camada de serviço. Assim, o código escrito na camada de domínio é sempre invocado indiretamente pelas classes de cliente da camada de serviço. O código da camada de domínio normalmente é um aspecto da lógica de negócios interna de seu aplicativo.
Considerações sobre o design
A camada de domínio viabiliza recursos de OOP no Apex para seu aplicativo, mas faz isso de uma forma alinhada (principalmente por convenções de nomenclatura) com os termos e os conceitos do domínio do aplicativo e com as melhores práticas da plataforma.
Aqui estão algumas considerações de design para pensar.
Acompanhar com o Trail Together
Deseja acompanhar um especialista enquanto trabalha nesta etapa? Veja este vídeo que faz parte da série Trail Together.
Como usar classes de domínio dos serviços
Vamos ver o OpportunitiesService
apresentado no módulo Padrões empresariais do Apex: camada de serviço para refatorar alguns comportamentos do método applyDiscounts
até um método de classe de domínio.
O código a seguir mostra uma nova implementação do método de serviço applyDiscounts
. Desta vez ele está usando a nova classe Opportunities que criamos nesta unidade. Essa classe está encapsulando a lógica que faz os cálculos de desconto por meio de seu próprio método applyDiscount
.
public static void applyDiscounts(Set<Id> opportunityIds, Decimal discountPercentage) { // Unit of Work // …
// Validate parameters // ...
// Construct Opportunities domain class Opportunities opportunities = new Opportunities( [select Id,Amount, (select UnitPrice from OpportunityLineItems) from Opportunity where Id in :opportunityIds]);
// Apply discount via domain class behavior opportunities.applyDiscount(discountPercentage, uow);
// Commit updates to opportunities uow.commitWork(); }
Como usar classes de domínio de acionadores
Vamos considerar também outro ponto de entrada. Conforme ilustrado no diagrama na seção Padrão Domain, os usuários invocam acionadores do Apex nas interfaces do usuário do Salesforce ou com manipulação de código dos registros por DML ou pelas APIs do Salesforce.
Considerando o papel que a classe de domínio tem de encapsular toda a lógica e comportamentos de determinado objeto de domínio, precisamos fazer com que as chamadas do acionador do Apex sejam também encaminhadas para os métodos de classe pertinentes.
Assim como em vários padrões emergentes em torno de acionadores do Apex, é bom manter apenas o mínimo de lógica no acionador. Os acionadores do Apex não são classes e têm limitações para refatorar código ou usar princípios de OO, como herança. Eles são lugares ruins até mesmo para lógicas não tão complexas.
O código do acionador do Apex a seguir é viabilizado pelo uso da classe fflib_SObjectDomain que é parte da biblioteca de código aberto Padrões empresariais do Apex. Essa classe forma uma classe base para todas as classes de domínio em seu aplicativo. Mais sobre isso na próxima unidade!
O método estático fflib_SObjectDomain.triggerHandler
faz com que o método aplicável na classe Opportunities seja chamado pela leitura das variáveis de contexto do acionador do sistema, Trigger.isAfter
, Trigger.isBefore
, Trigger.isInsert
, Trigger.new
e assim por diante. O código que está nos acionadores do Apex usando esse padrão é, intencionalmente, muito simples.
trigger OpportunitiesTrigger on Opportunity (
after delete, after insert, after update, after undelete, before delete, before insert, before update) {
// Creates Domain class instance and calls appropriate methods
fflib_SObjectDomain.triggerHandler(Opportunities.class);
}
A classe Opportunities referenciada no código acima contém métodos como onBeforeInsert
e onAfterUpdate
, que implementam o comportamento desse objeto quando essas operações ocorrem.
Recursos
- GitHub: Padrões empresariais do Apex
- Publicação do blog: Martin Fowler: Modelo de domínio
- Wikipédia: Domínio (engenharia de software)
- Wikipedia: Separação de preocupações
- Publicação do blog: Horas Apex do Salesforce: Padrões empresariais do Apex
- Vídeo: Padrões empresariais do Apex
- Publicação do blog: Martin Fowler: Catálogo de padrões de arquitetura de aplicativos corporativos