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

レガシーシステムにおけるPHP8バージョンアップのアプリ対応記録

7028eb7f1d5bf62b440e4e6894c4922c?s=47 don
October 02, 2021

 レガシーシステムにおけるPHP8バージョンアップのアプリ対応記録

7028eb7f1d5bf62b440e4e6894c4922c?s=128

don

October 02, 2021
Tweet

Transcript

  1. #phpconf ©2021 RAKUS Co., Ltd. #phpconf レガシーシステムにおける PHP8バージョンアップの アプリ対応記録 2021/10/2

    - 2021/10/3 PHP Conference Japan 2021 頓花 貴俊
  2. #phpconf 自己紹介 • 頓花 貴俊 (どんが たかとし) • 所属 ◦

    株式会社 ラクス ◦ 販売管理システム【楽楽販売】 • 技術 ◦ メイン:PHP、Javascript、PostgreSQL ◦ 経験 :Java、C言語、Fortran
  3. #phpconf 目次 • イントロダクション • 影響の大きかった主な変更点 • 課題と対応 • 今回の対応を振り返って

    • 最後に
  4. #phpconf 今回、お伝えしたいこと I. 対応時に意識すること A. 全量把握し、対策を練ること B. 品質の担保に対し、費用対効果を考慮したテスト計画を立てるか II. バージョンアップまでに意識すること

    A. 静的な型を意識した実装を行う B. こまめにリファクタリングする
  5. #phpconf イントロダクション 01

  6. #phpconf イントロダクション PHP製品の弊社での取り組み 2年 に 1 回 、バージョンアップを実施 • EOL

    の 回避 • サービスの品質担保 上記の両方を満たすために
  7. #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 一つ飛ばし
  8. #phpconf イントロダクション 実施前の懸念点 • (着手当時) 弊社の他商材を含め、 ほかのWebサービスでの実績がほとんどなかった • リリース日が大きく変更できないため、 開発期間が決まっている

    • PHP8.0 で 下位互換性のない変更点 が多数ある
  9. #phpconf 影響の大きかった主な変更点 02

  10. #phpconf 影響の大きかった主な変更点 • 緩やかな比較演算子の挙動変更 • 警告レベルの変更

  11. #phpconf 影響の大きかった 主な変更点 緩やかな比較演算子の 挙動変更

  12. #phpconf 緩やかな比較 とは PHPでは 厳密な比較 「===」 型まで同じかまで判定する 緩やかな比較「==」 型の相互互換を行った後に判定する 上記が存在します。

  13. #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 ※ 左右関係なし
  14. #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 ※ 左右関係なし
  15. #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 要注意
  16. #phpconf 緩やかな比較演算子の挙動変更 - 関数・式 - • 演算子 == , !=

    , > , >= , < , <= • 配列関数 in_array()、array_search()、array_keys() • ソート関数 sort()、rsort()、asort()、arsort()、array_multisort() • switch文
  17. #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
  18. #phpconf 影響の大きかった 主な変更点 警告レベルの変更

  19. #phpconf 警告レベルの変更 • ERROR に 変更されたエラー ◦ 配列関数の引数に配列以外の型を指定 ◦ BCMath関数の引数に数値形式以外を指定

    ◦ implode()の歴史的な問題の削除 • WARNING に 変更されたエラー ◦ 未定義の変数の読み取り ◦ 未定義の配列のキーを読み取り ◦ 配列でない値のインデックスにアクセス
  20. #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
  21. #phpconf 警告レベルの変更 - 具体例 - • WARNING に 変更されたエラー ◦

    未定義の変数の読み取り ◦ 未定義の配列のキーを読み取り ◦ 配列でない値のインデックスにアクセス PHP 7.x ⇒ 出力:null PHP 8.x ⇒ 出力:null | Warning
  22. #phpconf 課題と対応 04

  23. #phpconf 問題の前提 • PHPの型に寛容であるという特性 • レガシーなコードを使い続けている状態   → 型チェックをせず、暗黙の型変換を使用してい箇所が多い ⇒

    静的コード解析で影響箇所の調査ができない状態
  24. #phpconf 緩やかな比較演算子の挙動変更 - 課題 - 演算子や標準関数を含め 影響箇所 は 約2.7万 →

    本来、すべて動作が変わるか確認が必要 (※ アプリ全体のphpコード は 約47万行) ⇒ すべてを 前後関係含めて、チェックは不可能
  25. #phpconf 警告レベルの変更 - 課題 - 引数の型や返値の型が宣言されていない箇所が多い → 静的なコード解析が実施できない ⇒ すべてを

    前後関係含めて、チェックは不可能
  26. #phpconf 対応案 1. 以前と同様の挙動をする関数(ラップ関数)を作成し、 すべての箇所を置き換える 2. すべての箇所を複数パターンでテストを行い、 問題があった箇所を修正する

  27. #phpconf 対応案 1. 以前と同様の挙動をする関数(ラップ関数)を作成し、 すべての箇所を置き換える 2. すべての箇所を複数パターンでテストを行い、 問題があった箇所を修正する ⇒ 問題点:新たなコード負債となる

    ⇒ 問題点:膨大な時間がかかる
  28. #phpconf 対応案 1. 以前と同様の挙動をする関数(ラップ関数)を作成し、 すべての箇所を置き換える 2. すべての箇所を複数パターンでテストを行い、 問題があった箇所を修正する ⇒ 問題点:新たなコード負債となる

    ⇒ 問題点:膨大な時間がかかる
  29. #phpconf 今回どのように対応したのか ➢ 演算子に対する対策:修正対象を絞る ➢ 関数に対する対策:チェック関数で調査 緩やかな比較演算子の挙動変更 警告レベルの挙動変更 品質の担保は? ⇒ E2Eテスト・手動テストで確認 ➢

    通過テストで確認
  30. #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 〇
  31. #phpconf ➢ チェック関数で調査 ◦ 通過しても動作が変わるか確認できない ▪ 引数が正常かチェックする関数を作成 今回どのように対応したのか - 実例

    - 例) 発見不具合:「array_key_exist()」第一引数「””」第二引数「0,1,2」の挙動変更 ・第二引数 の 配列内 で 型 が違うもの ・第一引数 の 型 と 第二引数 の 配列の値 の型が違うもの 上記 をチェックし、ログとして出力
  32. #phpconf ➢ 通過テストで確認 ◦ 変更点はエラーになるので、実際に通過すれば確認可能 今回どのように対応したのか - 実例 -

  33. #phpconf 品質の担保 • 自動テスト ◦ E2E テスト・ユニットテストで重要機能をテスト → データパターンが用意されている •

    手動テスト ◦ データバリエーションが必要ない箇所のテスト → テストパターンを、「0件, 1件, 複数件」と データが存在しないとき ⇒ 自動テストと手動テストで確認
  34. #phpconf 今回の対応を振り返って 05

  35. #phpconf 今回の対応を振り返って 一言でいうと、 影響範囲が広い

  36. #phpconf 今回の対応を振り返って 影響範囲が広いことへの対策 ターゲットを絞ること ⇒ 品質を担保するには?

  37. #phpconf 品質を担保するには? • カバレッジをどうやって上げるかの観点 • どこまでテストするのかの観点 ⇒ 品質の担保に対し、費用対効果を考慮したテスト計画を立てる 限られた時間の中で、テストの効果を考慮しテストを計画

  38. #phpconf 見つかった不具合 • 動作テストで発見された不具合 10件程度 • リリース半年内で発見された不具合 2件 (※ 軽微なもの)

    → 調査 ・不具合発見時の再調査 ⇒ 全量把握・それに対する検討 により 品質を担保 → チーム内 で 修正方針の検討 なぜ、不具合が少なかったのか?
  39. #phpconf 余談 • 見送りの選択肢は? → 途中、PHP7.4 も選択肢に上がったが 問題の先送りになるだけなのでなんとか対応する方針へ • 工数は?

    → 前回のバージョンアップ( PHP7.1 → PHP7.3) 時の 2 倍 以上
  40. #phpconf これからのバージョンアップに向けて • ミドルウェアの更新で使用可能 • 通常のリリース毎のデグレチェック ➢ 自動テストを追加する メリット

  41. #phpconf これからのバージョンアップに向けて テストが必要な対象画面の自動テストの作成には 手動テスト 実施工数 の 約 5 倍 かかる想定

    デメリット → どのテストケースを自動化するのか ⇒ 見極めが必要 ➢ 自動テストを追加する • コストが高い ⇒ 今回は作成コストには合わない、手動テスト実施
  42. #phpconf PHPバージョンアップの今後 • 推奨されない宣言・関数の削除 • 型の制限の強化 • エラーレベルの変更 ⇒ 新規コード:静的な型を意識した実装を行う

    ⇒ 既存コード:コード負債は小まめにリファクタリングする
  43. #phpconf 最後に 05

  44. #phpconf 今回、お伝えしたいこと I. 対応時に意識すること A. 全量把握し、対策を練ること B. 品質の担保に対し、費用対効果を考慮したテスト計画を立てるか II. バージョンアップまでに意識すること

    A. 静的な型を意識した実装を行う B. 小まめにリファクタリングする
  45. #phpconf ご清聴ありがとうございました!