1

鉴于:

  1. 我们的组织有一个标准的窗体应用程序
  2. 表单和业务逻辑交织在一起——即自治视图。我们知道自治视图模式使编写单元测试变得困难。目标是采用单一表单并将表示逻辑与表单本身分离,以便我们拥有一个独立的域实体/对象,可以更轻松地针对它编写单元测试。
  3. 我们没有进行完全重写。我正在研究一种渐进的方法,它允许单独处理一个屏幕。
  4. 经过一些研究,我认为Presentation Model模式或MVVM模式最适合这个组织做事的方式。
  5. 该组织通常更喜欢较少的间接层,因此更简单(即使不太健壮)更好。
  6. 从过去到现在的转变应该是公式化的(很容易教任何已经熟悉内部概念的开发人员)。这就是为什么他们要坚持使用 Windows 窗体而不是 WPF 等其他新技术。
  7. 域模型对视图(表单)一无所知。该表单将完全了解域模型的更改。这使得 2 层间接。再 1 个就好了(这就是我允许 MVVM 的原因)。

我发现的大多数 MVVM 示例都说明了它如何与 WPF 配合使用,而不是与普通的旧 Windows 窗体配合使用。

两个问题:

考虑到这一切,我所说的有没有让你认为我没有走上好的道路或者我走错了路?我希望向管理层提出一些建议。

最后,你知道一个很好的在线代码示例可以帮助我充实一个原型吗?

4

4 回答 4

1

也许您能做的最好的事情就是着眼于单一职责原则来查看您的代码库。自治视图(以及支持它的 winforms)如此难以测试的主要原因之一是,开发人员倾向于将所有内容集中在一个事件处理程序中。

在 SO- https://stackoverflow.com/questions/16599778/asp-net-mvc3-linq-make-multiple-related-rows-fields-in-a-1-to-many-relationshi上提出这个问题,它是关于MVC3,但它完全是一团糟——一种负责配置网格视图、配置响应和检索数据以填充网格视图的方法。甚至很难知道从哪里开始回答问题,更不用说编写任何合理的(阅读:简洁和快速执行)测试以确保解决方案有效。

如果您可以仔细检查您的代码,并仔细地将所有业务逻辑和/或集成点封装到服务/组件/接口(和实现)中,最好在外部单独的程序集中。

一旦您将所有逻辑分解为单独的组件,每个组件都专注于自己的关注点,您就可以为其编写测试以确保它们执行预期的任务,而无需测试应用程序的任何其他部分,这些将是您的服务. 您希望将每种服务类型拍摄为由实现支持的接口。

在您编写和测试了所有这些不同的项目和程序集之后,您可以使用控制反转(依赖注入的一种形式)将它们重新引入您的应用程序。这进一步将您的 UI 与您的应用程序要执行的各种业务逻辑分离。这里的梦想是,您将到达一个地方,当您准备好重写 UI 时,您可以重用已经编写和测试的业务逻辑组件。

我认为 winform 类将有一个接受许多参数的构造函数(上面讨论的各种服务的混合)。DI 框架将负责为 winform 类提供服务。之后,理想情况下,您的 winforms 事件处理程序将相对较小,只需使用从各种表单字段收集的参数值调用服务方法。

这是一篇关于在 winforms 中使用Castle Windsor(依赖注入框架)的帖子:Using Castle.Windsor with Windows Forms Applications。有许多不同的 DI 框架,我使用 Castle Windsor 是因为它是我第一次学习的,它们基本上都做同样的事情,所以,你需要做的就是找到一个你觉得舒服的。

这是一个基于 Web 应用程序的关注点分离教程,但应该对如何从现有的“厨房水槽”应用程序中识别和重构服务具有指导意义。

这个答案正在变成一本书,而且非常抽象。主要的是你需要将应用程序视为一组乐高积木,你可以将它们组合起来产生功能(每个积木都是一个问题),而 UI 只是将积木粘合在一起的粘合剂(这个类比并不完美) .

确实,它更像是艺术而不是科学,但你可以训练你的思维以这种方式看待问题,一旦你这样做了,编程通常会变得容易得多。曲线有点陡,但是,坚持下去,你会到达那里。

于 2013-05-17T02:45:32.010 回答
0

我认为您最好的选择是将ElementHosts放入现有的 winforms 应用程序中,并将 WPF 内容放入其中。然后您可以使用 WPF 和 MVVM 并逐步将您的 winforms 应用程序升级到 WPF。

即使您在 winforms 中使用某种辅助框架,您也总是会遇到一些限制,这些限制会导致肮脏的、hacky 的解决方案污染您试图实现的清洁度。

例如,winforms 中没有任何东西可以提供与ItemsControl带有DataTemplates. 看一下WPF中带有 some的这个示例。无论您包含多少第三方框架,您都无法在带有 的 winforms 中实现类似的功能。ListBoxDataTemplatesListBox

底线:ElementHosts在每个 Form 中放入 WPF 内容,您可以逐渐将所有 winform 的混乱清理成一个干净、MVVM、可测试、独立于分辨率、简单漂亮的 WPF UI。我坚持(并且没有人能够证明我错了)这是从 winforms 中获得任何体面的唯一方法。

于 2013-05-17T14:58:21.727 回答
0

在 WPF 中,我们可以在视图中的对象和 ViewModel 中的内容之间进行数据绑定,因为 MVVM 是 WPF 的完美模式。

我从这个例子中学习了 MVVM:http ://www.scottlogic.co.uk/blog/colin/2011/05/a-simple-windows-phone-7-mvvm-tombstoning-example/

这是一个 Windows Phone 教程,但如果你能理解它的工作原理,你就可以轻松地将它与任何 WPF 应用程序一起使用。

于 2013-05-17T01:47:30.897 回答
0

我讨厌成为一个回答我自己的问题的人,但额外的研究和实验已经说明了一些事情。

理想的解决方案是领域对象的提取本身在本质上与组织中使用的设计实践非常相似。从本质上讲,它应该是从其所有 UI 荣耀中提取一个视觉形式,到一个更抽象的形式(“VM”或视图模型),它体现了在表单(组合、按钮等)上使用的概念,而无需使用实际的用户控件。然后,VM 将绑定到实际找到控件的视图。

不幸的是,这是一项艰巨的工作,其中抽象必须足够健壮,才能以与它们映射到的控件类似的方式运行。由于我们的组织有几十个自定义控件,这不是一个简单的命令。

以一个简单的内部组合框为例。组合表示具有一组受限选择选项的输入。我们的数据模型是一个内存数据集。该组合绑定到一个特定的表格,并且当用户填写表格并因此提供标准时,他允许的选择被进一步过滤。该组合向用户显示一个值 (DisplayMember) 并将另一个值持久保存到数据库 (ValueMember)。可能不止于此。但是,组合的“字段”抽象必须考虑其中一些概念,以便最终可以正确映射到视图。此外,我们的表单订阅了大量源自其控件的事件。这些必须以某种方式映射。所以在我看来,大量的表单(视图)功能必须在 VM 中有对应的功能。

我最初认为可以提取表单及其组成控件的非常一般的抽象,然后将该抽象(与原始表单非常相似)映射到视图。虽然这可能是可能的,但我现在认为这是不切实际的,并且它本身可能会带来一系列广泛的新问题。

因此,虽然我想避免针对实际表单实例运行测试,但我认为这可能比尝试添加抽象层更好。构建这种抽象类似于使用另一种范式重写我们的屏幕,因此不保留屏幕的原始形状。也就是说,即使我们可能一次重写一种形式从而允许逐渐过渡,最终版本也不会像希望的那样重用原始结构。

于 2013-05-17T19:53:45.073 回答