Autoencapsulamento – quando o esforço é válido?

Facebook
VKontakte
share_fav

O encapsulamento de dados é um princípio central na orientação a objetos. Isso quer dizer que os campos de um objeto não devem ser expostos publicamente. Em vez disso, todos os acessos de fora do objeto deveriam ser via métodos de acesso (getters e setters). Existem linguagens que permitem campos acessíveis ao público, mas geralmente advertimos que os programadores não façam isso. Autoencapsulamento vai um passo adiante, indicando que todo o acesso interno a um campo de dados também deve passar por métodos de acesso. Somente os métodos de acesso devem tocar os dados. Se o campo de dados não estiver exposto ao exterior, isso significará adicionar acessores privados adicionais.

Aqui está um exemplo de uma classe Java razoavelmente encapsulada:

Classe charge
  private int units;
  private double rate;  public Charge(int units, double rate) {
    this.units = units;
    this.rate = rate;
  }
  public int getUnits() { return units; }
  public Money getAmount() { return Money.usd(units * rate); }

Ambos os campos são imutáveis. O campo de unidades é exposto a clientes da classe por meio de um getter, mas o campo de taxa é usado apenas internamente. Portanto, não precisa de um getter.

Aqui está uma versão usando autoencapsulamento:

Classe ChargeSE
  private int units;
  private double rate;  public ChargeSE(int units, double rate) {
    this.units = units;
    this.rate = rate;
  }
  public int getUnits()    { return units; }
  private double getRate() { return rate; }
  public Money getAmount() { return Money.usd(getUnits() * getRate()); }

Autoencapsulamento significa que getAmount precisa acessar ambos os campos através de getters. Isso também significa que eu tenho que adicionar um getter para rate, que eu deveria fazer privado.

Encapsular dados mutáveis geralmente é uma boa ideia. Funções de atualização podem conter código para executar validações e lógica consequente. Ao restringir o acesso através de funções, podemos apoiar o UniformAccessPrinciple, o que nos permite esconder quais dados são computados e quais são armazenados. Esses acessores nos permitem modificar as estruturas de dados, mantendo a mesma interface pública. As linguagens diferem em detalhes do que é “externo” para um objeto por vários tipos de AccessModifier, mas a maioria dos ambientes suporta encapsulamento de dados até certo ponto.

Eu passei por algumas organizações que trabalhavam com autoencapsulamento obrigatório e usá-lo ou não era um tema regular de debate desde a década de 90. Seus defensores disseram que o encapsulamento foi um benefício, que você gostaria de incorporá-lo ao acesso interno também. Os críticos argumentaram que foi uma cerimônia desnecessária que levou a um código desnecessário que obscureceu o que estava acontecendo.

Minha opinião sobre isso é que na maioria das vezes há pouco valor no autoencapsulamento. O valor do encapsulamento é proporcional ao escopo do acesso a dados. Classes são geralmente pequenas (pelo menos as minhas são), então acesso direto não será um problema dentro desse escopo. A maioria dos acessores são atribuições simples para o setter e de recuperação para o getter, por isso há pouco valor em usá-los internamente.

Mas há circunstâncias comuns em que o autoencapsulamento vale o esforço. Se houver lógica no setter, então é aconselhável considerá-lo para todas as atualizações internas também. Outra circunstância é quando a classe é parte de uma estrutura de herança, caso em que os acessores fornecem valiosos pontos de hook para subclasses para substituir o comportamento.

Portanto, o meu primeiro passo usual é usar o acesso direto aos campos, mas refatorar usando Campo de autoencapsulamento se as circunstâncias o exigirem. Muitas vezes, as forças que me levam a considerar autoencapsulamento eu posso resolver, extraindo uma nova classe.

Leitura adicional

Kent Beck discute essas compensações sob os nomes Acesso Direto e Acesso Indireto em Implementation Patterns e Smalltalk Best Practice Patterns.

Agradecimentos

Ian Cartwright, Matteo Vaccari e Philip Duldig comentaram os rascunhos deste artigo.

***

Martin Fowler faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela Redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://martinfowler.com/bliki/SelfEncapsulation.html

ver iMasters