Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

[Dúvida] Compartilhando Exemplo de aplicação do Pattern Strategy

Boa tarde, Pessoal, tudo bom?

Eu trabalho com Salesforce e a linguagem de programação que utilizamos (Apex) é praticamente um Java desatualizado rsrs. Mas, de qualquer forma, gostaria de compartilhar uma possível solucao de um problema bem recorrente usando o Pattern Strategy e pedir a opinião de vocês =P (Se for possível claro rsrs).

Já adianto uma dúvida, eu não poderia criar Overloads em uma Interface e optar por implementar somente uma opção, poderia?

Vou compartilhar os códigos e dando pequenas explicações.

MUITO OBRIGADO.

Alguns conceitos:

Dentro de um ambiente salesforce, podemos validar um Insert ou Update de registros antes de serem enviados para o Banco de Dados. De forma didática, existe uma estrutura de Triggers (Parecido com que temos em bancos relacionais) com metodos beforeInsert/beforeUpdate para executar validacoes.

Interface criada para Validacoes de Registros antes de serem inseridos ou atualizados:

public interface RecordValidation {

    void validate(Map<Id, SObject> records, Map<Id, SObject> oldRecords);

}

Exemplo de Classe Concreta de uma validacao. Neste caso, eu criei um cenário que não precisou necessáriamente um oldRecords.(Por isso perguntei do overload na interface hahaha)

public with sharing class AccountActiveValidation implements RecordValidation{

    public void validate(Map<Id, SObject> records, Map<Id, SObject> oldRecords) {
        for(String recordId: records.keySet()) {
            if(records.get(recordId).isActive != true) {
                records.get(recordId).addError('Esse registro nao está ativo');
            }
        }
    }
}

Exemplo de uma classe Service para o tipo de Objeto Account:

public with sharing class AccountService {

    AccountActiveValidation activeValidation;
    List<RecordValidation> validations = new List<RecordValidation>();
    private Map<Id, Account> accounts;
    private Map<Id, Account> oldAccounts;

    public AccountService(Map<Id,Account> accounts, Map<Id, Account> oldAccounts) {
        this.accounts = accounts;
        this.oldAccounts = oldAccounts;
        this.createValidations();
    }

    void validate() {
        for (RecordValidation validation : validations) {
            validation.validate( this.accounts, this.oldAccounts);
        }
    }

    void createValidations() {
        this.validations.add(new AccountActiveValidation());
    }

}

E a trigger em si:

public with sharing class AccountTH {

    private AccountService service;
    private Map<Id, Account> oldRecords;
    private Map<Id, Account> records;

    public AccountTH() {
        this.records = new Map<Id, Account>( (List<Account>) Trigger.new);
        this.oldRecords = new Map<Id, Account>( (List<Account>) Trigger.old);
        this.service = new AccountService(this.records, this.oldRecords);
    }


    beforeUpdate() {
        this.service.validate();
    }

    beforeInsert() {
        this.service.validate();
    }
}
2 respostas
solução!

Oi Cauê!

No seu caso você precisa realizar diversas validações, antes de um insert ou update, e criou uma interface com cada validação sendo uma implementação, certo? Ficou muito bom e essa é uma boa utilização desse pattern, para evitar que a classe service fique muito extensa e difícil de manter.

Inclusive, no terceiro curso de Spring Boot (a ser publicado em breve na plataforma) eu utilizei essa mesma abordagem :D O código do projeto está aqui: https://github.com/rcaneppele/2771-spring-boot/tree/main/src/main/java/med/voll/api/domain/consulta/validacoes/agendamento é na funcionalidade de agendamento de consultas que o pattern foi aplicado.

Bons estudos!

Opa, obrigado pelo retorno Rodrigo =).

Fico feliz de ter aplicado de forma correta rsrs, a ideia é já colocar em prática no dia a dia aqui.

Inclusive, já vou apresentar a solução para meus superiores para virar, talvez, um pattern geral de utilização para todos os projetos da empresa! Fiquei super animado hahaha.

E também estou animado para esta formação de Spring Boot que está por vir. Quero tirar proveito do Apex ser uma lingua bem parecida com o Java e, quem sabe, poder trabalhar com as duas coisas =P.

Abraços e muito obrigado pelos cursos!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software