$30 off During Our Annual Pro Sale. View Details »

Simple Strategy to Read PHP More Easily

inouehi
November 10, 2023

Simple Strategy to Read PHP More Easily

『ちょこっとラクするPHPコード読解術』

Qiita Night〜PHP〜
2023/11/10 19:15~
https://increments.connpass.com/event/297095/

inouehi

November 10, 2023
Tweet

More Decks by inouehi

Other Decks in Technology

Transcript

  1. 2023/11/10 Qiita Night〜PHP〜
    ちょこっとラクするPHPコード読解術

    View Slide

  2. 2
    ● Hiroki Inoue
    ● Software Engineer
    ● Engineering Manager @ WHITEPLUS, Inc.
    About Me

    View Slide

  3. 3
    PHPで書かれたコードの読み方に興味がある方向けのトークです。
    恐らく主に初心者の方向けだと思います。
    誰向けのLT?

    View Slide

  4. 4
    アジェンダ
    前提
    伝えたいこと
    01
    02
    結論
    解決したい課題
    03
    04
    Xxxxxxの活用方法
    05
    まとめ
    06

    View Slide

  5. 5
    静的解析(Psalm, PHPStan, RectorやPHP Parser)等の仕様を理解する目的で読むことが多いです。
    IDEはPHPStormです。
    前提

    View Slide

  6. 6
    あなたのコードの読み方を教えて下さい!
    でもその前に私のやり方を紹介します。
    #QiitaNight
    伝えたいこと

    View Slide

  7. 7
    Xdebugを活用しよう!
    結論

    View Slide

  8. 8
    Xdebugを活用しよう!
    デバッグ以外に利用したっていいじゃない。
    結論

    View Slide

  9. 9
    解決したい課題

    View Slide

  10. 10
    コードが込み入ってくると迷子になりやすい。
    覚えることと考えることを同時にやるのは負担が大きい。
    覚えることを減らして、考えることに集中したい。
    解決したい課題

    View Slide

  11. 11
    解決したい課題
    コードが込み入ってくると迷子になりやすい。
    覚えることと考えることを同時にやるのは負担が大きい。
    覚えることを減らして、考えることに集中したい。

    ● コードベース全体を理解しようとしない。
    ● 思考過程やメモをコード中に書きながら読み進める。
    ● 確認したいことをどこかに箇条書きしながら読み進める。
    ● 簡単化する。
    ● 機械に委譲する。☜本日のスコープ

    View Slide

  12. 12
    解決策(再掲)
    ● コードベース全体を理解しようとしない。
    ○ 目的を絞る、確認する機能を絞る。
    ○ issueを起点に読み始めるようにしている。
    ● 思考過程やメモをコード中に書きながら読み進める。
    ○ コードの外に書こうとすると、メモと該当箇所の紐付けが煩わしい。
    ● 確認したいことをどこかに箇条書きしながら読み進める。
    ○ 読んでいる内に目的を忘れるのを防ぐ。読むのに集中できる。
    ● 簡単化する。
    ○ シンプルな処理で挙動を確認する。
    ○ 徐々に複雑にしながら、挙動の差異に着目して処理を追う。
    ● 機械に委譲する。☜本日のスコープ

    View Slide

  13. 13
    解決策(再掲)
    ● コードベース全体を理解しようとしない。
    ○ 目的を絞る、確認する機能を絞る。
    ○ issueを起点に読み始めるようにしている。
    ● 思考過程やメモをコード中に書きながら読み進める。
    ○ コードの外に書こうとすると、メモと該当箇所の紐付けが煩わしい。
    ● 確認したいことをどこかに箇条書きしながら読み進める。
    ○ 読んでいる内に目的を忘れるのを防ぐ。読むのに集中できる。
    ● 簡単化する。
    ○ シンプルな処理で挙動を確認する。
    ○ 徐々に複雑にしながら、挙動の差異に着目して処理を追う。
    ● 機械に委譲する。☜本日のスコープ

    View Slide

  14. 14
    Xxxxxxの活用方法
    Xdebugの活用方法

    View Slide

  15. 15
    1行ずつ読み間違うことなく読み進められる。
    ステップ実行

    View Slide

  16. 16
    例えばLaravelの起動処理を知りたいと思った時
    ステップ実行

    View Slide

  17. 17
    index.phpを読みに行くと…
    ステップ実行
    $app = require_once __DIR__.'/../bootstrap/app.php';
    $kernel = $app->make(Kernel::class);
    $response = $kernel->handle(
    $request = Request::capture()
    )->send();
    $kernel->terminate($request, $response);

    View Slide

  18. 18
    ジャンプできない…
    ステップ実行
    $app = require_once __DIR__.'/../bootstrap/app.php';
    $kernel = $app->make(Kernel::class);
    $response = $kernel->handle(
    $request = Request::capture()
    )->send();
    $kernel->terminate($request, $response);

    View Slide

  19. 19
    ジャンプできない⇨前の処理を読みクラスを特定してメソッドを探すという手間と脳内メモリ消費…
    ステップ実行
    $app = require_once __DIR__.'/../bootstrap/app.php';
    $kernel = $app->make(Kernel::class);
    $response = $kernel->handle(
    $request = Request::capture()
    )->send();
    $kernel->terminate($request, $response);

    View Slide

  20. 20
    ステップ実行すると…
    ステップ実行
    $app = require_once __DIR__.'/../bootstrap/app.php';
    $kernel = $app->make(Kernel::class);_____________________________________________________
    $response = $kernel->handle(
    $request = Request::capture()
    )->send();
    $kernel->terminate($request, $response);

    View Slide

  21. 21
    ステップ実行
    class Application
    public function make($abstract, array $parameters = [])
    {
    $this->loadDeferredProviderIfNeeded($abstract = $this->getAlias($abstract));__________
    return parent::make($abstract, $parameters);
    }
    実際の処理順に従いメソッドの中に進む

    View Slide

  22. 22
    ステップ実行
    if文があると…
    protected function loadDeferredProviderIfNeeded($abstract)
    {
    if ($this->isDeferredService($abstract) && ! isset($this->instances[$abstract])) {
    $this->loadDeferredProvider($abstract);
    }
    }

    View Slide

  23. 23
    ステップ実行
    if文があると…
    protected function loadDeferredProviderIfNeeded($abstract)
    {
    if ($this->isDeferredService($abstract) && ! isset($this->instances[$abstract])) {
    $this->loadDeferredProvider($abstract);
    }
    }
    メソッド

    View Slide

  24. 24
    ステップ実行
    if文があると…
    protected function loadDeferredProviderIfNeeded($abstract)
    {
    if ($this->isDeferredService($abstract) && ! isset($this->instances[$abstract])) {
    $this->loadDeferredProvider($abstract);
    }
    }
    メソッド 変数 変数

    View Slide

  25. 25
    ステップ実行
    if文があると…
    protected function loadDeferredProviderIfNeeded($abstract)
    {
    if ($this->isDeferredService($abstract) && ! isset($this->instances[$abstract])) {
    $this->loadDeferredProvider($abstract);
    }
    }
    メソッド 変数 変数
    プロパティ

    View Slide

  26. 26
    ステップ実行
    trueなのかfalseなのか目で確認できる
    protected function loadDeferredProviderIfNeeded($abstract)
    {
    if ($this->isDeferredService($abstract) && ! isset($this->instances[$abstract])) {
    $this->loadDeferredProvider($abstract);__________________________________________
    }
    }

    View Slide

  27. 27
    ステップ実行
    処理が複雑になると、もうどこから手をつけようか…という気分に

    View Slide

  28. 28
    ステップ実行
    処理が複雑になると、もうどこから手をつけようか…という気分に
    1行ずつ着実にみていける

    View Slide

  29. 29
    変数の中身が見れる⇨変数を覚えておく必要がない
    変数

    View Slide

  30. 30
    変数

    View Slide

  31. 31
    変数

    View Slide

  32. 32
    変数
    とてもじゃないが覚えきれない

    View Slide

  33. 33
    スタックトレースがみれる⇨処理経路に気づける。また、それを覚える必要がない。
    スタックトレース

    View Slide

  34. 34
    例えばEloquentのscopeがどのように呼び出されるのかを知りたい時
    スタックトレース

    View Slide

  35. 35
    scopeメソッドの中にブレークポイントを仕掛けて処理を実行すると…
    スタックトレース
    class Post extends Model
    {
    use HasFactory;
    public function scopeTitle($query, $str)
    {
    ⚫ return $query->where('name', $str);__________________________________________
    }
    }

    View Slide

  36. 36
    スタックトレース

    View Slide

  37. 37
    一つ遡ると、scopeTitle()メソッドを組み立てていることがわかる
    スタックトレース
    public function callNamedScope($scope, array $parameters = [])
    {
    return $this->{'scope'.ucfirst($scope)}(...$parameters);
    }

    View Slide

  38. 38
    更にいくつか遡ると、Post::title("xxxx");からマジックメソッドがトリガーされていることがわかる
    スタックトレース
    public static function __callStatic($method, $parameters)
    {
    return (new static)->$method(...$parameters);
    }

    View Slide

  39. 39
    スタックトレースから当該箇所にジャンプできる。
    スタックトレースからのジャンプ

    View Slide

  40. 40
    スタックトレースから当該箇所にジャンプできる。
    スタックトレースからのジャンプ
    ☜ click!!_

    View Slide

  41. 41
    スタックトレースから当該箇所にジャンプできるし、変数の中身も見れる。
    スタックトレースからのジャンプからの変数

    View Slide

  42. 42
    ● Xdebugを使って静的解析を読む時は並列処理をoffにしましょう。
    ● Xdebug以外にも便利なツールたち。
    ○ IDE
    ○ ChatGPT
    ○ PHPUnit
    and more...
    ● とはいえ前提知識が多いに越したことはない。
    ○ 例えば、PHPのマジックメソッドを知らないとなぜ呼び出されるのかわからない
    おまけのTips

    View Slide

  43. 43
    まとめ

    View Slide

  44. 44
    まとめ
    ● コードは読むものじゃない、(機械に)読ませるものだ。
    ● Xdebugに助けてもらいましょう。

    View Slide

  45. ご清聴ありがとうございました

    View Slide