Почему нельзя возвращать NULL?
Vložit
- čas přidán 28. 05. 2024
- Негативные последствия возвращения Null и как же работать правильно.
Курс, о котором шла речь в видео: Enterprise patterns - bit.ly/3hYyWhk
Курсы для новичков:
JAVA - bit.ly/2Z42wL6
JAVA Start - bit.ly/3boc7Ba
Инструментарий JAVA - bit.ly/32Xwl0S
Automation QA (Java) - bit.ly/3gZe8oJ
ANDROID - bit.ly/3jWAedB
C#/.NET - bit.ly/331EcL8
C# START - bit.ly/3lQfLZF
PYTHON - bit.ly/2Z4UBgo
FRONT-END - bit.ly/2Z42NxC
WORDPRESS Developer - bit.ly/2EWUsET
SALESFORCE Developer - bit.ly/3lMsf4k
UI/UX дизайн - bit.ly/32TaveV
Project management - bit.ly/3gSAmbP
Обучение на проекте - bit.ly/2DsgpuZ
Продвинутые курсы для состоявшихся девелоперов:
GRASP and GoF Design patterns - bit.ly/354aeIM
Сайт Foxminded: bit.ly/3lNYikt
Foxminded в ФБ: / foxmindedco
FoxmindEd в Instagram: / foxminded.ua
Foxminded в VK: foxminded
Мой Telegram: t.me/nemchinskiyOnBusiness
Мой блог: www.nemchinsky.me
0:00 - вступление Сергея Немчинского
00:27 - кто еще считает, что Null возвращать нельзя?
02:02 - почему нельзя возвращать NULL: обработка ошибок вручную
04:48 - почему нельзя возвращать NULL: неоднозначное понимание
06:16 - реклама
07:22 - почему нельзя возвращать NULL: нарушение мышления программиста, нагромождение кода
10:38 - почему нельзя возвращать NULL: медленный провал, затруднение поддержки системы
13:31 - история про индусов
15:13 - использование Null в изменяемых и незавершенных объектах
17:15 - как же тогда работать?
Всю пандемию возвращал null, теперь коллекторы названивают...
Посмотри кузнецова, научись экзепшона всем вставлять
Так можно и П.Е получить)
Вахах
@@LionKing-qp1lk нелюбители исключений уже идут за вами.
garbage collector'ы
- Микола, слыхав, як паскали наш null называють?
- Як?
- Nil! Поубивав би гадів!
Он так и называется в паскале
Avazart my bad😂
Олег Литвиненко в Свифте тоже nil. Я кстате тоже целую лекцию по этому поводу записал
на lua тоже
да и в golang
Когда пацики с района стреляют сигаретку, а ты, вместо ответа "не курю", падаешь и притворяешься мёртвым.
добавлено:
Забыл, ещё можно отдать им пустую пачку)
а исключение - это что в таком случае?)
@@maxlich9139 , падение же
@@daniilpalii6743 да это вроде null
@@maxlich9139 не, нул - это ответить "нету сижек". Исключение - упасть.
Sergei Menshikov нет, исключение - это дать ему по башке и сказать: разберись в своих ошибках.
Не возвращай нал, возвращай безнал!
Теперь буду вместо Null возвращать «Sergey Nemchinskiy»
NemchinskyDislikesNullException
SergeyNemchinskiyException
А если булево, то NotNemchinskyException
Лучше ссылку на это видео
😂
Однажды русский программист из Калифорнийской компании вернул «zhopa», вместо Null. Всем понравилось, стали использовать. Потом стали нумеровать zhopa1, zhopa2, когда просто zhopa было недостаточно. Как-то звонят из Тайваня, говорят остановился весь завод, мы не понимаем из-за чего - даёт ошибку zhopa37 !
Ты что-то перепутал. Ошибку zhopa37 выдавал сервер Диабло3 на релизе.
Однажды русские программисты из Германии, ночью, не зная как назвать методы, назвали их xyinja1, xyinja2. Так никто и не возражал.
у каменщиков есть анекдот: кладет кладку смотрит кривовато, штукатуры заштукатурят, штукатуры - шпаклевщики зашпаклюют, шпаклевщики - поклейщики обоев что нибудь придумают, поклейщики - сносите всю стену нафиг.
Кек
Типичный медлннный фейл :)
Там есть еще одна итерация. Поклейщики все валят на мебельщиков, а им похеру, потому как форматная пила пилит только прямо. И мебель будет состоять из прямых линий. И в конце заказчик "а чой та у миня тута щель с палец, между меблей и стеной, и такая кривая", а исполнитель мебели "хз, у строителей надо спрашивать".
Это пример, когда эксепшен проскакивает вверх по коллстеку, но каждый метод "считает", что обработать должны еще выше. А потом все приложение крешится.
Ждём следующий выпуск - "почему нельзя возвращать -1".
Почему любой стейт надо в енум, даже если там только он/офф
@@MikhailKolesnikov потому что любим обмзаться ооп
@@TeppopucT enum - ни разу не ооп, просто превращение цифр в читаемый вид и контроль за тем, чтобы не засунули туда то, чего там быть не может. Внутри-то там всё-равно цифры живут.
@@MikhailKolesnikov Чтобы код был красивый. Енум не жрёт ресурсов, он просто даёт бОльшую свободу и контроль, чем если делать то же самое через константы.
В Си, например, вообще нет эксепшонов. Там функции либо через возвращаемое значение какой-то код возвращают (типа 0 - всё норм; отличное от 0 значение - какая-то ошибка и т.д.); либо в функцию в качестве параметра передаётся указатель на int, в который функция выводит код ошибки.
Краткий итог всего видео: Рубисты молчать.
:D
@Глядач че бьля7
Гоферам тоже заткнуться! :)
А в кристале как удобно с Nil работать... Видео дичька беспонтовая. Если обизяна сидит и не ждёт nil от выборки - ну кто тут её доктор?
фу короче. Старая дичь.
Не знаю про Ruby, но если это функциональное программирование, то в Haskell это норма: поиск в словаре - результат Maybe, т.е. или Nothing (ничего не найдено), или значение в обёртке Just.
Допустим, у класса User есть поле с типом Group которое может быть пустое. У Group поле title и другие.
Нам нужно вывести список юзеров с названиями их групп. Как быть без null? Возвращать вместо группы объект типа Group с пустым полем title? Это еще больше багов породит, причем намного хуже чем NPE, например в БД добавится пустая строка.
И как по сети передать, тому же фронту? Фронт получит какой-то объект с пустым title, ему это дикое условие проверять надо будет вместо простого == null.
Ну тут была больше речь о возврате null если не удалось посчитать или загрузить данные из метода / сервиса. Что то не получилось, выкинь исключение определенного типа. Суть видео можно было свести к тому, что в интерфейсе можно перечислить положительный результат работы метода и все возможные исключения. Null не дает понимания о природе ошибки
@@grommaks В случае ошибки null возвращать нельзя, это понятно. В моем примере null это не ошибка, юзеры без групп это нормальный случай. В видео речь о том, что null никогда нельзя возвращать.
@@drovoseg в этом случае null это нормально
@@drovoseg в чем проблема вернуть пустой масив групп? Если их нет? На фронте проверят через groups.length!==0
использовать паттерн NullObject. Я же рассказывал :)
Как будто мне не придётся проверять параметры на null, если в своих программах я перестану возвращать null. Есть же тысяча коллег, чьим кодом я пользуюсь.
Да, это должно быть запрещено на уровне языка. Но тут речь о договорённостях.
@@user-fg7hf4qo8m Отсутствие результата - это тоже результат, и религиозные фанатики могут идти лесом. Если вы засунете в функцию exception, то это не поменяет ничего, потому что вызывающий код точно так же ставится перед фактом необходимости проверки данного исключения, если оно вылетит. Т. е. все это по факту пустой треп о том, куда ставить проверку, но никак не отменяет самой проверки.
@@beltar2 если функция возвращает null, бывает очень трудно найти причину ошибочного поведения, т.к. программа свалиться где-нибудь позже, иногда сильно позже. И там, в отладке, единственно, что вы увидите - это то, что пришёл null. Гораздо легче исправить ошибку, если программа вылетит непосредственно на ней.
Отсутствие результата тоже имеет право на существование в некоторых сценариях, но тогда это должно быть сразу оговорено. Хорошо, если язык сам заставляет делать проверки в таких случаях.
@@user-fg7hf4qo8m Тут я с вами соглашусь, что мерзкое окошко исключения сразу будет неплохо бодрить, однако данная ситуация все равно может быть автоматически распространена на любые вызовы, не нашел в коллекции что-то, вернул индекс -1. Это точно так же может пойти по системе, а может в следующей строке рвануть "List Index Out of Range" или как там оно в конкретном языке называется. В этом плане вероятность ухода ошибки дальше сильно снижается, т. к. если вы получали объект, то вы хотели с ним что-то сделать вот прям сейчас, а значит и по хоботу получите тут же. Кроме того, сама по себе ситуация, когда результата нет является первой, которую следует тестировать, если этого не делается, то тут извините, но говорить вообще не о чем.
Но в целом обрабатывать исключения намного геморойнее, чем числовые коды (или enum), и делать это во всех случаях, когда возможно отсутствие результата, неважно в каком виде это сигнализируется, приятного мало.
Как вариант, могу предложить что-то вроде BOOL TrySomething(int Id; out MyClass ReturnValue); Даже если язык позволяет не проверять вызов, сама по себе конструкция уже говорит: "Засунь меня в if".
@@beltar2 исключение обрабатывать проще: достаточно обернуть в try самый верхний вызов. Но я говорил не об этом, а о статическом анализе.
Например, если функция может вернуть null, компилятор должен заставит отработать такую ситуацию. В таком случае, у вас гарантировано не будет ошибок null reference. Например, такая фишка есть у typescript.
Правильно было бы: "Возвращать null в ДЖАВЕ, если ты еще учишься и не совсем понимаешь последствия этого - не стоит, но в конкретных ситуация опытные программисты вполне могут его использовать, а в других языках это вообще может быть хорошей практикой".
Опытные программисты-говнокодеры могут его использовать и на практике используют постоянно. А те, кто знает, что это тупо всегда находят способ его не использовать. Создатель Null сказал, что это была самая крупная ошибка в его жизни, которая нанесла за последние 60 лет убытков многим компаниям на миллиарды долларов и продолжает наносить, так как NullReferenceException кидается в 50% случаев неполадок в программе.
@@Lee-su5pg я не джавист и мне вот интересно, это такая особенность языка, что NullReferenceException аж в 50% случаев? В моей практике это крайне малый процент.
Александр Lee ну мужик, если я начну приводить примеры где null НЕОБХОДИМО использовать, тыж начнешь объяснять, что автор это уже сказал и это все понятно, а ты про говнокодеров... Конструкция null необходима, а говнокодеры и без нее найдут способы наговнокодить. А вот то что в джаве это такая проблема, когда во многих яп возвращения null является нормальной практикой, это уже претензии к джаве.
звучит как типичное название аниме
на си так вообще единственной
1) Тема Optional не раскрыта :)
2) Еще можно было бы акцентировать внимание на том, что если есть метод, который может найти и вернуть *несколько* объектов, а может и ни одного (0..*), то в случае если не нашёл ничего, то обязательно нужно возвращать пустую коллекцию (или пустой массив), а не тупо null "для экономии памяти". А то видел я такое как-то. В результате вместо обычного итератора, который для 0 объектов просто сработал бы 0 раз, приходилось писать if+итератор.
P.S. 8:55 "... если каждый метод на входе будет проверять не null ли все его 20 параметров..." - явная проверка параметров *публичных* методов на null (а точнее не конкретно на null, а вообще на корректность) является хорошим тоном при разработке API: у публичного метода должна быть предусмотрена "защита от дурака".
Да, тоже ждал, когда будет речь об Optional и - о, боже, нет! - о монадах, но видимо Сергей слишком Star.
так чего далеко ходить, в жабаскрипте так штатный match от строки работает. типа если ничо не нашел возвращает undefined. какая религия запрещает возвращать пустой массив - ума не приложу. в итоге условия вставлять надо (да, иногда это 4 символа лишних но некрасиво же).
@@TwilightSun32 Тоже в первую очередь вспоминается match из JS. Он возвращает null, а не undefined. Но к нему претензии только с точки зрения неудобств. Это не значит, что никакая функция не должна возвращать null. Видел такое решение, и сам перенял: ( s.match(…) *|| [ ]* ) - то есть в любом случае возвращается массив, это заметно упрощает алгоритмы.
@@user-bs6qw5gr1o да, я именно такую запись и имел ввиду когда писал про четыре символа. То что синтаксис позволяет сделать проверку краткой не отменяет же её наличия.
Он хотел сказать Optional но у него получилось Опшены :D ну ладно, и на том спасибо)
Вы посмотрите на API Java. Там огромное кол-во методов, которые выкидывают NULL, но это не особо волнует всех этих экспертов.
А кто сказал, что api java написано гениально? Смотришь в исходники, а там код как будто обфусцирован. Ну и совместимость, тянущуюся 25 лет, никто не отменял.
@@protiv_bio если вы говорите о том что API Java написано ужасно и на нем не следует учиться, тогда можно считать разработчиков самой Java - больными людьми. Просто гениальный подход, пишем код на Java, но исходники стандартных либ не смотрим, т.к. там все сделано через одно место.
@@protiv_bio на самом деле, если глянуть в код .NET - там тоже как будто обфускация. Но читая-читая-читая Рихтера или других толковых людей, начинаешь понимать, что это на самом деле очень сложная оптимизация. А где оптимизировать, если не в фреймворке
тоже самое в Android SDK
За годы существования Java к самому ООП неоднократно менялись подходы, но обратная совместимость, как уже упоминали, ни кто не отменял.
И весь код в try, а в catch перезапуск приложения, и вот тебе абузоустойчевость)
Ну вы даете, народ! Из-за какого-то NULL заставили человека писать видео на 20 минут
Да это ещё что - какой-то там NULL заставил создателя Java рвать на себе волосы.
Хехех
А мы-то что? Он первый начал!
Он только рад
@@alexlitsov9032 Сергей Немчинский любит поболтать.
Что за бред? Почему null приравнивается к Exception или вообще к какой-то ошибке? Null это нормальное значение, которое показывает, например, что в мапе нет значения по этому ключу.
"возврат НАЛА =откат=преступная коррупция" :))
Не все так однозначно 😉
Ведь строить бизнеслогику на эксепшенах тоже некомильфо. Эксепшен это когда что-то пошло не так, а кейс когда в таблице или в мапе чего-то нет, т.е. нулл - вполне штатная ситуация😉
Да и с точки зрения перформанса каждый раз возбуждать исключение затратно в java.
Тут уже надо конкретный случай рассматривать. Возможно, то, что в map может не оказаться объекта - это следствие неправильной архитектуры, и там вполне подошли бы nullObject-ы. Либо обращение к потенциальному источнику null-ов построить как-то иначе. Либо структура данных сделана не лучшим образом.
Писал моды на Lua для одной игрушки - там весь код приходилось увешивать проверками, потому что, получив какой-то конкретный объект, не было никакой гарантии, что все поля у него заполнены, и при обращении к ним приходилось сначала проверять, "есть ли кто дома".
Такой косяк был из-за архитектуры, а конкретно - нарушения LSP: в одних "объектах" все поля были заполнены нормальными данными, в других объектах, "наследованных" от того же родителя, часть полей могла просто не использоваться и быть равной nil (аналог null в lua). Будь архитектура правильной, "классы" бы расширялись, а не обрезались под конкретный случай, и лишних проверок не потребовалось бы.
+1 Эксшепны для бизнес логики это тоже плохой паттерн
@@user-lq1gk7li9y Естественно, но эксепшн имеет тип, может взлететь до первого catch, catch может отлавливать свой тип исключений, там хранится место ошибки.
Т.е. вы пытаетесь загрузить продукт по id...зачем это делать если мы не уверены что такой id существует? Если продукт был удален в промежутках получения этого id клиентом и совершением запроса, то это исключение. Т.е. исключения не должны отрабатывать в штатном режиме...но они упрощают работу с кодом
не знаю как в Жабке а в .Net если пытаешся из Dictionary вытащить что то при помощи dict[key] он кинет keyNotFound или что то в этом роде. для таких случаев есть TryGet
@@zariumsheridan3488 Незнаю как в жаба, но в php есть оператор @ чтобы заглушить вылетание ошибок и нотисов, а потом делаешь иф и выкидываеш исключение...чтобы все работало однородно.
А в шарпах получается есть два вида try и tryGet?
А если сериализуется JSON и у пользователя есть поле которое не установлено, значение его null
надеюсь следующее видео будет о том, почему нужно юзать котлин с null-safe и возвращать нулл
- Почему не кинуть exception из метода?
- Потому что генерация exception - дорогая по времени операция.
Что лучше?
Objecx x = callMethod();
if (x == null) { // Мы знаем, что если метод не отработает, то вернётся null
// handle error
}
try {
Object x = callMethod();
} catch (SomeException x) { // Мы должны знать, какой exception ловить
// Handle error
}
Что, сильно ситуация поменялась? Не думаю. Всё равно ошибки надо (сюрприз!) отрабатывать, от этого никуда не деться.
- Код полезет в коллекцию и получает NPE.
- Не выполнена конвенция о том, что в коллекции не могут храниться NULL-объекты.
- Метод называется getSomethingByName(), а на самом деле должен называться getSomethingByNameOrReturnNull();
- А JAVADOC для чего существует? Что мешает в описании параметра написать "can return null if "
- Вы получаете объект, который NULL;
- Брехня. Вы получаете ССЫЛКУ, которая не ссылается на валидный instance объекта, а не объект. Нарушением ООП это не является от слова совсем.
- Мы спускаемся с абстрактного мышления до уровня байтиков.
- #&*%*! А машина чем оперирует? Абстрактным мышлением вашим или байтиками? Вы железяку программируете или какую-то абстрактную эфимерную среду?
- Если вы упали сразу, то у программистов не возникает вопросов, как обработать этот Exception.
- Ну, смотря как упали. Если упали на проде и повредили какие-то важные данные этим падением (например, вызвали инконсистентность). Вообще-то, падать, в принципе, нехорошо.
- Если вы пишете серьёзную систему, весь основной блок находится в try/catch.
- Ой не зарекайтесь. Если система подразумевает обработку ошибок при вызове каждого метода, никакой try/catch вас не спасёт. Мало того, жирный try/catch - это антипаттерн. Вы чему людей учите?
Ну и т.д. и т.п.
Вообще-то когда метод может кинуть Exception у него будет throws и компилятор прогера пошлет если он этот Exception не обработает или не перекинет. А если метод вернет null, то прогер вообще не в курсе вернул метод null или нет и может ли он вернуть null в принципе.
"А машина чем оперирует". А компилятор на что? Не надо опускаться до процедурного программирования.
@@homo-ergaster Если exception наследуется от RuntimeException, то его упоминание в throws (сюрприз!) необязательно. Иначе везде бы были throws NullPointerException и тому подобные описания.
Разница между null и эксепшеном в том, что в случае с эксепшеном ты знаешь ЧТО именно обрабатывать, а в случае с null нифига не знаешь. А если этот null перед тем как положить программу пролетел через 100500 методов, ты вообще хрен БЫСТРО разберёшься, как исправить баг (конечно, если твоё приложение - не калькулятор из десяти-пятнадцати файлов). А если ты ещё и кидаешь null из МНОГИХ методов, будешь сидеть и офигевать. Что? Откуда? Какого хрена? Я же всё правильно сделал. 🙃 А если дотуда дошёл эксепшен, ты смотришь - эксепшен такой-то, ага - вот эта хрень значит отвалилась - по-быренькому исправил и не получил сильно по башке (или как вариант, не встрял на многомиллионные издержки).
В итоге что лучше: пожертвовать чуть больше памяти, или сидеть потом офигевать? Вопрос, конечно, философский. Но у меня есть подозрение, что тому, кто любит всё делать "руками", не нужны ООП-языки. Если памяти действительно так жалко, может нужно задуматься над тем, чтобы все проги сразу писать на ассемблере? 🙃
@@user-qh2ru8wk4t То же самое можно сказать про RuntimeException, который пролетел через 10 методов. Вы точно также нифига не поймёте, что произошло и почему, потому что исходные данные, которые привели к ошибке, в описании к RuntimeException не сохранены.
Вообще, если у вас возникают проблемы с пробросом NULL на 10 уровней вверх, то у вас, скорее всего, проблема с архитектурой вашего приложения.
> по-быренькому исправил и не получил сильно по башке (или как вариант, не встрял на многомиллионные издержки)
Ну, то есть, навернул костыль вместо того, чтобы родить фундаментальное решение, я правильно понимаю?
> В итоге что лучше: пожертвовать чуть больше памяти, или сидеть потом офигевать
Я предлагаю пожертвовать чуть больше мозгов. Ибо вы становитесь заложником LIE # 3:
cellperformance.beyond3d.com/articles/2008/03/three-big-lies.html
> все проги сразу писать на ассемблере?
Проблема ассемблера только в одном: он не переносим между разными аппаратными архитектурами, и под каждую архитектуру придётся писать код по-новому. Для решения этой проблемы был придуман Си.
@@homo-ergaster LIE # 1
cellperformance.beyond3d.com/articles/2008/03/three-big-lies.html
Классный формат видосов!
Логика нарушена. Почему, если возвращается null, то нужно переименовать метод в getStudentOrNull, а если выбрасывается эксепшон, то метод не нужно назвать getStudentOrThrowException?
по идеи если на метод повесить throws то его не нужно так называть?
Потому что компилятор заставит тебя его явно обработать. А о том, что метод может возвращать Null программист мог не знать или забыть
@@redeyes256 чего? Хотя да про указатели оказывается нам уже знать не надо
@@redeyes256 Это к сожалению проблема компиляторов и самих языков, потому что он также должен заставить обработать Null, если он там возможен
@@Gimli_Dwarf не понял к чему это вообще написано и причем здесь указатели
Долго слушал, и всё что я понял, так это то что автор сразу предлагает писать больше кода только ради того, чтобы не было NULL.
c++: постоянно использую возвращение nullptr в методах/функциях типа FindSomething(). Очень удобно. И когда это Something не найдено - это один из штатных вариантов, не требующий никаких эксэпшнов. В стандартных с++ контейнерах метод find возвращает какой-нить итератор end() в котором связанный указатель на Something равен nullptr. Какая тут принципиальная разница? Кроме того что без лишней конструкции в виде итератора - удобнее.
NullObject - это же по смыслу то же что и NULL, нам все равно для него нужно будет писать код отличный от случая с норм объектом типа if (NullObject != FindObject()) ... ручками в клиентском коде. И если такой NullObject заполненный дефолтными значениями попадет потом в какой-то список, чем это будет лучше попадания NULL? Уж лучше пусть прога упадет при обращении к нулевому указателю, чем не упадет и будет производить какие-то (рушащие логику) операции с дефолтными значениями NullObject, считая их правильными значениями полноценного Object.
NullPtr - смарт-указтель, он прямо говорит что null в нем неслучайное значение
Серега спасибо за видео!!
Спасибо большое, было полезно данную информацию услышать!!)))
Осталось теперь запилить видео почему нельзя кидаться эксепшнами. И где взять тип Either. И зачем NULL object, если есть Optional.
Optional закрывает конкретный случай, а null-объектов может быть несколько, если бизнесово их нужно различать.
Отличное объяснение, но хочу добавить, что в современных языках существует концепция nullable типов.
В rust например, в стандартной библиотеке для возврата нулевого указателя есть специальный тип Option, который может содержать в себе или объект или None. Если функция возвращает этот тип, то программист перед использованием объекта должен его явно "сконвертировать", либо проверив на None при помощи if let, либо вызвав у него специальный метод, кидающий исключение в случае None. Очень удобно, и никто не сможет "забыть" проверку на null, как часто бывает в Java или "забыть" try{} catch{}, как часто бывает в с++.
Так в Java тоже есть Optional. Но это ведь не null.
Спасибо за рекомендации книг! 👍
Здравствуйте Сергей, посмотрел ваше видео про курсы, заинтересовал подход. Посоветуйте, если я знаю core, сталкивался со спрингом, сталкивался с jdbc. Но уверенности в знаниях нет, имеет ли смысл сразу пойти на курс под названием Java EE? Реально ли с не очень большим запасом знаний, потянуть первые задания??
GetObjectByNameOrThrowObjectNotFoundIfNotFound
Лаконичненько )
Спорный вопрос. Обкладывать все вызовы try-catch? Что ожидать? Какой крутизны должен быть стек catch-a
Или другое - ловиться в catch наверху и разруливать стектрейс?
Что мешает использовать ?? .? подводя к дефолту/nullObject если прям очень надо?
Спасибо за видео! Полезно знать
Спасибо за хорошую и полезную мысль.
Кидать эксепшн из геттера только потому что по переданному айдишнику ничего не нашлось? Пожалуй я не готов быть экспертом.
Так сказано же, что кидать исключение в случае, если по указанному айдишнику всегда 100% должно вернуться что-то, отличное от null, что в общем-то логично - если метод всегда должен возвращать объект, а не возвращает, то где-то проеб и лучше кинуть исключение
@@shitposting_box Ааа, я понял, вместо простого нал, вернуть нал в обертке, может на уровне экспертов это и круто, но у ребят попроще точно все поломается когда они получат объект с нужным интерфейсом, но при этом полностью голый. Что значит "100% всегда что-то вернется "я не уловил, такое может быть только если метод параметров не принимает и всегда одно и тоже возвращает.
Или если это чистая функция, но мы ведь про геттеры.
@@user-rv5gy6mt3x допустим, мы конструируем объект, скажем, автомобиль. В его конструкторе инициализируем двигатель, но бизнес правилами авто без двигателя не должно существовать... Ставить null и везде в клиентах автомобиля проверять его? Или бросить исключение и ловить его в коде обладающем знаниями о том что с этим исключением делать?
@@justkrybik Я не люблю подобные примеры потому как они очень отдаленные, мы говорим не о уровне бизнес требований, а гораздо более мелком, хотя даже здесь я уже заранее знаю что однажды бизнес скажет: "А нет, все таки может быть авто без двигателя когда двигатель на кап ремонт вытащили". Вообще подобные ситуации уже давно решаются тайп хинтами, а мы обсуждаем предложение автора вообще никогда и ни при каких обстоятельствах не возвращать нал.
Очень-очень субъективная вкусовщина адептов истинного ООП (особенно в энтерпрайзе).
Лично для меня оч полезный видос оказался. Спасибо.
Хорошее видео. Спасибо!
Сергей, добрый день. Полностью согласен с тем, что вы сказали в видео. Однако всегда интересовал вопрос: почему когда мы пытаемся в Hibernate достать из базы поле с несуществующим id, мы получаем просто null вместо exception? Или таким фреймворкам возвращать null можно?
не знаю, как в Hipernate , но в Entity Framework есть метод First(), который вернёт эксепшн, а есть FirstOrDefault(), который вернёт нул. По-моему, логично
А если писать на котлине? Есть ли смысл кидать exception, если тип возвращаемых данных заранее тебе говорит, будет null или нет?
Нет, конечно. В нормальный языках такой хрени нет :)
Проблема только если это используются в связке с сырым jvm который плевать хотел на ненулабельность котлина.
Alex Smith через рефлекшн записать null в notnull поле)
@@it-6411 так Gson любит делать.)
Очередное классное видео от дяди Серёжи
Хочу добавить, что это вкусовщина и не стоит вовзодить это правило в абсолют, иногда NULL подходит лучше.
Примеры:
1. Не найден DSN - дальнейшее выполнение программы не имеет смысла.
2. Не найден менеджер для клиента - ОК, с этим клиентом пока не работают менеджеры.
Если в первом случае действительно лучше кинуть исключение, то во втором exception не подходит, так как:
а) Это не ошибка, а эксепшены обычно кидают в случае ошибок
б) Exception в данном случае тоже накладывает ограничение на клиентский код, более того он требует более громоздкой формы от клиента - try catch.
Приемлемо ли тогда иметь метод Find, который будет возвращать null? Например repository.FindById(20) возвращает null если данные не найдены. Конструкция простая и не вижу смысла ее усложнять.
Ты неверно понимаешь нэйминг. Если ты пытаешься получить что-то по уникальному полю, который определяется внутри вашей системы, то это всегда Get, иначе как вы смогли получить это что-то уникальное (например ID), если его ещё нет в системе. Если ты пишешь слово Find - то это должен быть поиск по не уникальным полям, а значит результатом будет коллекция. В случае если ничего не найдено, то это пустая коллекция. Единственный вариант с null - это поиск по уникальному внешнему ключу, который задаётся не вашей системой (например FindByExternalKey; Самый простор пример - это номер вашего паспорта, он уникален, но не вы создаёте/задаёте его, но вам нужно проверить зарегистрирован ли человек с таким номером паспорта у вас..). В данном случае вы пытаетесь проверить существует ли сведения о неком внешнем (не вашем) бизнес объекте, и этот случай близок к тому случаю, когда в видео говорилось что null допускается перед первым созданием объекта в некоторых архитектурных решениях.
@@iShredar Любой ID может быть удален со временем, но остаться в логах или прилететь по api. Некоторые таблицы чистятся, за ненадобностью. ID может быть введен пользователем с UI при поиске. В этом случае он вполне может отсутствовать, так как пользователь может ошибиться.
Не понятен пример про возврат пустой коллекции, я же спрашивал про repository.FindById, а не про Find
@@vad6525 Если вопрос был именно про repository (или любой слой, который работает с хранением данных), то стоило это указать сразу в вопросе, а не в примере. В таком слое нэйминг является больше договорённостью внутри команды, но как правило он соответствует тому что используется в Business терминах/правилах. Такой слой доступа данных - это просто прослойка, предоставляющая данные из хранилища в понятном виде для вашего приложения. В таком случае, я считаю вполне нормально получить null для одиночного объекта, так как по сути его вернёт ваша база. Но этот слой не должен быть доступен напрямую с вашего UI, то есть между UI слоем и слоем предоставления данных (repository ) должна быть прослойка, которая преобразует эти "сырые" данные, в вид соответствующий Business терминам/правилам. И вот тут уже null не допустим. Если вы что-то запрашиваете по ID то, что было удалено или не существует вовсе - исключение. Осталось что-то в логах? - логи не часть приложения или бизнеса, логи это побочный продукт жизнедеятельности, для них свои правила работы;
может прилететь по api? - проблема с архитектурой (не берём случаи, когда данные обрабатывались в некоторой задаче в момент удаления, тут банальное исключение)
"Не понятен пример про возврат пустой коллекции"
пусть нужно выполнить поиск по неуникальному полю, например FindStudentsByName, даже если ничего не найдено, не стоит возвращать null, правильно будет вернуть пустую коллекцию, что-то вроде new List ();
Думал раз затрагиваем тему NUll, то стоит сказать и об использовании Optional, но Сергей решил его проигнорировать.
Это что-то типа из разряда Enum?
PlayerKiller Yakutia это надстройка над null. Вы можете на ютубе к примеру вбить и узнаете больше.
Он же сказад про wrapper-классы (Future, Optional) как первый вариант
Hamster Go получается я пропустил. Тогда извиняюсь.
@@GK-tw7nu конечно можно, ты ведь возвращаешь не null, а обертку, из которой ты не прочитаешь значение без get(), а get() нормальный программист без проверки делать не будет. Тут хоть бейся головой об стену, не забудешь проверить))
Удачи ! Спасибо.
Что скажете про добавление методов `bool Exists(int id)` или `bool TryGet(int id, out Student student)`?
20:17 то есть возвращать бизнес невалидный обьект? мдаааааааа, fail-fast как говорится
А с чего вдруг, в озвученном случае, это невалидный объект? Видимо давлением газов рвущегося пукана уши заложило...
Потому что проверить возвращаемое значение проще, чем проверять поля этого значения
а потом мы еще этот объект мутировать будем, красота.
C# 8.0 добавил понятие nullable (ссылочные типы, допускающие значение null) и сделал объекты как бы не допускающими null. И теперь почвилось куча предупреждений в местах, где идёт обращение без проверки на нуль или передача таких значений в методы без это1 поддержки. Стало удобнее. Теперь, если твой метод всё таки может вернуть нуль, то ты добавляешь знак вопроса к имени метода.
А вот такой вопрос - я юзаю apache http и метод получения респонса требует обернуть его в трайкетч. А мне, собственно, нужно вернуть json который я беру из респонса. Соответственно объявлять json мне приходится вне трайкетча налом. Как будет правильно поступить в таком случае? Или кидать рантайм эксепшен в трайкетче где я отправляю запрос и получаю респонс - это нормально?
Мордочка))))) Так мило))))
А вообще супер объяснения, огромное спасибо за работу!
Создавать NullObject это: тратить ресурсы на создание и удаление не нужного обьекта. И все равно по бизнес логике может быть необходимо проверить этот NullObject, пустой он или полный.
каждый чих будем заворачивать в try except, а потом удивляться чего так все тормозит
Спасибо! Хороший урок!
Вообще звучит классно, нужно просто попрактиковаться с таким приемом.
есть класс Person
ему сколько-то лет
поле age
но сколько - неизвестно
значит оно == null
null просто сообщает, что возраст на данный момент не определен (и это правда).
это реальная, жизненная ситуация, ведь мы можем знать имя человека, но не знать его возраста.
поэтому в любом случае нужно каким-то образом обрабатывать ситуацию, когда возраст ещё неизвестен, но мы уже что-то хотим с ним делать.
и null кмк удобный и лаконичный способ для этого
никогда не имел серьезных проблем с этим (хотя может потому, что не пишу на jаva?)
твой пример ничего общего с видео не имеет. Там про возврат null из метода, а не о свойстве обьекта, хотя в описанном случае практичнее указать age: -1
по классике тебе нужно создать новый ValueObject Age со значением Undefined каким-то. Ну, или Optional можно использовать. Вобще, это правильно, но не практично зачастую. Хотя, в видео речь больше об объектах (Person), а Age это все-таки Value, несколько иная сущность.
@@jelooJusta Чем getProperty() не метод?
@@jelooJusta Возраст age==0 обманывает. Мы должны помнить, что 0 подразумевает отсутствие.
@@AnatolyPashmorha В видео вообще запрещается возвращать NULL, в любом случае
Null и undefined можно и нужно возвращать. Но только там где это нужно.
а если возвращать к примеру new Student(), это же объект который равный null, но но все же) так тоже не надо, или это что-то меняет?
Сергей как обойти ситуацию с null, если зависимости от того найден один или несколько обьектов зависит бизнес логика?
Использование "NULL обьектов" в первой докрине заканчивается появлением в базе "пустых" записей через связи, которые затем вытягиваются в общем списке, и не только. Так что NULL обьект тоже зло, и использовать его нужно очень аккуратно, что бы не сохранить его в базу или где то еще.
нельзя использовать NULL, это потому что у вас JAVA головново мозга. Если бы был С++
головново мозга то и NULL можно было использовать с assertions.
разработчики таких языков как Java или С# кроме языка ни о чём не думают. Как это будет работать по производительности ?.
Ни накладывают ли исключение дополнительные расходы ? и тд. Скажем вы когда нибуть думали что если в язык С дабавят
искючения и скажем в едре Линукс изменять все коды вызврата на исключения. Ну ответь очевидно. Я думаю может конкретно
в Java возвращять NULL это плохо (или С#). Видео должно было называться "Почему нельзя возвращать NULL в Java ?"
В плюсах можно возвращать объекты по значению и ссылки не могут быть NULL. Там этой проблемы не возникает.
@@Salabar_ а объекты, созданные с помощью new?
Он же и говорит о случаях, когда не юзаются умные указатели
@@V_ft Видос именно о неопределенности в интерфейсе функций. Если функция возвращает указатель, то ты всегда проверяешь его на NULL, даже если кажется, что такого не бывает. Потому что так принято. И это не так сильно бесит, потому что есть value-типы и ссылки, которые и используются в 95% функций. В Джаве же ты не можешь по сигнатуре понять, может она сломаться или нет: ты либо проверяешь буквально каждую строчку, либо ловишь NRE, либо так, как описано в видосе.
Возвращать null нужно только в том случае если это логично и подразумевается, что это штатная работа программы/метода, что ошибки в их работе не было, а просто, например, нет данных.
Так что насчёт optional? Использовать его как альтернативу возврата null и паттерна Null Object?
A как же стандартный JPA? Он-то как раз возвращает NULL, если в методе findById я впишу несуществующий ID, без всяких исключений и null object-ов.
Или просто «quod licet Jovis non licet bovis»? :D
Файнд и Гет -- как бы намекают, что они про разное…
Иногда возвращать null - нормально, иногда выкидывать exception - нормально, а иногда дефолтные объекты возвращать тоже норм :) Нужно от бизнес-логики идти. Думаю, нужно видео с противоположными аргументами "Почему нужно возвращать NULL?", ну чтобы всесторонне тему разобрать, за и против) а то пока только с одной стороны) не хватает взгляда с двух сторон, это как у нормальных журналистов, которые с разных сторон вопрос освещают
хороший канал, спасибо
Окей, но чем тогда отличается возвращение null от выбрасывания исключения в тех кейсах когда программа должна продолжить свою работу
Например аутентификация когда мы пытаемяся найти пользователя с определённым юзернеймом и от того, есть ли такой пользователь зависят дальнейшие действия , получается что вызывающий кот все равно должен обработать ситуацию только уже не с null, а с перехватлм исключения
рубисты молчать)0
Полезное видео.
К сожалению, "вершиной" программирования считается применение паттернов, при чем в таком формате, что чем больше паттернов использовал при написании модуля N - тем лучше.
А вот об умении писать код без null, об умении писать код с минимальным количеством if (когда код не витвится на 100500 вариантов, а "течет" по одному маршруту) - почти никто не говорит.
Ну и написание нескольких слоев авто-тестов (юнит, приемочные, интеграционные) должно быть по умолчанию, но, к сожалению, не везде они есть, и далеко не везде они покрывают весь функционал.
Будет ли новое видео про Go?
Очень классные и информативные видео, спасибо! Только смотрят их не только опытные разработчики, но и люди с маленьким опытом. В связи с чем было бы ещё круче вставлять, хотя бы, скрины с примерами кода для визуального понимания.
Если бы там были скрины, было бы не все так однозначно :-)
Офигеть прервёмся на рекламу. У меня перед твоей рекламой в этот момент вылезло ещё две.
adblocker
на всех операционках есть, даже на iPhone спокойно есть способ блочить рекламу
Претензии к ютубу - он сам решает, куда и сколько рекламы вставлять.
@@0imax Временные метки определяет автор видео, так было года два назад...что то поменялось?
@@grommaks Ты включаешь монетизацию, а ютуб сам решает какую рекламу и в каком количестве ставить. Причём сейчас всё настолько печально, что в зависимости от контента монетизация может быть недоступна, например, если в видео есть просто демонстрация оружия (порой даже страйкбольного) или какая-нибудь жесть, пусть даже это исторические материалы.
Ну а временнЫе метки, которые под полосой прокрутки - это уже автор делает, но на рекламу это вроде как не влияет.
Почему бы не возвращать какой-нибудь Optional тип, у которого будет свойство HasValue в значении True, если в Optional есть экземпляр нашего T, и False если нет? По моему идеальная вещь
В тех случаях, где есть вероятность вернуть null да.
Спасибо, с удовольствием послушал лекцию. Как оказалось, неосознанно уже натыкался натакие грабли неоднократно, но как именно чинить не знал, только ваоиант с дефолтными значениями.
А данное утверждение актуально например для работы в Unreal Engine? Если я возвращаю nullptr, когда нет например персонажа по указателю 🤔
Серега, переходи на JAVA 3, а именно KOTLIN, в котором узаконили возвращать null, потому что есть nonnull и nullable переменные. Бреслав отдельно подчеркивал, что null в котлине это тоже самое, что Optional.empty() в жаве, только без оберки и следовательно со всех точек зрения бесплатное.
И не надо оборачивать никакими проверками на null и специально следить, что тебе запихнут в String null не надо (null запихнут только в String?), все на уровне компилятора. Пример:
val name: String? = null
val length: Int? = name?.length //тут будет null и можно вызывать у null объекта метод без всякой if (..!=null) обертки
val length: Int = name?.length ?:0 // а тут ноль, кому не надо nullable переменных, тот и думает про default значение
val length: Int = name!!.length //а тут выпадет исключение, для любителей кидать и ловить исключения
Ээээх. Котлин, конечно, крут. Жаль что вакансий в энтерпрайзе на котлине кот наплакал (
@@homo-ergaster дописывать и подерживать, конечно надо на JAVA, но все новые микросервисы мы на котлине начинаем. Мне кажется все так.
@@svetopolk Ну не все. Если команда на Java и часть ее сопротивляется переходу на Kotlin, то хрен получится новое писать на нем.
@@homo-ergaster если большая часть команды сопротивляется то действительно не переходят. Только весь вопрос - а сопротивляются ли? Это реальный кейс?
@@svetopolk ну многие в команде его не знают и им в лом изучать, поэтому против. Потом в качестве IDE используем NetBeans, которая Kotlin не очень хорошо поддерживает, руководство не хочет покупать IDEA.
Вообще, каждый раз бросать исключение - весьма дорогое удовольствие. Нал стоит гораздо дешевле по производительности. Так что в каждой конкретной задаче надо смотреть и решать индивидуально, не надо как мантру повторять "главное не возвращать нал".
По дефолту он правильно говорит. А высокопроизводительные участки кода это всегда особый кейс, в котором часто нужно многое от чего отойти
С объектом понятно... А что с листами? Если вызываем что-то типа getAll(), но ничего не найдено. Что лучше: вернуть пустой лист или кидать not found?
Хороший вопрос. Просто не слушать автора и фигачить по-старому. Он решил похоливарить.
извините за дилетантский вопрос, но какая необходимость найденную или не найденную запись в базе данных возвращать на клиент в виде объекта как экземпляра класса? почему не в виде хеш-таблицы или сразу в виде JSON-структуры значений полей, т. е. в "родном" для "веб-морды" формате?
Тут говорят о языках со статической типизацией, которые стараются проверять ошибки при компиляции. Тот способ, который вы предлагаете, ближе к кожуре и другим языкам с динамической типизацией.
А как же быть с null в БД? Али переводить всё на not null, дабы, не дайте боги, не написать лишнюю проверку?
Зависит от логики. Зачем null в БД, для полиморфизма? Тогда hibernate на себя берет ответственность следить за этими полями. Если бизнес-значение может быть null, тогда можно обернуть в Optional/кидать runtime exception на геттере поля, при этом в throws его еще указать.
Вернуть объект с пустыми полями?
@@protiv_bio >обернуть в optional
Чтобы получить nullpointer, но с другим названием 😂
@@stormvoid7017 когда ты получаешь optional и не проверяешь его, это как минимум странно. Когда ты получаешь Object, ты рассчитываешь, что там лежит object. Таковы правила, и не я их придумал.
@@protiv_bio то есть проверять не равенство null`у, а что там скажет isPresent? Великолепная логика. Меняем одну проверку на другую.
Исключения на многих языках вроде как довольно дорогая ситуация, поэтому наверное не все следует реализовывать с помощью них. Но так конечно автор прав. Вообще в языках должно быть уже прямое указание, что там null быть не может, как в Swift.
Неважно дорогая или нет. На мой взгляд, тут другое ограничение. Исключения надо использовать только как исключения... сюрприз, да? То есть когда произошла реально ненормальная ситуация (ну например идет попытка активации несуществующей учетки, или БД недоступна, или чтение из файла завершилось ошибкой и т п). БЛ же на них строить - чистой воды безумие.
@@robotE13 вот соглашусь. и глобально контракт нам говорит, может ли объект вернуть нал или ошибку. поэтому с этой точки зрения вообще никакой разницы нет, ошибку обработать только "дороже" с точки зрения написания кода
Буду кодить прогу следующую, на ошибку зафигачу "Усе погано!"..)
Поступлю также)
А можно рассказать о вариантах решения проблемы? По факту получается нужно весь вызывающий код оборачивать в try catch. А много кто говорил , что эт прям тоже не очень. И чем по ресурсоемкости отличается проверка на null и прерывание по try catch. Допустим я вибираю метод Single, и например по любой фигне, которую вбил пользователь кидается exception. Разве это также не накладывает ограничений на вызывающий код?
Сергей, спасибо! Расскажи о тестировании для не тестировщиков. Какие виды тестов бывают? В каких случаях обязательно тестировать код, когда отложить на потом? И т. д.
Я не Сергей, но отвечу
Самый базовый вид тестов - unit тесты. Ими тестирую функционал в пределах класса или модуля. Есть методология TDD, при которой сначала пишутся тесты, а потом под них подгоняется код (до его готовности). Писать или нет зависит от проекта, если вы работаете один, над небольшим проектом, то написанием тестов сильно усложните себе жизнь. С ростом проекта, в геометрической прогрессии возрастает шанс появления ошибок и регрессий, при внесении нового функционала. В таком сценарии наличие тестов сыграет вам на руку и позволит гораздо быстрее находить ошибки.
P.S. Написание качественных/несущих пользу тестов, требует качественного кода.
"Nooone " прошипел python и уполз под корягу.
А есть ли разница? Стол или table?
1. null это не всегда ошибка. отсутсвие чего-либо это абсолютно нормальная ситуация, особенно когда вы работаете с неявной формализацией. при этом дефолтный объект тоже не всегда хорошо.
2. если вы не проверяете входные значения из не своего кода, вас прибьёт любой безопасник. это я вам как безопасник говорю.
3. не все языки умеют нормально обрабатывать исключения, например python. тогда код превращается в многоуровневую фигню из try except
Касательно Java: а если я вместо null верну Optional? Это норм решение или такое же г. как и сам null?
Да, это может стать холиварной темой. Но, поскольку исключения подтверждают правила, то в некоторых случаях возвращать нул полезно или даже необходимо. Например при реализации итератора и метода next().
"Почему нельзя возвращать NULL?"
потому что надо с умным видом плодить классы
А на каждый класс - свой интерфейс.
кстати, а почему вместо NULL не возвращать пустой массив или пустую хеш-таблицу?
@@user-nz2hh9po2r Если речь о любых коллекциях (массивы, списки...), то лучше, конечно, вернуть пустой, чем null
@@0imax в хороших ЯП все объекты и есть списки и/или массивы
@@user-nz2hh9po2r Ну под капот мы не лезем, так-то любой класс - это куча массивов с указателями на данные и на функции.
Хорошо, тогда что делать, если функция вызывается во многих местах в коде, и каждый раз подобное событие ненахождения чего то должно выдавать немного разную ошибку в эксепшен? А в третьем месте это вообще должно быть выдано не как эксепшен, а как молчаливая запись ошибки в некий журнал событий? По мне так закладывать эксепшен в код метода общего назначения это какая то дичь.
В JS (и не только) есть конструкция optional chaining которая прекрасно решает эту проблему. Object?.method?.() ?? ; вуаля, поведение аналогично паттерну NullObject ничего не произойдет и ошибки не будет. Так или иначе, что бы мы ни использовали всегда есть плата в виде каких-то проверок или перехватчиков, мы в любом случае не можем игнорировать отсутствие объекта в результате, это кейс который должен быть обработан, чем бы результат не являлся и какой бы паттерн мы не применили. Чтобы программисту было понятно что метод может вернуть null хорошо использовать аннотации и IDE которые могут это показать. Не вижу ничего страшного в современных языках использовать null, большинство решило эту проблему и умеет работать с null корректно.
Взяли меня масленком на работу программистом. И нужно было написать парсер. И в одном из методов я возвращал null. Продакшн я положил...и причём это выяснилось уже во время релиза. Потому что null был в очень особенном случае. Было весело))) Поэтому null я вообще теперь стараюсь не трогать))))))
Ну это больше вопрос к тестированию 😉
О такой гипотетической ситуации я тут писал сторонникам возврата null, а вот и живой пример :)
Дурак тут тот кто сделал null таким особенным
@@lyloo6577 Указатели в никуда были ещё в Си. В джава не стали придумывать что-то особенное.
@@0imax я имела ввиду, что не надо на такую повсеместно используемую штуку как null весить особенное поведение. Это примерно как человек который на "привет" отвечает ударом в морду )
как жить дальше если даже javax.persistence.EntityManager.find() возвращает null?
Это же другой слой приложения. Тут как бы про доменный слой больше говорилось...ну мне так показалось...наверно 🦊
WebDev. GromMax ну я так понял автора что в любом слое это плохо
@@alexanderchumachev3520 Я вам так скажу, если ваш домменный слой будет работать с классами фреймворка, то это путь к проблемам при обновлении.
Нужно сделать адаптер, который уже эти null заменит на exception и использовать ваш адаптер во всем проекте. Когда фреймворк обновится...ваш адаптер сломается...но это всего одно место в проекте)
Если вы делаете приложение калькулятор...то тут можно не заморачиваться.
Вывод, не важно чтт делает фреймворк или библиотека. Сделайте адаптер и работайте с консистентным набором классов
WebDev. GromMax Мой каментарий был сарказм, я категорически не согласен что есть необходимость везде нулы поубивать. Фреймворк работает верно
По-моему, прекрасно все упомянутые проблемы решены в Kotlin:
- явное именование методов, например listOf(1, 2, 3).firstOrNull { it > 2 }
- Null-safety: вы всегда твёрдо знаете (если речь не идёт о легаси-библиотеке) и вынуждены это учитывать, где может быть null, а где -- нет
- Изящные синтаксические конструкции для обработки null'ов, вроде Elvis Operator.
А если метод обновляет существующие данные объекта. И мы можем же передать только измененные поля, и тогда в момент присваивания мы можем проверить является ли один из параметров null, и если он является то мы не изменяем это поля. Здесь получается null используется как у индусов)что можно сделать в данной ситуации?
Обработка эксепшена гораздо дороже проверки на null
Паттерн "преждевременная оптимизация" передаёт привет.
@@0imax преждевременные роды передают привет
@@vladgonchar сочувствую.
Мне нравится, как в Laravel сделано. Есть метод find(), который вернёт null, и есть метод findOrFail(), который бросит исключение (которое, если не поймать, просто даёт 404-й статус ответа), если что-то не нашлось. Таким образом когда ты ожидаешь, что чего-то не будет, есть возможность не замарачиваться с try/catch, а если не ожидаешь - пишешь findOrFail(). Ну конечно надо доку прочитать, и знать.
Ну да, и количество методов увеличивается в 2 раза ради ровно одного null.
IMHO возвращать null, если элемент не найден - это норма. По крайней мере, стандартные коллекции так работают. А вот если что-то пошло не так - согласен, не стесняйтесь кинуть Exception.
Помимо всего прочего, бросание специфического эксепшена помимо возврата нулл имеет ещё одно преимущество: когда в методе мы работаем с 2-мя (или больше) объектами (например, связываем их) и любой из них нужно проверить на существование. Тогда возврат нула (если предполагается, что метод вообще должен что-то вернуть) не даёт понятия, какой из объектов не найден. С эксепшином же мы можем передать, какого из объекта нет.
А также метод может не возвращать ничего и работать даже с одним объектом, требующим проверки на существование, нам же выше нужно сообщить, что метод по сути не выполнил ничего, с объектом ничего не произошло (по причине его отсутствия), а не просто "проглотить" типа ничего не произошло. То есть стратегия бросания эксепшена - действенная и универсальная