Comments 13
Хм...
"Null return" - плохо
"Т.е. проверили, и если случай негативный, то либо return, либо если в цикле continue." - сами же пишете код который возвращает object|null.
Ага. Идёшь такой в репозиторий и просишь вернуть что-то по ID, например. А он тебе вместо null возвращает какой-то NullObject, который "такой же, только без хвоста". И как будем проверять какой http status code возвращать? 404 или 200?
Опять-таки, если ты ожидаешь iterable, то логично его и вернуть. В случае с коллекцией логично, что возвращаешь коллекцию, просто пустую. Но в случае одного объекта, которого может по логике и не найтись зачем выдавать что-то искусственное? Всё равно где-то придется проверять настоящий это объект или нет. Почему не сразу?
Хорошая коллекция. Хочется уточнить 2 момента.
Дублирование кода ненужно рассматривать дословно. Нельзя дублировать одинаковое решение одной и той же проблеммы. Т.е. вполне можно и нужно дублировать код, если он используется для решения совершенно разных задач, т.к. в дальнейшем скорее всего логика будет развиваться по разному.
Передача параметров через DTO. Многие так и делают, но по феншуй DTO предназначен не для передачи данных между классами, а для передачи данных в дорогих удаленных вызовах (API). Для передачи группы параметров между классами / методами правильнее использовать PO (Parameters Object)
Как же я люблю такие статьи. Одни буквы и минимум кода. Сделайте для каждого утверждения в статье код. Лично я мотал, для новичка немного будет не понятно, так как нет примера кода.
Null return
Вот совсем не понял каким образом NullObject решает какие-либо проблемы nullable return.
На личном опыте в большинстве мест с таким возвратом достаточно обернуть его в if:
if ($user = $this->userRepository->findById($id)) {
//...do something
}
Не сильно усложняет структуру кода, и не вредит читабельности.
Как альтернатива, для случаев когда получение null из метода неприемлемо можно выбросить из него исключение. В таком случае и дополнительного уровня вложенности не появится и тайпхинтиг выйдет более строгий, ну а весь последующий после вызова такого метода код будет работать только в случае получения полноценного результата из него.
$user = $this->userRepository->getById($id);
//...do something
Ну а для того чтобы отличать эти методы принимаем правило по неймингу:
методы которые могут вернуть null - должны иметь префикс find..
методы которые не могут вернуть null но могут бросить исключение - должны иметь префикс get..
Это в первую очередь касается всяких репозиториев, в других местах с nullability ответа не сильно сталкивался.
А как быть с геттерами в сущностях? Свойства могут быть nullable.
Откуда эта инфа с find / get ? Эсли у меня findItems() / getOneById() методы. Find - поиск по сути и лучше возвращать пустой массив, зачем там null? Не вводите народ в ступор
еще удачи с NullObject описывать вложенные nullable-сущности, красота будет прям)
Всегда придерживаюсь всех этих правил. Действительно, всё намного надёжнее, очевиднее, да и проще как-то.
Например, в Laravel лучше возвращать, если ничего не было найдено, пустую коллекцию нежели null.
Вот тут немного смешно, учитывая, что херова куча встроенного в Laravel функционала может возвращать именно null. Да и nullsafe в php тоже есть и всякий сахарок типа
$object->getSome()?->doSomethingMore()
выглядит местами понятнее (да, оно работает только на чтение, но и проверку is_null никто не отменял тоже)
В целом согласен, но после примеров кода, не оформленных даже по PSR-12 становится как-то грустно.
Code smells — обзор на примере PHP