Fowler e Getters

Martin Fowler escreveu um belo artigo em seu Bliki sobre getters e encapsulamento. Em Getter Erradication Fowler começa falando sobre como a prática de evitar getters a todo custo confunde o sentido real de encapsulamento e termina dando uma ‘rule of thumb‘ (uma regrinha rápida para ser aplicada por padrão) para identificar se uma classe possui seu encapsulamento violado.

Acho que Martin vai direto no ponto quando fala de encapsulamento não é simplesmente quebrado pelo uso de getters, apesar de ser uma boa prática não oferecer métodos get/set (ou seu equivalente em outra linguagem de programação) se você não precisa deles.

O termo ‘Information Hiding’ é usado como se os dados de um sistema fossem privados à um objeto só, como se apenas apra aquele objeto esta informação fosse importante.

Por mais que faça sentido evitar que objetos “saibam demais”, este não é o real objetivo do encapsulamento. O sistema é feito para manipular dados, que foram inseridos pelo usuário, estes dados geralmente não são nada secretos nem deveriam ser. O ponto em encapsular um objeto é apenas evitar que sua implementação fique exposta e esconder dados de acesso externo é apenas uma consequência disso.

Como este é um assunto recorrente em fóruns e listas, vamos a um pequeno exemplo para ajudar a entender melhor…


class Telefone{
private String ddi;
private String ddd;
private String numero;
private String ramal;

public String getNumero(){
String t = "";

if(ddi!=null) t = t + "+"+ddi;
if(ddd!=null) t = t + "("+ddd+")";
t= t + numero;
if(ramal !=null) t = t + " RAMAL " +ramal;
return t;
}

}

Se você olhar bem, o método getNumero() retorna todos os dados privados. O objetivo de fazê-los privados aqui não é esconder esta informação, o objetivo é esconder que quem implementou a classe quis separar cada componente do número de telefone por algum motivo. Pode ser que outro subsistema precise apenas de todos os DDDs registrados.

Não haveria problema real em expôr os atributos como públicos exceto pelo fato que cada um que os consulte iria precisar montar a String, e que se essa decisão de design tiver que mudar (por exemplo, eliminando o ramal) você vai ter alterar todos os objetos que a utilizam.

Recentemente eu vivi uma situação que ilustra este tipo de coisa na prática. Eu tinha um objeto ‘Recurso’ num sistema de gerenciamento de tarefas. este objeto recebia tarefas e as listava.

Acontece que quanto mais tarefas forem assignadas, mais a lista crescia. Para a maioria das funcionalidades eu só precisava das tarefas que ainda não haviam sido completadas mas estas estavam na mesma lista que as completadas. Essa decisão manteve o design simples enquanto foi possível ser mantida. Neste cenário eu poderia simplesmente liberar o acesso à minha lista de tarefas, afinal nada ali era ’secreto’.

Acontece que quando o objeto fosse salvo e carregado do banco de dados o consumo de memória ia ser absurdamente alto pela lista de tarefas que o Recurso carregava. A solução óbvia foi mantêr mais de uma lista de tarefas, na verdade foi dividido em três: tarefas concluídas, tarefas em execução e tarefas futuras.

Por mil motivos, havia um método getTarefas() que retornava uma lista ordenada com odas as tarefas do Recurso, compeltas ou não. Se ao invés deste método houvesse acesso direto á lista de tarefas (vazando o fato de que eu usava uma lista para as tarefas) eu estaria em maus lençóis. Como o encapsulamento ajuda foi muito fácil transformar o método para que, ao invés de retornar a lista, retornasse uma concatenação das três listas (não que isso tenha uma performance boa…).

Ao não expôr minha decisão de ter uma lsita de tarefas eu não precisei expôr o fato que eu mudei este design. Para as classes que a utilizam, a classe continua com a mesma cara de sempre.

E se você está cansado de ver classes que só têm um bando de get/set dê uma olhada neste artigo.

2 Responses to “Fowler e Getters”

  1. [...] são dois exemplos simples que mostram o quanto encapsulamento é importante. Você não precisa de objetos para ter encapsulamento (apesar de que se você tem objetos deveria [...]

  2. [...] o motivo do uso desses pares, antes mesmo de sairmos usando de forma desenfreada.Links InteressantesFowler e GettersGetter ErradictorWhy getter and setter methods are evilSHARETHIS.addEntry({ title: “Getters e [...]