Separar leitura da tela, cálculo e apresentação do resultado
Tutorial · prática orientada · IntermediárioEventos de formulários e units Delphi
Unit principal compilada e exercitada com DCC32 37.0, build 37.0.59082.6021. Referência editorial: Delphi 11.3 e 13.2; essas duas versões não foram verificadas individualmente.Documentação, instalação e limites de Fundamentos em seis units
Um evento OnClick começa pequeno. Depois ganha validação, leitura de banco, cálculo, log e atualização de vários controles. O problema aparece quando outra tela precisa da mesma regra e a alternativa mais rápida parece copiar o evento.
Vamos separar um cálculo de duração entre horários. O cenário é um agendamento, mas a função não conhecerá formulário, navegador ou banco de dados.
Defina o caso de uso em linguagem simples
A necessidade inicial é: receber início e fim válidos e devolver a duração em minutos. Antes de escolher classes, defina os limites: fim anterior ao início é inválido; horários iguais representam duração zero.
O exemplo trabalha com dois TDateTime na mesma referência temporal. Ele não resolve fusos, horários de verão ou agendamentos que atravessam mudanças de offset. Isso precisa de um contrato específico numa aplicação real.
Extraia a regra para uma unit
Crie Agenda.Duracao.pas:
unit Agenda.Duracao;
interface
function DuracaoEmMinutos(const Inicio, Fim: TDateTime): Double;
implementation
uses
System.SysUtils;
function DuracaoEmMinutos(const Inicio, Fim: TDateTime): Double;
begin
if Fim < Inicio then
raise EArgumentException.Create('Fim anterior ao início');
Result := (Fim - Inicio) * 24 * 60;
end;
end.A saída é Double porque pode haver fração de minuto. Arredondar para minutos inteiros exige outra decisão: arredondar para cima, para baixo ou para o mais próximo produz comportamentos diferentes. Não esconda essa regra dentro de uma formatação.
Deixe o evento traduzir a interação
No formulário, o evento pode ler valores dos controles, chamar DuracaoEmMinutos e mostrar a saída. A mensagem visual pode tratar EArgumentException de maneira compreensível. Falhas inesperadas devem seguir o mecanismo de diagnóstico da aplicação.
Evento do formulário
→ converte entradas visuais
→ chama cálculo/caso de uso
→ apresenta resultado ou problema de entradaEvite levar a função de volta ao formulário para atualizar labels. Se o cálculo passa a salvar o agendamento, essa gravação deve ter autorização e uma transação definida, em vez de SQL espalhado pelo evento.
A separação ajuda a testar e também a enxergar o que acontece no servidor. UniGUI atende múltiplas sessões; o acesso aos formulários e módulos precisa respeitar o contexto de sessão descrito na arquitetura oficial.
Não crie serviços sem responsabilidade
Uma classe que apenas chama outra classe e não expressa nenhuma fronteira pode aumentar a navegação sem melhorar o desenho. Para este cálculo puro, uma função é suficiente.
Uma classe de caso de uso se torna útil quando precisa coordenar dependências e um comportamento definido: verificar autorização, carregar dados, aplicar a regra e persistir o resultado. Não confunda essa coordenação com uma nova pasta.
Teste sem sessão web
Num projeto de console, construa horários usando EncodeDate e EncodeTime. Confira duração zero, trinta minutos e uma hora. Para fim anterior ao início, a expectativa é uma exceção.
Como o cálculo usa ponto flutuante, compare valores com uma tolerância definida, não apenas com igualdade literal em todos os cenários. Teste também segundos quando seu contrato permitir precisão abaixo de um minuto.
A unit foi compilada; duração zero, 30 minutos, 60 minutos e intervalo negativo passaram no projeto de verificações. A integração visual ainda precisa ser exercitada. Ao integrar, teste o evento no navegador e confirme que uma entrada inválida não executa a gravação.
Desafio e continuidade
Acrescente uma regra de duração máxima configurável. Escreva primeiro os exemplos de entrada e os resultados esperados. Decida se ultrapassar o máximo rejeita o agendamento ou apenas gera um aviso: a função não deve inventar essa política.
Para separar coordenação e regra, leia Tela, serviço e domínio.
Wiring do exemplo de duração
Controles início/fim → conversão TDateTime → Agenda.Duracao.DuracaoEmMinutos → saída visual.
- Leia e converta os valores no evento.
- Passe valores à função, não componentes.
- Traduza EArgumentException para erro junto dos campos.
- Teste zero, 30 minutos e fim anterior no console antes de ligar o formulário.
O desafio corresponde à duração usada no artigo. Estado de sessão precisa de dono; singleton global não deve guardar usuário. Console disponível; wiring UniGUI e versão instalada não executados nesta revisão.
Duas sessões podem acabar compartilhando dados de um usuário?
Escolha um evento de formulário e identifique nele a interação visual, a regra de negócio e o acesso a dados. Esboce como separá-los e quem deve ser dono do estado de sessão.
Ver uma pista para começar
Revise variáveis globais e o ciclo de vida dos módulos. Separe o estado de cada usuário e verifique autorização no servidor, mesmo quando a interface oculta uma ação.
Não precisa acertar de primeira. Observe o resultado e explique o que mudou.