never throw
v2.0.0
提供一种严格键入的方法来处理PHP应用程序的成功和错误结果。
受到Neverwor的启发,因此我们正在简单地实现PHP的Never。
投掷和捕捉与使用goto语句非常相似 - 换句话说;它更加努力地对您的程序进行理由。其次,通过使用抛出,您可以假设功能的呼叫者正在实现捕获量。这是已知的错误来源。示例:一个开发人员抛出,另一个开发人员使用该功能,而无需事先知道该功能会投掷。因此,Edge Case已被遗忘了,现在您有不愉快的用户,老板,猫等。
话虽如此,肯定有一些很好的用例可以投入您的程序。但是比您想象的要少得多。
tl; dr:no throw =更快乐的生活和应用。生产中的错误较少,并增加了PHP应用中的干燥和可重复使用的东西。
自v2.0.0以来
composer require shipsaas/never-throw NeverThrow\Result类,并随时可以延长。
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是没有类型的!
上述“异常”或“错误”根本不是例外或错误。他们是结果。它们是我们系统中可预测的,合理的部分。我的启发式是,如果他们是一个好的产品经理会关心的话,它们并不是例外,您不应该扔它们!
例外是我们无法合理地计划的不可预测的事情,系统不应尝试恢复,我们不应向用户路由。
麻省理工学院许可证