我应该使用可选构造函数将域对象映射到视图模型吗?

2024-02-15

我希望能够通过更新视图模型并将贡献域模型作为参数传递(如下面的代码)来将域模型映射到视图模型。我的动机是避免重复使用映射代码并提供一种简单的映射方法(尚未使用自动映射器)。一位朋友说视图模型不应该知道有关传递到可选构造函数的“付款”域模型的任何信息。你怎么认为?

public class LineItemsViewModel
{
    public LineItemsViewModel()
    {
    }

    public LineItemsViewModel(IPayment payment)
    {
        LineItemColumnHeaders = payment.MerchantContext.Profile.UiPreferences.LineItemColumnHeaders;
        LineItems = LineItemDomainToViewModelMapper.MapToViewModel(payment.LineItems);
        ConvenienceFeeAmount = payment.ConvenienceFee.Fee;
        SubTotal = payment.PaymentAmount;
        Total = payment.PaymentAmount + payment.ConvenienceFee.Fee;
    }

    public IEnumerable<Dictionary<int, string>> LineItems { get; set; }
    public Dictionary<int, string> LineItemColumnHeaders { get; set; }
    public decimal SubTotal { get; set; }
    public decimal ConvenienceFeeAmount { get; set; }
    public decimal Total { get; set; }
}

这是一个相当古老的问题,其答案已被接受,但为了详细说明所提供的答案并解决评论部分中出现的问题,正在提供此附加答案。

正如所提出的,这个问题有点不确定。当被问及在软件开发方面是否应该以某种方式完成某些事情时,该问题可以被理解为关于支配所讨论主题的底层设计原则的问题,当这些设计原则不统一时应该应用,或者两者兼而有之。为了帮助客观地讨论该主题,让我们依次考虑这两个方面。

创建构造函数以将值从一个对象映射到另一个对象的特定做法会在两个对象之间创建耦合。视图模型包含与系统内特定视图有关的属性和/或行为。由于此类对象的目的是对特定视图进行建模,因此封装用于从系统内的另一种类型初始化模型的内部状态/值的映射逻辑意味着视图模型现在包含可能因某种原因需要修改的代码除了视图建模方式的更改之外。此类更改可能会导致模型行为的其他方面受到不利影响,从而导致系统行为出现意外回归。管理系统内组件解耦以防止通过耦合多个关注点而导致行为意外回归的原则称为单一职责原则。

何时应用这些原则的问题有点困难。重要的是要记住,软件通常是在编写时考虑到一些目标(例如解决一些业务问题、促进娱乐或教育等),并且对于任何给定的软件来说最好的都是与手头的任务相关的。为作为特定公司的旗舰产品而创建的软件系统所做的选择可能与为解决当前问题而开发的系统所做的选择有很大不同。还需要考虑促进某些类型的解耦所需的工作范围。一些解耦技术相对容易整合,而另一些解耦技术可能更困难,甚至为初始实现以及添加到负责软件维护的团队中的每个新开发人员提供了逐步学习曲线。虽然没有任何启发式方法能够完美地做出此类决策,但测试驱动开发提出了在出现重复之前不引入抽象的启发式方法。例如,策略模式是一种遵守开放/封闭原则的优秀技术,该原则控制对象的设计,以允许它们在不同的场景中应用,而无需修改现有代码。然而,当遵循测试驱动开发实践时,在观察到第二个用例之前不会引入策略模式。通过遵循这种启发式,开发人员被迫将他们的精力限制在手头的任务上,只编写完成任务所需的代码而不重复,从而最大限度地减少浪费并最大化可维护性(通过最小化复杂性)。

尽管如此,软件工程既是一门科学,也是一门艺术。它是一门科学,因为有一些规则来控制为了达到某些目的可以做什么和不可以做什么,但它也是一门艺术,因为你做得越多,就会做得越好,并且需要做出明确的权衡最终必须主观地做出。例如,作为客户端软件开发人员,我通常从不参与生命周期较短的应用程序的设计和开发。因此,我不会等到看到重复才将基于约定的依赖项注入引入到我的应用程序中。在软件系统生命周期之初,在应用程序中引入一致使用依赖注入的成本比等到您开始感觉到需要它时要低得多。

关于在视图模型中添加映射代码的具体示例,虽然它确实将视图模型耦合到特定的域模型,但实际上我不认为这是一个大问题。视图模型不太可能与其他域模型一起使用,并且引入的代码类型(即映射)的性质通常不包含业务逻辑,因此这种 SRP 违规导致系统显着回归的可能性是远小于应用程序或域层的 SRP 违规。

也就是说,我不认为在构造函数中添加映射逻辑的过程可以节省任何时间。如果要创建一个单独的类来封装大多数语言中领域对象和视图模型之间的映射,我们只讨论额外的几行代码。这是实现上的差异:

// constructor
public ViewType(DomainType domainType) {
...
}


// mapper class
public class ViewTypeMapper { 
  public ViewType Map(DomainType domainType) {
  ...
  }
}

因此,您要么执行 return new ViewType(domainType),要么执行 return new ViewTypeMapper().Map(domainType)。我只是看不出在这种情况下解耦会增加任何重要的工作。在大多数情况下,即使进行讨论,您也已经浪费了公司或客户的时间和金钱,因为与仅创建单独的类来表示相比,您最终总是会花费更长的时间来讨论它映射,或者如果您要继续设置 Automapper。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我应该使用可选构造函数将域对象映射到视图模型吗? 的相关文章

  • 关于JSON和序列化的问题

    我的视图模型有一个强类型视图 其中包含一个对象 Person 和一个技能列表 人是很直率的 我像这样使用 Html Helpers Html TextBoxFor m gt m Person FirstName 我提交表格并得到我想要的 问
  • Android中如何通过ViewModel类在Activity和Fragment之间共享数据?

    我想知道是否可以传递一个在 Activity 类中声明的字符串数据 并将该字符串数据传递给 ViewModel 类 然后将数据传递给 Fragment 类 视图模型类 class TimeTableViewModel extends Vie
  • C# 中 LINQ 中的按多列分组

    我有一个类如下 public class ActualClass public string BookName get set public string IssuerName get set public DateTime DateOfI
  • ASP.NET MVC 3,如何正确制作主题

    我正在寻找有关如何以最佳方式在 MVC 3 中实现 主题 的输入 我想需要一个自定义视图引擎来负责定位视图文件等 我还希望主题系统是可扩展的 这样 如果它只是其中一个视图 我想更改其他视图 但仍使用默认值 有点像 Orchard 项目吗 想
  • 仅为登录用户显示菜单项

    我是 ASP NET MVC 新手 正在使用该框架的 1 0 版本 我有一个 site master 页面 其中包含以下硬编码菜单 div ul li li li li li li li li ul div
  • MVC5 实体框架的问题

    我在我的 Web 应用程序中使用 Visual Studio 2013 中的 ASP NET MVC5 Entity Framework 6 我正在尝试我的模型工作 但由于某种原因而出现错误 我已经尝试过 Fluent API 和它自己的模
  • ASP.NET 中获取当前域的最佳方法是什么?

    我想知道在 ASP NET 中获取当前域的最佳方法是什么 例如 http www domainname com subdir http www domainname com subdir 应该产生http www domainname co
  • 为什么要调用base.OnActionExecuting(filterContext);?

    我只是在看我的一些旧代码 我有一个动作过滤器 OnActionExecuting 方法 最后我有 base OnActionExecuting filterContext 为什么到处搜索我都看到这个很多次了 我还看到 在我的旧授权标签中 我
  • If else 在 Web 网格列中

    如何在 webgrid 列中添加条件 if else grid GetHtml tableStyle table table bordered columns grid Columns grid Column RealName Name g
  • 使用 ASP.Net vNext 发送邮件

    一般来说 在传统的 ASP Net 和 Net 中 发送邮件是通过System Net Mail所在的类System dll 现在有了KRE vNext好像就没有了System Net Mail作为一个单独的包 参考 net453 框架在p
  • 从 Orchard 内的主题渲染图像

    我刚刚选择 Orchard 来构建我的博客 作为创建这个新博客的努力的一部分 我正在创建一个自定义主题 这个自定义主题同时具有 CSS 和图像 我的问题 我的问题基本上可以归结为 如何渲染属于主题一部分的图像 到目前为止我已经尝试过的 我尝
  • .NET-MVC - 通过 SSL 重写 URL + 某些 URL?

    我有一个运行 IIS 6 NET MVC 和单个域名的网络服务器 该网站使用 URL 重写来生成如下 URL 域名 com controller action 我愿意强行一 1 个控制器 to use SSL 其他的应该无需 SSL 即可工
  • MVC 操作过滤器和多线程

    我目前遇到了操作过滤器的线程问题 在我的应用程序上 我使用 ActionFilter 来执行每个操作的跟踪 此跟踪将提供统计信息 例如调用的持续时间 并记录参数被派往行动 实际的跟踪实现 由其他团队完成 使用 IDisposable 对象
  • 绑定到 ViewModel 时如何更新 Model?

    我有一个 HttpPost 操作方法签名如下 HttpPost public ActionResult Edit ExistingPostViewModel model Save the edited Post 现在 在过去 当我没有使用
  • ASP.NET Core Tag Helper Checkbox 不保存未选中的值

    我正在使用标签帮助程序在 MVC 表单中添加一个复选框 div class form group div
  • 获取没有非标准端口的原始 url (C#)

    第一个问题 环境 MVC C AppHarbor Problem 我正在调用 openid 提供商 并根据域生成绝对回调 url 在我的本地机器上 如果我点击的话 效果很好http localhost 12345 login Request
  • 如何使用C#在asp.net中下载xml文件

    我正在使用网络应用程序ASP NET 与 MVC3 我是 mvc3 的新手 我的网页上有一个下载按钮 当我要单击下载按钮时 我希望能够打开该 XML 文件 我尝试过一些代码更改动作结果但我没有打开文件 通过使用下面提到的代码 我收到一个下载
  • PDF 在 Safari 中隐藏 Jquery Modal

    这是与我有关的事情this https stackoverflow com questions 24052681 pdf hide jquery modal in ie问题 在 IE 中 我在对话框中使用 iframe 解决了问题 所以它工
  • 禁用视图中所需的验证特定字段 ASP.NET MVC 4

    如果有人能给我一些提示 我将不胜感激 我搜索了一段时间 我什至找到了一个帖子 我认为它可以解决我的问题 但它没有 在某些情况下禁用必需的验证属性 https stackoverflow com questions 5367287 disab
  • 检测 ASP.NET MVC 上的会话过期

    我构建了一个购物车 它使用会话状态在用户浏览商店时保留购物车数据 我遇到一个问题 如果我在购物车的第 1 步上长时间打开浏览器窗口 然后按 转到第 2 步 我的操作会引发错误 因为第 2 步操作假定会话尚未过期并且ShopCart 对象处于

随机推荐