má pratica de programação ? .... (teste) ? valu1 : (teste2) ? value2 : value3

31 respostas
Lavieri

é ma pratica de programação ??? … (teste) ? valu1 : (teste2) ? value2 : value3

tenho quase 100% de certeza que é… mais fica ai a pergunta ^^

public static String calculateCheckDigits(Cnpj cnpj) { return (cnpj.isNull()) ? null : (cnpj instanceof CnpjValid) ? cnpj.getCheckDigits() : VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS); }

2° opção…

public static String calculateCheckDigits(Cnpj cnpj) { if (cnpj.isNull()) return null; else if (cnpj instanceof CnpjValid) return cnpj.getCheckDigits(); else return VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS); }

3° opção

public static String calculateCheckDigits(Cnpj cnpj) { String result = null; if (!cnpj.isNull()) { if (cnpj instanceof CnpjValid) result = cnpj.getCheckDigits(); else result = VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS); } return result; }

31 Respostas

tnaires

Não acho que seja má prática. É um recurso que a linguagem disponibiliza, e deve ser usado desde que não comprometa a legibilidade da sentença.

fabio.nascimento

Lavieri:
é ma pratica de programação ??? … (teste) ? valu1 : (teste2) ? value2 : value3

tenho quase 100% de certeza que é… mais fica ai a pergunta ^^

public static String calculateCheckDigits(Cnpj cnpj) { return (cnpj.isNull()) ? null : (cnpj instanceof CnpjValid) ? cnpj.getCheckDigits() : VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS); }

2° opção…

public static String calculateCheckDigits(Cnpj cnpj) { if (cnpj.isNull()) return null; else if (cnpj instanceof CnpjValid) return cnpj.getCheckDigits(); else return VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS); }

3° opção

public static String calculateCheckDigits(Cnpj cnpj) { String result = null; if (!cnpj.isNull()) { if (cnpj instanceof CnpjValid) result = cnpj.getCheckDigits(); else result = VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS); } return result; }

Opção 1 - Ahhh se eu eu pego um codigo desse pela frente… ahh se eu pego…
Opção 2 - Caminha pra verbosidade, bem melhor de se ler.

Vejo que muitos reclamam do java dizendo que não é verboso, mas quem faz isso são alguns codificadores brincalhoes mesmo, pq na ansia de escrever menos linha de codigo, acabam por danificar a leitura do mesmo.

Quem pega uma “encrenca” dessas pela frente, muitas vezes tem que ficar adivinhando qual a proposta do metodo, pelo amor de deus viu !

Má prática ou não, por favor não escreva desse jeito!

Fabio Nascimento

tnaires

fabio.nascimento:
Vejo que muitos reclamam do java dizendo que não é verboso, mas quem faz isso são alguns codificadores brincalhoes mesmo, pq na ansia de escrever menos linha de codigo, acabam por danificar a leitura do mesmo.

Quem pega uma “encrenca” dessas pela frente, muitas vezes tem que ficar adivinhando qual a proposta do metodo, pelo amor de deus viu !

Má prática ou não, por favor não escreva desse jeito!

Fabio Nascimento


Como eu falei, acho válido usar desde que não comprometa a legibilidade da sentença. O primeiro exemplo está realmente horrível de se ler e, consequentemente, de dar manutenção. Porém, também não concordo com a atitude extremista de que “todo código que usa o operador ternário é ruim de ler”.

No final das contas, é uma questão de gosto; mas como nem todo o código que a gente encontra na vida está da forma que a gente sonha, acho válido conhecer e usar o recurso.

Lavieri

não estou recriminando o operador ternario, acho ate muito bom ele, como no exemplo abaixo

public Long toLong() { return (isNull()) ? null : new Long(toString()); }

se vou atribuir o valor, e preciso de um IF/ELSE prefiro usar o operador ternario…
o fato era que ali, era if, else if, else … ou seja, ia ficar meio estranho…

for isso estou tentando evitar escrever mais de 1 return no código, a primeira opção retira o return, mais estava notando que mesmo assim só complicava + ainda o código… a segunda opção é xeia de returns… e a 3° inclui uma variável a + o result …

eu prefiro um código que vc escreva com um return só, fica mais facil de ler, e em lugar de ficar usando apenas if, com returns… vc se acustuma a usar o else, por exemplo na segunda opção de código os else ali são totalmente dispensaveis, pois o código só passa a diante se o if não ocorrer, portanto não precisa do else… mas mesmo assim eu prefiro escrever o else, acho que fica mais legivel…

entre a 2ª e a 3ª opção ??? … vejo muita gente criticando a regrinha la da sun, de so ter um return… não sei c criar essas variáveis dentro do scopo diminuem a performance, tipo a result ali da 3ª opção…

por enquanto estou usando a 3° opção, apenas para não usar + de 1 return, mais ainda fico em duvida

tnaires
Na segunda opção, se você está usando mais de um return, não precisa escrever os elses. O código poderia ficar assim:
public static String calculateCheckDigits(Cnpj cnpj) {
    if (cnpj.isNull())
        return null;

    if (cnpj instanceof CnpjValid)
        return cnpj.getCheckDigits();
    
    return VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS);
}
Lavieri
tnaires:
Na segunda opção, se você está usando mais de um return, não precisa escrever os elses. O código poderia ficar assim:
public static String calculateCheckDigits(Cnpj cnpj) {
    if (cnpj.isNull())
        return null;

    if (cnpj instanceof CnpjValid)
        return cnpj.getCheckDigits();
    
    return VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS);
}

porem é mais legivel com o else.... já que tenho q escrever if, ainda + 2, já que tem os retunrs... não vejo motivo pra omitir os elses... so vai tornar + dificil a leitura... com o else fica claramente explicito, que o segundo evento só ocorre caso o 1° não ocorra, sei que o return implica isso... porem de toda forma a leitura fica melhor ^^

diegosantiviago

eu não acho má prática.

existem casos e casos. Eu utilizo bastante aqui no BEA Weblogic. ;D

luistiagos

qualquer opção que não seja a primeira ta bom… operadores ternarios encadeados não cheirão bem…
se isto for uma app web a má pratica esta em delegar para o java a validação do cnpj coisa que poderia ser feito em javascript o qual seria mais rapido pois não iria precisar fazer nenhuma requisição ao servidor…

fantomas

Minha opinião sobre a questão:

Como já disseram, é um recurso da linguagem logo pode ser utilizado tranquilamente; as indicações que eu já vi para este caso são as seguintes:

  1. Desde a muito tempo os entendidos em boas práticas pedem para utilizar um único RETURN, dizem que fica mais fácil de localizar bugs, aumenta a facilidade de se fazer manutenção e nos força a construir um algoritimo mas interessante; me parece que algumas linguagens não deixam vc fazer isso (return no meio fluxo) acho que Pascal é uma delas.

  2. Ao utilizar o return utilize parenteses para retornos compostos (return( a == b )) caso contrario use sem parenteses ( return a ).

  3. As linguagens C e Java e similiares nunca foram linguagens fortes na construção de bons algoritimos, são boas de sintese ( eu acho essa parte bastante discutivel, os puritanos gostam dela)

public static String calculateCheckDigits(Cnpj cnpj) { return (cnpj.isNull()) ? null : (cnpj instanceof CnpjValid) ? cnpj.getCheckDigits() : VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS); }

Neste caso, para utilizar essa estrutura de forma mais legivel teriamos que simplificar o máximo possível o código deste método a sugestão é fazer as seguintes perguntas:

a) Este método é necessário?
b) É necessário verificar se é nulo dentro deste método?
c) Será que uso de instanceof (neste caso) não é um indicador de que nossos objetos estão deixando de fazer alguma coisa que eles mesmos poderiam fazer?

O livro de refatoração do Mr. Martin fowler tem bastante coisas sobre este tema, vale a pena verificar.

Espero ter ajudado em alguma coisa.

flws

Marky.Vasconcelos

em meus programas eu uso mais para simplificar no lugar de if/else

como assim:

value *= cot.isForaCapital() ? 1.5d : 1d;
value *= cot.isRetorno() ? 1.5d : 1d;
diegosantiviago

No meu caso:

...
* @throws RASException
* @ejbgen:local-method transaction-attribute="Supports"
*/
	public RasVO getData() throws RASException {
		RasVO rasVO = new RasVO();
        rasVO.setCd_ras(this.getCdRas() == null ? 0 : this.getCdRas().longValue());
        ...
ViniGodoy

Eu usaria a segunda.

Mas sem os elses, já que o return interrompe o fluxo, eles não são necessários.

if (cnpj.isNull())   
        return null;   
    if (cnpj instanceof CnpjValid)   
        return cnpj.getCheckDigits();   

    return VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS);

Essa abordagem tem uma série de vantagens:

  1. É fácil de ler.

  2. É muito fácil entender que o método retornará null quando o CPNJ for nulo. Não precisamos ler o resto do código, pois o return ali não deixa margem para dúvidas. No caso 3, como o código está aninhado, pode haver algo abaixo do if, e portanto, temos que ler o código até o final para entender onde ele realmente sai. Até por isso, sou radicalmente contra a opinião de que um único return é positivo. Talvez fosse em 1980, mas essa prática certamente não se reforça nos dias de hoje.
    Usar returns da forma que coloquei é uma prática conhecida como code guards. Ou seja, mova o código que protege seu método de processamento indesejado para o início, separando as condições de saída com condições simples que levam a um return ou lancem uma exception. É recomendada pelo livro Refactoring. Também não é bom usar elses, pois note que um programador tem que realmente ler seu if inteiro para entender que o último return refere-se a condição final. Isso não ocorre com o código sem elses, já que esse return está fora da identação e claramente fora de qualquer if.

  3. Evita aninhamentos desnecessários no código. Veja quanta identação foi usada na terceira opção. Se você tivesse mais condições, mesmo que elas fossem de escape (como as que você tem ali) teria um código muito identado e difícil de ler.

  4. Não dá margem para um programador descuidado colocar código entre 2 returns daqueles de maneira acidental. O que ocorreria, por exemplo, se alguém colocasse um código qualquer após o if, da terceira opção. No segundo caso, o sujeito tem realmente que pensar se uma condição de guarda deve ser modificada, o que geralmente não é necessário.

  5. É mais fácil separar o trecho de código representado por cada if ali em cima. Note seria muito difícil separa esas função em funções menores para o caso da opção 3. O código está fortemente associado pelos comandos (no caso, if e else).

tnaires

Lavieri:
porem é mais legivel com o else… já que tenho q escrever if, ainda + 2, já que tem os retunrs… não vejo motivo pra omitir os elses… so vai tornar + dificil a leitura… com o else fica claramente explicito, que o segundo evento só ocorre caso o 1° não ocorra, sei que o return implica isso… porem de toda forma a leitura fica melhor ^^

Eu até ia argumentar, mas o ViniGodoy falou tudo o que eu queria falar :smiley:

T

Eu sempre omito os parênteses no “return”, porque senão ele parece uma chamada de método, o que ele não é. Mas isso é uma questão de gosto.

É a mesma coisa para o “throw” (por exemplo, "throw new FrameworkException (ex, “ABCD”); ") porque ele não é uma chamada de método.

É que muita gente boa em C/C++ costuma pôr parênteses no “return” para ficar parecido com o “for” e o “if”, que têm parênteses. (É uma cisma que tenho dos tempos do Pascal, onde você tenta não usar parênteses desnecessários até que se depara com os operadores lógicos AND e OR, que têm a mesma precedência em Pascal que os operadores * e + respectivamente, o que não é nem um pouco “natural”. Então acaba tendo um monte de parênteses em lugares esquisitos.)

B

O segundo é o melhor, de longe.

O primeiro eu não saberia saber o que faz com uma olhadela.

O terceiro parece que a pessoa não sabe que existe else if. Pior que eu já tive que dar manutenção em código em produção com isso, identado até mãe do cara.

tnaires
fantomas:
me parece que algumas linguagens não deixam vc fazer isso (return no meio fluxo) acho que Pascal é uma delas.
Em Pascal não há return. Há uma variável chamada Result cujo valor pode ser atribuído a qualquer momento dentro do corpo da função. A sua atribuição não interrompe a execução do método; o exemplo abaixo em Java
if (cnpj.isNull())
    return null;

if (cnpj instanceof CnpjValid)
    return cnpj.getCheckDigits();

return VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS);
ficaria assim em Pascal:
if cnpj.IsNull then
  Result := '' // string em Pascal não é objeto
else if cnpj is CnpjValid then
  Result := cnpj.GetCheckDigits
else
  Result := bla bla bla;
Aqui os elses são necessários pois, como falei, Result não interrompe o fluxo de execução.
diegosantiviago

Em pascal eu utilizava o nome da função para utilizar o retorno. Mas quando vira assembly, tem o result mesmo…

ViniGodoy

O result não, mas o exit sim:

if cnpj.IsNull then
begin
  Result := '' // string em Pascal não é objeto
  exit;
end;

if cnpj is CnpjValid then
begin
  Result := cnpj.GetCheckDigits
  exit;
end;

Result := bla bla bla;
O problema é que o pascal é muito mais prolixo e esse monte de begin e end começa a piorar a legibilidade. O VB também tem uma variável em cada função, mas ao invés de result, o nome dela é igual ao nome da função.
function getCpf() as String 
   if IsNull(cnpj) then
        getCpf = null
        exit function
   end if
   'etcc...etc...etc..
end function
ViniGodoy

Depende se você está usando o turbo pascal ou o object pascal.

diegosantiviago

Claro que existe o result no Pascal!

Veja:

ftp://ftp.freepascal.org/pub/fpc/docs-pdf/ref.pdf

Página 45, última linha.

tnaires

diegosantiviago:
Claro que existe o result no Pascal!

Veja:

ftp://ftp.freepascal.org/pub/fpc/docs-pdf/ref.pdf

Página 45, última linha.


Aparentemente, ninguém contestou a existência do Result.

diegosantiviago

eu tinha entendido como se ele tivesse falado que o result não existisse :slight_smile:

Lavieri

É ?? ai o cara vai, desliga o java script, ou milhões de opções… ai vem o código sujo pra dentro do teu sistema… ^^ … no way … a validação por ajax deve existir, mais como uma ferramenta a +, e não como substituição das validações do seu negocio

Lavieri

fantomas:

public static String calculateCheckDigits(Cnpj cnpj) { return (cnpj.isNull()) ? null : (cnpj instanceof CnpjValid) ? cnpj.getCheckDigits() : VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS); }

Neste caso, para utilizar essa estrutura de forma mais legivel teriamos que simplificar o máximo possível o código deste método a sugestão é fazer as seguintes perguntas:

a) Este método é necessário?
b) É necessário verificar se é nulo dentro deste método?
c) Será que uso de instanceof (neste caso) não é um indicador de que nossos objetos estão deixando de fazer alguma coisa que eles mesmos poderiam fazer?

O livro de refatoração do Mr. Martin fowler tem bastante coisas sobre este tema, vale a pena verificar.

Espero ter ajudado em alguma coisa.

flws

só respondendo…

a) esse método é necesario ^^ , principalmente para um outro chamado, createRandom() … que cria um cnpj randómico, e varios outros métodos…

b) é preciso testar se é nulo sim, o objeto Cnpj pode ter valor nulo e mesmo assim ser um objeto instanciado…

c) aqui é um atalho, pois existe uma subclasse CnpjValid, que só aceita Cnpjs válidos, não pode instanciar cnpj invalido para essas classes… e nesse caso basta retornar os proprios digitos desta classe … para as outras classes é preciso calcular… porem! troquei o instaceof, por outra checagem… que esta abaixo… com ela eu verifico se o Cnpj é valido, para qualquer instancia, e evito de recalcular os digitos

((cnpj.valid != null) && (cnpj.valid == true))
Lavieri

Depois de ler tudo… depois de ler muito artigo por ai, do pessoal contestando o único return…

acho que o melhor é utlizar mais de 1 apenas em condições de guarda… e no resto manter 1 return… e vou fazer isso… ogrigado a todo mundo ai que deu opinião ^^

jingle
vocês gostam desses "if" sem as chaves?
if (cnpj.isNull())
    return null;

if (cnpj instanceof CnpjValid)
    return cnpj.getCheckDigits();

return VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS);

eu realmente acho estranho, acho mais facil de ver quando tem as chaves...(mesmo não sendo necessarias)

if (cnpj.isNull()){
    return null;
}
if (cnpj instanceof CnpjValid){
    return cnpj.getCheckDigits();
}
return VerifierDigits.getValidDigits(cnpj, BASE_LENGTH, FACTOR, COEFICIENTS);
fantomas

No documento CodeConventions.pdf na página 11 dizem que o indicado é NÃO utilizar esta forma.

flws

tnaires

Particularmente, eu também.

M

Viva as chaves no if! :smiley:

aleck

É ?? ai o cara vai, desliga o java script, ou milhões de opções… ai vem o código sujo pra dentro do teu sistema… ^^ … no way … a validação por ajax deve existir, mais como uma ferramenta a +, e não como substituição das validações do seu negocio

Estou pra ver um sistema hoje em dia que funciona sem javascript.

Voltando ao topico, gosto de seguir o sun code convention, entao nada de tirar as perninhas dos ifs e colocar um monte de return no meio do codigo.

Andre_Fonseca

oi

passei por uma situação hoje onde eu tinha que preencher um objeto de resposta baseado em 1 ou 2 objetos de entrada..

neste caso eu teria que fazer um montão de ifs para cada objeto/campo

uma das alternativas é você usar reflection para pegar o valor da propriedade e checar qual delas nao esta nula..

aproveitei um código que já estava pronto aqui usando BeanUtils..

mas, como a estrutura dos meus objetos pode variar bastante, eu achei melhor, por conta da pressa também, fazer tudo com ifs mesmo

Resposta resp = new Resposta();
Consulta cons1 = returnConsulta1();
Consulta cons2 = returnConsulta2();

if (cons1!=null && cons1.getCampo()!=null) {
  resp.setCampo(cons1.getCampo());
}
if (cons2!=null && cons2.getCampo()1=null) {
  resp.setCampo(cons2.getCampo());
}

Operador ternário para mim fica elegante apenas quando o teste é simples

Eu faria

String valor = (obj!=null && obj.getCampo()!=null) : obj.getCampo() : "";

Mas acho complicado

Integer valor = ((obj1!=null && obj1.getCampo()!=null) || (obj2!=null && obj2.getCampo()!=null)) ? Integer.valueOf((obj1.getCampo() * obj2.getCampo())*2) :  null;

:shock:

Criado 15 de janeiro de 2009
Ultima resposta 16 de jan. de 2009
Respostas 31
Participantes 14