Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHP における静的解析(あるいはそもそも静的解析とは) / #phpcondo_yasai ...
Search
Shohei Okada
January 11, 2024
Programming
1
500
PHP における静的解析(あるいはそもそも静的解析とは) / #phpcondo_yasai static analysis for PHP
2024/01/11 開催「PHPカンファレンス北海道2024 全然野菜」(
https://connpass.com/event/298365/
)の発表資料です。
Shohei Okada
January 11, 2024
Tweet
Share
More Decks by Shohei Okada
See All by Shohei Okada
どうして手を動かすよりもチーム内のコードレビューを優先するべきなのか
okashoi
3
870
パスワードのハッシュ、ソルトってなに? - What is hash and salt for password?
okashoi
3
130
設計の考え方 - インターフェースと腐敗防止層編 #phpconfuk / Interface and Anti Corruption Layer
okashoi
10
3.1k
"config" ってなんだ? / What is "config"?
okashoi
0
900
ファイル先頭の use の意味、説明できますか? 〜PHP の namespace と autoloading の関係を正しく理解しよう〜 / namespace and autoloading in php
okashoi
3
1.1k
MySQL のインデックスの種類をおさらいしよう! / overviewing indexes in MySQL
okashoi
0
730
【PHPカンファレンス沖縄 2023】素朴で考慮漏れのある PHP コードをテストコードとともに補強していく(ライブコーディング補足資料) / #phpcon_okinawa 2023 livecoding supplementary material
okashoi
3
1.8k
その説明、コードコメントに書く?コミットメッセージに書く? プルリクエストに書く? - #phpconfuk 2023
okashoi
15
5k
いろいろなフレームワークの仕組みを index.php から読み解こう / index.php of each framework
okashoi
2
2.7k
Other Decks in Programming
See All in Programming
AppRouterを用いた大規模サービス開発におけるディレクトリ構成の変遷と問題点
eiganken
1
440
CQRS+ES の力を使って効果を感じる / Feel the effects of using the power of CQRS+ES
seike460
PRO
0
240
PHPUnitしか使ってこなかった 一般PHPerがPestに乗り換えた実録
mashirou1234
0
420
テストコードのガイドライン 〜作成から運用まで〜
riku929hr
7
1.4k
ESLintプラグインを使用してCDKのセオリーを適用する
yamanashi_ren01
2
230
混沌とした例外処理とエラー監視に秩序をもたらす
morihirok
13
2.2k
責務を分離するための例外設計 - PHPカンファレンス 2024
kajitack
9
2.3k
Swiftコンパイラ超入門+async関数の仕組み
shiz
0
170
「とりあえず動く」コードはよい、「読みやすい」コードはもっとよい / Code that 'just works' is good, but code that is 'readable' is even better.
mkmk884
6
1.4k
watsonx.ai Dojo #6 継続的なAIアプリ開発と展開
oniak3ibm
PRO
0
170
AWS re:Invent 2024個人的まとめ
satoshi256kbyte
0
100
VisionProで部屋の明るさを反映させるシェーダーを作った話
segur
0
100
Featured
See All Featured
BBQ
matthewcrist
85
9.4k
Learning to Love Humans: Emotional Interface Design
aarron
274
40k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
120k
How to train your dragon (web standard)
notwaldorf
89
5.8k
Fashionably flexible responsive web design (full day workshop)
malarkey
406
66k
A Modern Web Designer's Workflow
chriscoyier
693
190k
Code Reviewing Like a Champion
maltzj
521
39k
Documentation Writing (for coders)
carmenintech
67
4.5k
Automating Front-end Workflow
addyosmani
1366
200k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.2k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
132
33k
GitHub's CSS Performance
jonrohan
1030
460k
Transcript
PHP における静的解析 (あるいはそもそも静的解析とは) 2024-01-11 PHPカンファレンス北海道2024 全然野菜
なにかがおかしいコード <?php // ... if ($empty($hoge)) { // ... }
<?php // ... if (empty($hoge)) { // ... } たぶんこう書きたかったんやろなあ
実話です · 私が 1 年目のときに自分がつくったバグ · 実際には長いコードの一部であり、デバッグに半日かかった · エラーハンドリング等も不十分だったのもある ·
PHP 的には構文エラーではないので余計に気づきにくい · $empty という変数は定義可能であるため
PHP における静的解析 (あるいはそもそも静的解析とは) 2024-01-11 PHPカンファレンス北海道2024 全然野菜
「静的解析」とは プログラムを実行せずに行う解析のこと · 構文エラー検出 · コーディングスタイルチェック · 複雑性の検出 · 型のチェック
· etc. ...... c.f.)動的解析:自動テスト、プロファイリング etc. ......
PHP の静的解析ツール例 · php -l コマンド · PHPMD · PHP_CodeSniffer(phpcs)
· PHPStan · Psalm · Phan · (PhpStrom)
PHP の静的解析ツール例 · php -l コマンド · PHPMD · PHP_CodeSniffer(phpcs)
· PHPStan ←本日取り上げるのはこちら · Psalm · Phan · (PhpStrom)
PHPStan https://phpstan.org/ ぞうさん かわいいね
PHPStan で検出できるもの(一例) · 構文エラー · 未定義の変数/定数/関数/クラス/メソッド · 間接的に typo を検出できる
· 型の不整合 · エラーチェック漏れなど · 冗長なコード
Web ブラウザ上でおためしできます https://phpstan.org/try
Q. 何がおかしい? <?php $environment = $_ENV['APP_ENV']; if ($enviroment === 'production')
{ // ... } https://phpstan.org/try
A. 変数の typo <?php $environment = $_ENV['APP_ENV']; if ($enviroment ===
'production') { // ... } https://phpstan.org/try
<?php /** @var string $heystack */ if (strpos($heystack, 'a') ===
fasle) { // ... } https://phpstan.org/try Q. 何がおかしい?
<?php /** @var string $heystack */ if (strpos($heystack, 'a') ===
fasle) { // ... } https://phpstan.org/try A. Boolean リテラルの typo
<?php /** @var string $dsn */ $pdo = new PDO($dsn);
$statement = $pdo->prepare('SELECT * FROM users WHERE id = ?;'); $statement->executeStatement([1]); https://phpstan.org/try Q. 何がおかしい?
<?php /** @var string $dsn */ $pdo = new PDO($dsn);
$statement = $pdo->prepare('SELECT * FROM users WHERE id = ?;'); $statement->executeStatement([1]); https://phpstan.org/try A. 存在しないメソッド
<?php function getMonth(DateTimeImmutable $dt): int { return $dt->format('n'); } $now
= new DateTime(); echo getMonth($now); https://phpstan.org/try Q. 何がおかしい?
<?php function getMonth(DateTimeImmutable $dt): int { return $dt->format('n'); } $now
= new DateTime(); echo getMonth($now); https://phpstan.org/try A. 戻り値の型の不整合
<?php function getMonth(DateTimeImmutable $dt): int { return $dt->format('n'); } $now
= new DateTime(); echo getMonth($now); https://phpstan.org/try A. 引数の型の不整合
備考)PHP の DateTime と DateTimeImmutable <<interface>> DateTimeInterface DateTime DateTimeImmutable 互換性はない
<?php /** @var string $heystack */ $index = strpos($heystack, 'a');
echo substr($heystack, $index); https://phpstan.org/try Q. 何がおかしい?
https://phpstan.org/try <?php /** @var string $heystack */ $index = strpos($heystack,
'a'); echo substr($heystack, $index); A. 型の不整合(false チェック漏れ)
余談)PHPDoc と組み合わせてより高度な型情報を扱える 今回は割愛 <?php declare(strict_types = 1); class Person {
/** @var int<0, max> $age */ public int $age; } /** * @param non-empty-list<Person> $persons */ function findOldestPerson(array $persons): Person { $oldestPerson = $persons[0]; foreach ($persons as $person) { if ($person->age > $oldestPerson->age) { $oldestPerson = $person; } } return $oldestPerson; }
余談)PHPDoc と組み合わせてより高度な型情報を扱える 今回は割愛 <?php declare(strict_types = 1); class Person {
/** @var int<0, max> $age */ public int $age; } /** * @param non-empty-list<Person> $persons */ function findOldestPerson(array $persons): Person { $oldestPerson = $persons[0]; foreach ($persons as $person) { if ($person->age > $oldestPerson->age) { $oldestPerson = $person; } } return $oldestPerson; }
さて https://speakerdeck.com/twada/growing-reliable-code-phperkaigi-2022?slide=10
さて https://speakerdeck.com/twada/growing-reliable-code-phperkaigi-2022?slide=10 静的解析を実施するのは だいたいこのタイミング(たぶん)
冒頭のコードを PHPStan にかけると <?php // ... if ($empty($hoge)) { //
... }
冒頭のコードを PHPStan にかけると https://phpstan.org/r/45d617bb-1bc1-4e2a-a1e9-24b8deeefff9
冒頭のコードを PHPStan にかけると https://phpstan.org/r/45d617bb-1bc1-4e2a-a1e9-24b8deeefff9
つまり https://speakerdeck.com/twada/growing-reliable-code-phperkaigi-2022?slide=10 静的解析ツールを使っていれば 不具合の発見のタイミングを早め傷を小さく収められた (また、ツールによって瞬時に発見できた)
まとめ · 静的解析ツールを使うとテストコードを書く以外の方法で 潜在的な不具合(うっかりミス等)を発見できる · ツールを使いこなして生産性をあげよう · (発展)PHP における型を意識した設計、実装の幅を広げてくれ る
· あくまで外部ツールであり、PHP のランタイムそのものを安 全にしてくれるわけではないので注意