DEV Community

Java Efetivo (livro)
Java Efetivo (livro)

Posted on

Item 50: Faça cópias defensivas quando necessário

"Você deve programar defensivamente, partindo do princípio que os clientes de sua classe farão o melhor para destruir as invariantes dela"

Java como linguagem segura:

  • Java previne erros de memória comuns em C/C++, mas não isola totalmente as classes de interações indesejadas de outras classes.
  • Programação defensiva é necessária, assumindo que os clientes da classe podem tentar violar suas invariantes.

Classes imutáveis e segurança:

  • Exemplo de classe "Period" que parece imutável mas pode ser corrompida devido à mutabilidade de objetos como Date.
  • Solução: Fazer cópias defensivas de parâmetros mutáveis ao recebê-los no construtor.
public Period(Date start, Date end) {
    this.start = new Date(start.getTime()); // Cópia defensiva
    this.end = new Date(end.getTime());
    if (this.start.compareTo(this.end) > 0)
        throw new IllegalArgumentException(start + " after " + end);
}

Enter fullscreen mode Exit fullscreen mode

Cópias defensivas em construtores:

  • Cópias defensivas devem ser feitas antes da validação de parâmetros para evitar vulnerabilidades (ex: ataque TOCTOU).
  • Evitar usar clone() para cópias defensivas de objetos potencialmente não confiáveis, preferindo construtores ou métodos de fábrica estáticos.

Getters e mutabilidade:

  • Problema: Getters podem expor componentes internos mutáveis, permitindo mutações externas.
  • Solução: Getters devem retornar cópias defensivas de objetos mutáveis.
public Date getStart() {
    return new Date(start.getTime()); // Cópia defensiva
}

Enter fullscreen mode Exit fullscreen mode

Aplicação a classes mutáveis:

  • Cópias defensivas também se aplicam a classes mutáveis que armazenam referências a objetos mutáveis fornecidos pelos clientes.
  • Exemplo: Ao armazenar um objeto em um Set ou Map, deve-se considerar se o objeto pode ser modificado posteriormente.

Retorno de componentes internos:

  • Ao retornar componentes internos mutáveis, considere retornar cópias defensivas ou views imutáveis.

Uso de objetos imutáveis:

  • Sempre que possível, use objetos imutáveis como componentes internos para evitar a necessidade de cópias defensivas.

Custos e alternativas:

  • Cópias defensivas podem impactar a performance; alternativas incluem confiar na documentação ou em contratos claros de uso.
  • Em casos de transferência explícita de controle, como em padrões de design (ex: wrapper), a cópia defensiva pode ser dispensada.

Conclusão:

  • Use cópias defensivas para proteger a integridade das classes, exceto quando o custo for impraticável ou a confiança mútua for estabelecida, sendo necessária uma documentação clara.

Exemplos do livro:

Image description

Image description

Image description

Image description

Image description

Top comments (0)