现在,我有一个名为StyleBundle的域名实体。这个StyleBundle有一个样式列表:
public class StyleBundle
{
public StyleBundle(List<Style> styles)
{
this.Styles = styles;
}
public IEnumerable<Style> Styles { get; private set;}
}
因此,在我的原始设计中,永远不应该使用空样式列表创建StyleBundle。领域专家基本上认为这是一条很好的规则。
我在构造函数中使用了一个guard子句写了这个:
if (styles.Count() == 0)
throw new Exception("You must have at least one Style in a StyleBundle.");
确保我无法在无效状态下创建StyleBundle。我认为异常是有道理的b / c在没有至少一个Style的情况下创建的StyleBundle在系统中是特殊的。
当然,在项目的其余部分进行了改变,现在应该可以让用户创建一个没有样式的StyleBundle,但不应该允许他们在没有样式的情况下PURIST一个StyleBundle。
所以现在我正在查看我的guard子句,并意识到我不能再从构造函数中抛出异常了。
继续前进,我有一个服务/应用程序层,我的代码隐藏在他们使用StyleBundles时与之交互。在我的服务层中,我有一个StyleBundleService类,该类向UI公开基本功能......其中包括“CreateStyleBundle”。
似乎我必须检查我的服务层以查看StyleBundle在持久存储到数据库之前是否有任何样式,但是关于这个决定的事情对我来说感觉“错误”。
任何人遇到类似的事情?基本上,当“new'ed up”时对象的状态与同一对象在持久性方面的状态之间的差异是什么?
谢谢! 麦克
答案 0 :(得分:6)
我会向您的实体添加IsValid
方法。这将检查实体当前是否处于有效状态(在您的情况下,检查是否存在样式)。
可以从Repository
调用此方法,以检查实体是否可以保留。您可以为特定实体的IsValid
方法添加更多规则,并且您可以实现诸如验证错误集合之类的内容,您希望抛出有意义的异常。
答案 1 :(得分:1)
扩展Wouter所说的内容,以及方便的BeforeSaving和BeforeDeleting方法:
public interface IDomainObject<T>
{
bool IsValid();
}
public interface IEntity<T> : IDomainObject<T>
{
}
public interface IAggregateRoot<T> : IEntity<T>
{
void BeforeSaving();
void BeforeDeleting();
}
public interface IAggregateRoot { //or simply IEntity depending on the model
bool IsValid();
}
public class StyleBundle : IAggregateRoot<T> {
return styles.Count() > 0
}
public class StyleBundleRepository : Repository<StyleBundle> {
}
public abstract class Repository<T> : IRepository<T> where T : class, IAggregateRoot<T> {
public T Save(T t)
{
t.BeforeSaving(); //for all AggregateRoots, maybe logging what the aggregate was like before the changes
if(!t.IsValid())
throw Exeception("Entity invalid");
EntityStore.Current.SaveChanges();
// "AfterSaving" here, i.e.: log how the entity looks after the update
}
}
编辑:我不亲自使用IsValid的想法,我使用完整的EntityValidationErrors类,我可以在尝试保存之前向客户端报告错误,不应该为空的东西,不应该是空的(如你的样式)等)
答案 2 :(得分:1)
有多种策略:
一些开发人员更喜欢在实体本身中创建2个方法,一个名为IsValid()
,它根据业务规则(一般验证)验证实体,另一个名为IsValidForPersistence()
,用于验证实体的持久性
关于IsValid()
我宁愿不通过验证所有输入来首先允许无效状态,并且支持不变量我使用工厂或构建器。
您可以查看链接http://www.codethinked.com/thoughts-on-domain-validation-part-1 一些想法。
答案 3 :(得分:0)
我知道,这个问题已经有三年了,但看到目前的答案是我想回答的问题。我们正在讨论域数据。因此,不能有一个有0个对象的有效StyleBundle。我想,你有一个前端编辑器,如果你创建一个“新”StyleBundle并且必须添加至少一个样式,然后点击“保存”按钮。
在前端的这一点上,你将没有域对象。您可能有一个数据传输对象,将使用“CreateNewStyleBundle”命令发送。
在我看来,域对象必须与持久性无关,并且应始终处于有效状态。如果你必须调用“IsValid”方法,那么你首先要避免使用域对象。
这只是我的拙见。