Uma das práticas mais controversas que aprendemos no início do aprendizado de muitas linguagens orientadas a objeto é 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:
{
limite;
saldo;
}
Autor(a)
Paulo Silveira
Paulo Silveira é CEO e cofundador da Alura. Bacharel e mestre em Ciência da Computação pela USP, teve sua carreira de formação em PHP, Java e nas maratonas de programação. Criou o Guj.com.br, o podcast do Hipsters.tech e o Like a Boss.
Inscreva-se em nossa Newsletter
Fique por dentro de conteúdos, insights e oportunidades do universo tech. Receba novidades e lançamentos direto no seu e-mail.
class
Conta
double
double
Rapidamente os tutoriais explicam o private para o encapsulamento. Mas aí como acessar? Getters e setters nela!
Qual é o sentido desse código? Para que esse setSaldo? e esse setLimite? e o getLimite? Você vai usar esses 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 e deveria 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, o que pode ser muito nocivo: como você vai logar aumentos de saldo, se a forma de alterar saldo de uma conta está espalhada por todo seu sistema?
Tirar dinheiro gera uma situação ainda mais delicada: se precisar verificar se há saldo na conta antes de subtrair um valor do saldo, onde ficará esse if? Espalhado por todo o sistema em diversos pontos? O que acontecerá quando precisar alterar essa regra de negócio?
Segue então a nossa classe Conta reformulada de acordo com essa necessidade:
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 sentiria falta de alguns métodos mais voltados a lógica de negócio da sua aplicação, como o saca e o deposita.
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 batizou de POS, ou programação orientada a strings), milhares de métodos estáticos, entre outros.
Todas essas práticas são comuns quando estamos começando a quebrar o paradigma procedural e confesso já ter sido um grande praticante de algumas. Você só vai utilizar bem o paradigma da orientação a objetos depois de errar muito.
O Phillip Calçado aborda esse tema, chamando essas classes de 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/JPA/ORM 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! Dessa forma evitamos um modelo de domínio anêmico.
No hibernate, e em outros ORMs, 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, há um artigo de POO da Alura que aborda mais sobre o assunto.
Vale relembrar que o exemplo é apenas didático. Trabalhar com dinheiro exige inúmeros cuidados, como não usar double. O foco desse post é para você parar para pensar antes de criar o getter e o setter. E, claro, pode ser que o seu caso justifique a criação desses métodos.
Esse post, criado em 2006 e atualizado em 2017 e depois em 2022, mostra como o design de classes continua seguindo algumas regras de boas práticas importantes. Fundamentos e conceitos são sim essenciais na nossa carreira.