Item 50: Faça cópias defensivas quando necessário
Java Efetivo (livro)
Posted on August 29, 2024
"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);
}
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
}
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:
💖 💪 🙅 🚩
Java Efetivo (livro)
Posted on August 29, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
career Burnout, Imposter Syndrome & More: What Junior Devs Really Experience 🕵️♀️
November 28, 2024