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

IIF

Quem já programou em Clipper e Visual Fox Pro deve lembrar da função IIF. Esta função simplesmente aceitava três parâmetros, um booleano, ou condição, e dois valores, caso verdadeiro e caso falso.
Ela era interessante porque substituia (em partes) o operador ternário ?: do C e poderia ser usada em expressões para se somar ou concatenar o valor correto dependendo da condição.
Ela servia para substituir um if ... else e uma variável temporária colocando tudo na mesma linha.

O seu formato era:

iif(condição, valor se verdadeiro, valor se falso): valor;

Ela retornava um valor que seria do mesmo tipo do segundo e terceiro argumento.

É possível criar inúmeras variantes dessa função, tanto no Lazarus como no Delphi. Usando variants poderiamos  criar uma vertente da função que funcionaria para qualquer tipo de dado primitivo.

Mas o Delphi é ainda mais flexível porque hoje temos Generics e o tipo TValue, que são mais flexíveis ainda. Com Generics, Variants e sobrecarga de operadores podemos utilizar sim qualquer tipo de valor, classes, objetos instanciados e assim por diante. Além disso, com expressões lambda e funções "inline" podemos inclusive colocar função/execução de código no IIF o que extrapola o seu objetivo de substituir o operador ternário. Ele se torna realmente um if...else. Esse tipo de coisa poderíamos fazer nas versões antigas do Delphi e no Lazarus apenas com ponteiros para métodos.

Esse código abaixo mostra um exemplo da função IIF e seu uso, inclusive com generics nas versões modernas do Delphi.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

function iif(condicao: Boolean; ValorVerdadeiro, ValorFalso: T): T;

implementation

{$R *.dfm}

function iif(condicao: Boolean; ValorVerdadeiro, ValorFalso: T): T; 
begin
  if condicao then
    Result := ValorVerdadeiro
  else
    Result := ValorFalso;
end;

function iif(condicao: Boolean; ValorVerdadeiro, ValorFalso: string): string;
begin
  if condicao then
    Result := ValorVerdadeiro
  else
    Result := ValorFalso;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  a,b, resultado: string;
  x,y: integer;
  debita: boolean;
begin

  a := 'Clube';
  b := 'Delphi';

  x := 1;
  y := 2;

  debita := true;
  resultado:= inttostr(iif(debita, y-1, y+1));
  ShowMessage(resultado);

  debita := false;
  resultado:= inttostr(iif(debita, y-1, y+1));
  ShowMessage(resultado);

  resultado:= iif(x=y, 'x é igual a y', 'x é diferente de y');
  ShowMessage(resultado);

  x := y;
  resultado:= iif(x=y, 'x é igual a y', 'x é diferente de y');
  ShowMessage(resultado);

  resultado:= iif((a<>'')and (b<>''), a + ' ' + b , 'um dos dois é vazio');
  ShowMessage(resultado);

  a := '';
  resultado:= iif((a<>'')and (b<>''), a + ' ' + b , 'um dos dois é vazio');
  ShowMessage(resultado);

  resultado:= iif(a=b, 'a e b são iguais', 'a e b são diferentes');
  ShowMessage(resultado);

end;

end.



Aqui criamos apenas duas versões, uma com generics (que funcionará para tudo) e uma com strings. Poderíamos criar com variants ou qualquer outra coisa.

Uma alteração interessante que pode ser feita também é declarar os argumentos/parâmetros das funções como const, assim eles não poderão ser temporariamente modificados por expressões lambda ou código dentro do corpo de IIF.


function iif(const condicao: Boolean; const ValorVerdadeiro, ValorFalso: T): T;

{...}

function iif(const condicao: Boolean; const ValorVerdadeiro, ValorFalso: T): T; 
begin
  if condicao then
    Result := ValorVerdadeiro
  else
    Result := ValorFalso;
end;


Espero que seja útil para todos. Pelo menos saudosista é ;)

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