「依存性サイクルなし」ルール(NDepend)はどの程度厳密に遵守していますか


10

背景:チームリーダーとして、私はNDependを週に1回程度使用して、コードの品質をチェックしています。特に、テストカバレッジ、コード行、循環的複雑度メトリックスは私にとって非常に貴重です。しかし、それが平準化と依存関係のサイクルになると、私は少し心配です... Patrick Smacchiaが、平準化の目標を説明する素晴らしいブログ投稿を公​​開しています。

明確にするために:「依存サイクル」の下で、2つの名前空間間の循環参照を理解しています。

現在、組み込み機器用のWindows CEベースのGUIフレームワークに取り組んでいます。Androidグラフィックスプラットフォームについて考えてみてください。ただし、非常にローエンドの機器向けです。フレームワークは、約50.000行のコード(テストを除く)の単一のアセンブリです。フレームワークは次の名前空間に分割されます。

  • コアナビゲーションとメニューサブシステム
  • 画面サブシステム(プレゼンター/ビュー/ ...)
  • コントロール/ウィジェットレイヤー

今日、私はコードを適切なレベルにするために半日を費やしました[Resharperのおかげで一般に問題はありません]。

だから私の質問:「依存サイクルなし」ルールをどの程度厳密に守っていますか?平準化は本当に重要ですか?


2
「依存サイクルなし」が循環参照がないことを意味する場合、言い訳はありません。それらは純粋な悪です。
Arnis Lapsa

@ollifant:「依存サイクルなし」と書くときに正確に何を意味するかを定義します。レイヤー間またはレイヤー内のクラス間?
Doc Brown

回答:


9

私は最近、2つのホワイトブックを作成し、Simple-Talkで.NETコードのアーキテクチャのトピックについて公開しました(1番目のブックは.NETアセンブリ、2番目のブックは名前空間とレベル化に関するものです)。

.NETアセンブリとVisual Studioプロジェクトによるコードベースのパーティション分割

名前空間を使用した.NETコンポーネントの定義

平準化は本当に重要ですか?

はい、そうです!

2番目の白書からの引用:

コンポーネント間の依存関係のグラフにサイクルが含まれている場合、サイクルに含まれるコンポーネントを個別に開発およびテストすることはできません。このため、コンポーネントのサイクルは、含まれるコンポーネントのエントロピーの合計よりも高いエントロピーを持つスーパーコンポーネントを表します。

(...)

非循環コンポーネントの制約が継続的に尊重される限り、コードベースは高度に学習可能で維持可能です。

  • 従来の建築では、重力の強さが低レベルのアーチファクトに圧力をかけています。これはそれらをより安定させます:移動するのが難しいという意味で「安定」します。
  • ソフトウェアアーキテクチャでは、非循環コンポーネントのアイデアに従うことで、低レベルのコンポーネントに圧力をかけます。これにより、リファクタリングが困難になるという意味で、より安定します。経験的に抽象化は、実装よりもリファクタリングの対象となることはあまりありません。このため、低レベルのコンポーネントには、面倒なリファクタリングを回避するために、主に抽象化(インターフェースと列挙)を含めることをお勧めします。

6

クラスまたは名前空間間の循環依存関係は決して許可しません。C#、Java、C ++では、インターフェイスを導入することで、循環クラスの依存関係をいつでも解消できます。

テストファーストをコーディングすると、循環依存関係を導入することが難しくなります。


4

これは常にトレードオフです。依存関係を回避する必要がある理由を理解するには、依存関係のコストを理解する必要があります。同様に、依存関係のコストを理解している場合は、特定のケースでそれが価値があるかどうかをより適切に判断できます。

たとえば、コンソールビデオゲームでは、主にパフォーマンス上の理由から、情報の密接な関係が必要な依存関係に依存することがよくあります。たとえば、エディションツールのように柔軟である必要がない限り、それは問題ありません。

ソフトウェアが実行しなければならない魔女の制約(ハードウェア、OS、または単なるデザイン(「よりシンプルなUI」のような))を理解している場合は、依存関係が実行されるべきではなく、依存関係が実行されていないことを理解するのは簡単です。 OK。

しかし、明確で明確な理由がない場合は、できる限り依存関係を避けてください。依存コードはデバッグセッションの地獄です。


2

このトピックが議論されるときはいつでも、参加者は通常、ビルド時と実行時のサイクルの違いを見失っています。前者はJohn Lakosが「物理設計」として扱ったものであり、後者は基本的にディスカッションには関係ありません(コールバックによって作成されるような実行時サイクルに巻き込まれないでください)。

これは、ジョン・ラコスはすべての(ビルド時)サイクルを排除することについて非常に厳格だったと述べています。ただし、Bob Martinは、バイナリ(たとえば、DLL、実行可能ファイル)間のサイクルのみが重要であり、回避すべきであるという態度を採用しました。彼はバイナリのクラス間のサイクルはそれほど重要ではないと信じていました。

私はこれについてボブ・マーティンの見解を個人的に持っています。ただし、このようなサイクルがないとコードが他の人にとって読みやすくなり、学習しやすくなるため、クラス間のサイクルにはまだ注意を払っています。

ただし、Visual Studioでビルドするコードは、バイナリ(ネイティブコードでもマネージコードでも)間の循環依存関係を持つことができないことに注意してください。したがって、サイクルに関する最も深刻な問題が解決されました。:)


0

ほぼ完全に、ビルドタイプの依存サイクルはHaskellでは不便であり、AgdaとCoqでは不可能であるため、これらは私が通常使用する言語です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.