我正在寻找有关为合同管理设计数据模型的一些建议。因此,合同的一般生命周期是:
我显然希望避免合同被接受的情况,比如金额被改变。这是我的课程:
[EnforceNoChangesAfterDraftState]
public class VendorContract
{
public virtual Vendor Vendor { get; set; }
public virtual decimal Amount { get; set; }
public virtual VendorContact VendorContact { get; set; }
public virtual string CreatedBy { get; set; }
public virtual DateTime CreatedOn { get; set; }
public virtual FileStore Contract { get; set; }
public virtual IList<VendorContractStatus> ContractStatus { get; set; }
}
[EnforceCorrectWorkflow]
public class VendorContractStatus
{
public virtual VendorContract VendorContract { get; set; }
public virtual FileStore ExecutedDocument { get; set; }
public virtual string Status { get; set; }
public virtual string Reason { get; set; }
public virtual string CreatedBy { get; set; }
public virtual DateTime CreatedOn { get; set; }
}
我省略了filestore类,它基本上是一个键/值查找,用于根据guid查找文档。
VendorContractStatus在Nhibernate中被映射为多对一。
然后我按照here所述使用自定义验证器。如果在VendorContractStatus集合中返回除草稿之外的任何内容,则不允许进行任何更改。此外,VendorContractStatus必须遵循正确的工作流程(您可以在挂起后添加拒绝,但如果存在拒绝或接受,则无法向集合中添加任何其他内容等。)
所有声音都好吗?一位同事认为我们应该简单地向VendorContract添加一个“IsDraft”bool属性,如果IsDraft为false,则不接受更新。然后我们应该在VendorContractStatus中设置一个方法来更新状态,如果在草稿之后添加了某些东西,它会将VendorContract的IsDraft属性设置为false。
我不喜欢这样,因为我觉得我弄乱了POCO并添加了应该在验证区域中存在的逻辑,这些类中不应该存在任何规则,并且他们不应该知道它们的状态。
对此有什么想法,从DDD的角度来看,更好的做法是什么?
从我的观点来看,如果将来我们想要更复杂的规则,从长远来看,我的方式将更加可维护。假设我们有一定数量的合同需要经理批准。我认为与VendorContractApproval类进行一对一映射会更好,而不是添加IsApproved属性,但这只是推测。
这可能是分裂,但这是我们已经完成的第一个真正的坚韧不拔的企业软件项目。任何建议将不胜感激!
答案 0 :(得分:1)
要考虑的两件事情;
1)您是否真的想要合同请求和有效合同的相同对象模型。难道他们不会有不同的用例适用于他们吗?
2)如果你确实想要使用同一个对象,这可能是一个很好的例子,可以使用state pattern来控制哪些动作对当前状态有效。
答案 1 :(得分:0)
在调用者尝试持久化VendorContract
实例之前不会强制执行规则这一事实可能会使错误更容易发生,并且使这些类更难使用,因为它们没有描述自己的行为或约束。
通过专注于单一功能来换句话说:被拒绝和接受的合同甚至不应该有Amount
的设置访问者。
听起来您可能正朝着anemic domain model(有时以较不偏见的名称'persistent model'所知),其中您的域对象只是没有业务逻辑的容器。那是not always a bad thing,但是在具有大量业务逻辑的系统中,风格重复代码并将规则分散到太多对象上,使得理解(以及维护和更改)管理域实体的规则变得非常困难。
答案 2 :(得分:0)
别。编写描述所需行为的测试。当您为所有用例(并重构)编写测试时,数据模型就完成了。