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?

questionAnswers(4)

yourAnswerToTheQuestion