通常、ドメインオブジェクトには、組み込みの型で表すことができるプロパティがありますが、その有効な値は、その型で表すことができる値のサブセットです。
これらの場合、値は組み込み型を使用して格納できますが、値は常にエントリの時点で検証されるようにする必要があります。そうしないと、無効な値で処理される可能性があります。
これを解決する1つの方法は、組み込み型のstruct
単一のprivate readonly
バッキングフィールドがあり、そのコンストラクターが指定された値を検証するカスタムとして値を格納することです。そうすれば、このstruct
タイプを使用することで、検証済みの値のみを使用することが常に確実になります。
基になる組み込み型との間のキャスト演算子を提供して、値が基になる型としてシームレスに出入りできるようにすることもできます。
例として、ドメインオブジェクトの名前を表す必要がある状況を取り上げます。有効な値は、1〜255文字の文字列です。これを表すには、次の構造体を使用します。
public struct ValidatedName : IEquatable<ValidatedName>
{
private readonly string _value;
private ValidatedName(string name)
{
_value = name;
}
public static bool IsValid(string name)
{
return !String.IsNullOrEmpty(name) && name.Length <= 255;
}
public bool Equals(ValidatedName other)
{
return _value == other._value;
}
public override bool Equals(object obj)
{
if (obj is ValidatedName)
{
return Equals((ValidatedName)obj);
}
return false;
}
public static implicit operator string(ValidatedName x)
{
return x.ToString();
}
public static explicit operator ValidatedName(string x)
{
if (IsValid(x))
{
return new ValidatedName(x);
}
throw new InvalidCastException();
}
public static bool operator ==(ValidatedName x, ValidatedName y)
{
return x.Equals(y);
}
public static bool operator !=(ValidatedName x, ValidatedName y)
{
return !x.Equals(y);
}
public override int GetHashCode()
{
return _value.GetHashCode();
}
public override string ToString()
{
return _value;
}
}
例が示すツーstring
としてキャストimplicit
、これが失敗することはできませんとしてではなくfrom- string
としてキャストexplicit
、これは無効な値のためにスローされますよう、もちろんこれらの両方のことのどちらかでしたimplicit
かexplicit
。
また、からのキャストによってのみこの構造体を初期化できますstring
が、IsValid
static
メソッドを使用してそのようなキャストが失敗するかどうかを事前にテストできます。
これは、単純な型で表すことができるドメイン値の検証を実施するのに適したパターンのように思われますが、頻繁に使用されたり、提案されたりすることはありません。その理由について興味があります。
だから私の質問は、このパターンを使用することの利点と欠点は何だと思いますか、そしてなぜですか?
これが悪いパターンだと思われる場合は、その理由と、あなたが感じていることが最良の代替案であることを理解したいと思います。
注:この質問は当初Stack Overflowで質問しましたが、主に意見ベース(皮肉にも主観的)として保留にされました。うまくいけば、ここでより多くの成功を収めることができます。
上は元のテキストで、もう少し考えてみると、保留になる前にそこで受け取った回答に部分的に対応しています。
- 回答で指摘された主なポイントの1つは、特にそのようなタイプが多く必要な場合に、上記のパターンに必要なボイラープレートコードの量にありました。ただし、パターンを守るために、これはテンプレートを使用して大幅に自動化することができ、実際には私にはそれほど悪くないように見えますが、それは私の意見です。
- 概念的な観点から見ると、C#などの強く型付けされた言語を使用して、強く型付けされた原則を複合値にのみ適用するのではなく、ビルトインタイプ?