Я слышал некоторые голоса, говорящие, что проверка возвращаемого нулевого значения из методов - это плохой дизайн. Я хотел бы услышать несколько причин для этого.
псевдокод:
variable x = object.method()
if (x is null) do something
oop
null
return-value
Koen
источник
источник
Ответы:
Причина отказа от возврата null заключается в том, что вам не нужно его проверять, и, следовательно, ваш код не должен следовать другому пути на основе возвращаемого значения. Возможно, вы захотите ознакомиться с шаблоном нулевого объекта, который предоставляет дополнительную информацию об этом.
Например, если бы я определил в Java метод, возвращающий коллекцию, я бы обычно предпочел возвращать пустую коллекцию (т.е.
Collections.emptyList()
), а не ноль, поскольку это означает, что мой клиентский код чище; например... что чище, чем:
источник
null
является «контейнером», который содержит ноль или один указатель на объекты. (Именно такMaybe
в этих случаях он явно моделируется Haskell , и тем лучше для этого.)Вот причина.
В « Чистом коде» Роберта Мартина он пишет, что возвращение нуля - плохой дизайн, когда вместо этого можно вернуть, скажем, пустой массив. Поскольку ожидаемый результат - это массив, почему бы и нет? Это позволит вам перебирать результат без каких-либо дополнительных условий. Если это целое число, может быть достаточно 0, если это хеш, пустой хеш. и т.п.
Предпосылка состоит в том, чтобы не заставлять вызывающий код немедленно обрабатывать проблемы. Вызывающий код может не беспокоиться о них. Вот почему во многих случаях исключения лучше, чем nil.
источник
Хорошее использование возврата null:
Плохое использование: попытка заменить или скрыть исключительные ситуации, такие как:
В этих случаях более адекватным является создание исключения, поскольку:
Однако исключения не следует использовать для обработки обычных условий работы программы, таких как:
источник
boolean login(String,String)
AuthenticationContext createAuthContext(String,String) throws AuthenticationException
Да, возвращение NULL - ужасный дизайн в объектно-ориентированном мире. Вкратце, использование NULL приводит к:
Подробное объяснение можно найти в этом сообщении в блоге: http://www.yegor256.com/2014/05/13/why-null-is-bad.html . Подробнее в моей книге « Элегантные объекты» , раздел 4.1.
источник
bool TryGetBlah(out blah)
илиFirstOrNull()
илиMatchOrFallback(T fallbackValue)
.isEmpty()
), и только если оно истинно, затем вызовите метод. Люди возражают против второго, говорят, что у него более низкая производительность, но, как говорит философия Unix, «цените человеческое время по сравнению с машинным временем» (то есть тривиально более низкая производительность тратит меньше времени, чем разработчики, отлаживающие код, который дает ложные ошибки).Кто сказал, что это плохой дизайн?
Проверка на нули - обычная практика, даже поощряемая, иначе вы рискуете повсюду получить NullReferenceExceptions. Лучше аккуратно обработать ошибку, чем генерировать исключения, когда в этом нет необходимости.
источник
Исходя из того, что вы сказали до сих пор, я думаю, что информации недостаточно.
Возврат null из метода CreateWidget () кажется плохим.
Возврат null из метода FindFooInBar () кажется прекрасным.
источник
Create...
одному элементу - возвращает новый экземпляр или бросает ;Get...
возвращает ожидаемый существующий экземпляр или выбрасывает ;GetOrCreate...
возвращает существующий экземпляр или новый экземпляр, если его нет, или выбрасывает ;Find...
возвращает существующий экземпляр, если он существует, илиnull
. Для запросов коллекции -Get...
всегда возвращает коллекцию, которая пуста, если совпадающие элементы не найдены.Его изобретатель говорит, что это ошибка на миллиард долларов!
источник
Это зависит от языка, который вы используете. Если вы работаете в таком языке, как C #, где идиоматический способ указать отсутствие значения - это вернуть null, тогда возврат null - хороший вариант, если у вас нет значения. В качестве альтернативы, в таких языках, как Haskell, которые идиоматически используют монаду Maybe для этого случая, возвращение null было бы плохим дизайном (если бы это было вообще возможно).
источник
null
в таких языках, как C # и Java, часто перегружены и придают какое-то значение в предметной области. Если вы найдетеnull
ключевое слово в спецификациях языка, оно просто означает «недействительный указатель». Это, вероятно, ничего не значит ни в какой проблемной области.null
или «не инициализировано»null
Если вы прочтете все ответы, станет ясно, что ответ на этот вопрос зависит от типа метода.
Во-первых, когда происходит что-то исключительное (проблема ввода-вывода и т. Д.), Логически возникают исключения. Когда что-то особенное - это, вероятно, тема для другой темы ..
Всякий раз, когда ожидается, что метод не даст результатов, есть две категории:
Пустые перечисления, строки и т. Д. - хорошие примеры
Как уже упоминалось, предполагается, что метод, возможно, не даст результата, поэтому он не является исключительным и, следовательно, не должен вызывать исключение. Нейтральное значение невозможно (например: 0 не является особенно нейтральным результатом, в зависимости от программы)
Пока у нас не будет официального способа обозначить, что функция может или не может возвращать значение null, я стараюсь иметь соглашение об именах, чтобы обозначить это.
Так же, как у вас есть соглашение Try Something () для методов, которые, как ожидается, не сработают, я часто называю свои методы Safe Something () когда метод возвращает нейтральный результат вместо null.
Я пока не совсем согласен с названием, но ничего лучшего придумать не мог. Так что я пока этим занимаюсь.
источник
У меня есть конвенция в этой области, которая мне хорошо послужила
Для запросов по одному элементу:
Create...
возвращает новый экземпляр или бросаетGet...
возвращает ожидаемый существующий экземпляр или бросаетGetOrCreate...
возвращает существующий экземпляр или новый экземпляр, если его нет, или бросаетFind...
возвращает существующий экземпляр, если он существует, илиnull
Для запросов по сбору:
Get...
всегда возвращает коллекцию, которая пуста, если не найдено подходящих [1] элементов[1] с учетом некоторых критериев, явных или неявных, указанных в имени функции или в качестве параметров.
источник
Get
когда ожидаю, что он там будет, так что если его нет, то это ошибка, и я выброшу - мне никогда не нужно проверять возвращаемое значение. Я использую,Find
если действительно не знаю, есть он или нет - тогда мне нужно проверить возвращаемое значение.Исключения составляют исключения обстоятельства.
Если ваша функция предназначена для поиска атрибута, связанного с данным объектом, и этот объект не имеет такого атрибута, может быть целесообразно вернуть значение null. Если объект не существует, может быть более подходящим создание исключения. Если функция предназначена для возврата списка атрибутов, а их нет, возврат пустого списка имеет смысл - вы возвращаете все нулевые атрибуты.
источник
Если это имеет какое-то значение, можно вернуть null:
В таком случае имеет смысл вернуть null, если идентификатор не соответствует существующей сущности, поскольку это позволяет отличить случай, когда совпадение не было найдено, от допустимой ошибки.
Люди могут подумать, что это плохо, потому что им можно злоупотреблять как «специальное» возвращаемое значение, указывающее на состояние ошибки, что не так хорошо, немного похоже на возвращение кодов ошибок из функции, но сбивает с толку, потому что пользователь должен проверить возвращаемый результат для null вместо того, чтобы перехватывать соответствующие исключения, например
источник
Это не обязательно плохой дизайн - это зависит от многих дизайнерских решений.
Если результатом метода является то, что не дало бы хорошего результата при нормальном использовании, можно вернуть null:
Если действительно всегда должен быть результат, отличный от NULL, может быть лучше выбросить исключение:
источник
Optional<>
В определенных сценариях вы хотите заметить сбой, как только он произойдет.
Проверка против NULL и отказ от утверждения (для ошибок программиста) или выдачи (для ошибок пользователя или вызывающего абонента) в случае сбоя может означать, что последующие сбои труднее отследить, поскольку исходный нечетный случай не был найден.
Более того, игнорирование ошибок может привести к уязвимостям безопасности. Возможно, пустота возникла из-за того, что буфер был перезаписан или что-то подобное. Теперь у вас нет сбоев, а это значит, что у эксплуататора есть шанс выполнить свой код.
источник
Какие альтернативы вы видите возвращению null?
Я вижу два случая:
В этом случае мы могли бы: вернуть Null или выбросить (проверенное) исключение (или, возможно, создать элемент и вернуть его)
В этом случае мы могли бы вернуть Null, вернуть пустой список или выдать исключение.
Я считаю, что return null может быть менее хорош, чем альтернативы, потому что он требует, чтобы клиент не забывал проверять значение null, программисты забывают и код
В Java выдача проверенного исключения RecordNotFoundException позволяет компилятору напоминать клиенту о необходимости обработки регистра.
Я считаю, что поиск, возвращающий пустые списки, может быть довольно удобным - просто заполните дисплей всем содержимым списка, о, он пуст, код «просто работает».
источник
Иногда возвращение NULL является правильным решением, но особенно, когда вы имеете дело с последовательностями разного типа (массивы, списки, строки и т. Д.), Вероятно, лучше вернуть последовательность нулевой длины, поскольку она приводит к более короткому и, надеюсь, более понятному коду, не требуя при этом гораздо большего количества написания со стороны разработчика API.
источник
Заставьте их вызвать другой метод постфактум, чтобы выяснить, был ли предыдущий вызов нулевым. ;-) Эй, для JDBC хватило
источник
Основная идея этой темы - защитное программирование. То есть код против неожиданного. Есть множество разных ответов:
Адамски предлагает посмотреть на образец нулевого объекта, и этот ответ был одобрен за это предложение.
Майкл Валенти также предлагает соглашение об именах, чтобы сообщить разработчику, чего можно ожидать. ZeroConcept предлагает правильное использование Exception, если это является причиной NULL. И другие.
Если мы создадим «правило», согласно которому мы всегда хотим заниматься защитным программированием, то увидим, что эти предложения верны.
Но у нас есть 2 сценария развития.
Классы «авторские» разработчик: Автор
Классы, "потребляемые" другим (возможно) разработчиком: Разработчик
Независимо от того, возвращает ли класс NULL для методов с возвращаемым значением или нет, разработчику необходимо проверить, действителен ли объект.
Если разработчик не может этого сделать, то этот класс / метод не является детерминированным. То есть, если «вызов метода» для получения объекта не выполняет то, что он «рекламирует» (например, getEmployee), это нарушает контракт.
Как автор класса, я всегда хочу быть таким же добрым и защитным (и детерминированным) при создании метода.
Итак, учитывая, что либо NULL, либо NULL OBJECT (например, if (employee as NullEmployee.ISVALID)) необходимо проверить, и это может потребоваться с коллекцией сотрудников, то подход с нулевым объектом является лучшим подходом.
Но мне также нравится предложение Майкла Валенти назвать метод, который ДОЛЖЕН возвращать значение null, например getEmployeeOrNull.
Автор, генерирующий исключение, лишает разработчика возможности проверить достоверность объекта, что очень плохо для коллекции объектов, и заставляет разработчика выполнять обработку исключений при ветвлении своего потребляющего кода.
Как разработчик, использующий этот класс, я надеюсь, что автор дает мне возможность избежать или запрограммировать нулевую ситуацию, с которой могут столкнуться их класс / методы.
Итак, как разработчик, я должен защищать метод от NULL. Если автор дал мне контракт, который всегда возвращает объект (всегда возвращает NULL OBJECT), и этот объект имеет метод / свойство, с помощью которого можно проверить действительность объекта, то я бы использовал этот метод / свойство для продолжения использования объекта. , иначе объект недействителен, и я не могу его использовать.
Суть в том, что Автор класса / методов должен предоставить механизмы, которые Разработчик может использовать в своем защитном программировании. То есть более четкое намерение метода.
Разработчик всегда должен использовать защитное программирование для проверки достоверности объектов, возвращаемых другим классом / методом.
С уважением
GregJF
источник
Другие варианты для этого: возврат некоторого значения, которое указывает на успех или нет (или тип ошибки), но если вам просто нужно логическое значение, которое будет указывать на успех / неудачу, возврат null для неудачи, а объект для успеха не быть менее правильным, затем вернуть истину / ложь и получить объект через параметр. Поэтому я лично не вижу ничего плохого в том, чтобы возвращать null как указание на то, что что-то пошло не так, и проверять его позже (чтобы узнать, удалось ли вам это или нет). Кроме того, слепо полагая, что ваш метод не вернет NULL, а затем основывает свой код на нем, может привести к другим, иногда трудным для поиска ошибкам (хотя в большинстве случаев это просто приведет к сбою вашей системы :), как вы будете ссылаться на 0x00000000 рано или поздно).
Другой подход - использовать исключение для указания сбоев, но здесь на самом деле гораздо больше голосов, которые говорят, что это ПЛОХОЙ метод (поскольку использование исключений может быть удобным, но имеет много недостатков).
источник
Null_function @wikipedia
источник
Ну, конечно, это зависит от цели метода ... Иногда лучше было бы выбросить исключение. Все зависит от случая к случаю.
источник
Если код выглядит примерно так:
Если у вас есть фиктивный объект, метод execute () которого ничего не делает, и вы возвращаете его вместо Null в соответствующих случаях, вам не нужно проверять регистр Null, и вместо этого вы можете просто сделать:
Итак, здесь проблема не между проверкой на NULL и исключение, а между вызывающей стороной, которая должна обрабатывать особые не регистры по-разному (каким-либо образом) или нет.
источник
Для моего случая использования мне нужно было вернуть Map from метод, а затем искать определенный ключ. Но если я верну пустую карту, это приведет к NullPointerException, и тогда это не будет сильно отличаться от возврата null вместо пустой карты. Но начиная с Java8 мы могли использовать Optional . Вышеупомянутое и является причиной введения дополнительной концепции.
источник
G'day,
Возвращение NULL, когда вы не можете создать новый объект, является стандартной практикой для многих API.
Почему, черт возьми, это плохой дизайн, понятия не имею.
Изменить: это верно для языков, где у вас нет исключений, таких как C, где это было соглашением в течение многих лет.
НТН
«Avahappy,
источник