DEV Community

Java Efetivo (livro)
Java Efetivo (livro)

Posted on

2 1 1 1 1

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

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more