Предоставьте строго напечатанный способ справиться с результатами успеха и ошибок для ваших приложений PHP.
Вдохновленный Neverthrow, так что здесь мы с простой реализацией Neverthrow от PHP.
Броски и ловушка очень похожи на использование операторов GOTO - другими словами; Это усложняет рассуждение о ваших программах. Во -вторых, используя бросок, вы предполагаете, что вызывающий абонент вашей функции реализует улов. Это известный источник ошибок. Пример: один бросок Dev, а другой Dev использует функцию без предварительного знания, которую будет выбросить функцию. Таким образом, и Edge Case остался без вести, и теперь у вас есть несчастные пользователи, боссы, кошки и т. Д.
С учетом всего сказанного, определенно есть хорошие варианты использования для добавления вашей программы. Но гораздо меньше, чем вы могли бы подумать.
TL; DR: НЕТ Брось = Счастливая жизнь и применение. Меньше ошибок в производстве и увеличение сухого и многоразового использования в ваших приложениях PHP.
PHP 8,2+ с v2.0.0
composer require shipsaas/never-throw NeverThrow\Result Class и готов к расширению в любое время.
isOk()isError()getOkResult()getErrorResult() Мы создадим два новых класса: успех и ошибка. И не стесняйтесь поместить какие -либо из ваших данных
use NeverThrow SuccessResult ;
use NeverThrow ErrorResult ;
// Success
class BookShipperOkResult extends SuccessResult
{
public function __construct (
public string $ bookingId
) {}
}
enum BookingErrors {
case NO_SHIPPER_AVAILABLE ;
case OVERWEIGHT_PACKAGE ;
case INVALID_ADDRESS ;
}
// Error
class BookShipperErrorResult extends ErrorResult
{
public function __construct (
public BookingErrors $ outcome
) {}
}Последний шаг перед использованием Neverthrow. Создание выделенного класса результатов помогает нам:
use NeverThrow Result ;
class BookShipperResult extends Result
{
public function getOkResult (): BookShipperOkResult
{
return parent :: getOkResult ();
}
public function getErrorResult (): BookShipperErrorResult
{
return parent :: getErrorResult ();
}
} public function createBooking ( User $ user , BookingOrder $ order ): BookShipperResult
{
$ hasAnyShipperAvailable = $ this -> shipperService -> hasAnyShipperAvailable ();
if (! $ hasAnyShipperAvailable ) {
return new BookShipperResult (
new BookShipperErrorResult (
BookingErrors:: NO_SHIPPER_AVAILABLE
)
);
}
$ isOverweight = ! $ this -> weightService -> isValid ( $ order );
if ( $ isOverweight ) {
return new BookShipperResult (
new BookShipperErrorResult (
BookingErrors:: OVERWEIGHT_PACKAGE
)
);
}
$ bookingId = $ this -> book ( $ user , $ order );
return new BookShipperResult ( new BookShipperOkResult ( $ bookingId ));
} $ bookingResult = $ this -> service -> createBooking ( $ user , $ order );
if ( $ bookingResult -> isError ()) {
$ errorResult = $ bookingResult -> getErrorResult ();
// handle error
return showError ( match ( $ errorResult -> outcome ) {
BookingErrors:: NO_SHIPPER_AVAILABLE => ' No shipper available at the moment. Please wait ' ,
BookingErrors:: OVERWEIGHT_PACKAGE => ' Your package is overweight ' ,
});
}
return showBooking ( $ bookingResult -> getOkResult ()-> bookingId );Как вы можете видеть с приведенным выше кодом, есть:
Это принесло бы развитию действительно потрясающе и не болит.
С строго напечатанными типами возврата, разработчики могут знать, что происходит с другими службами/библиотеками. Таким образом, делает многоразовый лучше. И нам не нужно обернуть попытку/поймать и настраивать наш код.
Не злоупотребляют исключениями, они должны использоваться только для неожиданных ситуаций (и ошибок! == Исключения, факт).
function transfer (): Transaction
{
if (! $ hasEnoughBalance ) {
thrown new InsufficientBalanceError ();
}
if (! $ invalidRecipient ) {
throw new InvalidRecipientError ();
}
if (! $ invalidMoney ) {
throw new InvalidTransferMoneyError ();
}
$ transaction = $ this -> transferService -> transfer (...);
if (! $ transaction ) {
throw new TransferFailedError ();
}
return $ transaction ;
}Большая часть этой функции на самом деле касается того, что может пойти не так, но наши типы сообщают нам только об успешном пути. Это означает, что 4/5 -е из вывода функции нетипирован !
Приведенные выше «исключения» или «ошибки» на самом деле не исключения или ошибки вообще. Это результаты. Они предсказуемые, разумные части нашей системы. Моя эвристика - если бы они были чем -то хорошим менеджером по продукту, это не заботится о том, что это не исключения, и вы не должны их бросать!
Исключения - это непредсказуемые вещи, которые мы не можем разумно планировать, о том, что система не должна пытаться восстановить, и мы не должны направляться к пользователю.
MIT Лицензия