Autofixture: 読み取り専用ではないプロパティの読み取り専用を非難

作成日 2013年06月04日  ·  4コメント  ·  ソース: AutoFixture/AutoFixture

私のドメインレイヤーには次のクラスがあります。

public class Telefone : IEntity
{
    public virtual int Id { get; protected internal set; }
    public virtual string Tipo { get; set; }
    public virtual string Numero { get; set; }
}

IDは内部で保護されています。 これは意図的なものであり、IDを生成するのはデータベースであり、読み取り専用である必要があります。
ただし、テストレイヤーでは、このプロパティのセッターにアクセスできる必要があります。

そのため、私のドメインレイヤーでAssemblyInfo.csに属性を追加しました。

[assembly: InternalsVisibleTo("MyTestLayer")]

これにより、テストレイヤーでIDを設定できますが、ドメインレイヤーでは設定できません。

テストレイヤー内
new Telefone()。Id = 1; //動作します!!

UIレイヤー内
new Telefone()。Id = 1; //コンパイルしません! 動作しません!

問題

var pessoa = fix.Build<Pessoa>()
    .With(p => p.Nome)
    .Do((pess) =>
    {
        fix.Build<Telefone>()
            .With(p => p.Id)
            .With(p => p.Tipo)
            .With(p => p.Numero)
            .OmitAutoProperties()
            .CreateMany(10).ToList().ForEach(pess.Telefones.Add);

        fix.Build<Email>()
            .With(p => p.Id)
            .With(p => p.Tipo)
            .With(p => p.Endereco)
            .OmitAutoProperties()
            .CreateMany(10).ToList().ForEach(pess.Emails.Add);
    })
    .OmitAutoProperties()
    .Create();

理論的には、上記のコードは機能するはずですが、私のロードテストでエラーが発生します。

プロパティ「Id」は読み取り専用です。

すべてのプロパティIdprotected internalです。

同じファイルで、同じテストで次のようなことができます。

new Telefone()。Id = 1; //動作します!!
new Email()。Id = 1; //動作します!!

question

全てのコメント4件

これは、ドメインモデルに_リークのある抽象化_があることを明確に示しています。 ドメインモデルは、特定の境界テクノロジーを念頭に置いて設計するべきではありません。

この特定の問題は、ドメインモデルが再利用できないことを非常に明確に示しています。

InternalsVisibleToは、テストライブラリへのアクセスのみを許可するため効果はありませんが、AutoFixtureはまったく別のアセンブリです。 これは、他のクライアントがドメインモデルを再利用できるようになることはないということを示しています。

最善の行動は、API設計を再検討することです。 通常、私は次のようなことをします:

`` `c#
パブリッククラスTelefone:IEntity
{{
public Telefone(int id)
{{
this.Id = id;
}

public virtual int Id { get; private set; }
public virtual string Tipo { get; set; }
public virtual string Numero { get; set; }

}
`` `

これは、私がフォローしているアーキテクチャのグループで多くの議論を引き起こしました。
このアプローチには大きな問題があります。

  1. IDの生成を担当するのはデータベースであり、オブジェクトが保存されたときにのみ生成されます。
  2. 新しいオブジェクトを作成するとき、どのIDをコンストラクターに渡す必要がありますか? コンストラクターにIDを入れることができません。
  3. Idはintシーケンシャルです。 リポジトリレイヤーは、ドメインの最も近いレイヤーです。 Idを生成するには、 max (id) + 1ような操作を行ってから、オブジェクトのIDを設定します。 しかし、読み取り専用の場合、IDを設定するにはどうすればよいですか?
  4. ReadOnlyプロパティでIdを設定する唯一の方法は、クラス自体の内部であるか、プロキシ/リフレクションを使用することです。

これらはすべて_問題_であることに同意しました。 それらの4つすべては、ドメインモデルが永続層に依存しており、それなしでは機能させることができないことを_強く_示しています。

  1. データベースがIDを割り当てる必要があるのはなぜですか? 唯一の要件は、IDが一意であることです。 これがGUIDがある理由です。
  2. 新しいGuidインスタンスをコンストラクターに渡します。
  3. IDがシーケンシャルなのはなぜですか? IDがシーケンシャルであるというアーキテクチャ上の理由はめったにありません。
  4. 同意しました。 アクセス修飾子が存在する理由があります。

私は問題を理解しています。 PKタイプをGuidに変更することはできませんが、実際に機能します。

問題はAutoFixtureに関連していないことを理解しましたが、興味があれば。 これについて議論するためのサンプルプロジェクトを作成し

ありがとう。

このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

ecampidoglio picture ecampidoglio  ·  7コメント

DeafLight picture DeafLight  ·  5コメント

josh-degraw picture josh-degraw  ·  4コメント

zvirja picture zvirja  ·  8コメント

JoshKeegan picture JoshKeegan  ·  6コメント