Upgrade to Pro — share decks privately, control downloads, hide ads and more …

コードの責務を例外で表現しよう PHPerKaigi2024

Takuma Kajikawa
March 08, 2024
250

コードの責務を例外で表現しよう PHPerKaigi2024

PHPerKaigi2024「コードの責務を例外で表現しよう」のスライドです。
https://fortee.jp/phperkaigi-2024/proposal/ccf82ead-5a28-4c15-a034-1ead5838f2c1

Takuma Kajikawa

March 08, 2024
Tweet

Transcript

  1. 3

  2. 一見、エラーが起きなさそうなシンプルなコード function addNumbers(int $a, int $b): int { return $a

    + $b; } 引数に文字列が渡される 加算した結果がPHPがサポートする整数型の最大値を超える 実行環境のマシンでメモリーが足りなくなった 7
  3. 起きそうなエラーのハンドリングをひたすらやる? try { $this->db->create(...$args); } catch (InvalidArgumentException) { // 引数の形式が間違っている時の処理

    } catch (PDOException) { // DB エラーに対する処理 // 省略 } catch (Throwable) { // その他のエラーが起きた時の処理 } 11
  4. 例外で処理を中断する = 責務の分離 throwすると、catchするまで処理が中断される class Id { public function __construct(int

    $value) { if ($value <= 0) { throw new InvalidArgmentException(); } $this->value = $value; } $id = new Id(0); // 以降は実行されない $this->repository->findById($id); 15
  5. @throwsで宣言された例外がある場合のハンドリング try { myLogic(); } catch (MyException $e) { //

    何かしらの処理 } 処理しない場合はさらに呼び出し元へ任せる事ができる。 /** * @throws MyException */ public function myLogicCaller() { myLogic(); } 17
  6. カスタム例外の定義例 final class CouldNotFindMeetup extends Exception { private function __construct(

    string $message, ) { parent::__construct($message); } public static function withId( MeetupId $meetupId ): CouldNotFindMeetup { return new self( "Could not find a meetup with ID {$meeupId->value()}" ); } } 24
  7. カスタム例外を投げるメソッドの定義 1. InvalidArgumentExceptionを投げる 2. RuntimeExceptionなどを投げる 3. ビジネスロジックで使う可能性のあるカスタム例外を投げる /** * @trows

    CouldNotFindMeetup // ...3 */ public function findById(int $id): MeetUp if ($id <= 0) { throw new InvalidArgmentException(); //...1 } $meetup = $this->dao->find($id); // ...2 if ($meetup === null) { throw CouldNotFindMeetup::withId($id); // ...3 } return $meetup; } 25