リファクタリングによって重複を減らせても、分かりにくい抽象化を加えたり、複雑さを別の場所に移したりすれば、変更はかえって難しくなることがあります。結果を評価するには、スコアを比較したりテストの成功を確認したりするだけでは不十分です。何を改善したいのかを定め、複数の兆候を観察し、システムが実際に変更しやすくなったかを検証する必要があります。
このガイドでは、指標を単独の目標にせず、リファクタリングの前後でPHPアプリケーションの保守性を測定する方法を説明します。同じ範囲を比較し、背景を記録すれば、クラス、モジュール、ビジネスフローのいずれにも適用できます。
単一の指標では保守性を証明できない理由

保守性とは、妥当なリスクの範囲内でシステムを理解し、テストし、変更できる能力です。これらの能力を単独で表せる指標はありません。行数が減っても複雑さが減ったとは限らず、カバレッジが上がっても有用なテストが増えたとは限りません。また、静的解析のスコアが良好でも、チームが設計を理解しているかは分かりません。
さらに、指標はリファクタリングとは無関係な理由でも変化します。ツールの更新、解析ルールの違い、対象範囲の変更、レポートへの生成コードの追加などがその例です。そのため、数値は算出方法、解析対象、既知の制約と合わせて解釈する必要があります。
目標は、変更によって抽象的に「コードが改善した」と証明することではありません。具体的な問題を解決し、不釣り合いなリスクを持ち込まなかったかを確かめることです。
改善したい変更能力を定める
測定の前に、検証可能で範囲を絞った仮説を立てます。たとえば、「このクラスから計算ルールを分離すれば、HTTPフローを起動せずにルールをテストできる」や、「このサービスの依存関係を減らせば、ルール追加に必要な変更を限定できる」といった仮説です。仮説が示すのは期待する成果であり、流行を理由に特定のアーキテクチャを指定するものではありません。
影響を受ける範囲と操作を明確にします。クラス、エンドポイント、コマンド、ジョブ、ビジネスルールなどが対象です。また、外部連携や今回対応しない既知の技術的負債など、対象外のものも記録します。範囲を定めないと、比較にリファクタリング以外の変更の影響が混ざる可能性があります。
仮説は、実際に確認できる問いに置き換えるとよいでしょう。ルールを見つけやすくなるか。実データベースなしでテストできるか。よくある変更に必要なモジュール数が減るか。チームが証拠に基づいて答えられる問いを少数選びます。
コードを変更する前に基準値を記録する
リポジトリ内で特定できる初期状態を記録し、変更後にも使うものと同じツールと設定を用います。PHPの対象範囲では、次のような兆候を組み合わせると有用です。
- 複雑さ: 長いメソッド、条件分岐、判断が集中している箇所を確認します。循環的複雑度は参考になりますが、ルールの理解しやすさを単独で表すものではありません。
- 結合度: 直接的な依存関係、責務の混在、インフラとの接続を特定します。変更の際に、無関係なコンポーネントを把握したり変更したりする必要があるかを確認します。
- 重複: 繰り返されているロジックを見つけます。その際、偶発的な重複と、別々に変更すべき類似ルールを区別します。
- テスト: 重要な振る舞いのうち何がカバーされているか、どのテストが信頼できるか、外部サービスを必要とする依存関係があるかを記録します。
- 運用とリリース: 対象範囲に関連する場合は、本番環境の障害や重大なリグレッション、変更のデプロイの難しさ、関連する手作業を記録します。
静的解析を使う場合は、ツール名、ルール、バージョン、実行コマンドを保存します。これらの情報がなければ数値を再現できません。設定で可能なら生成コードや外部コードを分け、除外項目も明記してください。
検証可能な指標を選び、限界を記録する
仮説に答えられる指標を選びます。ロジックの分離を目的としたリファクタリングなら、テストに必要な依存関係の数、関連する振る舞いを検証するテストの有無、チームメンバーが変更箇所を見つけるまでの時間などが指標になります。結合度の低減が目的なら、代表的なタスクで変更が必要なコンポーネント数を観察できます。
時間や件数を普遍的な真実として扱ってはいけません。タスクの規模、担当者の経験、中断の有無などが結果に影響します。利用する場合は条件を記録し、個人間の生産性比較ではなく、兆候として扱います。
各指標について、何を測るか、どう取得するか、どんな結果を期待するか、何を証明できないかの4点を記録します。たとえば、依存関係の数が減ったことは確認できても、新たな抽象化が理解しやすいことまでは証明できません。それは技術レビューで確認する必要があります。
同じ方法で変更前後を比較する
リファクタリング後は、同じ範囲を同じ設定で再分析し、可能な限り同等の条件で比較します。レビューでは、機能変更と構造変更を分けて扱います。両方を同時に変更した場合は、それぞれに対応する証拠を特定し、結果のすべてをリファクタリングの効果として扱わないようにします。
指標に加えて、実際の変更または代表的な変更を試します。ルールの修正、ビジネス条件の追加、連携の変更などです。変更が必要だったファイル、必要なテスト、疑問が生じた箇所を確認します。すでに比較可能な作業があるなら、人工的なタスクを作る必要はありません。ただし、逸話的な印象を決定的な結果として示してはいけません。
一貫した改善には、複数の兆候が伴います。たとえば、ルールのテストに必要な依存関係が減り、テストがより焦点を絞り、変更経路をチームが説明できることです。メソッドの複雑さが下がっても、ロジックが分散したり、処理の流れを追いにくくなったりした場合は、全体の評価を見直す必要があります。
測定結果をレビューとチームのフィードバックに組み合わせる
技術レビューでは、責務が明確になったか、名前がドメインを表しているか、新しいインターフェースが実際の必要性を解決するかを確認します。また、重複した契約、分かりにくい依存関係の逆転、意図しない振る舞いの変更、呼び出しを転送するだけの新しいレイヤーなど、持ち込まれたリスクも探します。
チームのフィードバックは、理解しやすさや運用性に関する証拠になります。ルールを見つける、テストを書く、変更の範囲を見積もることが以前より容易になったかを尋ねます。回答は具体例と結び付け、意見の相違も記録します。設計した本人には明快なアーキテクチャでも、保守する人には分かりにくいことがあります。
PHPでは、リファクタリングが既存の契約を守っていることも検証します。型、例外、副作用、シリアライズ、APIの観測可能な振る舞いが対象です。内部設計が整理されても、機能上のリグレッションや想定外の非互換性は補えません。
保守性の測定でよくある誤り
- カバレッジを追い求める: 割合を上げるために表面的なテストを追加することがあります。行が実行されたかだけでなく、振る舞いやリスクの高いケースをテストしているかを評価します。
- 行数の削減を評価する: コードを短くすると判断が隠れ、変更のレビューが難しくなることがあります。行数は明確さを直接測る指標ではありません。
- スコアの最適化: ツールに合わせてコードを変更しても、設計上の問題が残る場合があります。変化の意味を調べ、実際のタスクで効果を確認します。
- 範囲の異なる比較: 新規ファイル、除外されたコード、変更されたルールを混在させると、結果を正しく解釈できません。方法を一定に保つか、違いを説明します。
- 振る舞いを無視する: 機能変更を別途定義して検証する場合を除き、リファクタリングでは期待される振る舞いを維持する必要があります。
次の対応を決めるための簡易テンプレート

評価を終える際に、次の項目を記録します。
- 対象範囲と目的: どの部分をリファクタリングし、どの変更能力の改善を目指したか。
- 基準値と方法: コードのリビジョン、ツール、設定、対象範囲、除外項目。
- 観察された兆候: 変更前後の結果と、各指標の限界。
- 実践的な検証: テスト、技術レビュー、代表的な変更から得られた証拠。
- 未解決のリスク: カバーされていない振る舞い、先送りした技術的負債、確認が必要な運用上の影響。
- 判断: 仮説が裏付けられ、リスクが許容範囲なら続行します。兆候が混在する場合や理解しにくさがある場合は調整します。コストやリスクが期待する利益を上回る場合は中止します。
最後に問うべきなのは、コードのスコアが上がったかではなく、チームがその部分をより明確かつ確実に変更できるかです。再現可能な基準値、相互に補完する複数の兆候、率直なレビューがあれば、リファクタリングを行ったことと、改善が実証されたことを混同せずに判断できます。



