我有一组实体,目前由非常简单的类表示(本例进一步简化):
public class Item
{
public string Name { get; private set; }
public double MainValue { get; private set; } //should be exposed for editing in GUI
public double Value { get; private set; } //should be exposed for editing in GUI
}
public class Record
{
public Item Item { get; private set; }
public double Quantity { get; private set; } //should be exposed for editing in GUI
public double MainValue { get { return Item.MainValue*Quantity; } }
public double Value { get { return Item.Value*Quantity; } }
}
public class DayAccount
{
public DateTime Date { get; private set; }
public IEnumerable<Record> Records { get; private set; }
public double MainValueGoal { get; private set; } //should be exposed for editing in GUI
public double MainValueTotal { get { return Records.Sum(r => r.MainValue); } }
public double ValueTotal { get { return Records.Sum(r => r.Value); } }
public void Add(Record record) {}
public void Remove(Record record) {}
}将有一个用于访问、添加和持久化DayAccount实体的存储库类,但差不多就是这样。如果需要编辑这些实体的属性,最终用户应该能够通过GUI修改它们的一些属性,但是对它们的所有其他操作都是纯数据分析和只读的。这些实体还将由ORM持久化、读取和更新,并将作为MVVM模式中的模型。
首先,实施任何形式的保护值得吗?只有在程序员错误/类使用不当的情况下,才会发生无意的修改。也许这些实体应该是完全可变的,只要通过测试并通过测试,代码就应该被完整地记录下来,并被认为是安全的?
出于教育目的,假设保护措施不受意外变化的影响是强制性的。我怎样才能强制执行?在使用ORM时,使对象完全不可变并克隆它们可能会带来困难。在多线程上下文中提供简单的可变/不变开关是有误导性的。引入不可变接口(如在这个答案中公开可变对象)并不能强制执行不可变性,它只是隐藏对象--对于此代码的用户来说,它更显着,但不能完全防止程序员出错。
我正在使用C# 5和.NET Framework4.5。
好吧,我已经意识到我对领域驱动的设计和它的概念知之甚少。无论如何,基于这个线程中的两个答案,我提出了以下设计:
对我来说,这提出了两个新的问题。不可变域对象表示有效的实体,因此应该在构造函数中验证其所有值。另一方面,视图模型可以保存不正确的值,然后验证这些值(例如,在IDataErrorInfo实现中)。如何避免在视图模型和域对象之间重复验证逻辑?
第二个问题-要通过存储库存储/更新域对象,我需要跟踪ORM创建的DTO中的Id值,并将其设置在域对象中。困扰我的是,这是一个严格的持久化细节,与业务逻辑无关。这个持久化细节渗透到域中可以吗?
这个设计有多合理?我有没有朝正确的方向思考?
发布于 2015-04-06 14:17:38
。
只需给它私有设置器,并通过一个工厂创建它,而不是到处传递DTO。
如果您认为它应该是不可变的,那么使其不可变无疑是一个不错的主意,记录仍然有一个风险,一个新的开发人员将进入舞台并犯一些最初的错误。这不是世界末日,但您希望尽可能减少软件熵。
但是,我不建议使您的DTO不可变,因为大多数时候您不应该需要它。它是一个愚蠢的、简单的对象,它携带数据,但另一方面,域对象可以是不可变的,因为它反映了业务的实际生活需求。
发布于 2015-04-06 14:28:10
这些实体还将由ORM持久化、读取和更新,并将作为MVVM模式中的模型。
为什么?
我的意思是,您基本上是说您希望您的实体(业务逻辑使用的实体和ORM使用的实体)是不可变的,但是您希望您的模型(如UI所使用的)是可变的(至少在添加/编辑屏幕上是这样)。
所以把这两件事解耦,就像它们应该放在第一位一样。
https://softwareengineering.stackexchange.com/questions/278374
复制相似问题