Usando tratamento de exceções versus NSError em aplicativos de cacau
Olá a todos. Eu tenho lido sobre as sugestões da Apple para quando / onde / como usar o NSError versus @ try / @ catch / @ finalmente. Essencialmente, minha impressão é que a Apple acha melhor evitar o uso de construções de linguagem de manipulação de exceção, exceto como um mecanismo para interromper a execução do programa em situações de erro inesperadas (talvez alguém pudesse dar um exemplo de tal situação?)
Eu venho de Java, onde as exceções são o caminho a percorrer quando se quer lidar com erros. Admito que ainda estou no espaço de pensamento de Java, mas aos poucos estou tomando conta de tudo que o NSError tem a oferecer.
Uma coisa que estou pendurado é a tarefa de limpar a memória quando ocorre um erro. Em muitas situações (por exemplo, usando bibliotecas C, C ++, CoreFoundation, etc.) você tem muita limpeza de memória que precisa ser feita antes de sair de uma função devido a um erro.
Aqui está um exemplo que eu cozinhei que reflete com precisão as situações que eu tenho encontrado. Usando algumas estruturas de dados imaginárias, a função abre um identificador de arquivo e cria um objeto 'MyFileRefInfo' que contém informações sobre o que fazer com o arquivo. Algumas coisas são feitas com o arquivo antes que o identificador de arquivo seja fechado e a memória para a estrutura liberada. Usando as sugestões da Apple, tenho este método:
- (BOOL)doSomeThingsWithFile:(NSURL *)filePath error:(NSError **)error
{
MyFileReference inFile; // Lets say this is a CF struct that opens a file reference
MyFileRefInfo *fileInfo = new MyFileRefInfo(...some init parameters...);
OSStatus err = OpenFileReference((CFURLRef)filePath ,&inFile);
if(err != NoErr)
{
*error = [NSError errorWithDomain:@"myDomain" code:99 userInfo:nil];
delete fileInfo;
return NO;
}
err = DoSomeStuffWithTheFileAndInfo(inFile,fileInfo);
if(err != NoErr)
{
*error = [NSError errorWithDomain:@"myDomain" code:100 userInfo:nil];
CloseFileHandle(inFile); // if we don't do this bad things happen
delete fileInfo;
return NO;
}
err = DoSomeOtherStuffWithTheFile(inFile,fileInfo);
if(err != NoErr)
{
*error = [NSError errorWithDomain:@"myDomain" code:101 userInfo:nil];
CloseFileHandle(inFile); // if we don't do this bad things happen
delete fileInfo;
return NO;
}
CloseFileHandle(inFile);
delete fileInfo;
return YES;
}
Agora .. minha lógica Java me diz que seria melhor configurá-lo como uma estrutura try / catch / finally e colocar todas as chamadas para fechar o identificador de arquivos e liberar memória no bloco finally.
Igual a..
...
@try
{
OSStatus err = OpenFileReference((CFURLRef)filePath ,&inFile);
if(err != NoErr)
{
... throw some exception complete with error code and description ...
}
err = DoSomeStuffWithTheFileAndInfo(inFile,fileInfo);
if(err != NoErr)
{
... throw some exception ...
}
... etc ...
}
@catch(MyException *ex)
{
*error = [NSError errorWithDomain:@"myDomain" code:[ex errorCode] userInfo:nil];
return NO;
}
@finally
{
CloseFileHandle(inFile); // if we don't do this bad things happen
delete fileInfo;
}
return YES;
Estou louco em pensar que esta é uma solução muito mais elegante, com menos código redundante? Perdi alguma coisa?