Prática recomendada - domínios e códigos NSError para seu próprio projeto / aplicativo

114

Há uma postagem anterior do SO sobre a configuração de domínios de erro para seus próprios frameworks, mas qual é a prática recomendada em relação à configuração de domínios de erro e códigos de erro personalizados para seu próprio projeto / aplicativo ?

Por exemplo, supondo que você esteja trabalhando em um aplicativo com uso intensivo de Core Data com muitas validações, você deve apenas ficar com os códigos de erro de Core Data "prontos para uso" (como NSManagedObjectValidationErrorde CoreDataErrors.h) ou criar seus próprios MyAppErrors.he definir erros com mais especificidade (ou seja MyAppValidationErrorInvalidCombinationOfLimbs,?

Criar um domínio de erro personalizado e um conjunto de códigos de erro pode eliminar a ambigüidade de seu código significativamente, mas é uma sobrecarga muito grande para manter e é preciso se preocupar com conflitos de numeração de código de erro? Ou existem outras preocupações aqui?

Neal L
fonte

Respostas:

152

Eu pessoalmente uso um domínio de estilo DNS reverso. Por exemplo:

NSError * myInternalError = [NSError errorWithDomain:@"com.davedelong.myproject" code:42 userInfo:someUserInfo];

A terceira parte do domínio ( @"myproject") é usada apenas para diferenciar os erros deste projeto ( "My Project") dos erros de outro projeto ( "My Other Project"=> com.davedelong.myotherproject).

É uma maneira simples de garantir que não vou entrar em conflito com os domínios de erro de outra pessoa (se estiver usando código de terceiros), a menos que o desenvolvedor esteja propositalmente tentando mexer apenas com me (que eu acredito que seria altamente improvável. ..).

Quanto aos conflitos de numeração de código, não se preocupe com isso. Contanto que os códigos sejam exclusivos dentro de um domínio , você deve estar bem.

Quanto a erros de tradução, isso depende de você. Faça o que fizer, certifique-se de documentar bem. Pessoalmente , geralmente passo adiante os erros gerados pelo framework conforme eles chegam até mim, já que nunca tenho certeza de que vou lidar com todos os códigos e traduzir todas as informações do usuário em algo mais específico para o meu projeto. As estruturas podem alterar e adicionar mais códigos ou alterar o significado dos códigos existentes, etc. Isso também me ajuda a identificar mais especificamente de onde veio o erro. Por exemplo, se minha estrutura StackKit gerar um erro no com.stackkitdomínio, sei que é um problema de estrutura. No entanto, se gerar um erro no NSURLErrorDomain, então sei que veio especificamente do mecanismo de carregamento de URL.

O que você poderia fazer é capturar o erro quadro gerado e envolvê-la em um novo objeto de erro que tenha o seu domínio e de um código genérico, algo como kFrameworkErrorCodeUnknownou algo assim, e em seguida, coloque o erro capturado na userInfosob a NSUnderlyingErrorKey. CoreData faz muito isso (por exemplo, se você tentar save:um NSManagedObjectContext, mas tiver erros de integridade de relacionamento, receberá um único erro de volta, mas NSUnderlyingErrorKeyconterá muito mais informações, como especificamente quais relacionamentos estão errados, etc).

Dave DeLong
fonte
Como a apple também usa DNS reverso, parece apropriado que outros usem esse estilo também.
Johan Karlsson
36

Não tenho representante suficiente para comentar, mas para a resposta aceita por Dave DeLong, pode ser um pouco melhor usar em [[NSBundle mainBundle] bundleIdentifier]vez de @"com.myName.myProject". Dessa forma, se você alterar o seu nome ou o nome do projeto, ele será refletido com precisão.

Connor
fonte
4
Boa ideia. Se você estiver usando o Swift, deve usar o opcional desembrulhado: NSBundle.mainBundle().bundleIdentifier!(se você souber que o identificador do pacote está definido, o que eu acho que será o mais provável)
Juul
Por que você deseja refletir as alterações de nome do projeto no domínio de erro?
zrslv 01 de
1
@zrxq Certamente há valor em ter domínios de erro diferentes, mas imagine que você digitou incorretamente seu projeto ou mudou seu nome e deseja que ele seja refletido em todos os lugares. É melhor defini-lo dinamicamente do que codificado.
Connor
1
@vare Isso está claro, eu realmente não entendo quais benefícios práticos isso traria. Meu entendimento é que esses identificadores só precisam ser únicos no contexto do aplicativo, só isso. Ok, talvez você só queira que eles sejam esteticamente mais agradáveis, entendi!
zrslv 05 de
1
Sim, você trouxe um bom ponto. Há momentos em que você deseja que o domínio seja exclusivo, eu presumo ... por exemplo, talvez se você criar um SDK ou pod (cacau), você gostaria que seu domínio de erro refletisse de onde veio, não o do projeto nome. EDIT: Eu também (em minha resposta) gostaria de apontar que @ "com.myName.myProject" é idêntico ao bundleIdentifier neste caso, que as pessoas podem não saber.
Connor
4

Como criar um NSError personalizado:

Primeiro crie um Dicionário da mensagem de erro

NSDictionary *userInfo = @{   
   NSLocalizedDescriptionKey: NSLocalizedString(@"Unknown Error - Please try again", nil),
   NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"Unknown Error - Please try again", nil),
   NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Unknown Error - Please try again", nil)
                                               };
NSError *error = [NSError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] 
  code:-58 userInfo:userInfo];

Em seguida, atribua userInfo ao NSDictionary e pronto.

Mike Zriel
fonte