class Pedido { public String comprador; public double valorTotal; // outros atributos} |
class Pedido { private String comprador; private double valorTotal; // outros atributos public String getComprador() { return comprador; } public void setComprador(String comprador) { this.comprador = comprador; } public double getValorTotal() { return valorTotal; } public void setValorTotal(double valorTotal) { this.valorTotal = ValorTotal; } // outros getters e setters} |
Pedido está nesse momento, podemos fazer coisas como:Pedido p = new Pedido();// muda valor do pedido para 200 reais!p.setValorTotal(p.getValorTotal() + 200.0); |
Agora imagine que a regra de negócio do pedido mude: todo item comprado ganha desconto de 5% se o valor dele for superior a 1000 reais. Implementar essa mudança não será tarefa fácil. Precisaríamos fazê-la em diferentes classes do sistema.
Quanto tempo demoraremos para mudar o sistema? Não sabemos exatamente aonde devemos fazer as mudanças já que elas estão espalhadas pelo código. Esse, aliás, é um dos grandes problemas de códigos legados: uma simples mudança precisa ser feita em tantas classes e, na prática, sempre esquecemos algum ponto, e nosso sistema frequentemente quebra.
A classe
Pedido não foi bem desenhada. Demos acesso direto ao atributo valorTotal, um atributo importante da classe. Veja que o modificador private
nesse caso não adiantou de nada, já que demos também um setter para
ele. Vamos tentar diminuir o acesso ao atributo, criando métodos mais
claros para a operação de depósito:class Pedido { private String comprador; private double valorTotal; // outros atributos public String getComprador() { return comprador; } public double getValorTotal() { return valorTotal; } public void adiciona(Item item) { if(item.getValor() < 1000) this.valorTotal += item.getValor(); else this.valorTotal += item.getValor() * 0.95; }} |
Pedido, faremos uso desse novo comportamento:Pedido p = new Pedido();p.adiciona(new Item("Chuveiro Elétrico", 500.0)); |
Item item = new Item("Super Geladeira", 1500.0);// antigaif (item.getValor() > 1000) { c1.setValorTotal(c1.getValorTotal() + item.getValor() * 0.95);}else { c1.setValorTotal(c1.getValorTotal() + item.getValor());}// novac1.adiciona(item); |
Quando sabemos O QUÊ um método faz (igual ao método
adiciona, sabemos que ele adiciona um ítem no pedido, por causa do nome dele), mas não sabemos exatamente como ele faz, dizemos que esse comportamento está encapsulado!A partir do momento que as outras classes não sabem como a classe principal faz o seu trabalho, significa que as mudanças ocorrerão apenas em um lugar! Afinal, elas estão escondidas (encapsuladas)!
Ou seja, para implementar a regra de negócios nova, bastaria mexermos em um único lugar:
public void adiciona(Item item) { if (item.getValor() > 1000) this.valorTotal += item.getValor(); else this.valorTotal += item.getValor() * 0.95; // nova regra de negócio aqui} |
private é esconder acesso de
atributos que precisam ser acessados de maneira mais inteligente. Mas
veja que de nada adianta colocar todos os atributos como private e criar getters e setters para todos eles. Deixamos o encapsulamento “vazar” do mesmo jeito.Esconda os atributos, mas pense em comportamentos inteligentes para acessá-los. Uma ótima maneira para saber se o comportamento está encapsulado é olhar para o código que faz uso dele! Se conseguirmos dizer
o que o método faz, mas sem dizer como ele faz, então podemos afirmar que o comportamento está encapsulado!Muitas vezes deixamos esses princípios passarem. Se quiser revisitar essas e outras boas práticas de Orientação a Objetos junto com os instrutores da Caelum, há mais posts por aqui, como um específico sobre esse problema dos getters e setters, o excesso de ifs e o relacionamento bidirecional entre classes.
Fonte: blog.caelum.com.br
Nenhum comentário:
Postar um comentário