SlideShare a Scribd company logo
PHP版レガシーコード改善に 
役立つ新パターン 
ヤフー株式会社 
佐藤祐司 
2014/9/27 レガシーコード改善勉強会 #wewlc_jp
自己紹介 
佐藤 祐司 
• 2010年新卒入社 
• Webエンジニア 
• PHP 
@kuidaoring
今日話すこと 
• 私の業務とレガシーコード 
• パターンの紹介 
• これで幸せになれるのか
今日話すこと 
• 私の業務とレガシーコード 
• パターンの紹介 → 本日のメイン 
• これで幸せになれるのか
今日話すこと 
• レガシーコード改善の具体的な 
リファクタリングの具体的な方法 
• 今あるコードを何とかテストで保護して、 
自分が手を加える部分のテストを 
書けるようにしたい
今日話すこと 
• レガシーコード改善の具体的な 
リファクタリングの具体的な方法 
• 今あるコードを何とかテストで保護して、 
自分が手を加える部分のテストを 
書けるようにしたい
私の業務とレガシーコード
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
サービス 
サービス規模 
• 58.3億PV / 月 
• 1.4億UB / 月 
出典:Yahoo! JAPAN 媒体資料 2014年6月改訂版 (PDF) 
http://i.yimg.jp/images/marketing/portal/paper/media_sheet_open.pdf
サービス 
トップページを作る部署の中の一つ 
PJメンバー約40名 
• 開発約20名 
PCスマホアプリ… 
ここ
業務とレガシーコード 
こんなことありませんか? 
• 少ない自動テスト 
• リリース当時の開発メンバーはゼロ 
• どんどん開発メンバーが増える 
どうしてこんなふうになったのか
新規リリース時 
まずはローンチを目指す 
• ローンチ、リリース優先 
• ヒットするかはわからない 
ローンチだ!
リリース後 
サービスの成長を目指す 
• 機能を増やす 
• メンバーも少しづつ増える 
機能追加だ!
ある程度成熟して振り返ると 
• メンバーの入れ替わり 
• 歴史的経緯によるコード 
• 場当たり的な修正 
とりあえず 
直しました…! 
今⽇日からよろしく 
お願いします!
業務とレガシーコード 
• その時の判断が間違いだったかは 
わからない 
• 優先順位の話 
• ただしずっとそのままでいい 
というわけではない
業務とレガシーコード 
過去には一部似た状況になったが、 
• 有志による改善活動 
• 社内でもノウハウがたまってきた
ユニットテスト拡充 CI整備
開発フロー整備
業務とレガシーコード 
どうしたか 
• レガシーコードを地道に改善 
• レガシーコードを作りにくくする 
仕組みや体制を整備 
地道に少しづつ改善を進めた
パターンの紹介
パターンの紹介 
• レガシーコード改善の具体的な 
リファクタリングの具体的な方法 
• 今あるコードを何とかテストで保護して、 
自分が手を加える部分のテストを 
書けるようにしたい
PHPって 
• Webに特化 
• 置けば動く 
• HTMLに埋め込める 
• テンプレートエンジン 
• 標準関数が豊富
PHPにおけるレガシーコード 
• 環境に依存 
• 構造を持たない 
• スーパーグローバル変数 
• $_GET, $_POST, $_SESSION など 
• 不用意なexit
PHPにおけるレガシーコード 
サンプルコードを用いて説明 
• adminユーザと一般ユーザで見せる 
メニューを変更する
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
どう対応するのか 
1. テストを書けるようにする 
2. テストで保護する 
3. リファクタリング 
4. テスト、リファクタリングを繰り返す
どう対応するのか 
1. テストを書けるようにする 
2. テストで保護する 
3. リファクタリング 
4. テスト、リファクタリングを繰り返す
なにが問題になるか 
• DBに接続する 
• exitでスクリプトが終了 
• getパラメータが必要 
• ビューとロジックの混在
DBに接続
exitで終了
スーパーグローバル 
変数を参照して 
パラメータ取得
ビューとロジックが 
混在
どうにかしてテストを 
書けるようにするためのパターン
• 関数オーバーライド 
• ラップ関数
関数オーバーライド
関数オーバーライド 
• 名前空間を使って組み込み関数などを 
上書き 
• 実際には上書きしてない 
• 元ネタ 
PHPでネイティブ関数を含むコードのテスタビリティを上げる2つの方法 
- 絶品ゆどうふのタレ 
http://yudoufu.hatenablog.jp/entry/20110808/1312828535 
• 名前空間が接合部になる
関数オーバーライド 
index.php func() 
外部 
リソース 
プロダクトコード
関数オーバーライド 
index.php func() 
外部 
リソース 
プロダクトコード 
func() 
テストコード
接合部 
接合部とは、その場所を直接変更しなくて 
も、プログラムの振る舞いを変えることの 
出来る場所である 
レガシーコード改善ガイドより
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
コンストラクタで 
渡すオブジェクトによって 
振る舞いを変更できる
名前空間 
PHP5.3から導入 
PHP: 名前空間 ‒ Manual 
http://php.net/manual/ja/language.namespaces.php 
他の言語のパッケージやモジュールに相当
名前空間 
名前空間の影響を受けるもの 
• class 
• interface 
• trait(5.4以降) 
• 関数 
• 定数(const)
定義
参照
名前空間 
• 名前空間の中であれば、 
組み込み関数やグローバルな関数と 
同じ名前の関数を定義できる 
• 同じ名前空間内であれば、 
名前空間の指定を省略できる
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
組み込み関数と同じ 
名前で定義できる
名前空間内の関数が 
呼ばれる
関数オーバーライド 
どういう時に有効か 
• 上書きしたい対象が関数でしか 
用意されていない 
外部の影響を受ける組み込み関数を 
そのまま使っている場合など
ラップ関数
ラップ関数 
変数の参照などを直接行うのではなく 
関数を経由して行うようにする
どう対応するのか
なにが問題になるか 
• DBに接続する 
• exitでスクリプトが終了 
• getパラメータが必要 
• ビューとロジックの混在
どう対応するのか 
1. テストを書けるようにする 
• 環境の分離 
• スーパーグローバル変数の間接参照 
• exitの検討 
2. テストで保護する 
3. リファクタリング 
4. テスト、リファクタリングを繰り返す
どう対応するのか 
1. テストを書けるようにする 
• 環境の分離 
• スーパーグローバル変数の間接参照 
• exitの検討 
2. テストで保護する 
3. リファクタリング 
4. テスト、リファクタリングを繰り返す
環境の分離 
テスト実行時にもDBに接続しにいってしま 
う 
• DBに接続する関数をなんとかしたい 
• 関数オーバーライドを使う
環境の分離 
1. テスト対象のスクリプトに 
名前空間の定義を追加 
2. テストコードでテスト対象と 
同じ名前で名前空間の定義を追加 
3. 上書きしたい関数と同じ名前の 
関数をテストコードで定義
環境の分離 
1. テスト対象のスクリプトに 
名前空間の定義を追加 
2. テストコードでテスト対象と 
同じ名前で名前空間の定義を追加 
3. 上書きしたい関数と同じ名前の 
関数をテストコードで定義
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
環境の分離 
1. テスト対象のスクリプトに 
名前空間の定義を追加 
2. テストコードでテスト対象と 
同じ名前で名前空間の定義を追加 
3. 上書きしたい関数と同じ名前の 
関数をテストコードで定義
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
すでに他の名前空間が 
あればその下に追加
環境の分離 
1. テスト対象のスクリプトに 
名前空間の定義を追加 
2. テストコードでテスト対象と 
同じ名前で名前空間の定義を追加 
3. 上書きしたい関数と同じ名前の 
関数をテストコードで定義
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
関数オーバーライド 
プロダクトコード 
index.php db_get_user() 
DB
関数オーバーライド 
プロダクトコード 
index.php 
テストコード 
db_get_user() DB 
db_get_user()
注意 
名前空間を定義することで 
関数が呼び出せなくなる場合がある
名前空間の定義を 
追加
参照できなくなる
名前空間の影響 
どうするか 
• 関数を名前空間の外に再定義
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
どう対応するのか 
1. テストを書けるようにする 
• 環境の分離 
• スーパーグローバル変数の間接参照 
• exit, dieの検討 
2. テストで保護する 
3. リファクタリング 
4. テスト、リファクタリングを繰り返す
スーパーグローバル変数 
変数なので代入して書き換えが可能 
• 他のテストケースに影響してしまう 
• 変数を直接参照しなければいい 
• ラップ関数を使う
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
どう対応するのか 
1. テストを書けるようにする 
• 環境の分離 
• スーパーグローバル変数の参照 
• exitの検討 
2. テストで保護する 
3. リファクタリング 
4. テスト、リファクタリングを繰り返す
exitの検討 
exitのなにが問題になるか 
• スクリプトを終了 
PHPUnit自体も終了する 
• exitは関数ではない
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
実行されない
exit、dieの必要性の検討 
成功・失敗も 
わからず終了
exitの検討 
exitは言語構造、予約語 
• 名前空間内でも「exit」という 
名前の関数を定義できない 
• 「関数オーバーライド」が使えない
exitの検討 
どうするか 
• returnの代わりに使ってませんか 
• returnに変える 
• exitする部分をラップ関数にする 
• その後に関数オーバーライドを使う
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
PHP版レガシーコード改善に役立つ新パターン #wewlc_jp
どう対応するのか 
1. テストを書けるようにする 
2. テストで保護する 
3. リファクタリング 
4. テスト、リファクタリングを繰り返す
テスト 
• ビューとロジックが混ざっているので 
ロジックのみの検証はおそらく不可能 
• 条件によって変わるビューを検証する 
• assertRegex, assertContains 
• HTMLであればassertTagなど
どう対応するのか 
1. テストを書けるようにする 
2. テストで保護する 
3. リファクタリング 
4. テスト、リファクタリングを繰り返す
リファクタリング 
まずはベタなものを適切な単位に分離 
• ファイルを分離 
• 関数に分離 
• クラスに分離
課題 
globalが邪魔をする 
• グローバル変数ではなくなる 
ことによってうまく動作しなくなる 
• 「コンパイラまかせ」が使えないので 
動かすまでわからない
課題 
• 関数内でグローバル変数を参照している 
部分を引数に置き換えるように 
リファクタリングする 
• 地道に。。。 
• 参考 
テスト不能な PHP コードをリファクタリングするための戦略 
http:/www.ibm.com/developerworks/jp/opensource/library/os-refactoringphp/
これで幸せになれるのか
これで幸せになれるのか 
これだけで根本解決はできない 
• とりあえずテストは書けるようになった 
• 適用できるケースは 
それほど多くない(かも) 
• 今回は「今」できること
レガシー 
小改善 テストで 
保護 
リファクタ 
リング 
イケてる
これで幸せになれるのか 
全体を考えて設計の変更などを 
行う必要がある 
• フラットなPHPからフレームワークへ 
• 地道にテストコードを増やしていく 
継続的な改善が必要
ありがとうございました

More Related Content

What's hot (20)

PPTX
概念モデリング再入門 + DDD
Hiroshima JUG
 
PDF
ソーシャルゲームのためのデータベース設計
Yoshinori Matsunobu
 
PDF
理解して使いこなすDjangoのForm機能(2021 Django Congress発表資料)
KyutatsuNishiura
 
PDF
Airflowで真面目にjob管理
msssgur
 
PDF
フロー効率性とリソース効率性について #xpjug
Itsuki Kuroda
 
PPTX
設計と実装で 抑えておきたい サービスクラスと例外
Takuya Sato
 
PDF
C#でもメタプログラミングがしたい!!
TATSUYA HAYAMIZU
 
PDF
実装して理解するLINE LoginとOpenID Connect入門
Naohiro Fujie
 
PDF
開発速度が速い #とは(LayerX社内資料)
mosa siru
 
PDF
概念モデルって難しいですよね
Takuya Kawabe
 
PDF
ドメイン駆動設計の正しい歩き方
増田 亨
 
PDF
CQRS+ES on GCP
Masaki Toyoshima
 
PDF
アプリの鍵が消える時_Droid kaigi2018
ak_shio_555
 
PPT
ドメインロジックの実装方法とドメイン駆動設計
Tadayoshi Sato
 
PPTX
Startup Science ①
Masa Tadokoro
 
PDF
人生がときめくAPIテスト自動化 with Karate
Takanori Suzuki
 
PDF
今なら間に合う分散型IDとEntra Verified ID
Naohiro Fujie
 
PDF
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
Takuto Wada
 
PDF
世界でいちばんわかりやすいドメイン駆動設計
増田 亨
 
PDF
LIFFとの連携でさらに強力に。こんなに使えるLINEログイン
Naohiro Fujie
 
概念モデリング再入門 + DDD
Hiroshima JUG
 
ソーシャルゲームのためのデータベース設計
Yoshinori Matsunobu
 
理解して使いこなすDjangoのForm機能(2021 Django Congress発表資料)
KyutatsuNishiura
 
Airflowで真面目にjob管理
msssgur
 
フロー効率性とリソース効率性について #xpjug
Itsuki Kuroda
 
設計と実装で 抑えておきたい サービスクラスと例外
Takuya Sato
 
C#でもメタプログラミングがしたい!!
TATSUYA HAYAMIZU
 
実装して理解するLINE LoginとOpenID Connect入門
Naohiro Fujie
 
開発速度が速い #とは(LayerX社内資料)
mosa siru
 
概念モデルって難しいですよね
Takuya Kawabe
 
ドメイン駆動設計の正しい歩き方
増田 亨
 
CQRS+ES on GCP
Masaki Toyoshima
 
アプリの鍵が消える時_Droid kaigi2018
ak_shio_555
 
ドメインロジックの実装方法とドメイン駆動設計
Tadayoshi Sato
 
Startup Science ①
Masa Tadokoro
 
人生がときめくAPIテスト自動化 with Karate
Takanori Suzuki
 
今なら間に合う分散型IDとEntra Verified ID
Naohiro Fujie
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
Takuto Wada
 
世界でいちばんわかりやすいドメイン駆動設計
増田 亨
 
LIFFとの連携でさらに強力に。こんなに使えるLINEログイン
Naohiro Fujie
 

Similar to PHP版レガシーコード改善に役立つ新パターン #wewlc_jp (20)

PPTX
Sansan における Android アプリ自動テスト導入事例
Kenichi Tatsuhama
 
KEY
WordPress中級者への道!テンプレートタグはどう動くのか!?
Shinichi Nishikawa
 
PDF
2018年度 若手技術者向け講座 リファクタリング
keki3
 
PDF
4時間まったりWordPressテーマ作成講座
Shinichi Nishikawa
 
PDF
CodeIgniter入門
Sho A
 
PDF
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
Hisateru Tanaka
 
PDF
第1回python勉強会
Yoshio Shimomura
 
PDF
バリデーション駆動開発(仮称)で プロジェクトメンバー全員を幸せにした話
Kentarou Takeda
 
PDF
PHPフレームワーク入門
Sho A
 
PPTX
Php development efficiency improvement
伸幸 茂木
 
PPTX
PHP基礎勉強会
Yuji Otani
 
PDF
第10回rest勉強会 リファクタリング(サーバ編)編
ksimoji
 
PDF
はじめてのCodeIgniter
Yuya Matsushima
 
PDF
三位一体の自動化で壊せ DevとOpsの壁~アラサーエンジニアの挑戦~
Rakuten Group, Inc.
 
PDF
Weeklycms20120218
Yoshi Sakai
 
PDF
Phjosh(仮)プロジェクト
Moriyoshi Koizumi
 
PPTX
PHPCON_TOKYO_2022_Bigginer.pptx
Hideo Kashioka
 
PDF
Phpcon2001 in tokyo
Hideo Kashioka
 
PDF
Chef
yaasita
 
Sansan における Android アプリ自動テスト導入事例
Kenichi Tatsuhama
 
WordPress中級者への道!テンプレートタグはどう動くのか!?
Shinichi Nishikawa
 
2018年度 若手技術者向け講座 リファクタリング
keki3
 
4時間まったりWordPressテーマ作成講座
Shinichi Nishikawa
 
CodeIgniter入門
Sho A
 
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
Hisateru Tanaka
 
第1回python勉強会
Yoshio Shimomura
 
バリデーション駆動開発(仮称)で プロジェクトメンバー全員を幸せにした話
Kentarou Takeda
 
PHPフレームワーク入門
Sho A
 
Php development efficiency improvement
伸幸 茂木
 
PHP基礎勉強会
Yuji Otani
 
第10回rest勉強会 リファクタリング(サーバ編)編
ksimoji
 
はじめてのCodeIgniter
Yuya Matsushima
 
三位一体の自動化で壊せ DevとOpsの壁~アラサーエンジニアの挑戦~
Rakuten Group, Inc.
 
Weeklycms20120218
Yoshi Sakai
 
Phjosh(仮)プロジェクト
Moriyoshi Koizumi
 
PHPCON_TOKYO_2022_Bigginer.pptx
Hideo Kashioka
 
Phpcon2001 in tokyo
Hideo Kashioka
 
Chef
yaasita
 
Ad

More from Yahoo!デベロッパーネットワーク (20)

PDF
ゼロから始める転移学習
Yahoo!デベロッパーネットワーク
 
PDF
継続的なモデルモニタリングを実現するKubernetes Operator
Yahoo!デベロッパーネットワーク
 
PDF
ヤフーでは開発迅速性と品質のバランスをどう取ってるか
Yahoo!デベロッパーネットワーク
 
PDF
オンプレML基盤on Kubernetes パネルディスカッション
Yahoo!デベロッパーネットワーク
 
PDF
オンプレML基盤on Kubernetes 〜Yahoo! JAPAN AIPF〜
Yahoo!デベロッパーネットワーク
 
PDF
Persistent-memory-native Database High-availability Feature
Yahoo!デベロッパーネットワーク
 
PDF
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
Yahoo!デベロッパーネットワーク
 
PDF
eコマースと実店舗の相互利益を目指したデザイン #yjtc
Yahoo!デベロッパーネットワーク
 
PDF
ヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtc
Yahoo!デベロッパーネットワーク
 
PDF
Yahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtc
Yahoo!デベロッパーネットワーク
 
PDF
ビッグデータから人々のムードを捉える #yjtc
Yahoo!デベロッパーネットワーク
 
PDF
サイエンス領域におけるMLOpsの取り組み #yjtc
Yahoo!デベロッパーネットワーク
 
PDF
ヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtc
Yahoo!デベロッパーネットワーク
 
PDF
Yahoo! JAPAN Tech Conference 2022 Day2 Keynote #yjtc
Yahoo!デベロッパーネットワーク
 
PDF
新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtc
Yahoo!デベロッパーネットワーク
 
PDF
PC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtc
Yahoo!デベロッパーネットワーク
 
PDF
モブデザインによる多職種チームのコミュニケーション改善 #yjtc
Yahoo!デベロッパーネットワーク
 
PDF
「新しいおうち探し」のためのAIアシスト検索 #yjtc
Yahoo!デベロッパーネットワーク
 
PDF
ユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtc
Yahoo!デベロッパーネットワーク
 
ゼロから始める転移学習
Yahoo!デベロッパーネットワーク
 
継続的なモデルモニタリングを実現するKubernetes Operator
Yahoo!デベロッパーネットワーク
 
ヤフーでは開発迅速性と品質のバランスをどう取ってるか
Yahoo!デベロッパーネットワーク
 
オンプレML基盤on Kubernetes パネルディスカッション
Yahoo!デベロッパーネットワーク
 
オンプレML基盤on Kubernetes 〜Yahoo! JAPAN AIPF〜
Yahoo!デベロッパーネットワーク
 
Persistent-memory-native Database High-availability Feature
Yahoo!デベロッパーネットワーク
 
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
Yahoo!デベロッパーネットワーク
 
eコマースと実店舗の相互利益を目指したデザイン #yjtc
Yahoo!デベロッパーネットワーク
 
ヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtc
Yahoo!デベロッパーネットワーク
 
Yahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtc
Yahoo!デベロッパーネットワーク
 
ビッグデータから人々のムードを捉える #yjtc
Yahoo!デベロッパーネットワーク
 
サイエンス領域におけるMLOpsの取り組み #yjtc
Yahoo!デベロッパーネットワーク
 
ヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtc
Yahoo!デベロッパーネットワーク
 
Yahoo! JAPAN Tech Conference 2022 Day2 Keynote #yjtc
Yahoo!デベロッパーネットワーク
 
新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtc
Yahoo!デベロッパーネットワーク
 
PC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtc
Yahoo!デベロッパーネットワーク
 
モブデザインによる多職種チームのコミュニケーション改善 #yjtc
Yahoo!デベロッパーネットワーク
 
「新しいおうち探し」のためのAIアシスト検索 #yjtc
Yahoo!デベロッパーネットワーク
 
ユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtc
Yahoo!デベロッパーネットワーク
 
Ad

PHP版レガシーコード改善に役立つ新パターン #wewlc_jp