首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >设计应该通过GUI可更改但不受程序员错误影响的实体

设计应该通过GUI可更改但不受程序员错误影响的实体
EN

Software Engineering用户
提问于 2015-04-06 13:44:52
回答 2查看 1.1K关注 0票数 2

我有一组实体,目前由非常简单的类表示(本例进一步简化):

代码语言:javascript
复制
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。

更新

好吧,我已经意识到我对领域驱动的设计和它的概念知之甚少。无论如何,基于这个线程中的两个答案,我提出了以下设计:

  • 将有一个存储库类隐藏ORM和持久性逻辑。ORM适用于DTO(所有设置器公共,没有验证,默认构造函数)。存储库的用户看不到DTO,但能够查询存储库基于这些DTO创建的不可变域对象。
  • 对于添加/编辑实体,将创建一个视图模型,并使用域对象的值填充其属性。视图模型是完全可变的,具有所有的验证逻辑。在保存时,使用视图模型中的值创建一个新的域对象,然后通过存储库保存或更新。

对我来说,这提出了两个新的问题。不可变域对象表示有效的实体,因此应该在构造函数中验证其所有值。另一方面,视图模型可以保存不正确的值,然后验证这些值(例如,在IDataErrorInfo实现中)。如何避免在视图模型和域对象之间重复验证逻辑?

第二个问题-要通过存储库存储/更新域对象,我需要跟踪ORM创建的DTO中的Id值,并将其设置在域对象中。困扰我的是,这是一个严格的持久化细节,与业务逻辑无关。这个持久化细节渗透到域中可以吗?

这个设计有多合理?我有没有朝正确的方向思考?

EN

回答 2

Software Engineering用户

回答已采纳

发布于 2015-04-06 14:17:38

我建议将DTO映射到域对象,并使该域对象不可变

只需给它私有设置器,并通过一个工厂创建它,而不是到处传递DTO。

如果您认为它应该是不可变的,那么使其不可变无疑是一个不错的主意,记录仍然有一个风险,一个新的开发人员将进入舞台并犯一些最初的错误。这不是世界末日,但您希望尽可能减少软件熵

但是,我不建议使您的DTO不可变,因为大多数时候您不应该需要它。它是一个愚蠢的、简单的对象,它携带数据,但另一方面,域对象可以是不可变的,因为它反映了业务的实际生活需求。

票数 4
EN

Software Engineering用户

发布于 2015-04-06 14:28:10

这些实体还将由ORM持久化、读取和更新,并将作为MVVM模式中的模型。

为什么?

我的意思是,您基本上是说您希望您的实体(业务逻辑使用的实体和ORM使用的实体)是不可变的,但是您希望您的模型(如UI所使用的)是可变的(至少在添加/编辑屏幕上是这样)。

所以把这两件事解耦,就像它们应该放在第一位一样。

票数 4
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/278374

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档