PHP 응용 프로그램의 성공 및 오류 결과를 처리 할 수있는 엄격하게 입력 한 방법을 제공하십시오.
Neverthrow에서 영감을 얻은 So So Dere는 PHP에서 Neverthrow를 간단하게 구현했습니다.
던지기와 잡기는 goto 진술을 사용하는 것과 매우 유사합니다. 그것은 당신의 프로그램에 대한 추론을 더 어렵게 만듭니다. 둘째, Throw를 사용하여 기능의 발신자가 캐치를 구현하고 있다고 가정합니다. 이것은 알려진 오류의 원인입니다. 예 : 하나의 개발자가 던지고 다른 개발자는 기능이 던질 사전 지식없이 기능을 사용합니다. 따라서 에지 케이스가 손가락을 깎지 않고 이제 불행한 사용자, 보스, 고양이 등이 있습니다.
모든 말로, 프로그램에 던질 수있는 좋은 사용 사례가 있습니다. 그러나 당신이 생각하는 것보다 훨씬 적습니다.
tl; dr : throw = 더 행복한 삶 및 응용 프로그램. PHP 앱에서 생산 오류가 적고 건조 및 재사용 가능한 물건을 증가시킵니다.
v2.0.0 이후 PHP 8.2+
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가 유형 이 없음 을 의미합니다!
위의 "예외"또는 "오류"는 실제로 예외 나 오류가 아닙니다. 그들은 결과입니다. 그들은 우리 시스템의 예측 가능하고 합리적인 부분입니다. 내 휴리스틱은, 그들이 좋은 제품 관리자가 관심을 가질 것이라면, 예외가 아니며 당신은 그들을 던져서는 안된다는 것입니다!
예외는 우리가 합리적으로 계획 할 수없는 예측할 수없는 것들이며, 시스템이 회복을 시도해서는 안되며, 사용자에게 라우팅해서는 안됩니다.
MIT 라이센스