Porque é uma má prática ter atributos int? – java orientação-a-objetos classes

Pergunta:


Vi na resposta a essa pergunta https://pt.stackoverflow.com/questions/17015/qual-o-uso-de-uma-variável-estática-ou-final-em-java/17136#17136, que:

É uma má prática ter atributos int, a menos que sejam “constantes” ou você queira simular estruturas como da linguagem C.

Por que essa é uma má pratica?

Eu desejo indexar cada objeto da minha classe com um índice único. Pra isso eu pretendo usar um contador.

private static int contador = 0;

public final int indice;

public Objeto(String nome){
        this.nome = nome;
        this.indice = contador++;
}

Haveria uma alternativa “boa prática” a essa implementação que fiz?

Eu declarei o atributo indice como public, porém final. Haveria a necessidade de fazê-lo private e um método getter, tendo em vista que o fiz final?

Autor da pergunta Pedro H. N. Vieira

Resposta Comunidade:

Boas práticas

Vou te dizer o que é mais importante sobre este assunto: inventaram uma praga na cabeça dos desenvolvedores chamada “boa prática”.

O mundo do desenvolvimento ficará muito melhor quando as pessoas pararem de falar nisso. Essa é uma forma de dizer “faz aí do jeito que eu estou falando e não discuta”. O mesmo vale pra “má prática” que é um “estou dizendo que é ruim e ponto”. Assim não precisa explicar nada. Se fosse bom ou ruim mesmo a pessoa explicaria. Assim o desenvolvedor que está lendo aquilo pode decidir por conta própria se é bom ou ruim e quando deve ou não usar.

Quase tudo que existe pode ser bom ou ruim na maioria das situações, mas sem entender o porquê, não serve pra nada. Tudo tem exceção, claro. Então falou em “boa/má prática”, fuja da resposta. Ou a pessoa não sabe do que está falando ou é tendenciosa (claro que pode ser só preguiça/pressa em responder, mas como você vai saber?).

int como atributo

Aquela resposta linkada especificamente está muito além do escopo da pergunta dela e aí cai no problema de não fazer compreender o que realmente importava.

É um completo absurdo dizer que um atributo/campo não deve ser int. Nesse caso específico eu diria que não existe uma situação sequer que impeça, crie dificuldade, e principalmente seja uma “má prática” :). Um campo pode ser int sempre que for necessário.

Claro que ele não deve ser int se não é necessário ser. Mas aí é o que eu sempre falo: o certo é fazer o certo, não é fazer o que é “boa prática”. E o certo só dá para saber no caso concreto. Toda vez que você faz o certo em algum lugar e tentar transpor isso para outra situação, está fazendo errado. Cada situação é única. Algumas coincidentemente devem ter a mesma solução.

Eu acho que a resposta queria dizer que não é bom ter um campo público exposto e se confundiu na escrita, só isso.

Sem entrar em muitos detalhes porque esta não é a questão aqui, isso é algo que pode ser ruim em várias situações, especialmente em Java, e recomenda-se usar um método getter/setter para acesso a ele. De qualquer forma a frase é bem infeliz. Não vou discutir isso aqui (mas discordo do que costuma-se dizer como verdade absoluta), o assunto é outro, mas linkei perguntas abaixo que falam sobre o assunto, se precisar de mais informações ainda pode fazer uma nova pergunta específica.

Seu exemplo

O seu caso específico está usando o contador como privado. Ok. O problema do que está fazendo é que cria uma condição de corrida em ambientes concorrentes. Você pode ter o contador aumentando em 2 ou mais antes de ser usado em cada um, aí terá dois objetos com o mesmo índice. É bem raro acontecer. E justamente por isso o dia que acontecer será bem difícil reproduzir e descobrir o porquê.

O que está fazendo não é lá uma ideia das melhores. Eu tentaria fazer de outra forma. Mas como eu não sei qual é o problema, os requisitos, qualquer coisa que eu fale soará como “boa prática”.

Getter/Setter

O indice é público. Não há problema algum ser final e public. Isto em si não cria nenhum problema. Costuma ser melhor que seu acesso seja feito por um método acessor (veja nas perguntas abaixo o porquê), mas só costuma, se não tiver nenhum motivo para isso, pode deixar como público.

Eu concordo que em Java, que é uma linguagem que não gosta muito de syntatic sugar, costuma ser uma boa ideia acessar os campos por um método para garantir a melhor manutibilidade. Se você precisar mudar a forma de acesso no futuro não precisará mudar todos os códigos que consumiram sua classe. Em outras linguagens isto pode ser mais conveniente e dar mais liberdade, se a pessoa souber o que está fazendo.

Em Java, pra expor um campos publicamente (qualquer tipo de campo) você deve ter certeza que nunca terá alterações na forma de acessá-lo. É raro ter tanta certeza assim. Mas tem casos.

O resto do que falam sobre o assunto é teoria boba.

A resposta do ramaral tem um exemplo de como fazer o acesso com um método auxiliar. Note que não tem um setter, afinal não faria sentido ter em um campo marcado como final.

Conclusão

Nunca faça nada porque alguém disse pra você que é o certo, aprenda porque é o certo. Aí pode descobrir que a pessoa que te disse isto pode estar errada.

Fez certo em questionar aqui.

Pra falar a verdade acho que nenhuma das respostas nessas perguntas mostram bem essas questão por completo, mas lendo tudo já ajuda entender e formar uma opinião própria.

Em relação a “É uma má prática ter atributos int(públicos),….” não vejo o porquê, quanto muito poder-se-á questionar se ter atributos públicos, em geral, é bom.

O caso que apresenta nada tem haver com “boa prática” mas sim com “bom senso”/funcionalidade.

Nesse exemplo, sendo final, não vejo problema em ser public, ele não pode ser modificado.
No entanto, pelo facto de em Java o uso de getter/setter estar de tal forma enraizado, pode/deve ser considerada a utilização de um getter, se necessita aceder externamente a ele.

public class UmObjeto{

    private static int contador = 0;
    private final int indice;

    public UmObjeto(String nome){
        this.nome = nome;
        this.indice = contador++;
    }

    public int getIndice(){
        return indice;
    }
}

Também faria sentido se ele fosse uma “constante da classe”, nesse caso teria de ser também static, o que não é possível neste caso.

Concorrência

Se esta classe pode ser instanciada por mais de uma thread, declare o contador como AtomicInteger para garantir a sua integridade. Exemplo:

private static AtomicInteger contador = new AtomicInteger(0);

E, para incrementar:

this.indice = contador.incrementAndGet();

Quanto a usar atributo int ou Integer

Use o int quando quiser o valor default Zero e o Integer quando quiser a capacidade de ter um atributo null.

No seu caso, se não houver execução concorrente do construtor (instância da classe por mais de uma thread), int serve muito bem.

Quanto a declarar um getter para o índice

Depende da natureza do seu objeto.

Se ele é uma simples estrutura de dados, sem muitos outros atributos, se ele carrega pouco estado, pouco ou nenhum comportamento e as mudanças de estado são simples ou inexistentes, declarar como publico em vez de usar getter serve.

Agora, se este objeto é uma entidade importante no sistema, com complexos comportamentos e mudanças de estado, eventualmente vários atributos públicos, daí um getter pode cair melhor porque a classe pode ter mais necessidade de encapsulamento, uso uniforme, consumo em várias partes do código, e sofrer muitas mudanças.

De qualquer modo este é apenas um guia pois há quem prefira sempre declarar getters e nunca expor os campos da classe publicamente – por uma questão de padronização. A padronização é útil porque se já está decidido como fazer, você não tem que gastar energia tomando a decisão a cada vez, e como o getter é o método mais seguro, por assim dizer, ele serve em todas as ocasiões.

Eu particularmente não conheço motivos contra esta padronização – só dá mais trabalho pra codificar.

Por fim, talvez valha a pena mencionar que há ferramentas que exigem que você declare getters e setters mesmo em simples estruturas de dados. Em JSF, por exemplo, você declara na classe getNome() e setNome() e no código facelets você escreve apenas objeto.nome tanto para leitura quanto para escrita.

Para fins de esclarecimento:

int é um tipo primitivo. Variáveis do tipo int armazenam o valor binário para representar o inteiro desejado. int.parseInt(“1”) não faz sentido porque int não é um objeto, portanto não tem métodos. int no java são tipos primitivos e, não criamos objetos com tipos primitivos.

Integer é uma classe. Objetos do tipo Integer armazenam referencias para outros objetos. Isto é bom, economiza memória (não tem boa prática, é fato). Isto é um exemplo de transformar uma string em um objeto Integer por meio de um método estático Integer.parseInt(“1”).

Para ser mais específico, Integer é uma classe com um único atributo do tipo primitivo int usado quando você deseja ter o poder de atribuir NULL ao objeto, não necessariamente zero. Isso é usado em diversas situações e interessante para coleções e tipos genéricos.

Aqui estão classes do padrão Wrapper para representar tipos primitivos em objetos:

byte / Byte

short / Short

int / Integer

long / Long

boolean / Boolean

char / Character

float / Float

double / Double

Essas classes estendem de Object e tipos primitivos não porque não são objetos. Para usar Generics são necessários objetos, não tipos primitivos.

Desde o Java 5 temos autoboxing e a conversão de um primitivo em objeto wrapper é feita automaticamente, porém em algumas versões específicas da JVM ocorreu problemas de desempenho nessas conversões. Talvez seja isso que alguém quis dizer com “má prática”.

Lembrando que tipos primitivos podem ser comparados com ==, enquanto objetos devem ser comparados obrigatoriamente com .equals().

Fonte

Related Posts:

Qual a diferença entre AppCompatActivity e Activity? – android android-activity
Pergunta: Qual a diferença da AppCompatActivity para Activity ? A partir de qual versão a AppCompatActivity foi adicionada ao Android? Autor da pergunta Luhhh A diferença reside ...
Como abreviar palavras em PHP? – php string
Pergunta: Possuo informações comuns como nome de pessoas e endereços, e preciso que elas contenham no máximo 30 caracteres sem cortar palavras. Exemplo: 'Avenida Natalino João Brescansin' ...
Qual é a finalidade de um parêntese vazio numa declaração Lambda? – c# expressões-lambda característica-linguagem
Pergunta: Criei um exemplo de uma declaração Lambda sem argumentos, entretanto, estou com duvidas referente a omissão do parêntese vazio () na declaração. Veja o exemplo: class ...
Boas práticas para URI em API RESTful – api rest restful
Pergunta: Estou com dúvida em relação às URIs de alguns recursos da api que estou desenvolvendo. Tenho os recursos projetos e atividades com relação 1-N, ...
Dúvidas sobre a integração do MySQL com Java – java mysql netbeans
Pergunta: Estou criando um sistema no NetBeans, utilizando a linguagem Java e o banco de dados MySQL. Escrevi o seguinte código para realizar a conexão ...
Qual é a finalidade da pasta Model do framework Inphinit? – php inphinit
Pergunta: No Inphinit micro-framework existe a pasta Model que fica dentro da pasta application, e nela é onde ficam as classes, mas eu estou muito ...
Uso do ‘@’ em variáveis – javascript typescript coffeescript
Pergunta: Vejo em algumas linguagens que compilam para javascript, como TypeScript e CoffeeScript, o uso do @ em variáveis, como também, casos em que o ...
Qual tamanho máximo um arquivo JSON pode ter? – json arquivo
Pergunta: Vou dar um exemplo para conseguir explicar minha duvida: Preciso recuperar informação de imagens vindas de uma API, esse banco de imagens me retorna JSON's ...
O que é Teste de Regressão? – terminologia engenharia-de-software testes
Pergunta: Na matéria de Teste de Software o professor abordou um termo chamado Teste de Regressão, isto dentro da disciplina de teste de software. Sendo ...
O que é um construtor da linguagem? – php característica-linguagem
Pergunta: Em PHP, já li e ouvi várias vezes a respeito dos Construtores da Linguagem. Os casos que sempre ouvi falar deles foi em casos ...
Função intrínseca para converter numérico para string – cobol
Pergunta: Estou a tentar saber se existe alguma função intrínseca do COBOL para converter um data numérico para string sem precisar usar a cláusula REDEFINES: ( ...
Porque usar implements? – java android
Pergunta: Qual a diferença entre usar btn.setOnClickListener(new OnClickListener() { e public class MainActivity extends Activity implements OnClickListener{ Estive fazendo um curso de Android e meu professor falou que ...
O que é XHTML e quando deve ser usado? – html xml xhtml
Pergunta: O que eu sei é que o XHTML precisa ser XML válido. Isso implica, por exemplo, que todas as tags precisam ser fechadas. Por ...
Uma placa aceleradora de vídeo pode melhorar o desempenho não-gráfico? [fechada] – desempenho
Pergunta: Para desenvolver em Ruby on Rails, eu utilizo aqui uma máquina virtual do VirtualBox com Ubuntu Server 14.04 sem interface gráfica instalada. Recentemente descobri uma ...
Concat() VS Union() – c# .net
Pergunta: Qual a diferença entre Concat() e Union() ? Quando usar Concat() e quando usar Union() ? Somente pode ser usado em list ? ...

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *