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

PHPプロジェクトの結合バランスを可視化する #php_night

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

PHPプロジェクトの結合バランスを可視化する #php_night

PHP Tech Talk Night ~ after phpcon 2026 ~ の登壇資料です。
https://vivion.connpass.com/event/400619/

Vlad Khononov の "Balancing Coupling in Software Design" (ソフトウェア設計の結合バランス) の考え方を元に、コードの解析・リポジトリの解析・AIによる推論を組み合わせて、PHPプロジェクトの結合バランスを計測し設計改善を定量的に判断する方法を紹介します。

Avatar for Takuma Kajikawa

Takuma Kajikawa

August 27, 2026

More Decks by Takuma Kajikawa

Other Decks in Programming

Transcript

  1. 梶川 琢馬 𝕏 @kajitack 株式会社 TechBowl VPoT TechTrain の開発/メンター PHP

    カンファレンスにたくさん参加してます! 次は PHP カンファレンス新潟で登壇します! スライドは X で公開します! x.com/kajitack 2/29
  2. 強度 境界を越えて共有している「知識」の量で決まる 侵⼊結合 相⼿が公開して いない内部を使う 強度 10 機能結合 相⼿の振る舞いや 前提を知っている

    強度 8 モデル結合 相⼿のドメイン モデルを共有する 強度 3 共有が多い コントラクト結合 統合のために ⽤意した契約だけ 強度 1 共有が少ない 段階の間で最も差が開くのは、モデル結合と機能結合の間(3 と 8) 15/29
  3. 例:同じ「イベントを非同期で送る」 でも、共有する知識で強度が変わる 渡すもの 強度 専用の DTO を渡す コントラクト結合 Eloquent モデルをそのまま渡す

    モデル結合 別のリスナが終わっている前提で動く 機能結合 失敗したら呼び出し元で打ち消しが要る 機能結合 統合用ではないキューを直接読む 侵入結合 16/29
  4. 強度の計測方法 AST(抽象構文木) で計測。nikic/php-parser を使用。 強度 PHPコードでの対応 侵入結合 具象クラスの継承、trait の use、静的プロパティの参照

    機能結合 モデル結合 コントラクト結 合 new、静的メソッド呼び出し、型が判っている変数へのメソッド呼び出し、コンテナ経由の解 決 引数と戻り値の型、プロパティの型、instanceof、catch、クラス定数、属性、文字列で書かれ たクラス名 interface と抽象クラスへの依存 17/29
  5. 距離 知識が移動する空間の広さ 距離が離れるほど、変更を合わせる労⼒が増える トスコの更変 ⽂ メソッド オブジェクト 名前空間 ライブラリ サービス

    システム 本ツールが測っている範囲 同じ強度の依存でも、同じファイルの中と別サービスの間では意味が違う 18/29
  6. 例: 距離によってリリース時の影響が変わる 結合している相手 直すときに起きること 同じ名前空間の中 1 つの PR で両方を直せる 別の名前空間、同じリポジトリ

    PR は 1 つだが、レビュアーや開発者が複数 別のチームが持つパッケージ 相手の予定を待つため、デプロイも別になる 19/29
  7. 強度と距離の組み合わせ 縦は強度、横は距離 ⾼ 度強 ⾼凝集 密結合 低 度強 ⼀緒に変わるものが近くにある ⼀緒に変わるのに遠い

    低凝集 疎結合 モジュラー 複雑 関係が薄いのに近くにある 関係が薄く、離れている 距離 低 距離 ⾼ 複雑 モジュラー 21/29
  8. 変動性の計測方法 一定期間のコミット数やメッセージで判断する 手順 中身 数える git log で、モジュールごとの変更コミット数(既定 12 か月)

    順位に 全モジュールの中で上位何 % かを見て、上位 10% を 10、上位 30% を 6、上位 60% を 3、それ以下を 1 する にする一度も変わっていなければ順位に関係なく 1。生の回数を使わないのは、チームごとにコミット の粒度が違うため 種類を 分ける feat と perf は機能追加、fix は修正、refactor ほかは整備 23/29
  9. 結合バランス = max(|強度 - 距離|, 10 - 変動性) + 1

    スコアの最大値を 10 にした場合の数式 24/29
  10. 組み合わせて計測したイメージ $ coupling-meter /path/to/project --depth=2 クラス 1840 / 参照 12530

    / モジュール 22 / 組 111 / 解析コミット 2317 Shell バランスが崩れている組: 20 / 111 直す順(均衡度の低い順。max(|強度 - 距離|, 10 - 変動性) + 1) BAL STRENGTH STR DIST VOL CO-CHG MODULE PAIR 1 model 3 3 10 48% Shop\Checkout -> Shop\Catalog 2 functional 8 7 10 40% Billing\Invoice -> Shop\Catalog 4 intrusive 10 7 10 25% Legacy\Reports -> Shop\Orders 指摘 [型に出ない結合] Shop\Checkout -> Shop\Catalog 型の上は model だが、16 回のコミットで同時に変わっている(48%) [踏み込んだ依存が動いている] Legacy\Reports -> Shop\Orders 内部に踏み込んだ依存が 31 箇所あり、25% のコミットで同時に変わっている 25/29
  11. 計測ツールの比較 結合だけでなく、各種ツールを組み合わせて使うとより良い 測る単位 ツール 出力 型と、バグの可能性 PHPStan、Psalm 違反かどうか 層をまたぐ依存 deptrac

    違反かどうか 1 つの関数の読みにくさ moznion/cccc 循環的複雑度、認知的複雑度 複雑度の数値 機械的なコンポーネントの間の結合 今回のツール 直す順(均衡度) ドメイン知識やコードの意味による結合 skillや人 直す順(均衡度) 26/29
  12. 作ってみた感想 コーディングエージェントから呼び出す形にすると便利 実行しながら概念について理解しやすくなる 著者が公開している claude skill (vladikk/modularity) と組み合わせて、 機械的な計測ができそうな部分を徐々にツール化していくと改善しやすい 機械的な検査は

    LLM だと比べてコストや安定性の面で有利 一方で、コードの意味の分析はドメイン知識を与えた AI や人間の方が有利 汎用的なツールを作るより、各プロジェクトに特化した方が良いかも? 命名規則やフレームワークによる暗黙的な呼び出しとか、コードベースに現れない サービス間の結合など... 27/29