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

A API GetuserNameEx

Primeiro de tudo, a função GetUserNameEx se encontra na dll Secur32.dll e, como outras funções da API do windows, possui duas versões, uma ANSI (GetUserNameExA) e uma WIDE (GetUserNameExW).

Abaixo segue o cabeçalho para importação dessas duas funções.

function GetUserNameExA(NameFormat: TEXTENDED_NAME_FORMAT; lpBuffer: PAnsiChar; var nSize: DWORD): BOOL; stdcall external 'Secur32.dll' name 'GetUserNameExA';
function GetUserNameExW(NameFormat: TEXTENDED_NAME_FORMAT; lpBuffer: PWideChar; var nSize: DWORD): BOOL; stdcall external 'Secur32.dll' name 'GetUserNameExW';


Atenção especial para o parâmetro NameFormat do tipo TEXTENDED_NAME_FORMAT. Ele é na verdade um Enum com alguns valores fixos. (no C também é um enum, e usa-se um ponteiro para ele)

  TEXTENDED_NAME_FORMAT  =
  (
    NameUnknown            = 0,
    NameFullyQualifiedDN   = 1,
    NameSamCompatible      = 2,
    NameDisplay            = 3,
    NameUniqueId           = 6,
    NameCanonical          = 7,
    NameUserPrincipal      = 8,
    NameCanonicalEx        = 9,
    NameServicePrincipal   = 10,
    NameDnsDomain          = 12
  );

Criei essas duas funções que me retornam uma string (UnicodeString no Delphi 2010) ou AnsiString para testar e facilitar o uso da GetUserNameEx (A ou W).

function TForm1.VtrGetUserNameExW(NameFormat: TEXTENDED_NAME_FORMAT): string;
var
  I: DWord;
begin
  I := 1000;
  SetLength(Result, I);
  GetUserNameExW(NameFormat, PChar(Result), I);
  Result := string(PChar(Result));
end;

function TForm1.VtrGetUserNameExA(NameFormat: TEXTENDED_NAME_FORMAT): AnsiString;
var
  I: DWord;
begin
  I := 1000;
  SetLength(Result, I);
  GetUserNameExA(NameFormat, PAnsiChar(Result), I);
  Result := AnsiString(PAnsiChar(Result));
end;



Estou alocando um espaço de 1000 caracteres para o resultado. É arbitrário. Quem souber uma maneira melhor de fazer isso, talvez usando outra api para saber o tamanho do nome do usuário de antemão, por favor me avise.

para testar chamo todas as funções, GetUserNameEx (A e W) passando todos os parâmetros possíveis de NameUnknown (0) a NameDnsDomain (12) e vejo o resultado.

procedure TForm1.Button2Click(Sender: TObject);
var
  enf: TEXTENDED_NAME_FORMAT;
begin
    Memo1.Lines.Add('Versão Wide -----------------------------------');
    enf := NameUnknown;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameFullyQualifiedDN;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameSamCompatible;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameDisplay;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameUniqueId;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameCanonical;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameUserPrincipal;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameCanonicalEx;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameServicePrincipal;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameDnsDomain;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));


    Memo1.Lines.Add('Versão Ansi -----------------------------------');
    enf := NameUnknown;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameFullyQualifiedDN;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameSamCompatible;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameDisplay;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameUniqueId;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameCanonical;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameUserPrincipal;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameCanonicalEx;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameServicePrincipal;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameDnsDomain;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

end;


Comentários

Postagens mais visitadas deste blog

Busca de CEP com o Lazarus - Parte 1 - UrlEncode

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

Uso de memória no SQL Server