Esta caraterística continua com um novo paradigma: manusear dados de uma forma orientada a eventos. O 4D 21 fornece uma série completa de eventos relacionados com operações de base de dados(salvar ou soltar).
Os eventos ORDA podem substituir os gatilhos e oferecem muitas mais vantagens: mais controle, permitindo codificar sua lógica de negócios (incluindo trabalhos demorados como imprimir faturas ou armazenar dados externos) diretamente em uma função de classe de dados ORDA. Respondem a eventos ao nível dos dados, tais como novo, modificar, guardar, largar (CRUD)
Os eventos ORDA oferecem uma granularidade precisa e um tratamento de erros sofisticado, conduzindo a uma forte integridade dos dados e a uma melhor organização do código.
Descubra como implementar a lógica empresarial adequada em cada passo de uma ação de guardar ou largar.
Eventos ORDA – Uma valsa em vários momentos
Neste post anterior do blogue, revelámos o primeiro evento de uma longa série: o evento tocado.
Os novos eventos de operação da base de dados foram concebidos para serem utilizados na camada ORDA através de entidades tratadas com a palavra-chave This o que não é possível com gatilhos.
Em comparação com os accionadores, estes eventos oferecem uma granularidade mais fina para detetar etapas específicas das operações da base de dados e um tratamento de erros sofisticado que pode interromper a ação, se necessário.
Ao contrário dos accionadores, os eventos não só permitem implementar acções antes das acções de guardar/aderir. Podem também executar acções durante e após as operações de guardar/aderir.
O tratamento de erros é poderoso, pode devolver erros personalizados com diferentes graus de gravidade e informações extra detalhadas para o utilizador final.
Anteriormente, podia implementar algumas funções para este efeito, mas tinha de as chamar manualmente sempre que fosse necessário.
Agora, essa caraterística oferece uma lógica completa orientada a eventos, acionada automaticamente no momento apropriado. Implemente uma vez e deixe o motor 4D lidar com isso em tempo de execução:
- Dados inconsistentes podem ser rejeitados de antemão sem envolver a camada de persistência
- Interações com sistemas externos podem acontecer precisamente quando os dados 4D são persistidos
- As ações podem ser acionadas quando o salvamento/lançamento falha
E a boa notícia é que, ao contrário dos gatilhos, ORDA não bloqueia toda a tabela subjacente de uma classe de dados ao salvar / soltar uma entidade. Vários eventos podem ser executados em paralelo, desde que envolvam entidades distintas (ou seja, registos).
Se depender de um bloqueio total de toda a tabela para tratar números de sequência únicos ou similares, terá de o fazer por sua conta, por exemplo, com singletons – o que lhe permite bloquear apenas quando necessário – e ter controlo total sobre este processo.
As diferentes fases de uma operação de base de dados
Quando uma ação de guardar ou largar é executada, estes eventos permitem-lhe implementar a lógica comercial em três fases distintas da ação:
- Validação da ação de guardar ou largar: Útil para verificar a consistência dos dados relativos a esta ação, por exemplo:
- O status da entidade prestes a ser descartada está definido como “TO DELETE” ?
- A data de partida é inferior à data de chegada numa entidade de reserva?
Graças a este evento, pode parar a ação de guardar/eliminar e devolver um erro ao utilizador final. Isto garante que os dados serão consistentes e estarão prontos antes de entrar na ação de guardar/eliminar propriamente dita.
- Durante a ação de guardar / largar: Utilize esta opção se precisar de sincronizar as operações da base de dados com um sistema externo, por exemplo:
- Ao salvar uma entidade, gravar dados em um disco, criar um documento em um Google Drive, etc.
Neste evento, pode devolver erros em caso de falha na paragem da ação. Estes erros podem então ser tratados no evento após descrito abaixo.
- Após a ação de guardar ou largar: Aqui pode tomar medidas em relação a potenciais erros que surjam durante as acções de guardar/aderir, por exemplo:
- Marcar um produto como “A verificar” porque ocorreu um erro durante a ação de largar
Graças a estes eventos, cada passo da ação de guardar ou largar pode ter a sua própria lógica comercial dedicada.
Estes eventos são acionados assim que a operação da base de dados é acionada utilizando o ORDA ou o servidor REST.
Vamos ver isto em ação com exemplos
onde implementar eventos
Os eventos ORDA devem ser implementados na classe Entidade utilizando a palavra-chave event palavra-chave.
os eventos de validação
Estes eventos são acionados antes da ação de guardar ou largar e podem parar a ação devolvendo um erro. Neste caso, os outros eventos descritos abaixo (exceto o evento after) não são acionados.
Podem ser implementados:
- No nível do atributo: para verificar a consistência de um atributo específico
- No nível da entidade: para verificar o conteúdo da entidade globalmente ou comparar atributos
Exemplo:
Neste exemplo, na classe ProductsEntity, foi implementado um eventovalidateSave para o atributomargin . O utilizador não pode guardar um produto com uma margem inferior a 50%. Neste caso, é devolvido um erro para interromper a ação de guardar e dar feedback ao utilizador final.
// ProductsEntity class
//
// validateSave event at attribute level
Function event validateSave margin($event : Object) : Object
var $result : Object
//The user can't create a product whose margin is < 50%
If (This.margin<50)
$result:={errCode: 1; message: "The validation of this product failed"; \
extraDescription: {info: "The margin of this product ("+String(This.margin)+") is lower than 50%"}; seriousError: False}
End if
return $result
A mesma lógica aplica-se a um eventovalidateDrop. Por exemplo, pode impedir um utilizador de largar um produto cujo estado não seja “A eliminar”.
os eventos de guardar / largar
Estes eventos são acionados precisamente durante a ação de guardar ou largar e podem devolver erros se algo correr mal. Podem ser implementados:
- Ao nível do atributo: para monitorizar as alterações de valores de atributos específicos
- Ao nível da entidade: para verificar globalmente o conteúdo da entidade ou comparar atributos
Exemplo:
Neste exemplo, na classe ProductsEntity, foi implementado um evento degravação para o atributouserManualPath . Quando um produto é guardado, o documento do manual do utilizador é criado no disco e o seu caminho é armazenado no atributo userManualPath atributo. Estas duas acções devem ser coerentes.
Se ocorrer um erro durante a criação do documento do manual do utilizador no disco, é devolvido um erro para dar feedback e para prosseguir no evento seguinte (afterSave), descrito abaixo.
Note-se que o conteúdo do ficheiro é gerado previamente fora do eventode gravação, porque pode ser demorado.
// ProductsEntity class
// saving event at attribute level
Function event saving userManualPath($event : Object) : Object
var $result : Object
var $userManualFile : 4D.File
var $fileCreated : Boolean
If (This.userManualPath#"")
$userManualFile:=File(This.userManualPath)
// The user manual document file is created on the disk
// This may fail if no more space is available
Try
// The content of the file has been generated and stored in a map in Storage.docMap previously
$docInfo:=Storage.docMap.query("name = :1"; This.name).first()
$userManualFile.setContent($docInfo.content)
Catch
// E.g.: No more space on disk
$result:={errCode: 1; message: "Error during the save action for this product"; extraDescription: {info: "There is no available space on disk to store the user manual"}}
End try
End if
return $result
A mesma lógica aplica-se a um evento deabandono. Por exemplo, pode deixar cair o documento do manual do utilizador enquanto deixa cair o produto.
os eventos após
Estes eventos são acionados após a ação Guardar ou Largar. Uma vez que a ação está concluída, não podem devolver erros. O seu principal objetivo é acionar a lógica empresarial se ocorrer uma falha durante os eventos anteriores.
Se não tiver ocorrido nenhum erro, também podem tratar da lógica pós-sucesso – por exemplo, enviar uma mensagem de correio eletrónico de confirmação.
Estes eventos são implementados apenas ao nível da entidade.
Exemplo:
Neste exemplo, na classe ProductsEntity, foi implementado um eventoafterSave. Se o atributo userManualPath não tiver sido guardado corretamente anteriormente, o seu valor é reposto para ser consistente com o documento do manual do utilizador em falta no disco.
// ProductsEntity class
Function event afterSave($event : Object)
If (($event.status.success=False) && ($event.status.errors=Null)) // $event.status.errors is filled if the error comes from the validateSave event
// The userManualPath attribute has not been properly saved
// Its value is reset
If ($event.savedAttributes.indexOf("userManualPath")=-1)
This.userManualPath:=""
This.status:="KO"
End if
End if
A mesma lógica aplica-se a um eventoafterDrop –por exemplo, quando a largada de um produto falha, é possível registar o incidente.
Nota: as operações longas devem ser evitadas tanto quanto possível nos eventos. Se possível, essas operações devem ser implementadas noutro local.
Não espere pela implementação de eventos para confiar numa forte integridade dos dados.
Descarregue o HDI para se aprofundar nos detalhes de implementação dos eventos ORDA e veja o vídeo abaixo para obter mais detalhes sobre a execução do HDI.
Adicionar o link do vídeo EN
