Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

梶川 琢馬 𝕏 @kajitack 株式会社 TechBowl VPoT TechTrain の開発/メンター PHP カンファレンスにたくさん参加してます! 次は PHP カンファレンス新潟で登壇します! スライドは X で公開します! x.com/kajitack 2/29

Slide 3

Slide 3 text

3/29

Slide 4

Slide 4 text

4/29

Slide 5

Slide 5 text

“片方を変えると ある特定の変更について もう片方も変えざるを得ないとき その2つは結合している ” Kent Beck Coupling, 2022 newsletter.kentbeck.com/p/coupling 5/29

Slide 6

Slide 6 text

“ 設計とは隙間で起こるものだ ” Kent Beck 島田浩二 訳『ソフトウェア設計の結合バランス 持続可能な成長を支えるモジュール化の 原則』インプレス、2025 序文 6/29

Slide 7

Slide 7 text

結合度 コンポーネント(関数やクラスのまとまりなど)の関係性 ある特定の変更について片方を変えると、 もう片方も変えざるを得ないとき、その 2 つは結合している 7/29

Slide 8

Slide 8 text

結合度が高いと? 「変更の難易度を上げ、システムの柔軟性と 信頼性を低下させる」 コンポーネントに変更を加えた場合、依存している 他のコンポーネントも一緒に変更やテストを しなければならない頻度が高くなる 8/29

Slide 9

Slide 9 text

“ 本来密接に連携すべきコンポーネントまで無理に引き剥が して疎結合にしようとすると、変更のたびに複数の サービスをまたいだ複雑な調整が必要になり、 「分散した巨大な泥団子」という悲惨なアーキテクチャに 終わる ” Vlad Khononov 島田浩二 訳『ソフトウェア設計の結合バランス 持続可能な成長を支えるモジュール化の 原則』インプレス、2025 9/29

Slide 10

Slide 10 text

“結合している」とは言うが、 「このサービスはあのサービスと どのように?どんな変更に関して? ” Kent Beck『Tidy First?』29章 結合 10/29

Slide 11

Slide 11 text

結合バランス 良い結合=強度、距離、変動性の 3 つの次元が 最適な状態 3 つの観点からどんな結合の仕方をしているか?その バランスを取ることを目指す ソフトウェア設計の結合バランス 持続可能な成長を支えるモジュール化の原則 Vlad Khononov 著/島田 浩二 訳 11/29

Slide 12

Slide 12 text

結合バランス = 強度 XOR 距離 OR NOT 変動性 12/29

Slide 13

Slide 13 text

“ 将来的には、コードベースを分析し 3 つの数値を自動的に評価するツールが 登場することを期待している ” Vlad Khononov 島田浩二 訳『ソフトウェア設計の結合バランス』インプレス、2025 第 10 章 同じ節は「警告: これは正確な科学ではない」から始まる 13/29

Slide 14

Slide 14 text

coupling-meter 計測するツールをつくってみた ※まだ試作段階 https://github.com/TechBowl-japan/coupling-meter 14/29

Slide 15

Slide 15 text

強度 境界を越えて共有している「知識」の量で決まる 侵⼊結合 相⼿が公開して いない内部を使う 強度 10 機能結合 相⼿の振る舞いや 前提を知っている 強度 8 モデル結合 相⼿のドメイン モデルを共有する 強度 3 共有が多い コントラクト結合 統合のために ⽤意した契約だけ 強度 1 共有が少ない 段階の間で最も差が開くのは、モデル結合と機能結合の間(3 と 8) 15/29

Slide 16

Slide 16 text

例:同じ「イベントを非同期で送る」 でも、共有する知識で強度が変わる 渡すもの 強度 専用の DTO を渡す コントラクト結合 Eloquent モデルをそのまま渡す モデル結合 別のリスナが終わっている前提で動く 機能結合 失敗したら呼び出し元で打ち消しが要る 機能結合 統合用ではないキューを直接読む 侵入結合 16/29

Slide 17

Slide 17 text

強度の計測方法 AST(抽象構文木) で計測。nikic/php-parser を使用。 強度 PHPコードでの対応 侵入結合 具象クラスの継承、trait の use、静的プロパティの参照 機能結合 モデル結合 コントラクト結 合 new、静的メソッド呼び出し、型が判っている変数へのメソッド呼び出し、コンテナ経由の解 決 引数と戻り値の型、プロパティの型、instanceof、catch、クラス定数、属性、文字列で書かれ たクラス名 interface と抽象クラスへの依存 17/29

Slide 18

Slide 18 text

距離 知識が移動する空間の広さ 距離が離れるほど、変更を合わせる労⼒が増える トスコの更変 ⽂ メソッド オブジェクト 名前空間 ライブラリ サービス システム 本ツールが測っている範囲 同じ強度の依存でも、同じファイルの中と別サービスの間では意味が違う 18/29

Slide 19

Slide 19 text

例: 距離によってリリース時の影響が変わる 結合している相手 直すときに起きること 同じ名前空間の中 1 つの PR で両方を直せる 別の名前空間、同じリポジトリ PR は 1 つだが、レビュアーや開発者が複数 別のチームが持つパッケージ 相手の予定を待つため、デプロイも別になる 19/29

Slide 20

Slide 20 text

距離の計測方法 最も近い共通の名前空間までの段数で測る 多くのモジュールが依存する相手は 1 段近く、触る人が分かれている組は 1 段遠くする 20/29

Slide 21

Slide 21 text

強度と距離の組み合わせ 縦は強度、横は距離 ⾼ 度強 ⾼凝集 密結合 低 度強 ⼀緒に変わるものが近くにある ⼀緒に変わるのに遠い 低凝集 疎結合 モジュラー 複雑 関係が薄いのに近くにある 関係が薄く、離れている 距離 低 距離 ⾼ 複雑 モジュラー 21/29

Slide 22

Slide 22 text

変動性 変更が起きる頻度を決める 密結合、低凝集な結合に対して変動性が高ければ改善した方が良い ドメイン知識による分類: 競争優位性の高い機能は変更されやすい コード品質による分類: 設計が悪くて何回も変更しなければいけない 22/29

Slide 23

Slide 23 text

変動性の計測方法 一定期間のコミット数やメッセージで判断する 手順 中身 数える git log で、モジュールごとの変更コミット数(既定 12 か月) 順位に 全モジュールの中で上位何 % かを見て、上位 10% を 10、上位 30% を 6、上位 60% を 3、それ以下を 1 する にする一度も変わっていなければ順位に関係なく 1。生の回数を使わないのは、チームごとにコミット の粒度が違うため 種類を 分ける feat と perf は機能追加、fix は修正、refactor ほかは整備 23/29

Slide 24

Slide 24 text

結合バランス = max(|強度 - 距離|, 10 - 変動性) + 1 スコアの最大値を 10 にした場合の数式 24/29

Slide 25

Slide 25 text

組み合わせて計測したイメージ $ 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

Slide 26

Slide 26 text

計測ツールの比較 結合だけでなく、各種ツールを組み合わせて使うとより良い 測る単位 ツール 出力 型と、バグの可能性 PHPStan、Psalm 違反かどうか 層をまたぐ依存 deptrac 違反かどうか 1 つの関数の読みにくさ moznion/cccc 循環的複雑度、認知的複雑度 複雑度の数値 機械的なコンポーネントの間の結合 今回のツール 直す順(均衡度) ドメイン知識やコードの意味による結合 skillや人 直す順(均衡度) 26/29

Slide 27

Slide 27 text

作ってみた感想 コーディングエージェントから呼び出す形にすると便利 実行しながら概念について理解しやすくなる 著者が公開している claude skill (vladikk/modularity) と組み合わせて、 機械的な計測ができそうな部分を徐々にツール化していくと改善しやすい 機械的な検査は LLM だと比べてコストや安定性の面で有利 一方で、コードの意味の分析はドメイン知識を与えた AI や人間の方が有利 汎用的なツールを作るより、各プロジェクトに特化した方が良いかも? 命名規則やフレームワークによる暗黙的な呼び出しとか、コードベースに現れない サービス間の結合など... 27/29

Slide 28

Slide 28 text

“将来に備えるためのものだった モジュール性(結合の仕方)はかつて 今はそれに加えて AI が扱えるようにするためでもある ” Vlad Khononov The Golden Age of Modularity, 2025(筆者訳) vladikk.com/2025/03/30/golden-age-of-modularity 28/29

Slide 29

Slide 29 text

PHPプロジェクトの結合 バランスを可視化する 結合が悪いのではなく、どのように結合しているのかが大事 強度と距離と変動性の 3 つの指標で結合バランスを測る 強度は「知識の共有の仕方」 距離は「知識が移動する空間の広さ」 変動性は「よく変更されるかどうか」 今回は AST や git log を使って解析する方法で計測してみた 機械的に測りきれない部分を AI で補助的に補う 変更のしやすさだけでなく、AI が扱うためにも結合度は有用 29/29