Slide 1

Slide 1 text

#RAKUSMeetup ©2020 RAKUS Co., Ltd. PHP標準関数との戦い 加納 悠史

Slide 2

Slide 2 text

#RAKUSMeetup 加納 悠史 カノウユウジ PHPer 趣味はダイビング 業務内容:メールディーラー の開発 @Ykanoh65 株式会社 ラクス

Slide 3

Slide 3 text

#RAKUSMeetup メールディーラーとは 問合せメールを一元管理! 顧客対応サポートツール

Slide 4

Slide 4 text

#RAKUSMeetup メールディーラー ● 2001年にサービス提供開始 ● 6,000社以上の導入実績 ● メール/Webマーケティング市場 11年連続シェア No.1 !!※ ※ 出典:ITR「ITR Market View:メール/Webマーケティング市場 2020」メール処理市場ベンダー別 売上金額シェア 2009-2019年度(予測値)

Slide 5

Slide 5 text

#RAKUSMeetup メールディーラー ● 2001年にサービス提供開始 ● 6,000社以上の導入実績 ● メール/Webマーケティング市場 11年連続シェア No.1 !! ⇒ 19年モノ の レガシーシステム

Slide 6

Slide 6 text

#RAKUSMeetup 標準関数との戦い

Slide 7

Slide 7 text

#RAKUSMeetup count() 関数

Slide 8

Slide 8 text

#RAKUSMeetup ことの始まり PHP バージョンアップ ● v7.1 → v7.3 ● count() 関数の仕様変更を発見

Slide 9

Slide 9 text

#RAKUSMeetup count()関数の仕様変更 PHP 7.2 以降の挙動  → カウントできない型を引数にすると Warning が発生 print( count(1) ); // 出力:1 print( count("hoge") ); // 出力:1 print( count(null) ); // 出力:0 Warning: count(): Parameter must be an array or an object that implements Countable in %s on line %d code php.log

Slide 10

Slide 10 text

#RAKUSMeetup 対応案 すべての count() 関数に対して... A. カウント可能な値のみ渡すよう修正 - そもそも NULL や int をカウントしている方がおかしいでしょ B. カウントできない値も許容するオリジナル関数で置換え - 全 count() 関数なんて見てられない - オリジナル関数で NULL や int は 0 や 1 を返せばOK

Slide 11

Slide 11 text

#RAKUSMeetup count() の数を確認

Slide 12

Slide 12 text

#RAKUSMeetup 2,232 個所

Slide 13

Slide 13 text

#RAKUSMeetup 対応案 A. カウント可能な値のみ渡すよう修正 - そもそも NULL や int をカウントしている方がおかしいでしょ B. カウントできない値も許容するオリジナル関数で置換え - 全 count() 関数なんて見てられない。 それが現実。 - ラッパー関数にて NULL や int は 0 や 1 を返せばOK 無理... すべての count() 関数に対して... 採用

Slide 14

Slide 14 text

#RAKUSMeetup 採用した対策案 ● 自作の関数 mdCount() を作成 ○ 共通関数として 共通関数ファイルに定義 ● すべての count() 関数を置き換え 一件落着...

Slide 15

Slide 15 text

#RAKUSMeetup 対応完了後の コードレビューにて... あれ...?

Slide 16

Slide 16 text

#RAKUSMeetup 第一ノ問題 消したはずの count() 関数が増殖している

Slide 17

Slide 17 text

#RAKUSMeetup なぜ復活していたのか? ● 並行開発されていたブランチからの混入 ● ルール周知不足による使用 ⇒ 使わせない仕組みがなければ増殖する

Slide 18

Slide 18 text

#RAKUSMeetup 対策 プロセスによる対策 ● コーディング規約に追加 ● コードレビュー観点に追加 技術的な対策 ● 自動検出(検討中)

Slide 19

Slide 19 text

#RAKUSMeetup 第二ノ問題 オリジナル関数を 使えない処理の存在が発覚

Slide 20

Slide 20 text

#RAKUSMeetup おさらい:採用した対策案 ● 自作の関数 mdCount() を作成 ○ 共通関数として 共通関数ファイルに定義 ● すべての count() 関数を置き換え

Slide 21

Slide 21 text

#RAKUSMeetup おさらい:採用した対策案 ● 自作の関数 mdCount() を作成 ○ 共通関数として 共通関数ファイルに定義 ● すべての count() 関数を置き換え

Slide 22

Slide 22 text

#RAKUSMeetup おさらい:採用した対策案 ● 自作の関数 mdCount() を作成 ○ 共通関数として 共通関数ファイルに定義 ● すべての count() 関数を置き換え 問題の処理では 共通関数ファイル を読み込んでいなかった!

Slide 23

Slide 23 text

#RAKUSMeetup 共通関数を読み込んでいない... メールディーラーの構成 ● オートロードは利用していない ○ クラス化されていないため利用不可 ● 共通関数ファイルは 処理の先頭で読み込むルール ○ 例: ○ 不用意に読み込みファイルを増やすと危険 require_once "common.php"; 関数名の競合など...

Slide 24

Slide 24 text

#RAKUSMeetup 対応策 新しい共通関数ファイルを作成 ⇒ すべての処理で読み込むようにする 1. mdCount2()(仮称) を作成 2. 旧 mdCount() は mdCount2() を呼び出すよう変更

Slide 25

Slide 25 text

#RAKUSMeetup 対応策 新しい共通関数ファイルを作成 ⇒ すべての処理で読み込むようにする 1. mdCount2()(仮称) を作成 2. 旧 mdCount() は mdCount2() を呼び出すよう変更

Slide 26

Slide 26 text

#RAKUSMeetup 対策:auto_prepend_fileを活用 auto_prepend_fileとは ● php.ini の設定値 ● メイン処理の前に実行するファイルを指定 → コードの修正を少なく前処理を定義することが可能 https://www.php.net/manual/ja/ini.core.php#ini.auto-prepend-file

Slide 27

Slide 27 text

#RAKUSMeetup 対策:auto_prepend_fileを活用 1. mdCount2()(仮称) を作成 → auto_prepend_file で読み込み 2. 旧 mdCount() はどうする?   → mdCount2()(仮称) を呼び出すよう変更 修正コストを抑えつつ対応することに成功

Slide 28

Slide 28 text

#RAKUSMeetup まとめ / ふりかえり 対応が完了しても安心してはダメ! 今回の対応策 ● count() の仕様変更 ⇒ オリジナル共通関数で対応 ● count() が増殖 ⇒ 規約とコードレビューで防止 ● オリジナル関数が呼べない ⇒ 新しい共通関数ファイルを作成 ● 新共通関数ファイル呼び出し ⇒ auto_prepend_file の活用で対応 今後の対応 ● 増殖防止策:ツールによる自動検知を導入 ● 共通関数ファイルの mdCount() の廃止 再発の芽を完全に摘む為に、 count()との闘いはもう少しだけ続く・・・・