Лучшая практика - домены и коды NSError для вашего собственного проекта / приложения

114

Есть предыдущая публикация SO о настройке доменов ошибок для ваших собственных фреймворков, но как лучше всего настроить домены ошибок и пользовательские коды ошибок для вашего собственного проекта / приложения ?

Например, предположим, что вы работаете над приложением, интенсивно использующим Core Data, с большим количеством проверок, следует ли вам просто придерживаться готовых кодов ошибок Core Data (например, NSManagedObjectValidationErrorот CoreDataErrors.h) или создать свои собственные MyAppErrors.hи определять ошибки с помощью больше конкретики (т. е. MyAppValidationErrorInvalidCombinationOfLimbs?

Создание настраиваемого домена ошибок и набора кодов ошибок может значительно устранить неоднозначность кода, но не слишком ли много накладных расходов для обслуживания и нужно ли беспокоиться о конфликтах нумерации кодов ошибок? Или здесь есть другие проблемы?

Нил Л
источник

Ответы:

152

Я лично использую домен в стиле обратного DNS. Например:

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

Третья часть домена ( @"myproject") используется только для того, чтобы отличать ошибки этого проекта ( "My Project") от ошибок другого проекта ( "My Other Project"=> com.davedelong.myotherproject).

Это простой способ убедиться, что я не собираюсь конфликтовать с чужими доменами ошибок (если я использую сторонний код), если только этот разработчик целенаправленно не пытается связываться только со мной (что, я считаю, маловероятно. ..).

Что касается конфликтов нумерации кодов, не беспокойтесь об этом. Если коды в домене уникальны , все должно быть в порядке.

Что касается ошибок перевода, решать вам. Что бы вы ни делали, обязательно хорошо документируйте это. Лично я обычно просто передаю ошибки, сгенерированные фреймворком, по мере их появления, поскольку я никогда не уверен, что обработаю все коды и переведу все данные userInfo в нечто более специфичное для моего проекта. Фреймворки могут изменяться и добавлять больше кодов, или изменять значение существующих кодов и т. Д. Это также помогает мне более точно определить, откуда возникла ошибка. Например, если мой фреймворк StackKit генерирует ошибку в com.stackkitдомене, я знаю, что это проблема фреймворка. Однако, если в файле возникает ошибка NSURLErrorDomain, значит, я знаю, что это произошло именно из-за механизма загрузки URL-адреса.

Что вы можете сделать, так это зафиксировать ошибку, сгенерированную фреймворком, и обернуть ее в новый объект ошибки, содержащий ваш домен и общий код, что-то вроде kFrameworkErrorCodeUnknownили что-то в этом роде, а затем поместить зафиксированную ошибку в файл userInfoпод NSUnderlyingErrorKey. CoreData делает это часто (например, если вы попытаетесь save:создать NSManagedObjectContext, но у вас есть ошибки целостности отношений, вы получите одну ошибку, но она NSUnderlyingErrorKeyбудет содержать гораздо больше информации, например, какие именно отношения неверны и т. Д.).

Дэйв Делонг
источник
Поскольку Apple также использует обратный DNS, другим кажется уместным использовать этот стиль.
Йохан Карлссон
36

У меня недостаточно комментариев, чтобы прокомментировать, но для принятого ответа Дэйва ДеЛонга, возможно, было бы немного лучше использовать [[NSBundle mainBundle] bundleIdentifier]вместо @"com.myName.myProject". Таким образом, если вы измените свое имя или название проекта, оно будет отображаться точно.

Коннор
источник
4
Отличная идея. Если вы используете Swift, вам следует использовать развернутый необязательный параметр: NSBundle.mainBundle().bundleIdentifier!(если вы знаете, что идентификатор пакета установлен, что, я думаю, будет наиболее вероятно)
июл
Зачем вам нужно отражать изменения имени проекта в домене ошибок?
zrslv 01
1
@zrxq Конечно, есть смысл иметь разные домены ошибок, но представьте, что вы неправильно написали свой проект или изменили свое имя, чтобы оно отражалось повсюду. Лучше установить динамически, чем жестко.
Коннор
1
@vare Это ясно, я действительно не понимаю, какие практические преимущества это принесет. Насколько я понимаю, эти идентификаторы просто должны быть уникальными в контексте приложения, вот и все. Хорошо, может быть, вы просто хотите, чтобы они были более эстетичными, я понял!
zrslv
1
Да, вы подняли хороший вопрос. Бывают случаи, когда вы хотите, чтобы домен был уникальным, я бы предположил ... например, возможно, если вы создаете SDK или (какао) Pod, вам нужно, чтобы ваш домен ошибок отражал то, откуда он появился, а не проект название. РЕДАКТИРОВАТЬ: Я также (в своем ответе) хотел указать, что @ "com.myName.myProject" в этом случае идентичен bundleIdentifier, о котором люди могут не знать.
Коннор
4

Как создать собственный NSError:

Сначала создайте словарь сообщения об ошибке

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];

Затем назначьте userInfo NSDictionary и готово.

Майк Зриэль
источник