Como não aprender Java e Orientação a Objetos: getters e setters

Postado em 14. set, 2006 por em Arquitetura, Java

Atualização 2012: conheça o novo curso online da Caelum Aprimorando a Orientação a Objetos com Java.

Muitas pessoas perguntam “como aprender OO?“. Há várias maneiras de aprender OO, creio que não tenha uma melhor, mas existem maneiras de não aprender.

Uma das práticas mais controversas que aprendemos no início é a geração indiscriminada de getters e setters. Os exemplos básicos de centenas de tutoriais java estão recheados com getters e setters da pior espécie: aqueles que não fazem sentido algum. Considere:

class Conta {
  double limite;
  double saldo;
}

Rapidamente os tutoriais explicam o private para o encapsulamento. Mas aí como acessar? Getters e setters nela!

class Conta {
  private double limite;
  private double saldo;

  public double getSaldo() {
    return saldo;
  }

  public void setSaldo(double saldo) {
    this.saldo = saldo;
  }

  public double getLimite() {
    return limite;
  }

  public void setLimite(double limite) {
    this.limite = limite;
  }
}

Qual é o sentido desse código? Para que esse setSaldo? e esse setLimite? e o getLimite? Você vai usar esse métodos? Nunca crie um getter ou setter sem sentir uma real necessidade por ele. Isso é uma regra para qualquer método, mas particularmente os getters e setters são campeões: muitos deles nunca serão invocados, e grande parte do restante poderia ser substituído por métodos de negócios. Códigos do tipo conta.setSaldo(conta.getSaldo() + 100) se espalharão por todo seu código. Segue então a nossa classe Conta reformulada de acordo com essa necessidade:

class Conta {
  private double saldo;
  private double limite;

  public Conta(double limite) {
    this.limite = limite;
  }

  public void deposita (double x) {
    this.saldo += x;
  }

  public void saca(double x) {
    if(this.saldo + this.limite >= x) {
      this.saldo -= x;
    }
    throw new IllegalArgumentException("estourou limite!");
  }

  public double getSaldo() {
    return this.saldo;
  }
}

E nem estamos falando de test driven development! Testando a classe Conta rapidamente você perceberia que alguns dos getters e setters anteriores não têm uso algum, e logo sentiria falta de alguns métodos mais voltados a lógica de negócio da sua aplicação, como o saca e o deposita acima. Esse exemplo é muito trivial, mas você pode encontrar por aí muitas classes que não tem a cara de um java bean que expõem atributos como Connection, Thread , etc, sem necessidade alguma!

Existem sem dúvida práticas piores: utilização de ids para relacionar os objetos, arrays não encapsuladas como estruturas, código fortemente baseado em comparação de Strings hardcoded (que o Guilherme Silveira sarcasticamente carinhosamente batizou de POS, ou programação orientada a strings), milhares de métodos estáticos, entre outros. Todas essas práticas são muito comuns quando estamos começando a quebrar o paradigma procedural, e confesso já ter sido um grande praticante de muitas delas. Um professor sempre me disse que você só vai utilizar bem o paradigma da orientação a objetos depois de errar muito.

O Phillip Calçado tem um artigo simplesmente incrível que de certa forma aborda esse tema: classes fantoches (puppets). Uma classe fantoche é a que não possui responsabilidade alguma, a não ser carregar um punhado de atributos! Onde está a orientação a objetos? Uma grande quantidade de classes fantoches são geradas quando fazemos Value Objects, entidades do hibernate, entre outros.

Mas o que colocar nas minhas entidades do hibernate e nos meus VOs além de getters e setters?“. Antes de tudo, verifique se você realmente precisa desses getters e setters. Para que um setID na sua chave primária se o seu framework vai utilizar reflection ou manipulação de bytecode para pegar o atributo privado, ou se você pode passá-la pelo construtor? Sobre value objects, você realmente precisa dos seus setters? Em muitos casos VOs são criados apenas para expor os dados, e não há necessidade alguma para os setters… bastando um bom construtor!

No hibernate costumo colocar alguns métodos de negócio, algo parecido como na classe Conta. Minhas entidades possuem uma certa responsabilidade, em especial as que dizem respeito aos atributos pertencentes a elas.

Para quem ainda está aprendendo, a apostila da caelum de java e orientação a objetos tem algumas dessas discussões e procura ensinar OO comentando sempre dessas más práticas, como por exemplo o uso de herança sem necessidade.

Paulo Silveira

Mais sobre o autor

Tags: , , , ,

78 Respostas para “Como não aprender Java e Orientação a Objetos: getters e setters”

  1. Araceli

    27. abr, 2011

    Excelente conteúdo, o pior de tudo é ter visto e participado de projetos desorientados. rs…
    Mas sempre vão existir erros deste tipo, que atire a primeira pedra quem ainda não cometeu este pecado. rs…

  2. Ótimo post. Realmente aprendemos a colocar getters e setters de qualquer maneira, seu post me abriu os olhos. Obrigado!!!

  3. Rael Max

    06. jul, 2011

    Quando estudei OO na faculdade essa foi a coisa me eu mais questionei nas aulas. Getters e Setters demais. :)

  4. Flávio Correia Lima

    19. jul, 2011

    Olá, não tenho muita experiência com Java. Começando a estudar mais a fundo agora. Fiquei com uma dúvida à respeito dos getters e setters. Além de prover acesso aos atributos esses métodos auxiliam no encapsulamento. Se eu quiser alterar a forma como acesso ou como altero o atributo a alteração ocorre apenas em um lugar (no getter ou setter). Quando você deixa de construir esses métodos você não está abrindo mão do encapsulamento? Se você precisar (em um momento futuro) alterar a forma de acesso você vai poder criar um getter ou setter, entretanto, terá que modificar em todos os lugares onde está acessando o atributo. Existe alguma saída pra isso (como o uso de properties em Python, por exemplo)?
    Abraços

  5. Pedro

    30. ago, 2011

    Ótimo post,
    Desde a época da facul nunca entendi o real motivo desses gets and sets, não programo em java ainda, porem é bem semelhante com o que acontece no C#, na vdd no C# faz menos sentido ainda…….kkkkk
    são coisas totalmente dispensaveis, tipo se vc observar alguns códigos……vc notará que as vezes para fazer uma simples tarefa que seria possivel realizar-la com 2 variaveis……a pessoa utiliza 2 ou 3 métodos com mais variaveis declaradas dentro dos métodos……….tipo não consigo entender pq as pessoas fazem isso……kkkkk
    Parabens pelo post + 1 vez….
    vlew

  6. Rodrigo

    02. set, 2011

    Interessante, mas o título está incorreto.

    No caso de programas escritos em Java, a maior motivação para getters and setters é a especificação Java Beans, a qual diversos frameworks se baseiam para acessar propriedades dos objetos.

    Com isso, algumas vezes precisamos SIM criar getters and setters, mesmo que apenas para referenciarmos “propriedades” na camada de apresentação ou para fazer o mapeamento objeto relacional (JPA, por exemplo, requer as entidades com construtor default, fazendo uso de setters para setar as propriedade dos objetos).

    A questão chave não é “como não aprender Java e OO”, e sim apresentar Java como sendo limitada em não suportar uma noção de propriedades mais elegante (como suportada por Scala ou C#).

  7. Paulo Silveira

    02. set, 2011

    Olá Rodrigo

    Na nossa opinião (e de alguns autores), o título não está incorreto.

    Na JPA, que você mencionou, não precisa de getters e setters para acessar propriedades dos objetos (seção 2.1, “The persistent state of an entity is represented by instance variables, which may correspond to JavaBeans properties” Seção 2.2 “The persistent state of an entity is accessed by the persistence provider runtime either via JavaBeans style property accessors (“property access”) or via instance variables (“field access”)“). Ela usa diretamente os atributos privados, como no Hibernate. Logo não há necessidade alguma de programar com esse monte de getter e setter. Bom é ter apenas os métodos necessários, os de lógica de negócio, pro seu objeto não acabar sendo apenas um punhado de dados, como uma estrutura qualquer.

    Mesmo se precisasse, aí é uma limitação do framework, e não da linguagem/OO. E OO em si não devemos ensinar baseado no que um framework obriga ou não você a fazer. Aliás, quanto mais obrigações um framework te impõe, mais acoplado ele é.

    Também não há relação com propriedades mais elegantes. Mesmo com propriedades, devemos tomar cuidado para não permitir reads/writes por default, e sim só se fizer muito sentido. Propriedades e getters/setters representam o mesmo problema se usados indiscriminadamente

    Como você disse, e como está escrito no próprio post, há casos em que os getters e setters são necessários sim. Mas não devem virar um hábito do programador.

  8. Rodrigo

    05. set, 2011

    Olá Paulo,

    > E OO em si não devemos ensinar baseado no que um
    > framework obriga ou não você a fazer.

    Concordo, mas o problema reside no modelo de propriedades seguido pela linguagem Java, e que desenvolvedores de frameworks ou de aplicações precisam se basear. Inclusive, essa noção de getters and setters está disseminada em Java (especificação Java Beans), não sendo seguido no ensino de outras linguagens OO (basta ler boas referências de Smalltalk, C++, …., Scala).

    Claro que Java é uma linguagem relevante (tenho mais experiência em Java, falar mal, é dar um tiro no meu próprio pé), mas seu processo de evolução está muito lento- e esse modelo de propriedades precisa ser repensado (conforme indicaram nas discussões iniciais sobre Java 7, apesar de terem evoluido pouco nesse sentido).

    Ao meu ver, sem “assumptions” como getters and setters (ou, de preferência, um modelo de componentes / propriedades de mais alto nível), fica difícil desenvolver frameworks com qualidade (pelo menos eu não considero o acesso direto a fields uma boa alternativa).

  9. Infax

    23. set, 2011

    Flávio, creio que você está assumindo que, sem getters e setters o programador tornaria os atributos públicos. Não é o que está sendo sugerido no artigo. O artigo sugere que alguns atributos são usados apenas para cálculos internos ou devem ser acessados com lógicas um pouco mais rebuscadas que um simples getter. O exemplo de método “saca” é um caso desses em que o valor do atributo saldo pode ser alterado sem usar o setter, mas usando um método que faz sentido dentro da lógica do negócio.

  10. Adams Zago

    19. out, 2011

    Sempre ouvimos dizer que, os métodos get e set devem possuir alguma razão de existir. Eu realmente concordo com isso. Logo fica uma dúvida. Numa aplicação JSF em que tenho uma lista de determinado objeto, a atualização desta lista deveria estar no get ou em outro método? Estando no get estaria ferindo algum padrão? Piorando a performance?

  11. Jesse James

    04. jan, 2012

    Parece que tem gente que não sabe ler. O artigo não é contra o uso de getters e setters, ele condena o uso indiscriminado. Os getters e setters são úteis mas devem ser usados de acordo com as regras do negócio, e respondendo a alguns que perguntaram: encapsulamento não é apenas ocultar atributos, mas tornar eles acessíveis apenas para satisfazer a aplicação, o exemplo citado emula o funcionamento de uma conta bancaria real onde não se atribui um valor a um saldo, mas esse valor é alterado via atividades inerentes à atividade bancaria como depositar e retirar dinheiro.

  12. Paulo Silveira

    04. jan, 2012

    Jesse, exatamente!!! É um alerta para a criação indiscriminada, que ocorre frequentemente.

  13. Marcelo Nalon

    18. jan, 2012

    Olá, também não tenho muita experiência com Java e estou apenas começando, mas concordo com o nosso amigo Flávio. No que eu aprendi até hoje, os métodos get e set servem para manter uma boa engenharia de software, uma vez que é mais fácil manter códigos que fazem uso deles. Pense numa classe bem grande que tenha vários métodos que utilizam um determinado atributo. Se por ventura for necessário por exemplo fazer uma modificação no nome do atributo, seria necessário alterar o nome em todos os métodos que utilizam esse atributo também. Usando get e set só seria necessário alterar o nome do atributo nesses dois métodos.

  14. Paulo Silveira

    18. jan, 2012

    Olá Marcelo

    Um simples refactoring de nome de atributo resolve esse problema com um clique. Nao é para nao ter de renomear um atributo que voce deve usar um getter/setter. Getter e setter só é bom se realmente faz sentido pro seu modelo, entao depende do domínio.

    Cria uma classe cheia de getter e setters, automaticamente, é um péssimo hábito em relação a engenharia de software. Aqui tem uma discussão mais aprofundada:
    http://www.arquiteturajava.com.br/livro/cuidado-com-o-modelo-anemico.pdf

  15. Marcelo Nalon

    18. jan, 2012

    Sim, é verdade… mas isso se você estiver usando uma IDE né.
    Interessante, no livro do Deitel, ele cita uso dos getters e setters como uma boa prática, por isso é sempre bom buscar mais de uma fonte de referência.
    Você tem esse livro disponível em pdf??

  16. Paulo Silveira

    19. jan, 2012

    oi Marcelo. o livro tem pra vender online:
    http://www.arquiteturajava.com.br

    o Deitel é enxuto em algumas partes de design. Receitas de bolo devem ser executadas com cautela.

  17. winstrol

    13. fev, 2012

    A melhor informação essencial é isto, que você tentar fazer muito bem para que o corpo se aproximando sem-teto e suas mão amiga. Estou tão inspirada quanto a isso, após ler o seu esta escrito artigos úteis e as suas opiniões sobre blog.caelum.com.br também que é tão atraente para fazer alguma coisa para aqueles

Trackbacks/Pingbacks

  1. Fragmental » Mais (ou melhor: menos!) Getters e Setters - setembro 19, 2006

    [...] O Paulo Silveira postou há uns dias no blog da Caelum um artigo sobre o uso indiscriminado de getters e setters, incluindo uma referência para o artigo daqui do Fragmental sobre “classes de dados”. [...]

  2. blog.caelum.com.br » Como não aprender orientação a objetos: Herança - outubro 14, 2006

    [...] Já falei sobre os problemas que os getters e setters podem trazer, caso usados de maneira indiscriminada. A bola da vez é a herança. [...]

  3. blog.caelum.com.br » Relacionamento bidirecional entre classes - março 28, 2007

    [...] Isso tudo pode ser muito mais complicado em relacionamentos 1:N e N:M. O conselho é tentar evitar o relacionamento bidirecional, e nunca cria-lo sem uma real necessidade, assim como já comentamos sobre evitar herança e evitar getters e setters. [...]

  4. » JustJava 2007, Arquitetura e Caelum » blog.caelum.com.br - outubro 8, 2007

    [...] Toda vez que uma classe de domínio é criada em um sistema como esses, suas irmãs também aparecem: BOs, VOs, LOs, XYZs. Utilizar TOs apenas para transportar objetos entre camadas (e não tiers) não faz sentido algum, polui o código e diminui flexibilidade e manutenção. Separar funcionalidade e dados entre BOs e VOs é outro grande problema: onde está a orientação a objetos? Entity beans apenas com getters e setters é um mau sinal. [...]

  5. O momento em que Java quase virou .Net e C++ ao mesmo tempo « Objectzilla - outubro 24, 2007

    [...] Estou convencido de que nunca na história desse país, o uso de gettes e setters foi tão criticado. E isso porque uma classe com apenas getters e setters não é muito diferente de uma struct no [...]

  6. O uso indiscriminado de getters e setters! « TJRN Developers - fevereiro 9, 2008

    [...] criar uma classe com seus atributos e colocar automaticamente todos os getters/setters possíveis. Este post da Caelum trata justante do uso indiscriminado de getters e [...]

  7. marcuscavalcanti » Blog Archive » Getters e Setters? - janeiro 14, 2009

    [...] código. Links InteressantesFowler e GettersGetter ErradictorWhy getter and setter methods are evilComo não aprender Java e orientação a objetosSHARETHIS.addEntry({ title: “Getters e Setters?”, url: [...]

  8. O que é encapsulamento? « S A B E R E S - maio 5, 2011

    [...] a leitura de um post no blog da caelum que explica sobre a criação de getters e setters, clique aqui para acessá-lo. É isso aí galera, espero que tenham gostado e não deixem de comentar. Até a [...]

  9. Scala: os cuidados com encapsulamento | blog.caelum.com.br - julho 26, 2011

    [...] A criação de getters e setters deve ser feita com cuidado: uma vez que a implementação é exposta através de um getter e setter, a remoção dele, para finalmente encapsulá-lo, implica na mudança de todas as chamadas a ele. Em Ruby, o mesmo cuidado pode ser tomado: [...]

  10. REFACTORING – Caso Real e boas maneiras Parte IV (Keep Walking…) « Yuri Adams - novembro 27, 2011

    [...] privilégio. Então é isso, mais um caso prático de como melhorar seu código. Excelente dica: Como não aprender OO com java. Excelente post da [...]

  11. POO – Material Complementar | Material de Acompanhamento – UFS - dezembro 3, 2011

    [...] Como não aprender Java e Orientação a Objetos: getters e setters Como não aprender orientação a objetos: o excesso de ifs Como não aprender orientação a objetos: Herança [...]

Deixar uma Resposta