Legibilidade do Código X Variável Temporária [RESOLVIDO]

12 respostas
M

Bom dia

Estou aqui fazendo um exercício de um agenda, na verdade refazendo…
E ai veio uma duvida pois dei uma olhada sobre como melhorar a legibilidade do codigo e ter desempenho

E ai queria uma ideia de vocês…

Tenho esse codigo

public void mostrar() {

		StringBuilder lista = new StringBuilder();
		int contador = 1;
		//int tam_Max = lista_Telefone.size();

		for (String telefone : lista_Telefone) {
			lista.append(contador + "=" + telefone).append(
					(contador < lista_Telefone.size()) ? " --- " : " ");
			contador++;
		}

		System.out.println(lista);
	}

O que seria melhor, usar uma variavel temporaria para se ter o valor do array e ficar mais facil de entender a comparação?

Ou usar

lista_Telefone.size()
este comando para não ter que utilizar variáveis temporárias?

Obrigado

12 Respostas

Rodrigo_Sasaki

usar uma variável local não vai afetar a sua performance. e vai melhorar a sua legibilidade.

Eu acho muito mais fácil quando é possível ler uma linha de código como um texto, não que a chamada a size() seja muito verbosa, mas quanto mais simples melhor, na minha opinião.

e também caso você ache que chamar size() pode afetar a performance, por sempre invocar um método, não se preocupe porque size é um atributo da classe ArrayList, é como se estivesse invocando um getter.

então resumidamente, fica a seu critério :slight_smile:

Agora eu acho listaTelefones ou até telefones melhor do que lista_Telefone :slight_smile:

M

Pois é, com a variável temporária eu acesso apenas uma vez essa função, deixo mais legivel o codigo para alguma outra pessoa…

Falta de criatividade é foda aqui kkkk

As vezes me falta uma boa definição para um nome de atributo ou metodo ou qualquer coisa

Obrigado

drsmachado

digaoneves:

Agora eu acho listaTelefones ou até telefones melhor do que lista_Telefone :)

Concordo.
Especificação javaBeans:
Nomes de variáveis começam com $, _ ou letras em minúsculo e, caso o nome seja a concatenação de mais de uma palavra, as palavras são agrupadas e a primeira letra da segunda palavra em diante, será sempre maiúscula, sem o uso de _ entre as palavras.
listaTelefone
nomeDeUmaVariavelComNomeMuitoMaiorDoQueRealmenteEPrecisoEUsual

rmendes08

Eu faria assim:

public void mostrar() {
    StringBuilder lista = new StringBuilder();
    int contador = 1;
    int tamanhoLista = listaTelefones.size();

    for (String telefone : lista_Telefone) {
        lista.append(contador + "=" + telefone);
                        
        if(contador < tamanhoLista){
            lista.append(" --- ");
        }else{
            lista.append(" ");
        }

        contador++;
    }

    System.out.println(lista);
}

Em Java, em convenção não usar o _ (underscore) para nomes de variáveis. Ao invés disso, use o famoso CamelCase.

Preocupe-se primeiro com a legibilidade e simplicidade do seu código. Otimize se necessário. Em 90% dos casos, otimizações estão ligadas ou à complexidade do algoritmo, utilização de recursos de I/O ou concorrência. Muito raramente variáveis locais degradam o desempenho da sua aplicação.

Particularmente, eu não gosto de abusar do operador ternário. Eu acho ele interessante para expressões simples e que aparecem em uma única linha, por exemplo:

String simNao = variavelBoolean ? "Sim" : "Não";

mas não gosto de colocar no meio de outras expressões.

M

essa eu não sabia sobre o uso de underscore, obrigado!

Rodrigo_Sasaki
rmendes08:
Eu faria assim:
public void mostrar() {

		StringBuilder lista = new StringBuilder();
		int contador = 1;
		int tamanhoLista = listaTelefones.size();

		for (String telefone : lista_Telefone) {
			lista.append(contador + "=" + telefone);
                        
                        if(contador < lista_Telefone.size()){
                           lista.append(" --- ");
                        }else{
                           lista.append(" ");
                        }

			contador++;
		}

		System.out.println(lista);
	}
Acho que você esqueceu de alterar o código inteiro, atribuiu o size() à uma variável local, porém não mudou o if :)
macario1983:
Pois é, com a variável temporária eu acesso apenas uma vez essa função
O que eu quis dizer é que você não vai sentir uma diferença na performance nesse caso, por isso fica a seu critério invocar o método sempre, ou atribuir à uma variável local. Apesar de que eu concordo que atribuir à uma variável local deixa o código mais legível.
ErickRAR
rmendes08:
Eu faria assim:
public void mostrar() {

		StringBuilder lista = new StringBuilder();
		int contador = 1;
		int tamanhoLista = listaTelefones.size();

		for (String telefone : lista_Telefone) {
			lista.append(contador + "=" + telefone);
                        
                        if(contador < lista_Telefone.size()){
                           lista.append(" --- ");
                        }else{
                           lista.append(" ");
                        }

			contador++;
		}

		System.out.println(lista);
	}

Acho que você esqueceu de utilizar o tamanhoLista. :)

Deixa, já arrumou...

sergiotaborda

macario1983:
Bom dia

Estou aqui fazendo um exercício de um agenda, na verdade refazendo…
E ai veio uma duvida pois dei uma olhada sobre como melhorar a legibilidade do codigo e ter desempenho

E ai queria uma ideia de vocês…

Tenho esse codigo

public void mostrar() {

		StringBuilder lista = new StringBuilder();
		int contador = 1;
		//int tam_Max = lista_Telefone.size();

		for (String telefone : lista_Telefone) {
			lista.append(contador + "=" + telefone).append(
					(contador < lista_Telefone.size()) ? " --- " : " ");
			contador++;
		}

		System.out.println(lista);
	}

Em geral o uso de variáveis locais, como já foi dito, é irrelevante para a performance porque o compilador vai acabar removendo todas elas(fazendo inline).

Contudo ha exceções a esta regra e vc caiu nela. Não é correto utilizar variáveis para substituir campos de objetos. Isso significa deixar OOP e ir para programação procedural.

Mas já que o seu problema é legibilidade e performance existem outras coisas com que se preocupar no seu código.

esta linha

lista.append(contador + "=" + telefone)

Deveria ser :

lista.append(contador).append("=").append(telefone)

Deixa mais claro o que vc está fazendo e usa um builder só. Ah! sim, use StringBuilder e não StringBuffer.
Um StringBuilder/Buffer não é uma lista. Use um nome mais adequado.

Outro ponto é o uso de um contador com for extendido. Isto é sintoma de que não deveria estar usando o for extendido.

Este outro código faz o mesmo, com menos variáveis, e como não usa o operador ternário é simples de ler

public void mostrar() {

		StringBuilder texto= new StringBuilder();
	
		for (int contador = 1, Iterator<String> it = telefones.iterator() ; it.hasNext();  contador++) {

                        final String telefone = it.next();

			texto.append(contador)
                        .append("=")
                        .append(it.next());

                         if (it.hasNext()){
                               texto.append(" --- ");
                         }
		}

		System.out.println(texto);
	}

Agora é claro que vc quer colocar um separador entre os itens e é claro que vc está criando um texto. O contador está onde deveria, dentro do for e será descartado no final, assim com o iterator. É claro que poderíamos escrever direto para o out em vez do stringbuilder, mas não esse o ponto aqui.
Mais direto ao ponto, usamos uma variável para explicitar o que é it.next. É um telefone. Isso é boa prática. Veja que porque está definida dentro do for esta variável será descartada no final do for, então ela não pesa. E como é final o compilador fará o inline. É preciso lembrar aqui que cada vez que vc usa {} você está definindo um escopo. Variáveis criadas dentro do escopo são eliminadas no final.
Colocar o final ali ou não, não é uma questão de gosto, colocar o final indica que vc está preocupado com a semantica e não apenas com a lógica.É como se o final significasse “estou definindo um nome para isto, mas não muda a logica”. Muita gente acha que o final só serve para declarar constantes, mas constantes são sempre estáticas (final static é uma constante, final sozinho não). O final serve para declarar que o valor não será alterado, sim, mas também serve para declarar variáveis que só existem para dar nome às coisas. E os nomes são o que torna o código legível.

Moral da história:

  1. Use variáveis semanticas
  2. Use-as no escopo certo
  3. Atributos já são variáveis semânticas ( não precisa de usar outra variável semântica)

Só um adendo ao 3)

Imagine que tem o codigo

ItemPedido item = ...

final String nomeCliente = item.getPedido().getCliente().getNome();

É errado usar “nomeCliente” aqui ? Pela regra 3), a principio sim. Contudo aqui vc estaria cometendo um erro pior se não usasse.
É que a chamada encadeada (chamada telescópica é o nome técnico) é um erro de design. Então o programador é forçado a usar isso porque o designer não pensou direito nas coisas. Aí o programador usar um variável semântica para simplificar o código. Isto é um uso licito de variável semântica e a exceção à regra 3.

M

sergiotaborda:

Contudo ha exceções a esta regra e vc caiu nela. Não é correto utilizar variáveis para substituir campos de objetos. Isso significa deixar OOP e ir para programação procedural.

Poderia me citar exemplos de exceções?

Mas já que o seu problema é legibilidade e performance existem outras coisas com que se preocupar no seu código.

Cara estou usando hashmap, então ficar um pouco mais complicado usar o Padrao Iterator…mas foi uma boa ideia

Eu ja tinha reparado no livro do Fowler ele usa as variáveis como final, só que n entendia…

Estes dias li que o final tanto serve para n estender e parece que melhora o desempenho do código…

sergiotaborda

macario1983:
sergiotaborda:

Contudo ha exceções a esta regra e vc caiu nela. Não é correto utilizar variáveis para substituir campos de objetos. Isso significa deixar OOP e ir para programação procedural.

Poderia me citar exemplos de exceções?

Assim de cabeça só me lembro dessa (não use variaveis para renomear atributos) e a outra seria não redefinir parâmetros. Básicamente a regra é : o que já tem nome, não renomeie. E a exceção à regra é a chamada telescópica.

:shock: :shock: No seu código não tem nenhum Map.
Além disso mapas também são iteráveis. O código se aplica na mesma basta mudar a coleção que está sendo iterada , no caso de Map pode ser map.values(), map.keys() ou map.entrySet()

Aplique mesmo se estiver usando Map.

M

Durante ao ler seu post eu mexia no codigo eu vi que a posibilidade de trabalhar seria usando ou key ou value do map…

Eu não usei o Iterator por preguiça mesmo kkkkk…pq o for aprimorado me apresenta mais facil…

So 1 coisa…

for (int contador = 1, Iterator<String> it = telefones.iterator() ; it.hasNext();  contador++)

Não sei pq mas da erro este trecho de codigo no Eclipse, ai eu tenho que declarar a variavel contato acima do laço…

Mas muito obrigado Sergio pelas ideias!

Sempre bom ter um codigo diferente pra se visualizar…

Vlw

regis_hideki

macario1983:
sergiotaborda:

:shock: :shock: No seu código não tem nenhum Map.
Além disso mapas também são iteráveis. O código se aplica na mesma basta mudar a coleção que está sendo iterada , no caso de Map pode ser map.values(), map.keys() ou map.entrySet()

Aplique mesmo se estiver usando Map.

Durante ao ler seu post eu mexia no codigo eu vi que a posibilidade de trabalhar seria usando ou key ou value do map…

Eu não usei o Iterator por preguiça mesmo kkkkk…pq o for aprimorado me apresenta mais facil…

So 1 coisa…

for (int contador = 1, Iterator<String> it = telefones.iterator() ; it.hasNext();  contador++)

Não sei pq mas da erro este trecho de codigo no Eclipse, ai eu tenho que declarar a variavel contato acima do laço…

Mas muito obrigado Sergio pelas ideias!

Sempre bom ter um codigo diferente pra se visualizar…

Vlw

Tenta substituir o último ponto e vírgula por uma vírgula:

for (int contador = 1, Iterator<String> it = telefones.iterator() ; it.hasNext(),  contador++)
Criado 24 de julho de 2012
Ultima resposta 24 de jul. de 2012
Respostas 12
Participantes 7