デザインのにおい:冗長な必須属性

これは、 ポカヨケデザインに関するシリーズの4番目の投稿です( カプセル化とも呼ばれます)



最近、マイクロソフトのテクノロジーイベントから熱狂的な投稿を読みました。

コードの[Required]属性は、nullを受け入れられないデータベースにレコードを自動的に作成し、Webページで検証を作成します-単純に[...]




私はそれが次のように見えるかもしれないと想像しました:

public class Smell { [Required] public int Id { get; set; } }
      
      





このようなものを見るたびに、私はもう少し死に近づいています。 すでに私の以前の投稿を読んでいれば、これがカプセル化を破る理由が痛いほど明確になるはずです。 [Required]属性が存在するにもかかわらず、 Idプロパティにvalueが割り当てられる保証はありません 。 属性は、返せない何かを宣言するごみの断片です。

このコードはフォールトトレラントではありません。

ツイートに記載されている属性は、プロパティを表示する必要があるが、データベーススキーマはnullを受け入れないというツール(場合によってはEntity Framework)に通知することを意図していることを理解していますが、それでも冗長です。 属性は、不変式を宣言する間違った方法です。



改訂されたデザイン

データが必要であることを宣言するより良い方法があるため、[Required]属性は冗長です。 これは.NET 1.0以降で可能です。 同じ宣言のポカヨーク版は次のとおりです。

 public class Fragrance { private readonly int id; public Fragrance(int id) { this.id = id; } public int Id { get { return this.id; } } }
      
      





この単純な構造設計は、フィールドが本当に必要であることを示しています(IDフィールドが正の値にしかなれない場合は、保護式を追加できます)。 Fragranceクラスのインスタンスは、IDでのみ作成できます。 これは構造的な設計であるため、この要件はコンパイラーのおかげで強化されているだけで、 迅速なフィードバックを提供します。

前述の[Required]属性は、オブジェクトをリレーショナルデータにマッピングする際の問題を解決するように設計されていることを理解していますが、オブジェクトとリレーショナル構造の間の不一致ホールを閉じる代わりに、それを拡張するだけです。

追加の冗長属性を導入する代わりに、チームはツールキットに上記のようなカプセル化の簡単なイディオムを理解させる必要があります。

これはそれほど難しくありません。 例として、DIコンテナーは、コンストラクターでエンコードされた構造情報に基づいてブルームします(これはauto-connectと呼ばれます)。 チームは、[必須]属性の裏でこれを行うことができます。 [必須]属性は、原始的で有毒なハックです。

これが、Entity Frameworkを使用しない主な理由です。 開発者がカプセル化を破らざるを得ない-私が妥協することを拒否する原則。



翻訳者から:投稿を翻訳として公開するのを忘れていました。 オリジナルの著者はマーク・シーマンです。 オリジナルへのリンク。



All Articles