领域驱动设计标识和价值对象
Domain Driven Design Identities and Value Objects
在 Vaughn Vernon Implementing Domain-driven Design 这本书和 code 中,他混合使用 Identity
和 ValueObject
作为标识符。
public interface IIdentity
{
string Id { get; }
}
public abstract class Identity : IEquatable<Identity>, IIdentity
{
protected Identity() => this.Id = Guid.NewGuid().ToString();
protected Identity(string id) => this.Id = id;
// Currently for Entity Framework, set must be protected, not private. will be fixed in EF 6.
public string Id { get; protected set; }
public bool Equals(Identity id)
{
if (object.ReferenceEquals(this, id)) return true;
if (object.ReferenceEquals(null, id)) return false;
return this.Id.Equals(id.Id);
}
public override bool Equals(object anotherObject) => Equals(anotherObject as Identity);
public override int GetHashCode() => (this.GetType().GetHashCode() * 907) + this.Id.GetHashCode();
public override string ToString() => this.GetType().Name + " [Id=" + Id + "]";
}
和值对象:
public abstract class ValueObject
{
// Returns all components of a value objects which constitute its identity.
protected abstract IEnumerable<object> GetEqualityComponents();
public override bool Equals(object obj)
{
if (object.ReferenceEquals(this, obj)) return true;
if (object.ReferenceEquals(null, obj)) return false;
if (this.GetType() != obj.GetType()) return false;
var vo = obj as ValueObject;
return GetEqualityComponents().SequenceEqual(vo.GetEqualityComponents());
}
public override int GetHashCode() => HashCodeHelper.CombineHashCodes(GetEqualityComponents());
}
我看到在某些情况下 ValueObject
被用作身份:
public class TaskId : ValueObject
{
public TaskId()
: this(Guid.NewGuid().ToString().ToUpper().Substring(0, 8))
{
}
public TaskId(string id)
{
AssertionConcern.AssertArgumentNotEmpty(id, "The id must be provided.");
AssertionConcern.AssertArgumentLength(id, 8, "The id must be 8 characters or less.");
this.Id = id;
}
public string Id { get; private set; }
protected override IEnumerable<object> GetEqualityComponents()
{
yield return this.Id;
}
}
其他情况下它们是纯的Identity
:
public class ForumId : SaaSOvation.Common.Domain.Model.Identity
{
public ForumId(string id) : base(id) { }
}
对我来说,所有值都应该是 value object,包括 identities,所以我不明白这里有一个显式 Identity
的区别类型。
使用他的演示代码,how/why 他是否选择了上述方法来建模身份,是否有 advantage/disadvantage 优于其他方法?
两种实现都在比较属性的相等性,因此两者都遵循值对象的概念。 Identity class 专用于自定义身份类型的可重用值对象,它仍然具有相同的要求(使用任意字符串, 通常从 GUID/UUID) 创建。仍然是一个值对象,但是如果除了字符串 id 之外不需要其他属性,在这种情况下可以使用这个,同时仍然使用单独的派生 classes(如 ForumId)强类型化不同类型的身份。
另一方面,ValueObject class 正在处理需要在相应派生中进行比较的任意属性classes.
我认为从 ValueObject 而不是从 [=16] 派生 TaskId 的意图=]Identity 如果您查看构造函数,就会变得更加清晰。在这种情况下,特定的业务规则 - id 必须是八个字符或更少 - 需要在构造时完成,这对通用标识实现的定义。
在 Vaughn Vernon Implementing Domain-driven Design 这本书和 code 中,他混合使用 Identity
和 ValueObject
作为标识符。
public interface IIdentity
{
string Id { get; }
}
public abstract class Identity : IEquatable<Identity>, IIdentity
{
protected Identity() => this.Id = Guid.NewGuid().ToString();
protected Identity(string id) => this.Id = id;
// Currently for Entity Framework, set must be protected, not private. will be fixed in EF 6.
public string Id { get; protected set; }
public bool Equals(Identity id)
{
if (object.ReferenceEquals(this, id)) return true;
if (object.ReferenceEquals(null, id)) return false;
return this.Id.Equals(id.Id);
}
public override bool Equals(object anotherObject) => Equals(anotherObject as Identity);
public override int GetHashCode() => (this.GetType().GetHashCode() * 907) + this.Id.GetHashCode();
public override string ToString() => this.GetType().Name + " [Id=" + Id + "]";
}
和值对象:
public abstract class ValueObject
{
// Returns all components of a value objects which constitute its identity.
protected abstract IEnumerable<object> GetEqualityComponents();
public override bool Equals(object obj)
{
if (object.ReferenceEquals(this, obj)) return true;
if (object.ReferenceEquals(null, obj)) return false;
if (this.GetType() != obj.GetType()) return false;
var vo = obj as ValueObject;
return GetEqualityComponents().SequenceEqual(vo.GetEqualityComponents());
}
public override int GetHashCode() => HashCodeHelper.CombineHashCodes(GetEqualityComponents());
}
我看到在某些情况下 ValueObject
被用作身份:
public class TaskId : ValueObject
{
public TaskId()
: this(Guid.NewGuid().ToString().ToUpper().Substring(0, 8))
{
}
public TaskId(string id)
{
AssertionConcern.AssertArgumentNotEmpty(id, "The id must be provided.");
AssertionConcern.AssertArgumentLength(id, 8, "The id must be 8 characters or less.");
this.Id = id;
}
public string Id { get; private set; }
protected override IEnumerable<object> GetEqualityComponents()
{
yield return this.Id;
}
}
其他情况下它们是纯的Identity
:
public class ForumId : SaaSOvation.Common.Domain.Model.Identity
{
public ForumId(string id) : base(id) { }
}
对我来说,所有值都应该是 value object,包括 identities,所以我不明白这里有一个显式 Identity
的区别类型。
使用他的演示代码,how/why 他是否选择了上述方法来建模身份,是否有 advantage/disadvantage 优于其他方法?
两种实现都在比较属性的相等性,因此两者都遵循值对象的概念。 Identity class 专用于自定义身份类型的可重用值对象,它仍然具有相同的要求(使用任意字符串, 通常从 GUID/UUID) 创建。仍然是一个值对象,但是如果除了字符串 id 之外不需要其他属性,在这种情况下可以使用这个,同时仍然使用单独的派生 classes(如 ForumId)强类型化不同类型的身份。
另一方面,ValueObject class 正在处理需要在相应派生中进行比较的任意属性classes.
我认为从 ValueObject 而不是从 [=16] 派生 TaskId 的意图=]Identity 如果您查看构造函数,就会变得更加清晰。在这种情况下,特定的业务规则 - id 必须是八个字符或更少 - 需要在构造时完成,这对通用标识实现的定义。