У вас всегда есть альтернативы получше.
В C # ссылочным типам может быть присвоено null
values. Это то, с чем разработчикам придется жить, пока они не начнут использовать классы для создания программного обеспечения. К сожалению, сотрудники Microsoft не могут просто запретить null
присвоение ссылочным переменным во время компиляции, потому что это нарушит кодовую базу почти каждого проекта.
Возвращение нуля - плохая практика
Что на самом деле не так с возвратом null
reference из метода?
Давайте посмотрим на этот простой метод:
FirstOrDefault
method молча возвращает null
, если в базе данных не найден порядок.
Здесь есть пара проблем:
- Вызывающие
GetOrder
method должны реализовать проверку нулевых ссылок, чтобы избежать полученияNullReferenceException
при доступе к членамOrder
class. Но как вызывающий должен знать, как правильно реализовать обработку ошибок? Должен ли вызывающий объект генерировать исключение, если он получает нулевую ссылку или возвращает код ошибки? - Когда каждый вызывающий объект реализует логику проверки самостоятельно, она будет дублироваться, и высока вероятность того, что логика не будет согласованной для всех вызывающих. Это нарушение принципа DRY.
- Получение
null
value неоднозначно для вызывающей стороны, потому что здесь не сказано, возвращается ли значение null из-за ошибки или из-за того, что порядок не был найден в базе данных. Возвратnull
определенно не является подходом к дизайну, ориентированному на предметную область. - Возврат
null
часто является нарушением принципа программирования быстро сбой.null
может появиться из-за какой-то проблемы в приложении. Проблема может даже перейти в рабочую среду, если разработчик не реализовал надлежащую обработку исключений, которая может помочь быстро обнаружить проблему.
Разработчики могут сделать несколько вещей, чтобы улучшить ситуацию, например использовать ссылочные типы, допускающие значение NULL, создать исключение или использовать шаблон проектирования нулевого объекта.
Использовать ссылочные типы, допускающие значение NULL
Если разработчику действительно нужно вернуть null
value из метода (в 99% случаев это не обязательно), тип возвращаемого значения можно пометить как ссылочный тип, допускающий значение NULL (функция была введена в C # 8.0).
Пометка возвращаемого типа как обнуляемого дает два основных преимущества:
- В сигнатуре метода четко указано, что он может возвращать пустую ссылку. Таким образом, вызывающие абоненты точно знают, что им необходимо реализовать обработку ошибок, просто взглянув на сигнатуру метода.
- Компилятор выдаст предупреждение, если вызывающий получает доступ к членам
Order
class без предварительной проверкиnull
reference.
Быстро потерпите неудачу, выбрасывая исключение
Принцип отказоустойчивости - важный принцип в разработке программного обеспечения. Идея довольно проста - как только приложение обнаруживает проблему (пустая ссылка), оно должно сгенерировать исключение.
Неправильное orderId
может быть вызвано следующими причинами:
- Библиотека автоматического сопоставления неправильно настроена для сопоставления
orderId
values. - Какой-то код случайно присвоил
orderId
variable неправильное значение перед вызовомGetOrder
method. - Интерфейс не передает идентификаторы заказов на сервер.
Каждая описанная причина - это ошибка в приложении. Таким образом, согласно принципу быстрого сбоя, как только система обнаруживает, что orderId
недействителен, она должна сгенерировать исключение.
Самый простой способ создать исключение для заказов, которые не найдены, - использовать First
method вместо FirstOrDefault
в реализации.
Но у нас есть другая проблема: вызывающие абоненты получат InvalidOperationException
без какой-либо ценной информации, потому что это обычное исключение .NET. Решением для этого является введение настраиваемого типа исключения, которое разработчик должен выдать, если заказ не был найден в базе данных.
Подводя итог преимуществам подхода с настраиваемыми исключениями:
- Шансы на обнаружение и устранение проблем до развертывания производственной среды намного выше.
- Вызывающий абонент получит подробную информацию о проблеме, что упростит процесс устранения неполадок.
Использовать шаблон проектирования нулевого объекта
Другой способ избежать возврата null
- использовать шаблон проектирования объекта Null.
Нулевой объект - это объект без поведения, подобный заглушке, который разработчик может вернуть вызывающей стороне вместо возврата null
value.
Вызывающему не нужно проверять порядок на наличие нулевого значения, потому что возвращается реальный, но пустой Order
object.
Шаблон нулевого объекта следует внимательно рассматривать как альтернативу генерации исключения. Использование шаблона противоречит принципу быстрого сбоя.
Этот шаблон следует использовать только тогда, когда вызывающие абоненты в противном случае проверяли бы объект на null
, чтобы пропустить доступ к его членам.
Заключение
Вывод прост - никогда не возвращайте пустые ссылки из ваших методов.