6 maneiras de fazer a mesma coisa, o que é considerado boas práticas?

As vezes tem tantas maneiras diferentes de fazer o mesmo código que nós ficamos na dúvida quanto a qual maneira usar. O que seria considerado "boa prática" pela comunidade e o que sua equipe entenderia melhor. Suponhamos que você esteja trabalhando dentro de um método de um Domain Service chamado UmDomainServiceChique(objetoDoDominio) que será chamado por uma API. Você tem uma regra de negócio chique para ser verificada que por enquanto chamarei de VerificaMinhaRegraChiqueComplexa(). Você chama UmDomainServiceChique(objetoDoDominio) e caso VerificaMinhaRegraChiqueComplexa() retorne true você vai querer que UmDomainServiceChique faça o que tem que fazer e a api retornar Ok 200, caso contrário você quer que a API responda um erro qualquer, tipo BadRequest, e retornar uma mensagem dizendo que VerificaMinhaRegraChiqueComplexa deu ruim. Eu vejo 6 maneiras de fazer isso, gostaria de saber a opinião de outrs devs sobre qual seria a maneira menos gambiarr

Capturar janelas, classes e textos com o lazarus

No meu artigo sobre a api do windows eu já mencionei sobre a importância de um programinha que identifique as janelas, handles e clases do windows.

Muitos programas nos "baixaki" da vida fazem isso, e alguns debuggers e cheaters para games também. Mas a maior utilidade que vejo para um programinha assim é poder identificar nomes de classes e handles de janelas não feitas por você, para interagir com sua aplicação.

Seja para colocar uma janela externa como child da sua, seja para capturar o conteudo de um textbox em outra janela, esse tipo de aplicação pode ser útil.

Eu usei muito para descobrir quais eram as classes por trás de alguns editores de propriedade e / ou editores de componentes não documentados do Delphi 7 para fazer meus próprios.

Hoje vamos fazer uma aplicaçãozinha dessas em lazarus.

Primeiro de tudo baixe a última versão do lazarus no site oficial.

Depois de instalado, a instalação é bem simples, inicie um novo projeto e crie uma janela como a da figura 1.

figura 1: uma janela fina, com um botão que não faz nada, só de teste, um label, e um timer

Colocamos nessa janela apenas um botão, um label, chamado lblHandle e um timer. O timer conterá toda a lógica do programa.

O botão servirá apenas como um teste dentro da propria janela, mas o objetivo do programa é que funcione para qualquer janela feita com a api do windows.

Janelas feitas com outras api's gráficas, como gtk, não funcionarão.

O objetivo do programa é mostrar o handle, o nome de classe e o texto de qualquer janela ou controle "windowed" de qualquer programa pelo qual estivermos passando a seta do mouse em um dado momento.

figura 2: o programa em funcionamento mostra o handle do visor da calculadora do windows

Para isso digite o código da listagem abaixo no evento onTimer do timer.


procedure TForm1.Timer1Timer(Sender: TObject);
var
   //criamos dois pchars, um para o nome da classe (c) e outro para o texto da janelas (t)
   t,c: pchar;
   //para obter um handle (na verdade um handle é um inteiro de 4 bytes sem sinal)
   h: Thandle;
   //usaremos um ponteiro para a estrutura POINT para obter a posição da seta do mouse
   p: PPOINT;
begin

     try
        try

           //vamos alocar memoria para o nosso PPoint com new, visto que é uma estrutura simples
           new(p);
           //para c e t usaremos getmem porque trata-se de vetores/strings. Limitaremos a 255 caracteres neste exemplo.
           GetMem(t, 255);
           GetMem(c, 255);

           //preenchemos todo o conteudo da memória alocada com #0 para que strings menores que 255 caracteres possam terminar com um #0 no seu final sem concatenar com lixo randomico de memória
           FillChar(c^, 255, #0);
           FillChar(t^, 255, #0);

           //obtemos a posição do cursor
           GetCursorPos(p);

           //obtemos o handle nesse ponto
           h := WindowFromPoint(p^);

           //obtemos o texto dessa janela (handle)
           GetWindowText(h, t, 255);

           //e o nome da classe (no caso de programas feitos em Delphi, há a vantagem de o nome da classe na api ser igual ao nome da classe na sua unit.pas)
           GetClassName(h, c, 255);

           //mostramos as informações no handle
           lbHandle.Caption := 'Handle: ' + IntToStr(h) + ' - Texto: ' + string(t) + ' - Classe: ' + string(c);

        except

        end;
     finally

            //desalocamos a memória
            dispose(p);
            Freemem(t);
            Freemem(c);

     end;

end;    
  

Veja que é importante desalocar a memória dentro de um bloco finally para garantir que não ocorram leaks (vazamentos de memória).

Você pode baxar os fontes aqui.

Espero que seja útil para vocês quanto foi para mim.

Amanhã teremos mais dicas do Lazarus.

Have Fun ;)

Comentários

Postagens mais visitadas deste blog

Uso de memória no SQL Server

Busca de CEP com o Lazarus - Parte 1 - UrlEncode

Botão Add This para adicionar seu post em qualquer rede