web-dev-qa-db-ja.com

C#6.0の新しいnull条件演算子はデメテルの法則に反しますか?

デメテルの法則 は次のように述べています:

  • 各ユニットは、他のユニットについて限られた知識しか持っていない必要があります。現在のユニットに「密接に」関連しているユニットのみです。
  • 各ユニットは、その友達とのみ会話する必要があります。見知らぬ人と話をしないでください。
  • 直接の友達とのみ話してください。

C#6.0では null-conditional operator と呼ばれる新しい演算子が導入されました。私見、それはコーディングを容易にし、読みやすさを向上させます。ただし、クラスフィールドをナビゲートしやすくなり、すでにnull(var x = A?.B?.C?.D?.E?.F?)。

この新しい事業者がデメテルの法則に反すると述べていることは正しいですか?

29
Arthur Rizzo

この新しい事業者がデメテルの法則に反すると述べていることは正しいですか?

番号*


* null条件演算子は、言語および.NETフレームワーク内のツールです。 Anyツールは、特定のアプリケーションの保守性を損なう可能性のある方法で悪用および使用される可能性があります。

しかし、ツールが悪用される可能性があるとは、必ずしもhas虐待されること、またはツールが保持される可能性のある特定の原則に違反すること。

デメテルの法則などは、コードの記述方法のガイドラインです。ツールではなく、人間を対象としています。したがって、C#6.0言語に新しいツールがあるという事実は、コードの記述と構造化にhowに必ずしも影響を与えるわけではありません。

新しいツールでは、それを ...コードを維持することになる人が暴力的な精神病者になる場合... として評価する必要があります。繰り返しますが、これはコードを書く人へのガイダンスであり、使用されているツールに関するものではないことに注意してください。

44
user53019

ちょっと。

1つのアクセスのみを行う場合(a?.Foo)の場合、次と同等です。

a == null ? null : a.Foo

ほとんどの人が同意するであろうことは、デメテルの法則の違反ではありません。その時点で、読みやすさを向上させるのは単なる構文上の砂糖です。

それ以上のもの、そしておそらくそれはデメテルの法則に違反するでしょう、そしてこの機能はその種の使用を促進する傾向があります。上記の「良い」使用法だけでは、この種の言語の変更を保証するのに十分ではないので、明確ではない良い使用法をサポートするために作成されたと思います。

とはいえ、デメテルの法則はそれ自体が法則ではなく、ガイドラインの1つであることを覚えておく価値があります。たくさんのコードがそれに違反し、うまく機能します。設計やコードの単純さは、デメテルの法則に違反することによるリスクよりも価値がある場合があります。

10
Telastyn

いいえ。演算子を単独で検討する場合と、連鎖的に使用する場合の両方について考えてみましょう。

.?A自体は、左の値と同じクラスの知識、および.A != nullが行うのと同じ方法でメソッドによって返される型に依存します。 Aプロパティが存在し、nullと比較できる値を返すことを認識する必要があります。

型付きプロパティがそうである場合、これはデメテルの法則に違反しているとしか主張できません。 Aを具象型として強制することもありません(その値は派生型である可能性があります)。ここでの結合は最小限です。

では、var x = A?.B?.C?.D?.E?.Fについて考えてみましょう。

つまり、Aはnullの可能性がある型であるか、またはBプロパティを持つことができます。これはnullの可能性がある型またはCである必要がありますプロパティなど、EプロパティのタイプがnullまたはFプロパティを持つことができるものになるまで続きます。

言い換えると、静的に型付けされた言語でこれを行うか、型付けが緩い場合に返される可能性がある型に制約を適用する必要があります。ほとんどの場合、C#は静的型付けを使用するため、何も変更していません。

その場合、次のコードも法律に違反します。

ExplicitType x;
var b = A.B;
if (b == null)
  x = null;
else
{
  var c = b.C;
  if (c == null)
    x = null;
  else
  {
    var d = c.D;
    if (d == null)
      x = null;
    else
    {
      var e = d.E;
      if (e == null)
        x = null;
      else
        x = e.F;
    }
  }
}

まったく同じです。さまざまな要素の結合を使用しているこのコードは、結合の完全なチェーンについて「知る」必要がありますが、デメテルの法則に違反していないコードを使用していますそのため、各ユニットは次のユニットと明確に結合されています。

9
Jon Hanna

オブジェクトは、動作をカプセル化したり、データを保持したりする目的で作成することができ、オブジェクトは、外部のコードと共有したり、作成者が個人的に保持したりする目的で作成することができます。

動作をカプセル化する目的(共有されているかどうかにかかわらず)、または外部コードと共有されるために作成されたオブジェクト(動作またはデータをカプセル化するかどうか)は、通常、それらのサーフェスインターフェイスを介してアクセスする必要があります。ただし、データ保持オブジェクトが作成者によって排他的に使用されるように作成されている場合、「ディープ」アクセスを回避するという通常の法則の理由は当てはまりません。オブジェクトにデータを格納または操作するクラスの一部が他のコードの調整を必要とする方法で変更された場合、前述のようにオブジェクトが1つのクラスの排他的使用。

と思いながら?オペレーターはおそらくより適切に設計されている可能性があります。オブジェクトがネストされたデータ構造を利用する十分な状況があり、オペレーターには多くのユースケースがあり、デメテルの法則によって表される原則に違反しません。それがLoDに違反するために使用される可能性があるという事実は、 "。"よりも悪いわけではないので、演算子に対する引数として解釈されるべきではありません。その点で演算子。

5
supercat