HN 日本語サマリー

← 一覧へ戻る
プログラミング

変更結合度:1行の修正がなぜ10ファイルに影響するのか

Change Coupling: Why One-Line Fixes Touch Ten Files (kb.buildingbetterteams.de)

9 pointsby mooreds0 コメント

要約

ソフトウェア開発における「変更結合度(Change Coupling)」という概念を解説する記事。これは、本来無関係に見えるコードが、ビジネスロジックや隠れた依存関係により、しばしば同時に変更される現象を指します。この結合度を理解することは、システムの構造を把握し、アーキテクチャ上の意思決定を行う上で重要であり、コードの変更履歴を分析することで、物理的な配置と実際の変更パターンとの乖離を発見し、保守性の向上につなげられると述べています。

全文翻訳

このページでトレードオフを最初に 変更結合度(Change Coupling)は、最適化すべき品質メトリックではなく、意思決定者が理解するためのツールです。完璧な結合度の整合性が目標ではありません。システムの実際の構造を理解することが目標です。すべてのアーキテクチャ上の決定には、コンテキストで考慮されなければならないトレードオフが伴います。 散発的な変更の問題 ペインポイント 私たちは皆、その状況に陥ったことがあります。1つの小さな機能を追加したいのに、6つのディレクトリにまたがる12個のファイルを変更することになってしまう。単純なバグ修正であるはずが、予期せぬ変更に波及したり、あるいはもっと悪いことに、予想して嫌悪するようになるのです。変更結合度は、コードレビューの半分が、意図した変更とは全く関係ないはずのファイルに関わっていることに気づいたときに明らかになります。悪い変更結合度は、コードの読み書きを遅くしますが、さらに悪いことに、集団的な認知負荷が、変更を行おうとする人々を圧倒してしまいます。変更結合度を無視すると、不快な驚きにつながります。 2つのコードビットが互いに呼び出したり参照したりしない場合、それらは無関係であると期待するでしょう。しかし、変更結合度は、無関係に見えるものが、システムを機能させるためにやはり隠れた変更の必要性を持っていることを示しています。これは、技術的な理由とビジネスロジックの両方で起こります。Xを変更すると、コードが直接示唆することに関わらず、Yを変更することになります。静的コード分析では、これらの依存関係を直接検出できませんが、コードベースで長期間作業することで感覚を養うことができます。プロジェクトの変更率を改善したいのであれば、自身のソフトウェアの変更結合度を理解することが極めて重要です。 どのような種類の結合度か? 私たちが書くコードは、コードを書く際に考慮する必要があることの表面的な層にすぎません。 多くの種類の結合度が存在します 物理的結合度:コードがファイル構造のどこにあるか 論理的結合度:概念的に互いに依存する関数 時間的結合度:シーケンスで発生しなければならないもの データ結合度:共有データ構造とフォーマット 制御結合度:一方のモジュールが他方の動作を制御する 変更結合度:一緒に頻繁に変更されるコード(私たちの焦点) すべての結合度が悪いわけではありません。結合度は必要な構造を提供しますが、多すぎると変更を妨げます。車のエンジンのように、一部の部品は結合されなければならず、他の部品は独立していなければなりません。フロントガラスワイパーがブレーキに結合されていることを望まないでしょう。最適化すべき理想的な結合度の比率はありません。0%と100%の両方の結合度は問題があります。0%では何も機能せず、100%では巨大な泥の塊よりも悪いです。 この分析は、あなたとあなたのチームがシステムの力学を理解し、完璧なメトリックを追いかけたり、結合度を完全に排除したりするのではなく、アーキテクチャ上の意思決定を導くための、感覚を養うツールです。 変更結合度は、最新のコード行を読むだけでは検出できないため興味深いものです。それは、システムがどのように進化するかの現実を示しており、どのように配線されているかではありません。これは、無関係に見えるコード間の驚くべきつながりを示すことができ、あるいは、見つけるのが難しいすべてのものが置かれる場所(しばしば「/utils」)を整理するのに役立ちますが、何が移動されるべきで、どこに移動されるべきかは明確ではありません。 最後に、変更結合度は「変更されないコード」対「変更されるコード」ではなく、「一緒に変更されるコード」に関連していることを理解することが重要です。コードが変更されるとき、それは一緒に変更されますか、それともそうではありませんか?これは、「このコードは変更されるのか?」という問いよりも、はるかに異なる洞察を提供します。これは進化的な安定性を示す可能性があります(それはそれ自体が深いトピックであり、この記事では探求するにはあまりにも広範すぎます)。 一緒に変更されるもの 一緒に変更されるべきものは一緒に住むべきです 変更結合度は、あなたのシステムが分割およびマージしたいと思うフォールトラインを明らかにします。重力や磁力のように考えてください。一緒に変更されるコードは、同じ場所に引き寄せる概念的な重みを共有します。 決して一緒に変更されないコード 近接しているにもかかわらず決して一緒に変更されないコードは、もはや目的を果たさない可能性のある人工的な結合度を示唆しています。 物理的結合度 vs 変更結合度マトリックス 「物理的」をコードのファイル場所と考えると、コードの物理的結合度と変更結合度を比較して、コードがどのような状況に陥る可能性があるか、そしてそれが一般的に保守可能な低認知負荷の状態にあるかどうかを考えることができます。この2x2マトリックスは、感覚を養うためのガイドとしてのみ使用され、公式な完璧な判断ではありませんが、それでも非常に役立ち、問題領域を示すか、あるいは問題の解決方法さえ示してくれます。他のいくつかの尺度では間違っているように見えるかもしれませんが、変更結合度に関しては問題ないように見えるコードを示すことさえあります。これは、システムの概念的な書き換えを計画している場合に、設計に情報を提供することができます。既存のシステムは、重要な何かを正しく行っていたのかもしれません。 変更結合度マトリックス コードが住みたい場所 vs 実際の場所に従う 物理的結合度 低 / 変更結合度 高 一緒に変更されるが、離れて住んでいるコード。これらの関数は、近隣になりたいと語っています。 例:認証ロジックが、一緒に頻繁に変更されるutils/、components/、services/に散らばっている。 物理的結合度 高 / 変更結合度 高 一緒に変更され、一緒に住んでいるコード。これはより理想的です。物理的なコードレイアウトは、コードの変更と対称的です。 例:新しい機能のために一貫して進化する、同じモジュール内の支払い処理関数。 物理的結合度 低 / 変更結合度 低 一緒に変更されることがまれで、同じ場所に格納されていないコード。実際の独立性を反映したクリーンな分離。 例:データベース接続ユーティリティと、独立して進化し、別々のモジュールに留まるUIコンポーネント。 物理的結合度 高 / 変更結合度 低 一緒に住んでいるが、一緒に変更されることがまれなコード。過去の決定による人工的な結合度である可能性があります。 例:「utils」モジュールに含まれる無関係なヘルパー関数。チームがより良い場所を思いつかなかったときに、そこに入れられたもの。 例:支払いシステム この例では、チームは支払いシステムに明確な関心の分離があると信じています。実際の金銭取引を処理するモジュール、手数料を計算するモジュール、そしてこの特定の支払いシステムに手数料の流れを調整する3番目のモジュールがあります。設計意図は、チームが一度に1つのモジュールだけを変更すればよく、通常は「Fee Engine」だけを変更すればよいというものでした。しかし、開発者は、Fee Engineの変更が、何らかの形で3つのモジュールすべてに変更を波及させると感じています。変更分析レポートは、それらが頻繁に3つのモジュールすべてを同時に変更することを確認します。概念レベルは健全ですが、モジュールがどのように変更結合されているかを見ると、コードを見る前に何かが間違っているという非常に強い兆候が得られます。 「一緒に変更されるものは一緒に住むべき」というのは、これらの3つが一緒に変更されるからといって、すべてを1つのファイルに入れるべきだという意味では文字通りではありません。むしろ、それらが一緒に引きつけられる原因を問うための感覚を養うガイドです。実際の実装がこのように結合されている理由は数多くあります。以下に例を挙げます。 トランザクションログに関するコンプライアンスルールのロジックが、元の実装で考慮されていなかった。永続化はトランザクションプロセッサにありますが、理由コードのルックアップテーブルの更新が必要です。 一部の国での異なる手数料構造では、トランザクションブロックに特別なデータ構造が必要であり、単一のフラットな数値ではこの金融システムでは不可能です。 加盟店契約には手数料の上限があるため、超過がないことを保証するために、手数料はトランザクションプロセッサで安全策として上限が設定されています。 データベース構造が、目に見えない方法で3つのモジュールを結合しています。 トランザクションモジュールを内部「顧客クレジットアカウント」との実際のトランザクションの管理でオーバーロードすること。 ...そして、私たちは一日の終わりまで状況を考え続けることができます。実際のシステムには実際の problemi があります。3つのモジュールすべてを1つに統合することは