Definição
- Um objeto deve permanecer em um estado utilizável e bem definido mesmo após lançar uma exceção durante uma operação.
- Métodos que garantem que o objeto não será alterado após uma falha possuem atomicidade de falha.
Métodos para obter atomicidade de falha
Objetos Imutáveis
- A atomicidade é inerente a objetos imutáveis porque seu estado não pode ser alterado após a criação.
Exemplo:
// Exemplo simplificado de um objeto imutável
public final class ImmutableObject {
private final int value;
public ImmutableObject(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
Validação de Parâmetros Antes da Operação
- Verificar a validade dos parâmetros antes de modificar o objeto.
Exemplo:
// Verificação de estado em um método Stack.pop()
public Object pop() {
if (size == 0) {
throw new IllegalStateException("Stack is empty");
}
Object result = elements[--size];
elements[size] = null; // Evitar vazamento de memória
return result;
}
Ordenação de Operações
- Garantir que partes passíveis de falha ocorram antes de alterar o estado do objeto.
Exemplo:
// Adicionando elemento em TreeMap (simulação)
public void addElement(TreeMap<String, Integer> map, String key, Integer value) {
if (key == null || value == null) {
throw new IllegalArgumentException("Key or value is null");
}
map.put(key, value); // Falhas na comparação ocorrem antes de alterar a estrutura
}
Cópias Temporárias
- Realizar operações em uma cópia temporária do objeto e substituir o original somente se a operação for bem-sucedida.
Exemplo:
// Simulação de operação em cópia temporária
public void sortList(List<Integer> list) {
List<Integer> temp = new ArrayList<>(list);
try {
Collections.sort(temp);
list.clear();
list.addAll(temp);
} catch (Exception e) {
// A lista original permanece intacta
}
}
Código de Recuperação
- Reverter o estado de um objeto ao original em caso de falha.
- Geralmente usado em estruturas de dados persistentes.
Exemplo:
public void updateRecord(Database db, Record record) {
Record backup = db.getRecord(record.getId()); // Fazer backup
try {
db.update(record);
} catch (Exception e) {
db.update(backup); // Reverter em caso de falha
}
}
Exceções Notáveis
- Erros irreparáveis como ConcurrentModificationException ou AssertionError:
- A atomicidade de falha não é garantida e nem necessária.
Custo e Complexidade
- Nem sempre é prático implementar a atomicidade de falha, especialmente em operações complexas ou de alto custo.
Boa Prática
- Métodos devem documentar o estado do objeto após uma falha se não garantirem atomicidade.
Resumo Final
- Recomendação: Toda exceção que faça parte da especificação de um método deve deixar o objeto no mesmo estado anterior à invocação.
- Exceções: Quando isso não for possível ou prático, a documentação da API deve ser clara sobre os impactos no estado do objeto.
Top comments (0)