quarta-feira, 6 de outubro de 2010

Qualidade na Prática - Verdadeiro Encapsulamento

É interessante verificar como podemos realizar um bom encapsulamento. Um objeto recebe seus atributos através de um construtor e mudanças são apenas permitidas através de envio de mensagens.
Encapsulamento na wikipedia:
A language mechanism for restricting access to some of the object's components.
Encapsular não significa apenas criar getters e setters, como a linguagem Java, infelizmente disseminou. Ultimamente tenho adotado a prática de tornar meus objetos imutáveis. A programação fica um pouco mais complicada, entretanto, acredito que os benefícios são maiores. No tectura existem duas discussões interessantes sobre o assunto: a primeira aborda os objetos 100% imutáveis. A segunda, criada por mim, aborda técnicas para tornar um objeto imutável, principalmente quando existem atributos que são objetos de classes mutáveis.

Nos posts do tectura existem alguns exemplos, inclusive de uma solução real em que estou trabalhando.

Para ilustrar este post, vou usar o exemplo bem comum, quando precisamos usar a java.util.Date para modelar as nossas datas.

A classe da API do java, Date é mutável, isto é, depois de criada, podemos alterar o seu estado. Assim, se quisermos que uma classe que use Date em um ou mais atributos seja imutável, não podemos devolver a referência ao atributo e sim um clone ou uma cópia dele. Este é um caso clássico em que um getter simples não resolve.

No post do tectura existem duas soluções. A primeira com cópia explícita da instância, conforme eu uso normalmente. A segunda através de um clone, que não sou muito inclinado a usar, devido ao cast necessário (mais detalhes no post), fornecida pelo Sérgio Lopes. Seguem abaixo as soluções:

Cópia explícita:

public Date getDataFinal() {
    if (dataFinal != null) {
        return new Date(dataFinal.getTime());
    }
   
    return null;
}

Clone:

public Date getDataFinal() {
    if (dataFinal != null) {
        return (Date) dataFinal.clone();
    }
   
    return null;
}

Quando precisamos modelar uma classe para criar objetos imutáveis, devemos usar este tipo de técnica (ou similar) com todas as classes da API do Java que são mutáveis. O Lucas Cavalcanti em uma de suas respostas colocou o seguinte:

a regra é: devolva cópias se o atributo é mutável (Date, List e arrays são mutáveis, por exemplo)

Existe uma forma interessante de deixarmos claro que um setter, por exemplo, não deve ser usado. É só usarmos a anotação @Deprecated, como muito bem sugeriu o Alberto Souza neste outro post do Tectura. A obrigação de usar setters é imposta por alguns frameworks do mercado.

Encapsulamento com getters e setters não significa, necessariamente, encapsular. Já vi diversos códigos onde os getters e setters são apenas disfarces para atributos que estão com o modificador de acesso private, mas de fato são públicos.

Quanta importância você está dando ao encapsulamento real nas suas soluções?

Nenhum comentário:

Postar um comentário