Slide 1

Slide 1 text

nullsafe演算子を使おう 〜if文地獄からの開放〜 PHPカンファレンス関西2024/02/11 仲見川勝人@NakMeKtt

Slide 2

Slide 2 text

- 仲見川 勝人(@NakMeKtt) - 職業 - Software Engineer - Mobile App, Front End, Server Side - 所属 - 株式会社ホワイトプラス - 宅配クリーニング「リネット」の開発 - Tech lead - アプリ開発G Engineering Manager 自己紹介 2 好きな技術領域 - Flutter, Android - サーバーサイド(PHP, Go) 好きなクラウドサービス - CloudRun、S3 好きなもの - ソーセージ、映画、アニメ、FF14、 新しい技術

Slide 3

Slide 3 text

みなさんnullチェックしてますか? 3

Slide 4

Slide 4 text

PHP8.0〜使ってますか? 4

Slide 5

Slide 5 text

nullsafe演算子使ってますか? $obj?->method() 5

Slide 6

Slide 6 text

nullsafe演算子はPHP8.0より導入され、プロパティやメソッ ドにアクセスするアロー演算子(->)を拡張したものです。 PHPドキュメントには以下のように記載されています 6

Slide 7

Slide 7 text

オブジェクトが null と評価された場合に、例外はスローされず、 null が返される点だけが異なります。 従来のアロー演算子は変数がnullであった場合、プロパティや メソッドが存在しないためエラーとなっていました。 nullsafe演算子はエラー(例外)を発生させずにnullが返るよ うになっています。 7

Slide 8

Slide 8 text

アロー演算子の例 実行結果 8 上記コードは3V4Lで試せます:https://3v4l.org/1nGrb

Slide 9

Slide 9 text

nullsafe演算子の例 実行結果 9 上記コードは3V4Lで試せます:https://3v4l.org/iiuuM ※エラー無し

Slide 10

Slide 10 text

オブジェクトの評価がチェインの一部だった場合は、 残りのチェイ ンはスキップされます。 ここがnullsafe演算子の非常に強力な所で、従来だとnullable の変数に対してメソッド呼び出しを行う場合is_nullなどで nullチェックが必要だったために、メソッドチェーンが書けま せんでした。 10

Slide 11

Slide 11 text

$repositoryがnullの場合その時点でnullが返され、 getUser(5)やnameプロパティは呼ばれません。 11

Slide 12

Slide 12 text

実際のコードでみていきます 12

Slide 13

Slide 13 text

こういうクラスがあって(1) 13 ※実際にはDBから取得する処理があると思ってください

Slide 14

Slide 14 text

こういうクラスがあって(2) 14

Slide 15

Slide 15 text

いまままではこう 15 ※実は$userのnullチェックは省略しても WARNINGレベルです。  $user->getName()だと例外が発生します。

Slide 16

Slide 16 text

nullsafe演算子を使うとこう 16

Slide 17

Slide 17 text

ユーザーから注文一覧を取得して、そこから最後の注文の注 文商品名をとりたいときこんな感じに…… 17

Slide 18

Slide 18 text

メソッドを切り出して早期リターンすればネストは深くなら ないもののif文の数は多い…… 18

Slide 19

Slide 19 text

こんな場合でもnullsafe演算子を使うとこう 19 以下のように改行しても大丈夫

Slide 20

Slide 20 text

劇的BeforeAfter if文が乱雑に積み重ねられたコードが 匠の手(nullsafe演算子)によって、 スッキリと変貌を遂げました 20

Slide 21

Slide 21 text

でもさー そもそもnullableじゃなければ いいんじゃない? 21

Slide 22

Slide 22 text

どんな時も、とにかくUserを返しちゃおう 22

Slide 23

Slide 23 text

これでOK! 23

Slide 24

Slide 24 text

ではないですよね。 これは擬似的なコードなので問題は起きませんが、 実際のアプリケーションの場合DBから値を取得するなど、 Userが存在しない場合も考慮するケースも存在します。 24

Slide 25

Slide 25 text

考慮してみましょう 25

Slide 26

Slide 26 text

呼び出し側 26

Slide 27

Slide 27 text

これは簡易ですがNull Objectパターンと呼ばれる物で、 呼び出しを行う際にnullチェックは回避することが可能です。 27

Slide 28

Slide 28 text

ユーザーが存在しない場合は例外を投げたい 28

Slide 29

Slide 29 text

Null Objectパターンの実装 29

Slide 30

Slide 30 text

ユーザーが存在しない場合は例外を投げたい(ver.2) 30

Slide 31

Slide 31 text

このケースはnullsafe演算子でもカバー出来ないためnull チェックを行う必要があります。 31

Slide 32

Slide 32 text

どのタイミングでnullが返るか分からなくても良ければ nullsafe演算子でも可能    ※このケースだとrepositoryがnullは別途ハンドリングした方が良いのでオススメはしません 32

Slide 33

Slide 33 text

nullsafe演算子を使うとこういった書き方も出来ますが…… 33

Slide 34

Slide 34 text

都度メソッドチェーンで取得する処理の無駄(※1) と、 代入とnullチェックを行う方が結果的にtype数も少なく読みやすく なります 34 ※1:もしgetOrder()がSQLを発行してたら目も当てられない

Slide 35

Slide 35 text

なので、実際の使いどころとしては注文のプロパティまで取得する よりは注文オブジェクトを取得するといった場面になります 35

Slide 36

Slide 36 text

まとめ(使いどころ、使い分け) ● アロー演算子(->) ○ nullableでないことが型宣言により分かっ ている場合やnullチェック後に参照する時 ● nullsafe演算子(?->) ○ nullableであることが型宣言により分かっ ている場合に1項目取得したい時 ● Null Objectパターン ○ 存在しない場合にも同じ振る舞い(名前を 返す等)をしてほしいもの 36

Slide 37

Slide 37 text

nullsafe演算子を用いる事で スマートに実装して行きましょう! 37

Slide 38

Slide 38 text

また、 今回はお話しませんでしたが、nullsafe演算子をより効率よ く使用するためには引数や戻り値にnullかどうか分かるように 型が定義されていることやPHPStanを用いた静的解析が欠か せません。ぜひPHPStanにも興味を持って頂ければと思いま す。 38

Slide 39

Slide 39 text

ご静聴ありがとうございました 39