COLOPL Tech Blog

コロプラのエンジニアブログです

PHPerKaigi 2023 に登壇させていただきました!

こんにちは。 SRE の工藤です。


3/23 (金) 〜 3/25 (日) で開催されたプログラミング言語 PHP に関するカンファレンス 「PHPerKaigi 2023」 の day1 (3/23) にて、 「Rector ではじめる "運用を止めない" PHP アップグレード 」という内容で登壇させていただきました!

speakerdeck.com

www.youtube.com

久々のオフライン主体のイベントということで会場は大盛りあがり!みなさんモチベーションが高く、とてもディープで楽しい発表が盛りだくさんでした。
一方で LT 大会では登壇者の推し色のペンライトを用いた (?) タイムキーピングが行われたり、 day2 では懇親会が開催されたり (私用で私は day1 のみの参加となってしまいましたが...) 良い意味で "PHPerKaigi らしさ" にあふれたイベントだったと感じています。

今回プロポーザルを提出させていただいた経緯としましては、以前 PHPConference 2022 でサイボウズさんの PHP に一時的にパッチを当てるという究極の方法で移行を行った発表を拝見させていただいたのがきっかけでした。

実はあの時コロプラでも似たようなことをやっており、これは是非コロプラの事例、特に Rector の便利さを紹介させていただきたいなと考えました。

運用型ゲームアプリとミドルウェア更新の難しさ

発表では、 Rector という静的解析・リファクタリングツールを用いて、弊社タイトル 『白猫プロジェクト NEW WORLD'S』 (以下: 白猫) の PHP バージョンアップを行った手法や戦略についてお話させていただきました。

「白猫」 はユーザー様に長く愛されているタイトルであり、日々新たなイベントや新機能の開発が行われ続けています。このように新機能の開発が止まることがなく、決まったリリースサイクルを持たないアプリケーションにおいてミドルウェアのバージョンアップを行うことには大きなハードルが立ちはだかります。

特にコロプラでは、可能な限りダウンタイムを発生させないことでユーザー様がゲームを遊べない時間を作らないノーメンテナンス方針を心がけており、アプリケーションサーバーを実行しているクラウドベンダーを他社クラウドから Google Cloud に切り替えた時にもメンテナンスは一切行いませんでした。これは主にインフラチームの努力の賜物ですが、アプリケーション側 (SRE) も負けていられません。

迫る EOL… 大規模な破壊的変更... 残された手段は...

そんな中、 「白猫」 で利用している PHP 7.4 の EOL (End of Life: サポート終了) が近づいてきました。サポートが終了したバージョンの PHP は新たな脆弱性が見つかっても修正されることはなく、古いバージョンを使い続けるためには Zend by Perforce が提供する有償サポートLinux ディストリビューション等の独自パッチを頼るしかなくなってしまいます。

そして何より、魅力的な新機能が使えません。 PHP は今もなお精力的に言語の改善が進められており、 8.0 からの match 式や 8.1 からの Union Types など、コードの品質向上やエンジニアの開発者体験にも大きく関わってきます。

以前、 PHP 7.2 が EOL し PHP 7.4 に移行した際には、まだそこまで破壊的な変更が少なかったためになんとか手作業で行うことができました。しかし PHP 8.0 の曖昧比較演算子に対する下位互換性のない変更の影響は甚大であり、実際に PHP 8.0 でアプリケーションを実行すると様々な箇所でエラーや意図しない動作が発生してしまいました。

こんな絶望的な状況の中、 Rector というツールと出会うことができました。

パーサー + 型推論 = 最強

発表の通り、 Rector は PHPStan を用いた静的解析による型推論情報と PHP-Parser による AST 操作を利用し、コードのリファクタリングが行えるツールです。

めちゃくちゃ雑に言ってしまうと、基本的になんでもできます。パーサーが解釈したトークンを望んだものに変換してしまえばいいのです。

つまり、 switch 文を if 文に書き換えることだってできるし、曖昧比較演算をすべて関数呼び出しに変換することだってできてしまいます。

伝家の宝刀 (?) colopl_bc とのあわせ技

コロプラには、 colopl_bc という下位互換性を担保するための関数を提供する PHP Extension を開発・保守しています。

そこで考えつきました。 "過去の曖昧比較演算子の代替となる関数を colopl_bc に実装し、 Rector で置き換えてしまえば良いのでは?" と...

とはいえ PHP Extension を保守していくのはとてもつらいです。具体的に言うと実装がすべて C なのですべての操作が危険です。安全性を担保するコストが大きすぎます。

ということで、まずは PHP で以前の比較演算子と同等の挙動をする関数を実装し、 Rector で実際に変換してみました。

なんとあっけなくうまく動作してしまいました。実行速度を除いて...

その後なんやかんやあって結局 colopl_bc に互換関数を実装することにしました。 Valgrind や PHPT によるテストをしっかりと行うことで安全性も担保することができました (と思います)

めでたしめでたし。

で、具体的にどうやったらいいの?...

登壇時はもう完全にこのツッコミを待っていたのですが、発表時は特に突っ込まれることはありませんでした、皆さんお優しい...

その後の Ask the speaker セッションにてワイワイ話す中で "そのルールとかいろいろ公開してよ" と多くのツッコミを受けることができました。目標達成!!! (?)

公開については検討中になりますので、まとまりましたらまた記事にさせていただきたいと思います!

おまけ

公開されてないのに説明されても...という感じではあると思うのですが、 colopl_bc では INI ディレクティブを設定することで曖昧比較やソートの互換性は保ちつつも E_DEPRECATED を投げる機能が備わっています。

プロダクション環境に突っ込んで colopl_bc の投げる E_DEPRECATED を潰していけばいつかは colopl_bc がなくても動くキレイなコードになるはずです...

 


ColoplTechについて

コロプラでは、勉強会やブログを通じてエンジニアの方々に役立つ技術や取り組みを幅広く発信していきます。
connpassおよびTwitterで情報発信していますので、是非メンバー登録とフォローをよろしくお願いいたします。

colopl.connpass.com

twitter.com

また、コロプラではゲームや基盤開発のバックエンド・インフラエンジニアを積極採用中です!
興味を持っていただいた方はぜひお気軽にご連絡ください。

colopl.co.jp