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
レガシーシステムにおけるPHP8バージョンアップのアプリ対応記録
Search
don
October 02, 2021
Programming
0
1.8k
レガシーシステムにおけるPHP8バージョンアップのアプリ対応記録
don
October 02, 2021
Tweet
Share
More Decks by don
See All by don
レガシーシステムへのPHPStan導入から半年での効果と課題
bosshawk
0
1.5k
レガシーシステムへのPHPStan導入から半年での課題と効果
bosshawk
1
1.3k
息の長いサービスの PHP8バージョンアップで見えた 課題と解決法 / Problems and solutions found when upgrading long-term services to PHP8
bosshawk
0
2.4k
[おすすめの技術書 LT会 - vol.2] 体系的に学ぶ安全なWebアプリケーションの作り方
bosshawk
0
20k
[PHPerKaigi 2021 (LT)] 新社会人のコード品質カイゼン記録
bosshawk
1
1.1k
Other Decks in Programming
See All in Programming
CSC509 Lecture 09
javiergs
PRO
0
140
よくできたテンプレート言語として TypeScript + JSX を利用する試み / Using TypeScript + JSX outside of Web Frontend #TSKaigiKansai
izumin5210
6
1.7k
AI時代におけるSRE、 あるいはエンジニアの生存戦略
pyama86
6
1.1k
LLM生成文章の精度評価自動化とプロンプトチューニングの効率化について
layerx
PRO
2
190
タクシーアプリ『GO』のリアルタイムデータ分析基盤における機械学習サービスの活用
mot_techtalk
4
1.4k
ペアーズにおけるAmazon Bedrockを⽤いた障害対応⽀援 ⽣成AIツールの導⼊事例 @ 20241115配信AWSウェビナー登壇
fukubaka0825
6
1.9k
CSC509 Lecture 11
javiergs
PRO
0
180
リアーキテクチャxDDD 1年間の取り組みと進化
hsawaji
1
220
ヤプリ新卒SREの オンボーディング
masaki12
0
130
WebフロントエンドにおけるGraphQL(あるいはバックエンドのAPI)との向き合い方 / #241106_plk_frontend
izumin5210
4
1.4k
Realtime API 入門
riofujimon
0
150
Generative AI Use Cases JP (略称:GenU)奮闘記
hideg
1
290
Featured
See All Featured
StorybookのUI Testing Handbookを読んだ
zakiyama
27
5.3k
A designer walks into a library…
pauljervisheath
203
24k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
109
49k
Optimizing for Happiness
mojombo
376
70k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
Put a Button on it: Removing Barriers to Going Fast.
kastner
59
3.5k
Embracing the Ebb and Flow
colly
84
4.5k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
16
2.1k
A Philosophy of Restraint
colly
203
16k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Building Your Own Lightsaber
phodgson
103
6.1k
How to Think Like a Performance Engineer
csswizardry
20
1.1k
Transcript
#phpconf ©2021 RAKUS Co., Ltd. #phpconf レガシーシステムにおける PHP8バージョンアップの アプリ対応記録 2021/10/2
- 2021/10/3 PHP Conference Japan 2021 頓花 貴俊
#phpconf 自己紹介 • 頓花 貴俊 (どんが たかとし) • 所属 ◦
株式会社 ラクス ◦ 販売管理システム【楽楽販売】 • 技術 ◦ メイン:PHP、Javascript、PostgreSQL ◦ 経験 :Java、C言語、Fortran
#phpconf 目次 • イントロダクション • 影響の大きかった主な変更点 • 課題と対応 • 今回の対応を振り返って
• 最後に
#phpconf 今回、お伝えしたいこと I. 対応時に意識すること A. 全量把握し、対策を練ること B. 品質の担保に対し、費用対効果を考慮したテスト計画を立てるか II. バージョンアップまでに意識すること
A. 静的な型を意識した実装を行う B. こまめにリファクタリングする
#phpconf イントロダクション 01
#phpconf イントロダクション PHP製品の弊社での取り組み 2年 に 1 回 、バージョンアップを実施 • EOL
の 回避 • サービスの品質担保 上記の両方を満たすために
#phpconf イントロダクション 今年EOLを迎える PHP7.3 → PHP8.0 の バージョンアップを実施 PHP バージョン
初回リリース日 アクティブサポート セキュリティサポート 8.0 2020/11/26 2022/11/26 2023/11/26 7.4 2019/11/28 2021/11/28 2022/11/28 7.3 2018/12/06 2020/12/06 2021/12/06 一つ飛ばし
#phpconf イントロダクション 実施前の懸念点 • (着手当時) 弊社の他商材を含め、 ほかのWebサービスでの実績がほとんどなかった • リリース日が大きく変更できないため、 開発期間が決まっている
• PHP8.0 で 下位互換性のない変更点 が多数ある
#phpconf 影響の大きかった主な変更点 02
#phpconf 影響の大きかった主な変更点 • 緩やかな比較演算子の挙動変更 • 警告レベルの変更
#phpconf 影響の大きかった 主な変更点 緩やかな比較演算子の 挙動変更
#phpconf 緩やかな比較 とは PHPでは 厳密な比較 「===」 型まで同じかまで判定する 緩やかな比較「==」 型の相互互換を行った後に判定する 上記が存在します。
#phpconf 緩やかな比較演算子の挙動変更 挙動が変わる対象 文字列 と 数値 の 比較 ($int ⇔
$string, $float ⇔ $string) $string : 整数形式 $int ⇔ (int) $string $string : 浮動小数形式 $int ⇔ (float) $string 上記以外 $int ⇔ (int) $string $string : 整数形式 $float ⇔ (float) $string $string : 浮動小数形式 $float ⇔ (float) $string 上記以外 $float ⇔ (float) $string PHP 7.x ※ 左右関係なし
#phpconf 緩やかな比較演算子の挙動変更 挙動が変わる対象 文字列 と 数値 の 比較 ($int ⇔
$string, $float ⇔ $string) $string : 整数形式 $int ⇔ (int) $string $string : 浮動小数形式 $int ⇔ (float) $string 上記以外 (string) $int ⇔ $string $string : 整数形式 $float ⇔ (float) $string $string : 浮動小数形式 $float ⇔ (float) $string 上記以外 (string) $float ⇔ $string PHP 8.x ※ 左右関係なし
#phpconf 緩やかな比較演算子の挙動変更 まとめると、 対象 文字列 と 数値 の 比較 ($int
⇔ $string, $float ⇔ $string) 事象 文字列側 が 数値形式でない 場合 数値側 が文字列 に変換され、比較結果が 反転 する 条件式 7.x 8.x 0 == "0" TRUE TRUE 0 == "0.0" TRUE TRUE 0 == "foo" TRUE FALSE 0 == "" TRUE FALSE 42 == " 42" TRUE TRUE 42 == "42foo" TRUE FALSE 要注意
#phpconf 緩やかな比較演算子の挙動変更 - 関数・式 - • 演算子 == , !=
, > , >= , < , <= • 配列関数 in_array()、array_search()、array_keys() • ソート関数 sort()、rsort()、asort()、arsort()、array_multisort() • switch文
#phpconf 緩やかな比較演算子の挙動変更 - 具体例 - フォーム から パラメータ が 「””」(空文字)
と 数値 で 比較している場合 PHP 7.x (int)“” == 0 ⇒ true PHP 8.x “” == (string) 0 ⇒ false PHP 7.x (int)“” < 1000 ⇒ false PHP 8.x “” < (string) 1000 ⇒ true
#phpconf 影響の大きかった 主な変更点 警告レベルの変更
#phpconf 警告レベルの変更 • ERROR に 変更されたエラー ◦ 配列関数の引数に配列以外の型を指定 ◦ BCMath関数の引数に数値形式以外を指定
◦ implode()の歴史的な問題の削除 • WARNING に 変更されたエラー ◦ 未定義の変数の読み取り ◦ 未定義の配列のキーを読み取り ◦ 配列でない値のインデックスにアクセス
#phpconf 警告レベルの変更 - 具体例 - • ERROR に 変更されたエラー ◦
配列関数の引数に配列以外の型を指定 ◦ BCMath関数の引数に数値形式以外を指定 ◦ implode()の歴史的な問題の削除 PHP 7.x ⇒ 出力:10.1 (string) PHP 8.x ⇒ Fatal error PHP 7.x ⇒ 出力:1 (int) PHP 8.x ⇒ Fatal error
#phpconf 警告レベルの変更 - 具体例 - • WARNING に 変更されたエラー ◦
未定義の変数の読み取り ◦ 未定義の配列のキーを読み取り ◦ 配列でない値のインデックスにアクセス PHP 7.x ⇒ 出力:null PHP 8.x ⇒ 出力:null | Warning
#phpconf 課題と対応 04
#phpconf 問題の前提 • PHPの型に寛容であるという特性 • レガシーなコードを使い続けている状態 → 型チェックをせず、暗黙の型変換を使用してい箇所が多い ⇒
静的コード解析で影響箇所の調査ができない状態
#phpconf 緩やかな比較演算子の挙動変更 - 課題 - 演算子や標準関数を含め 影響箇所 は 約2.7万 →
本来、すべて動作が変わるか確認が必要 (※ アプリ全体のphpコード は 約47万行) ⇒ すべてを 前後関係含めて、チェックは不可能
#phpconf 警告レベルの変更 - 課題 - 引数の型や返値の型が宣言されていない箇所が多い → 静的なコード解析が実施できない ⇒ すべてを
前後関係含めて、チェックは不可能
#phpconf 対応案 1. 以前と同様の挙動をする関数(ラップ関数)を作成し、 すべての箇所を置き換える 2. すべての箇所を複数パターンでテストを行い、 問題があった箇所を修正する
#phpconf 対応案 1. 以前と同様の挙動をする関数(ラップ関数)を作成し、 すべての箇所を置き換える 2. すべての箇所を複数パターンでテストを行い、 問題があった箇所を修正する ⇒ 問題点:新たなコード負債となる
⇒ 問題点:膨大な時間がかかる
#phpconf 対応案 1. 以前と同様の挙動をする関数(ラップ関数)を作成し、 すべての箇所を置き換える 2. すべての箇所を複数パターンでテストを行い、 問題があった箇所を修正する ⇒ 問題点:新たなコード負債となる
⇒ 問題点:膨大な時間がかかる
#phpconf 今回どのように対応したのか ➢ 演算子に対する対策:修正対象を絞る ➢ 関数に対する対策:チェック関数で調査 緩やかな比較演算子の挙動変更 警告レベルの挙動変更 品質の担保は? ⇒ E2Eテスト・手動テストで確認 ➢
通過テストで確認
#phpconf 今回どのように対応したのか - 実例 - ➢ 修正対象を絞る ◦ 比較演算子の結果が変わるパターンから 影響箇所を絞り込み、修正を実施(ラップ関数に変換など)
例) 発見不具合:「””==0」の Boolean値が変わる 0 (定数化含み)と比較しているものリストアップし、 比較側をキャストするように修正 比較1 等号 比較2 v7.3 v8.0 check 0 == 0 => true true 〇 0 == 'abc' => true false × 0 == '' => true false × 0 == true => false false 〇
#phpconf ➢ チェック関数で調査 ◦ 通過しても動作が変わるか確認できない ▪ 引数が正常かチェックする関数を作成 今回どのように対応したのか - 実例
- 例) 発見不具合:「array_key_exist()」第一引数「””」第二引数「0,1,2」の挙動変更 ・第二引数 の 配列内 で 型 が違うもの ・第一引数 の 型 と 第二引数 の 配列の値 の型が違うもの 上記 をチェックし、ログとして出力
#phpconf ➢ 通過テストで確認 ◦ 変更点はエラーになるので、実際に通過すれば確認可能 今回どのように対応したのか - 実例 -
#phpconf 品質の担保 • 自動テスト ◦ E2E テスト・ユニットテストで重要機能をテスト → データパターンが用意されている •
手動テスト ◦ データバリエーションが必要ない箇所のテスト → テストパターンを、「0件, 1件, 複数件」と データが存在しないとき ⇒ 自動テストと手動テストで確認
#phpconf 今回の対応を振り返って 05
#phpconf 今回の対応を振り返って 一言でいうと、 影響範囲が広い
#phpconf 今回の対応を振り返って 影響範囲が広いことへの対策 ターゲットを絞ること ⇒ 品質を担保するには?
#phpconf 品質を担保するには? • カバレッジをどうやって上げるかの観点 • どこまでテストするのかの観点 ⇒ 品質の担保に対し、費用対効果を考慮したテスト計画を立てる 限られた時間の中で、テストの効果を考慮しテストを計画
#phpconf 見つかった不具合 • 動作テストで発見された不具合 10件程度 • リリース半年内で発見された不具合 2件 (※ 軽微なもの)
→ 調査 ・不具合発見時の再調査 ⇒ 全量把握・それに対する検討 により 品質を担保 → チーム内 で 修正方針の検討 なぜ、不具合が少なかったのか?
#phpconf 余談 • 見送りの選択肢は? → 途中、PHP7.4 も選択肢に上がったが 問題の先送りになるだけなのでなんとか対応する方針へ • 工数は?
→ 前回のバージョンアップ( PHP7.1 → PHP7.3) 時の 2 倍 以上
#phpconf これからのバージョンアップに向けて • ミドルウェアの更新で使用可能 • 通常のリリース毎のデグレチェック ➢ 自動テストを追加する メリット
#phpconf これからのバージョンアップに向けて テストが必要な対象画面の自動テストの作成には 手動テスト 実施工数 の 約 5 倍 かかる想定
デメリット → どのテストケースを自動化するのか ⇒ 見極めが必要 ➢ 自動テストを追加する • コストが高い ⇒ 今回は作成コストには合わない、手動テスト実施
#phpconf PHPバージョンアップの今後 • 推奨されない宣言・関数の削除 • 型の制限の強化 • エラーレベルの変更 ⇒ 新規コード:静的な型を意識した実装を行う
⇒ 既存コード:コード負債は小まめにリファクタリングする
#phpconf 最後に 05
#phpconf 今回、お伝えしたいこと I. 対応時に意識すること A. 全量把握し、対策を練ること B. 品質の担保に対し、費用対効果を考慮したテスト計画を立てるか II. バージョンアップまでに意識すること
A. 静的な型を意識した実装を行う B. 小まめにリファクタリングする
#phpconf ご清聴ありがとうございました!