Polêmica sobre uso de getters e setters para modificação dos atributos na própria classe

Eu não soube onde colocar esse tópico, então pus aqui no Assuntos Gerais.

A questão é a seguinte: aqui na empresa surgiu essa discussão e queria saber a opinião de vocês.

Temos uma classe em padrão javaBeans, que é um managed bean do JSF.

Suponha o seguinte exemplo:

[code]
public class MeuBean {

private String str;

...
public String getStr() { return this.str; }
public void setStr(String str) { this.str = str; }

}[/code]

Em métodos internos de MeuBean, é mais adequado acessar os atributos diretamente ou via getters e setters?

Ou seja, qual a melhor forma de proceder:

Esta: void Metodo() { str = "teste"; syso(str); }

Ou esta? void Metodo() { this.setStr("teste"); syso(this.getStr()); }

Abraços!

eu costumo usa sempre o getter e setter, não sei se é o certou ou não, mas se algum dia precisar ser implementado algo sempre ao obter este valor ou ao alterar,
é só i e alterar no método get/set e ja vai sair funcionando sem precisar rever o código.

essa é a mesma resposta que expressei. Estamos centralizando o acesso a variável em um único lugar. Mas sou minoria nessa opinião e comecei a imaginar se estou exagerando nesta questão.

Por isso, queria ouvir a opinião dos demais.

Valeu!

Exagero. É puro preciosismo.

Se está dentro da classe, você pode acessar os atributos privados, sem problemas. Colocar getter ou usar o atributo diretamente é discutir o sexo dos anjos.

Acho que é mto simples… Pra que foram feitos os Getters e Setters? Certamente não foram feitos apenas para controlar a visibilidade, pois se fosse o caso se controlaria a visibilidade diretamente na propriedade. Então o que sobra, na teoria, é que esses métodos devem ser usados como forma padrão de acesso a atributos da classe.
O problema acho, é que com o tempo fomos notando que eles se tornaram apenas métodos burros que a gente propaga nos nossos códigos apenas pelo simples habito(e também por auxilio das nossas IDEs). Hoje, na minha opinião, a única serventia de um método que SÓ ALTERA VALOR é facilitar o debug do desenv.

Acho que qualquer coisa que adotamos como prática sem questionar, como os getters e setters, perdem o sentido. No entanto, já tive uns dois ou três casos em que precisei alterar o jeito com o qual o get funcionava:

public getAtributo() {
    if (atributo == null) 
        atributo = recuperaAtributoDoBanco 

    return atributo;
} 

Se as chamadas ao atributo não estivessem no get, ele nunca seria inicializado. O contra-argumento usado pelos meus colegas é que, nesse evento raro, era só refatorar.

De fato, seria uma refatoração mínima, por tender a ser rara demais pra ser levada em conta. Mas eu, pessoalmente, prefiro fazer assim.

Eu também acho esse tipo de discussão a mesma coisa que decidir entre 6 e meia dúzia, porém estamos adotando uma padronização de código e este quesito entrou na jogada.

Obrigado pelas suas opiniões!

Meu “pitaco” em cima disto…

O atributo é privado para as entidade externas; internamente a visibilidade dos atributos não é restrita, logo fica um pouco sem sentido vc acessar um método que se propõe encapsular os mesmos de dentro do bean.

Caso haja código nos set/get que envolve restrição ou segurança no acesso estes deveriam estar orientados a proteger / controlar acessos externos.

Se houver outro tipo de código além destes dentro de um set/get acredito que piora um pouco mais a situação porque provavelmente o método deva estar com um nome inadequado, que não descreve realmente o que ele faz.

Por isso que é sempre bom evitar classes enormes, para entre outras coisas ficar fácil a análise; fora isso tem o editor que coloca a cor para ajudar a identificar este tipo de coisa e ainda tem o this / super para ajudar a dizer em qual contexto está o atributo / método / operação.

Minha opinião…

flws

Não há a necessidade de usar acessores internamente. Em teoria, uma classe bem encapsulada sempre tem controle sobre os seus métodos e atributos internos, então ela sempre pode alterar a sua estrutura interna sem quebrar o contrato com outras classes.

Isso significa que mesmo que tenha que mudar o uso um atributo para um acessor, o retrabalho é pequeno, exceto se você tiver um monstro gigante nas mãos. Aí perguntamos por que a tua classe tem tanta responsabilidade assim.

Isso vem da sindrome do get/set.
É normal pegar classes com get/set para todos atributos, mesmo os que so sao acesssados internamente.

Atibutos so devem ter modificadores se forem acessados de fora da classe.
Classes bem projetadas nao necessitam acessar seus proprios atributos via modificadores.

[]´s

"

o compilador entende da mesma maneira. Mas não sei se o bytecode resultante será exatamente igual. Mas ninguém se preocupa em performance com java, então, acho que é irrelevante.

Hummm gostei!!!

1 - Use o membro privado diretamente quando não há lógica na atribuição
2 - Use os métodos gets e setters quando há lógica dentro desses métodos

A priori, use sempre privado… acesso é (imperceptivelmente) mais rápido, e menos tedioso para debug…

Simples assim…

Só vejo agora um caso aonde um método vai acessar os atributos internos através de getters/setters : se for um objeto imutável e trabalhar com copias de segurança / clone() for muito redundantes, afinal esta lógica normalmente está nos metodos acima citados.

Eu faço assim… acessar o atributo com leitura normalmente diretamente… uso Getters apenas se souber que o atributo precisa de inicialização… como estou programando dentro da propria classe normalmente eu sei disso… na duvida, acesso via o getter…

O set, eu não gosto de acessar diretamente… não por kestão de visibilidade ou não… pq acredito que o local para conter a logica de modificação do atributo deve estar dentro do set… sendo assim o uso corriqueiramente dentro da minha classe…

Não preciso ficar me lembrando assim de pormenores de modificação nem dentro da propria classe… dentro do set ficam meus Constranit e o que for necessario… não se acustumar com isso, pode levar a vc dentor de 1 ponto da classe se equivocar, e modifcar um atributo que é invalido pra sua logica… trocar o atributo dentro do set, vai garantir a logica… e testar os Constraint…

Só não modifico via SET, quando a mudança é totalmente interna e não passa por intervenção externa, ou seja, o meio externo não vai fazer com que o meu objeto possa sair do estado correto, ai por questão de performance, passo direto do set, pra não checar os constraint, mais é raro, geralmente vou via set…

por exemplo meu setName(String nome) sempre testa
Consistencies.notNull(nome);
Consistencies.sizeBetewen(3,50,nome);
Consistencies.onlyLatters(nome);

ai não da, pra ficar modificando por vias normais, por isso prefiro concentrar essas logicas no set, e modificar apenas por ele…

o getter acho mais livre, desde que não seja necessario o LAZY no atributo… ai eu acesso via getters tb… sendo assim, minhas entidades acesso tudo por setter e getters ^^

Na minha opinião, esse negócio de getters e setters vem de uma deficiência do java: A falta de suporte nativo na linguagem a properties. Na verdade esse negócio de getters e setters é uma gambiarra para contornar essa limitação da linguagem.

Na minha opinião, quando usar:
De fora da classe (inclusive subclasses), sempre usar os getters e setters.
De dentro da própria classe, caso ela seja final OR caso o getter AND o setter seja final OR caso você esteja se lixando para herança e sobrescrita, usar os atributos é melhor.
Caso possa-se criar subclasses e sobreescrever-se o getter ou o setter, então é melhor você pensar duas vezes antes de acessar o atributo diretamente. Neste caso prefira sempre usar o setter e o getter para que em caso de sobrescrita, o getter/setter sobrescrito seja invocado.

EDIT: Quase que esqueço de dizer. Em construtores, sempre use os atributos. Chamar métodos que podem ser sobreescritos de dentro de construtores cria todo tipo de dor de cabeça, comportamentos estranhos e bugs que você pode imaginar.

um exemplo onde da 1 puta galho…

se vc usar Hibernate, quando vc carrega dados do banco, ele cria um proxy do seu objeto, nesse proxy, os valores são nulls, das propriedades, mas quando vc invoca via GETTERS n SETTERS os valores aparecem…

eu tinha desenhado um equals basico, e não tava dando certo, depois de debugar fui ver que era a porra do proxy do hibernate, e tive q trocar tudo pra getter em vez de acesso direto

era assim

public boolean equals(Estado other) { boolean result; if (id == null) result = (other.id != null) ? false : equalsNamePais(other); else result = id.equals(other.id); return result; } private boolean equalsNamePais(Estado other) { return nome.equals(other.nome) && pais.equals(other.pais); }

tive que fazer ficar assim

public boolean equals(Estado other) { boolean result; if (getId() == null) result = (other.getId() != null) ? false : equalsNamePais(other); else result = getId().equals(other.getId()); return result; } private boolean equalsNamePais(Estado other) { return getNome().equals(other.getNome()) && getPais().equals(other.getPais()); }

Bug do Hibernate ou é lazy loading que ele faz?

é que ele usa proxy… vou mandar 1 screen, de um teste com 2 paises, que são iguais… pode ver que o teste (a variavel result) fica true, pq estou usando os métodos GETs

porem olhe nas variaveis do depurador, que as propriedades id, e nome, são nulls para o objeto pais… pore os getters e setters funcionam … hehehe … hibernate faz isso de proxy

da uma olhanda nessa img

o hibernate guarda os valores, reais do objeto, em um objeto proprio do proxy, em uma variável chamada target, vou abrir a tree pra vc ver

ve agora nessa imagem onde esta o valor real

por essas e por outras… que so uso getters e setter … o.O

Já deram uma olhada nisso:

http://blog.caelum.com.br/2006/09/14/nao-aprender-oo-getters-e-setters/

;D

Abraços