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是沒有類型的!
上述“異常”或“錯誤”根本不是例外或錯誤。他們是結果。它們是我們系統中可預測的,合理的部分。我的啟發式是,如果他們是一個好的產品經理會關心的話,它們並不是例外,您不應該扔它們!
例外是我們無法合理地計劃的不可預測的事情,系統不應嘗試恢復,我們不應向用戶路由。
麻省理工學院許可證