Arhn - архитектура программирования

Должен ли метод поиска возвращать значение null или выдавать исключение, если он не может произвести возвращаемое значение?

Я использую язык Java, у меня есть метод, который должен возвращать объект, если он найден.

Если он не найден, я должен:

  1. вернуть ноль
  2. выбросить исключение
  3. разное

Что лучше всего или идиома?


  • Что бы вы ни делали, обязательно задокументируйте это. Я думаю, что этот момент более важен, чем какой именно подход лучше. 07.10.2008
  • Это зависит от преобладающих идиом языка программирования. Пометьте этот вопрос тегом языка программирования. 02.10.2009
  • Возврат null может означать только успех или неудачу, что очень часто не содержит большой информации (некоторые методы могут давать сбой по-разному). Библиотеки должны лучше генерировать исключения, чтобы сделать ошибки явными, и таким образом основная программа может решить, как обрабатывать ошибку на более высоком уровне (в отличие от встроенной логики обработки ошибок). 20.08.2013
  • Мне кажется, что реальный вопрос, который задают, заключается в том, следует ли считать исключительным, если сущность не обнаружена, и если да, то почему? На самом деле никто не ответил достаточно, как прийти к такому выводу, и теперь вопросы и ответы закрыты. Очень жаль, что индустрия не пришла к консенсусу по этой важной теме. Да, я знаю, это зависит. Итак, объясните, почему это зависит от большего, чем если бы исключительное, бросьте 09.08.2018

Ответы:


1

Если вы всегда ожидаете найти значение, тогда вызовите исключение, если оно отсутствует. Исключение будет означать, что возникла проблема.

Если значение может отсутствовать или присутствовать, и оба значения допустимы для логики приложения, верните значение NULL.

Более важно: что вы делаете в других местах кода? Последовательность важна.

06.10.2008
  • @Ken: +1, было бы неплохо упомянуть, что если вы генерируете исключение, но можете обнаружить его априори (например, HasItem (...)), тогда пользователь должен предоставить указанный метод Has * или Contains. 07.10.2008
  • Если вы выбрасываете исключения в методах модели, это заставляет разработчика разрабатывать блоки try / catch из вызывающей области, что гарантирует, что процедуры, вызывающие эти методы модели, обрабатываются должным образом из этой области. В противном случае разработчик мог делать все, что хотел. Если хотите, считайте это интерфейсом для вызова методов модели. Если данных нет, скорее всего, вам все равно придется найти обходной путь. 30.05.2014
  • Вместо того, чтобы возвращать значение или ноль, если значение отсутствует, рассмотрите возможность возврата элемента Maybe ‹T›. См. mikehadlow.blogspot.nl/2011/01/monads -in-c-5-might.html. 29.09.2015
  • При использовании @ErwinRooijakkers способа выбора дизайна, начиная с Java 8, вы также можете вернуть Необязательно ‹T› 27.01.2016
  • Перед лицом двусмысленности возникает соблазн выбрать один подход и последовательно придерживаться его. Я считаю, что мы должны хорошенько подумать, какой из них более уместен, и судить об этом в индивидуальном порядке. В этом случае похожие по контексту случаи можно обрабатывать согласованным образом, и определение контекста выходит за рамки рассмотрения типов возвращаемых значений. 08.09.2016
  • Меня это немного беспокоит, каждый ответ повторяет одну и ту же пословицу: «Если что-то особенное, брось». Большинство инженеров знакомы с этим принципом. На мой взгляд, реальный вопрос здесь в том, как определить, следует ли считать это исключительным. OP ищет передовой опыт, например, в отношении чего-то вроде шаблона репозитория. Считается ли обычно исключительным, что объект не существует с заданным первичным ключом? Да, это то, что будет определять его сфера деятельности, но что предлагают большинство экспертов с многолетним опытом? Вот какой ответ мы должны увидеть. 09.08.2018
  • Кажется, это действительно вопрос личного мнения. Люди говорят о том, чтобы оставаться последовательными, но ответы здесь даже непоследовательны. Некоторые думают, что это правильно, а другие думают, что вы должны вернуть null. И хотя проект вашей команды может оставаться последовательным, в тот момент, когда вы начнете использовать чужую библиотеку, вы можете столкнуться с несогласованностью, потому что не были определены четкие отраслевые требования для этого распространенного сценария. Если значение может отсутствовать или присутствовать, и оба действительны ... return null Я бы ответил на это с помощью Q, как следует определить, действительны ли оба? 09.08.2018
  • @crush Я думаю, что руководящим принципом является какие параметры передаются функции. Если вы передаете идентификатор, например, упоминаете первичный ключ, то это следует считать исключительным, если этот элемент не найден, потому что указывает на несогласованное состояние в системе. Пример: GetPersonById(25) будет сгенерирован, если этот человек был удален, но GetPeopleByHairColor("red") вернет пустой результат. Итак, я думаю, что параметры что-то говорят об ожиданиях. 01.11.2018
  • Последовательность важна! 01.02.2019

  • 2

    Выбрасывайте исключение только в том случае, если это действительно ошибка. Если ожидается, что объект не существует, верните значение null.

    В противном случае это вопрос предпочтения.

    06.10.2008
  • Я не согласен. Вы можете генерировать исключения как коды состояния: NotFoundException 16.10.2017
  • Конечно, это не должно быть вопросом предпочтений. Вот как мы получаем несогласованный код - если не в коде вашей команды, то почти наверняка при переплетении кода других разработчиков с вашим собственным (внешними библиотеками). 09.08.2018
  • Я думаю, что обработка нулевого случая намного проще, чем NotFoundException. Подумайте, сколько строк try-catch вам нужно написать вокруг каждого отдельного запроса на повторное получение, которое вызывает NotFoundException ... Мне больно готовить весь этот код на моих глазах. 09.08.2018
  • Я хотел бы процитировать Тони Хора: я называю это своей ошибкой на миллиард долларов. Я бы не возвращал null, я либо генерирую исключение и обрабатываю его правильно, либо возвращаю пустой объект. 09.09.2019

  • 3

    Как правило, если метод всегда должен возвращать объект, используйте исключение. Если вы ожидаете случайного появления null и хотите обработать его определенным образом, используйте null.

    Что бы вы ни делали, я настоятельно не рекомендую третий вариант: возвращать строку с надписью «WTF».

    06.10.2008
  • Плюс один, потому что в старые добрые времена я делал это более пары раз в качестве быстрого грязного временного исправления ... плохая идея. Особенно, если его собираются пересмотреть, если вы студент. 13.03.2014
  • Я собирался проголосовать против, так как варианты WTF показались мне потрясающими ... но, видимо, у меня есть сердце 23.09.2015
  • бросить новый WtfExcepti????n 16.01.2018
  • Я думаю, было бы полезно, если бы в этом ответе говорилось о причинах, по которым метод всегда будет возвращать объект, а не случайное значение null. Что оправдывает такую ​​ситуацию? Приведите пример того, когда может существовать такое обстоятельство. 09.08.2018

  • 4

    Если null никогда не указывает на ошибку, просто верните null.

    Если значение null всегда является ошибкой, вызовите исключение.

    Если null иногда является исключением, запрограммируйте две процедуры. Одна процедура выдает исключение, а другая - это логическая тестовая процедура, которая возвращает объект в выходном параметре, а процедура возвращает ложь, если объект не был найден.

    Трудно злоупотребить рутиной Try. Очень легко забыть проверить значение null.

    Поэтому, когда null является ошибкой, вы просто пишете

    object o = FindObject();
    

    Если нуль не является ошибкой, вы можете написать что-то вроде

    if (TryFindObject(out object o)
      // Do something with o
    else
      // o was not found
    
    06.10.2008
  • Это было бы более полезным предложением, если бы C # предоставлял реальные кортежи, поэтому мы могли бы избежать использования параметра [out]. Тем не менее, это предпочтительный шаблон, поэтому +1. 06.10.2008
  • На мой взгляд, лучший подход - попытка. Тогда вам не нужно искать, что произойдет, если объект не может быть возвращен. Используя метод Try, вы сразу знаете, что делать. 07.10.2008
  • напоминает мне find и findOrFail из Laravel Eloquent 31.05.2018
  • @ErikForbes Я знаю, что ваш комментарий старый, но разве не нужно было определить объект с несколькими свойствами, который будет возвращен методом TryFindObject? Кортежи кажутся более ленивой парадигмой для программистов, которые не хотят тратить время на определение объекта, который инкапсулирует несколько значений. По сути, все кортежи в любом случае лежат в основе. 09.08.2018
  • @crush - Именованные литералы кортежей - это вариант, ИМО. Это ссылка на асинхронный шаблон Try Get с кортежами. stackoverflow.com/questions/1626597/ 09.04.2019

  • 5

    Я просто хотел резюмировать варианты, упомянутые ранее, добавив несколько новых:

    1. вернуть ноль
    2. выбросить исключение
    3. использовать шаблон нулевого объекта
    4. предоставить логический параметр вашему методу, чтобы вызывающий мог выбрать, хочет ли он, чтобы вы сгенерировали исключение
    5. предоставить дополнительный параметр, поэтому вызывающий может установить значение, которое он получит обратно, если значение не найдено

    Или вы можете комбинировать эти варианты:

    Предоставьте несколько перегруженных версий вашего геттера, чтобы вызывающая сторона могла решить, по какому пути идти. В большинстве случаев только первый из них реализует алгоритм поиска, а остальные просто охватывают первый:

    Object findObjectOrNull(String key);
    Object findObjectOrThrow(String key) throws SomeException;
    Object findObjectOrCreate(String key, SomeClass dataNeededToCreateNewObject);
    Object findObjectOrDefault(String key, Object defaultReturnValue);
    

    Даже если вы решите предоставить только одну реализацию, вы можете использовать подобное соглашение об именах, чтобы прояснить свой контракт, и это поможет вам, если вы когда-нибудь решите добавить и другие реализации.

    Вы не должны злоупотреблять им, но это может быть полезно, особенно при написании вспомогательного класса, который вы будете использовать в сотнях различных приложений с множеством различных соглашений об обработке ошибок.

    04.01.2009
  • Мне нравятся четкие названия функций, особенно orCreate и orDefault. 14.07.2015
  • Большую часть этого можно более четко записать с помощью Expected<T> findObject(String), где Expected<T> имеет функции orNull(), orThrow(), orSupplied(Supplier<T> supplier), orDefault(T default). Это абстрагирует получение данных от обработки ошибок. 06.10.2015
  • Я не знал об ожидаемом ‹T› до сих пор. Кажется, я новичок и, возможно, не существовал, когда писал исходный ответ. Может быть, тебе стоит сделать свой комментарий правильным ответом. 06.10.2015
  • Кроме того, Expected ‹T› - это шаблон C ++. Есть ли его реализации на других объектно-ориентированных языках? 06.10.2015
  • В Java 8 также возможен возврат Optional ‹T› (на других языках он называется «Может быть ‹T› и т. Д.). Это ясно указывает вызывающему, что возврат ничего не возможен, и не будет компилироваться, если вызывающий не обработал эту возможность, в отличие от null, который (в любом случае в Java) будет компилироваться, даже если вызывающий его не проверит. . 22.01.2019

  • 6

    Используйте шаблон нулевого объекта или создайте исключение.

    06.10.2008
  • Это настоящий ответ. Возвращать null - ужасная привычка ленивых программистов. 23.05.2013
  • Я не могу поверить, что этот ответ еще не был признан лучшим. Это настоящий ответ, и любой из этих подходов чрезвычайно прост и избавляет от лишнего кода или NPE. 06.09.2013
  • sourcemaking.com/design_patterns/null_object 06.09.2013
  • Если использовать шаблон нулевого объекта, как отличить случай, когда ключ отображается на нулевой объект, от случая, когда ключ не имеет отображения? Я бы подумал, что возврат бессмысленного объекта будет намного хуже, чем возврат null. Возврат null коду, который не подготовлен к его обработке, обычно приводит к возникновению исключения. Не лучший выбор исключения, но тем не менее исключение. Возврат бессмысленного объекта с большей вероятностью приведет к тому, что код будет неправильно считать бессмысленные данные правильными. 05.10.2014
  • Как будет вести себя нулевой объект при поиске сущности? Например, Person somePerson = personRepository.find("does-not-exist"); Предположим, этот метод возвращает нулевой объект для ID does-not-exist. Каким же тогда было бы правильное поведение для somePerson.getAge()? Прямо сейчас я еще не убежден, что шаблон нулевого объекта - правильное решение для поиска сущностей. 15.06.2015
  • Вот почему я сказал ИЛИ выбросить исключение, если в вашем случае нет смысла распространять NullPerson. Фактически, я думаю, что для поиска сущностей лучший подход - это выбросить, а затем ваш контроллер / служба / модель / что-то еще поймает и решит, будет ли он повторно генерировать или возвращать нулевой объект. Но да, ваш уровень доступа к данным должен выдавать, исключения легче поймать / отладить, чем задаться вопросом, почему у вас есть нуль где-то в цепочке. 15.06.2015
  • @supercat Нулевой объект должен находиться в другой ветви наследования, например. RealRecord: RecordBase и NullRecord: RecordBase. Тогда все, что принимает RealRecord, не может принимать NullRecord. RecordBase сообщает, что он может быть реальным или нулевым и сам по себе должен быть абстрактным. 26.04.2020
  • @SamuelDanielson: Одна из основных причин, по которой значения NULL полезны, заключается в том, что должен быть способ представления состояния элемента массива, который еще не был написан, и полезно иметь способ копирования состояния элементов массива это могло быть, а могло и не быть написано. Если бы кто-то хотел иметь предварительно заполненный массив, чтобы каждый элемент содержал NullRecord, весь код, который пытается прочитать массив, должен был бы преобразовать ссылку RecordBase в ссылку RealRecord, что не удалось бы, если элемент на самом деле является NullRecord, а я не не вижу, что можно было бы получить. 26.04.2020
  • @supercat Я не нашел языкового тега в вопросе. C ++, C # и Rust используют слово Default в своих стандартных библиотеках, чтобы отличать от Null в этом случае. Если мы действительно посмотрим на наши варианты на многих языках, мы сможем выразить ошибки с помощью исключений, часовых, значений по умолчанию, нулей, типов сумм, объединений, тегированных объединений, свернутых объединений, типов продуктов (атрибут isValid?) И т. Д. Я думаю, это просто зависит от насколько вы хотите, чтобы система типов помогла, и сколько ошибок должно быть допущено для расширения непроверенного интерфейса модуля. 26.04.2020
  • @SamuelDanielson: Если кто-то хочет иметь T[] с произвольным универсальным типом T, разрешите чтение элементов в тех случаях, когда не может быть статически доказано, что они были написаны, и определите поведение такого чтения, то он должен определить состояние по умолчанию для элементов массива, которые еще не были записаны. C # предоставляет унифицированный синтаксис для ссылки на значение по умолчанию любого произвольного T; для ссылочных типов возвращается значение null; для числовых типов - ноль; для типов структуры он дает структуру со всеми полями, содержащими значения по умолчанию. 26.04.2020

  • 7

    Будьте совместимы с API, которые вы используете.

    06.10.2008

    8

    Просто спросите себя: «Это исключительный случай, когда объект не найден»? Если ожидается, что это произойдет в ходе обычной работы вашей программы, вам, вероятно, не следует создавать исключение (поскольку это не исключительное поведение).

    Краткая версия: используйте исключения для обработки исключительного поведения, а не для обработки обычного потока управления в вашей программе.

    -Алан.

    06.10.2008

    9

    Преимущества выброса исключения:

    1. Более чистый поток управления в вызывающем коде. Проверка на null вводит условную ветвь, которая изначально обрабатывается с помощью try / catch. Проверка на null не указывает на то, что вы проверяете - проверяете ли вы на null, потому что ищете ожидаемую ошибку, или вы проверяете на null, чтобы не передавать его дальше в нисходящей цепочке ?
    2. Устраняет двусмысленность того, что означает «ноль». Является ли ноль представлением ошибки или является ноль тем, что фактически хранится в значении? Трудно сказать, когда у вас есть только одна вещь, на которой основывается это определение.
    3. Повышение согласованности между поведением методов в приложении. Исключения обычно отображаются в сигнатурах методов, поэтому вы лучше понимаете, для каких крайних случаев используются методы в учетной записи приложения и на какую информацию ваше приложение может реагировать. предсказуемым образом.

    Дополнительные объяснения с примерами см .: http://metatations.com/2011/11/17/returning-null-vs-throwing-an-exception/

    17.11.2011
  • +1, потому что пункт 2 отличный - ноль не имеет того же значения, что и не найдено. Это становится более важным при работе с динамическими языками, где Null фактически может быть объектом, который хранится / извлекается функцией - и в этом случае 13.10.2015
  • +1 за пункт №2. Нулевое значение является ошибкой? Имеет ли значение null то, что хранится для данного ключа? Нулевое значение указывает на то, что ключ не существует? Это настоящая цепочка вопросов, из которых ясно, что возвращение null почти никогда не бывает правильным. Это, вероятно, лучший ответ здесь, поскольку все остальные только что подбрасывали двусмысленность.Если это исключительное, бросьте 09.08.2018
  • Однако исключения могут привести к снижению производительности по сравнению с возвратами (например, в Java). А непроверенные исключения (например, в Java) могут появляться в непредусмотренных местах. 19.11.2020

  • 10

    это зависит от того, поддерживает ли ваш язык и код: LBYL (посмотрите, прежде чем прыгать) или EAFP (проще попросить прощения, чем разрешения)

    LBYL говорит, что вы должны проверять значения (так что возвращайте ноль)
    EAFP предлагает просто попробовать операцию и посмотреть, не удастся ли она (выбросить исключение)

    хотя я согласен с вышеизложенным ... исключения должны использоваться для исключительных условий / условий ошибки, а возврат null лучше всего при использовании проверок.


    EAFP против LBYL в Python:
    http://mail.python.org/pipermail/python-list/2003-May/205182.html (Веб-архив)

    06.10.2008
  • В некоторых случаях EAFP - единственный значимый подход. Например, в параллельной карте / словаре нет способа спросить, будет ли отображение существовать, когда оно будет запрошено. 05.10.2014

  • 11

    Исключения связаны с проектированием по контракту.

    Интерфейс объектов на самом деле является контрактом между двумя объектами, вызывающий должен соответствовать контракту, иначе получатель может просто выйти из строя с исключением. Возможны два контракта

    1) все входные данные метода действительны, и в этом случае вы должны вернуть null, если объект не найден.

    2) действителен только некоторый ввод, то есть тот, который приводит к найденному объекту. В этом случае вы ДОЛЖНЫ предложить второй метод, который позволяет вызывающему абоненту определить, будет ли его ввод правильным. Например

    is_present(key)
    find(key) throws Exception
    

    ЕСЛИ и ТОЛЬКО ЕСЛИ вы предоставляете оба метода 2-го контракта, вам разрешено генерировать исключение, ничего не найдено!

    06.10.2008

    12

    Зависит от того, что означает, что объект не найден.

    Если это нормальное состояние, верните null. Это просто то, что может происходить время от времени, и вызывающие абоненты должны это проверить.

    Если это ошибка, то вызовите исключение, вызывающие должны решить, что делать с ошибочным состоянием отсутствия объекта.

    В конечном итоге любой из них будет работать, хотя большинство людей обычно считают хорошей практикой использовать исключения только тогда, когда что-то, ну, исключительное произошло.

    06.10.2008
  • Как бы вы подробнее остановились на заявлении нормальное положение дел и по каким критериям вы будете использовать его, чтобы отличить его от ошибки. 14.06.2018

  • 13

    Вот еще пара предложений.

    При возврате коллекции избегайте возврата null, возвращайте пустую коллекцию, которая упрощает работу с перечислением без предварительной проверки на null.

    Некоторые API .NET используют шаблон параметра thrownOnError, который дает вызывающей стороне выбор, действительно ли это исключительная ситуация или нет, если объект не найден. Type.GetType является примером этого. Другой распространенный шаблон с BCL - это шаблон TryGet, в котором возвращается логическое значение, а значение передается через выходной параметр.

    В некоторых случаях вы также можете рассмотреть шаблон «Нулевой объект», который может быть либо значением по умолчанию, либо версией без поведения. Ключ в том, чтобы избегать нулевых проверок по всей базе кода. Дополнительную информацию см. Здесь http://geekswithblogs.net/dsellers/archive/2006/09/08/90656.aspx

    07.10.2008

    14

    Я предпочитаю просто возвращать значение NULL и полагаюсь на то, что вызывающий объект обработает его должным образом. Исключение (из-за отсутствия лучшего слова) - это если я абсолютно уверен, что этот метод вернет объект. В этом случае отказ является исключительным случаем, который должен и должен бросить.

    06.10.2008

    15

    В некоторых функциях я добавляю параметр:

    ..., bool verify = true)
    

    Истина означает выброс, ложь означает возврат некоторого возвращаемого значения ошибки. Таким образом, у любого, кто использует эту функцию, есть оба варианта. Значение по умолчанию должно быть истинным для тех, кто забывает об обработке ошибок.

    06.10.2008

    16

    Верните значение NULL вместо создания исключения и четко задокументируйте возможность возврата значения NULL в документации по API. Если вызывающий код не соблюдает API и не проверяет регистр NULL, это, скорее всего, все равно приведет к некоему «исключению с нулевым указателем» :)

    В C ++ я могу придумать 3 различных варианта настройки метода, который находит объект.

    Вариант А

    Object *findObject(Key &key);
    

    Возвращает null, если объект не может быть найден. Красиво и просто. Я бы пошел с этим. Приведенные ниже альтернативные подходы предназначены для людей, которые не ненавидят out-params.

    Вариант Б

    void findObject(Key &key, Object &found);
    

    Передайте ссылку на переменную, которая будет получать объект. Метод вызвал исключение, когда объект не может быть найден. Это соглашение, вероятно, более подходит, если на самом деле не ожидается, что объект не будет найден - следовательно, вы генерируете исключение, чтобы указать, что это неожиданный случай.

    Вариант В

    bool findObject(Key &key, Object &found);
    

    Метод возвращает false, если объект не может быть найден. Преимущество этого варианта перед вариантом A заключается в том, что вы можете проверить случай ошибки за один четкий шаг:

    if (!findObject(myKey, myObj)) { ...
    
    06.10.2008

    17

    имея в виду только случай, когда null не считается исключительным поведением, я определенно поддерживаю метод try, это ясно, нет необходимости «читать книгу» или «смотреть перед прыжком», как было сказано здесь

    так в основном:

    bool TryFindObject(RequestParam request, out ResponseParam response)
    

    а это значит, что код пользователя тоже будет понятен

    ...
    if(TryFindObject(request, out response)
    {
      handleSuccess(response)
    }
    else
    {
      handleFailure()
    }
    ...
    
    22.12.2010

    18

    Если клиентскому коду важно знать разницу между найденным и не найденным, и это должно быть обычным поведением, тогда лучше вернуть null. Затем клиентский код может решить, что делать.

    06.10.2008

    19

    Обычно он должен возвращать null. Код, вызывающий метод, должен решить, выбросить ли исключение или попытаться сделать что-то еще.

    06.10.2008

    20

    Или вернуть вариант

    Вариант - это, по сути, контейнерный класс, который заставляет клиента обрабатывать будки. У Scala есть такая концепция, посмотрите ее API.

    Затем у вас есть такие методы, как T getOrElse (T valueIfNull) для этого объекта, которые либо возвращают найденный объект, либо все альтернативы, указанные клиентом.

    06.10.2008

    21

    Предпочитать возвращать null -

    Если вызывающий использует его без проверки, исключение все равно произойдет прямо здесь.

    Если вызывающий на самом деле не использует его, не облагайте его налогом _1 _ / _ 2_ блок

    23.02.2011

    22

    К сожалению, JDK несовместим, если вы пытаетесь получить доступ к несуществующему ключу в пакете ресурсов, вы получаете исключение не найдено, и когда вы запрашиваете значение из карты, вы получаете null, если он не существует. Итак, я бы изменил ответ победителя на следующий: если найденное значение может быть нулевым, затем вызвать исключение, если оно не найдено, в противном случае вернуть null. Поэтому следуйте правилу с одним исключением: если вам нужно знать, почему значение не найдено, всегда вызывайте исключение или ..

    03.08.2011

    23

    Если предполагается, что он возвращает ссылку на объект, возвращение NULL должно быть нормальным.

    Однако, если он возвращает всю чертову штуку (как в C ++, если вы это делаете: 'return blah;' вместо 'return' (или 'blah' - указатель), то вы не можете вернуть NULL, потому что это не введите "объект". В этом случае я бы подошел к проблеме, выбрасывая исключение или возвращая пустой объект, для которого не установлен флаг успеха.

    06.10.2008

    24

    Не думайте, что кто-то упомянул накладные расходы при обработке исключений - требуются дополнительные ресурсы для загрузки и обработки исключения, поэтому, если это не настоящее событие, связанное с убийством приложения или остановкой процесса (дальнейшее продвижение принесет больше вреда, чем пользы), я бы предпочел передать обратно Ценность вызывающей среды может интерпретировать так, как считает нужным.

    06.10.2008

    25

    Я согласен с тем, что кажется здесь консенсусом (возврат null, если «не найден» является нормальным возможным результатом, или выбросить исключение, если семантика ситуации требует, чтобы объект всегда был найден).

    Однако существует третья возможность, которая может иметь смысл в зависимости от вашей конкретной ситуации. Ваш метод может вернуть какой-либо объект по умолчанию в состоянии «не найден», что позволяет вызывающему коду быть уверенным, что он всегда получит действительный объект без необходимости проверки на null или перехвата исключений.

    06.10.2008

    26

    Верните нулевое значение, исключения - это именно то, что: ваш код делает то, чего не ожидают.

    06.10.2008

    27

    Исключения должны быть исключительными. Верните ноль , если допустимо вернуть ноль.

    06.10.2008
  • Более-менее верно. См. boost.org/community/error_handling.html. 07.10.2008

  • 28

    Если метод возвращает коллекцию, то верните пустую коллекцию (как сказано выше). Но, пожалуйста, не Collections.EMPTY_LIST или тому подобное! (в случае Java)

    Если метод извлекает один объект, у вас есть несколько вариантов.

    1. Если метод всегда должен находить результат, и это реальный случай исключения, когда не удается найти объект, тогда вы должны выбросить исключение (в Java: пожалуйста, не отмеченное исключение)
    2. (Только для Java). Если вы можете допустить, что метод выдает проверенное исключение, вызовите исключение ObjectNotFoundException для конкретного проекта или подобное. В этом случае компилятор сообщает вам, если вы забудете обработать исключение. (Это моя любимая обработка ненайденных вещей в Java.)
    3. Если вы говорите, что все в порядке, если объект не найден, а имя вашего метода похоже на findBookForAuthorOrReturnNull (..), вы можете вернуть значение null. В этом случае настоятельно рекомендуется использовать какую-либо статическую проверку или проверку компилятора, которая предотвращает разыменование результата без проверки на null. В случае Java это может быть, например. FindBugs (см. DefaultAnnotation на странице http://findbugs.sourceforge.net/manual/annotations.html) или IntelliJ-Checking.

    Будьте осторожны, если решите вернуть нуль. Если вы не единственный программист в проекте, вы получите NullPointerExceptions (на Java или на других языках) во время выполнения! Поэтому не возвращайте значения NULL, которые не проверяются во время компиляции.

    21.08.2012
  • Нет, если код был написан правильно, ожидая null. Подробнее см. В ответе, получившем наибольшее количество голосов. 21.08.2012
  • Но только если вы убедитесь, что во время компиляции проверяются все значения NULL. Это можно сделать с помощью FindBugs @NutNull на уровне пакета и пометить ваш метод как который может возвращать null. Или использовать такой язык, как Kotlin или Nice. Но гораздо проще не возвращать null. 21.08.2012
  • Проще, возможно. Но часто совершенно неверно 21.08.2012
  • Извините, но что не так, если метод, обещающий найти книгу, не может их найти и выдает исключение? Вы знаете ошибку в миллиард долларов? infoq.com/presentations/ 21.08.2012
  • Еще раз: прочитайте ответ, получивший наибольшее количество голосов, для получения дополнительной информации. В основном: если это потенциально ожидаемый результат, что запрошенная книга не может быть найдена, исключением является неправильный поступок, который следует делать, когда запрошенная книга просто не найдена, а не возникает некоторая ошибка. 21.08.2012
  • Ответ, получивший наибольшее количество голосов, не должен быть единственно правильным. Я не согласен с ответом. Также не согласны Роберт С. Мартин (в книге «Чистый код: руководство по Agile Software Craftsmanshi») и Майкл Фезерс. И новые языки программирования, такие как Kotlin и Nice, подписываются на просмотр. И. Возможно, я слишком это принимаю близко к сердцу, но почему вы проголосовали против меня? Я не нарушал правила и мой ответ не так уж плох. 21.08.2012
  • Вы здесь много неправильно понимаете. Вы применяете условный совет повсеместно, что почти всегда плохо. Прочтите также и остальные ответы, за которые проголосовали "за". Ваш ответ просто утверждает абсолют и представляет для него крайне ошибочную логику. 21.08.2012
  • Я переписал ответ. Предыдущий ответ был только для Java. 22.08.2012

  • 29

    Если вы используете библиотеку или другой класс, который вызывает исключение, вам следует повторно выбросить его. Вот пример. Example2.java похожа на библиотеку, а Example.java использует ее объект. Main.java - это пример обработки этого исключения. Вы должны показать значимое сообщение и (при необходимости) трассировку стека пользователю на вызывающей стороне.

    Main.java

    public class Main {
    public static void main(String[] args) {
        Example example = new Example();
    
        try {
            Example2 obj = example.doExample();
    
            if(obj == null){
                System.out.println("Hey object is null!");
            }
        } catch (Exception e) {
            System.out.println("Congratulations, you caught the exception!");
            System.out.println("Here is stack trace:");
            e.printStackTrace();
        }
    }
    }
    

    Example.java

    /**
     * Example.java
     * @author Seval
     * @date 10/22/2014
     */
    public class Example {
        /**
         * Returns Example2 object
         * If there is no Example2 object, throws exception
         * 
         * @return obj Example2
         * @throws Exception
         */
        public Example2 doExample() throws Exception {
            try {
                // Get the object
                Example2 obj = new Example2();
    
                return obj;
    
            } catch (Exception e) {
                // Log the exception and rethrow
                // Log.logException(e);
                throw e;
            }
    
        }
    }
    

    Example2.java

     /**
     * Example2.java
     * @author Seval
     *
     */
    public class Example2 {
        /**
         * Constructor of Example2
         * @throws Exception
         */
        public Example2() throws Exception{
            throw new Exception("Please set the \"obj\"");
        }
    
    }
    
    22.10.2014
  • Если исключение, которое должно быть выброшено из функции, не является исключением во время выполнения, и ожидается, что вызывающий объект обработает его (вместо того, чтобы просто завершить программу), то вместо того, чтобы генерировать исключение из внутренней подсистемы, которого вызывающий не может ожидать, было бы лучше заключить внутреннее исключение во внешнее проверенное исключение, при этом «связав» внутреннее исключение, чтобы кто-нибудь, занимающийся отладкой, мог выяснить, почему было сгенерировано внешнее исключение. Например, example1 может использовать 'throw new MyCheckedException (Пожалуйста, установите \ obj \, e)', чтобы включить 'e' в выброшенное исключение. 22.01.2019

  • 30

    Это действительно зависит от того, ожидаете ли вы найти объект или нет. Если вы следите за школой мысли, что исключения следует использовать для обозначения чего-то, ну, эээ, тогда произошло исключение:

    • Найден объект; вернуть объект
    • Объект не найден; выбросить исключение

    В противном случае верните null.

    06.10.2008

    31

    Это зависит от характера метода и от того, как он будет использоваться. Если это нормальное поведение, когда объект не может быть найден, верните null. Если объект всегда найден, это нормальное поведение, генерировать исключение.

    Как правило, используйте исключения только тогда, когда что-то исключительное происходит. Не пишите код таким образом, чтобы генерация и перехват исключений была частью его нормальной работы.

    06.10.2008

    32

    Если не обнаружено, что это исключительное событие (т.е. оно должно быть там при нормальных обстоятельствах), бросьте. В противном случае верните значение «не найдено» (может быть нулевым, но не обязательно) или даже пусть метод возвращает логическое значение для найденного / не найденного и параметр out для фактического объекта.

    06.10.2008

    33

    Это зависит от вашего метода. Если ваш метод должен всегда возвращать действительный объект, и ни один из них не найден, можно использовать исключение. Если метод просто возвращает объект, который может быть, а может и не быть (например, изображение контактного лица), вы не должны выдавать ошибку.

    Вы также можете открыть метод, возвращающий логическое значение true / false, если этот метод действительно возвращает объект, поэтому вам не нужно: а) проверять значение null или б) перехватывать исключение.

    06.10.2008

    34

    «Другой» вариант может заключаться в том, чтобы позволить методу поиска принимать дополнительный параметр с объектом по умолчанию, который будет возвращен, если искомый объект не может быть найден.

    В противном случае я бы просто вернул null, если только это действительно не исключительный случай, когда объект не найден.

    06.10.2008

    35

    В коде уровня данных я иногда использую следующий код, позволяющий вызывающей стороне решить, означает ли «объект не найден» возникла ошибка.

    
    DataType GetObject(DBConnection conn, string id, bool throwOnNotFound) {
        DataType retval = ... // find object in database
        if (retval != null || ! throwOnNotFound) {
            return retval;
        } else {
            throw new NoRowsFoundException("DataType object with id {id} not found in database");
        }
    }
    
    DataType GetObject(DBConnection conn, string id) {
        return GetObject(conn, id, true);
    } 
    
    06.10.2008

    36

    Отсутствие объекта может произойти во время обычных операций и должно быть обработано вызывающей стороной, возвращающей NULL.

    Если объект не содержит, это указывает на ошибку вызывающим кодом или внутренним состоянием, тогда выполните assert.

    Если объект не содержит, указывает на нечастое событие. (Как будто кто-то удалил элемент из магазина, в то время как вы одновременно извлекали этот элемент.) Затем создайте исключение.

    06.10.2008
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..