"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:
Top comments (0)