8

抽象リポジトリを使用してドメインオブジェクトをロードする永続性のないドメインモデルがあります。私のリポジトリ(データアクセス層(DAL))の具体的な実装では、エンティティフレームワークを使用してSQLサーバーデータベースからデータをフェッチします。データベースには、そのvarchar列の多くに長さの制約があります。ここで、次のドメインクラスがあると想像してください。

public class Case
{
    public Case(int id, string text)
    {
         this.Id = id;
         this.Text = text;
    }

    public int Id { get; private set; }
    public string Text { get; set; }
}

そして、次のように定義された抽象リポジトリ:

public abstract class CaseRepository
{
    public abstract void CreateCase(Case item);
    public abstract Case GetCaseById(int id);
}

sqlserverのテーブルの[text]列は次のように定義されますnvarchar(100)

ドメインクラス( )は永続性を無視していると述べましたが、エンティティフレームワークが例外をスローするため、具体的なリポジトリの実装では最終的に保存できないパラメータCaseの値を許可するのは間違っていると感じています。textの割り当てtext100文字を超える場合、エンティティフレームワークで生成されたクラスのプロパティ。そこで、ドメインモデルでこの制約をチェックすることにしました。これにより、データをDALに渡そうとする前にデータの有効性をチェックできるため、エラーレポートがドメインオブジェクトに対してより中心的になります。コンストラクターとプロパティセッターで制約を確認するだけでよいと主張できると思いますが、同じような制約を持つクラスが何百もあるので、問題を解決するためのより一般的な方法が必要でした。

さて、私が思いついたのは、ConstrainedString次のように定義された、というクラスです。

public abstract class ConstrainedString
{
    private string textValue;

    public ConstrainedString(uint maxLength, string textValue)
    {
        if (textValue == null) throw new ArgumentNullException("textValue");
        if (textValue.Length > maxLength) 
            throw new ArgumentException("textValue may not be longer than maxLength", "textValue");

        this.textValue = textValue;
        this.MaxLength = maxLength;
    }

    public uint MaxLength { get; private set; }

    public string Value 
    { 
        get 
        {
            return this.textValue;
        } 

        set 
        {
            if (value == null)
                throw new ArgumentNullException("value");
            if (value.Length > this.MaxLength) throw new ArgumentException("value cannot be longer than MaxLength", "value");
            this.textValue = value;
        } 
    }
}

ConstrainedStringさらに、私は呼び出されたの実装を持っていますString100

public class String100 : ConstrainedString
{
    public String100(string textValue) : base(100, textValue) { }
}

したがって、その別の実装につながると、次のCaseようになります。

public class Case
{
    public Case(int id, String100 text)
    {
         this.Id = id;
         this.Text = text;
    }

    public int Id { get; private set; }
    public String100 Text { get; set; }
}

さて、私の質問は; いくつかの組み込みクラスまたは代わりに使用できる他のアプローチを見落としていますか?それとも、これは合理的なアプローチですか?

コメントや提案は大歓迎です。

前もって感謝します

4

3 に答える 3

1

あなたの検証はあなたのドメインモデルにあるべきだと思います。フィールドに対する制約は、いくつかのビジネス ロジックを直接表しています。とにかく永続化する前に、最終的には検証する必要があります。

于 2010-02-17T03:14:53.570 に答える
0

ケースの制約を変更する場合、新しいものを作成する必要があることは理にかなっています。コントラクトを変更したため、古いコードは要件を満たしているかどうかを認識できなくなります。

リポジトリが許可するものと許可しないものを心配する代わりに、クラスで許可するもの定義し、将来変更するリポジトリを操作する方法を確実に見つけてください。あなたはあなたの API を所有しています - あなたの依存関係はありません。

于 2010-02-17T03:44:41.800 に答える
0

これは多くの要因 (および個人的な好み) に依存すると思います。場合によっては、制約がドメイン オブジェクトの一部を形成する必要があります-たとえば、社会保障番号/パスポート番号...-これらは通常固定長であり、ドメイン ルールとして変更できません-データ永続性ルールではありません (ただし、データベースを制約する場合があります)。同じように)。

一部のユーザーは、ドメイン モデルにこれらの種類のチェックを持たず、代わりにプロパティに検証属性のようなものを持ち、別のバリデーターによってドメイン オブジェクトの外部で検査および実行できるようにすることを好みます。

メソッドで発生する可能性のある問題 (回避するのは難しくありません) は、ORM/Mapper を使用している場合は、データベースとの間で文字列を ConstrainedString にマップする方法を知ることです。

ConstrainedString は、ConstrainedString を構築する必要がある場合があるため、制約に関する追加情報を持つドメイン オブジェクトの問題を回避できない可能性があります。

于 2010-01-26T12:06:45.620 に答える