MVVM、UWP 和模板 10 - 模型与视图技术的独立性

MVVM, UWP & Template 10 - Independency of model from view technology

我对MVVM的理解是View负责用户表现逻辑,view-model负责交互逻辑和具体的数据从UI独立模型类转换,模型本身代表数据业务领域观点。

关键是模型 类 应该是 UI 独立的。

这是 UWP 开发模型和模板 10 BindableBase,模型 类 应该从中派生。它非常方便,但它将模型与特定的 UI 实现相关联,即 UWP + 模板 10。

我有一个数据访问层吐出域对象我想直接作为模型提供给 UI。域相当复杂。我不想做的是在 UI 中重新实现数据域对象,也不想用 UI 特定函数污染它。

对此有什么想法吗?

谢谢

恕我直言,我认为您可能想错了。

MVVM 的目标是完全按照您描述的方式分离您的逻辑。这种分离的目的是简化您的代码。这是否使视图模型可测试并分离关注点?是的。但是,我认为这些是简单性的次要目标 – 使您的代码易于管理和维护。

这是另一种说法。

MVVM 是 XAML 应用程序的绝佳方法。但是,如果 MVVM 没有使您的视图模型可测试或分离关注点,MVVM 仍然是 XAML 应用程序的绝佳方法,因为它大大简化了代码——更小、更简单、更独立。

物有所值。

您可能会争辩说 MVVM 创建了另一层代码,开发人员在推理和贡献基础之前必须理解这一层。我同意。但我不会因此断定 MVVM 是不切实际的。与其他逻辑耦合相比,增加的层是微不足道的。

现在回答你的问题。

您的数据层对象(可能是数据传输对象)非常像您的 UI 对象(可能是模型)。您的开发人员直觉迫使您通过多态性、代码生成或接口将相似的事物结合起来,以避免增加错误、复杂性和测试的机会。

考虑一下。

在您的数据层中创建的对象是为您的数据层创建的。同样,在您的 UI 图层中创建的对象是为您的 UI 图层创建的。结构相似性是领域相似性的副产品。当然,它们是相似的:然而,它们的意图却不同。为什么要合并它们?

您已经看到问题了。

您唯一的区别可能是数据层构造函数接收某种类型的数据 reader 并填充属性。这对数据层来说是完美的,但不适合 UI 层。您的 UI 层可能具有消息传递事件或处理交互的自定义​​方法。这对于 UI 层来说是完美的,但不适合数据层。

所以,相似点在哪里?

我认为包括我自己在内的开发人员倾向于将相似的事物视为可能相同的事物。您的数据相关功能不属于您的 UI 也不属于其他方式。相反,您需要做的是看到相似性,但要认识到它们是截然不同的对象,不应该变得相同。

我们很懒。

重复代码与测试和错误无关。并不真地。它是关于我们作为开发人员如何痴迷于“更聪明地工作而不是更努力地工作”,以至于我们倾向于看不起“努力工作”。如果一个对象是为一层构建的,它应该在该层中,而不是被另一层共享。我强烈地有这种感觉。

正确的解决方案

最简单的解决方案是让您的 DTO 在 DataLayer.Object 的数据层上进行序列化,然后在 UI 层上将其反序列化为 UILayer.Model。这是最简单和最简单的方法,并且足以让您强制数据和对象 API 以供其唯一层使用。

这意味着有两个几乎相同的对象:一个在数据层上,一个在UI层上。但这并不意味着有两个相同的对象。它们并不完全相同,因为它们的每一层、每一层都具有独特的功能。

没有功能怎么办?

怀疑这是否适用于没有添加功能的对象和模型是有道理的。我坚信,任何层中没有添加功能的对象和模型都只是在等待添加该功能。如果您假设存在 none 并根据该假设进行构建,您将迫使未来的您或即将到来的维护开发人员永远不要添加特定于层的功能。

这重要吗?

我认为是的。为什么?因为对象或模型中特定于层的功能允许我在数据对象或模型的上下文中为我的体系结构和实现添加复杂性(而不是复杂性),而不是像 managerhelper,或 utility。毫无疑问 Type.DoSomethingHelper.DoSomethingForType(Type).

更容易

其实我有三个

告诉你,我是这样做的:在我的项目中,你和我可能有相似的数据 layers/services。但是,我的 UI 层实际上有两个模型——不是一个。 (假设 Users 是数据类型。)我的 UI 层有 json.UserModels.Userjson.User 是一个简单的骨架结构,从我的服务中反序列化,并且与服务对象完全匹配。但是我的 UI 很少需要服务 API surface/structure。

Service(DataLayer.User) > | net | > UI(json.User > Models.User)

因此,然后 json.User 用于创建 Model.User,其结构完全满足我的 UI 层的需求 - 包括方法、事件和消息构造。在向 UI 添加功能时,我也可以自由更改 Models.User,包括合并来自 other/new 数据服务的数据。此外,Model.User 可以实现 INotifyPropertyChanged,其中数据层对象和 json 对象永远不会(或不需要)。

考虑一下

如果您将模型分开并防止一个代码库对另一个代码库产生不当影响,那么数据库中的任何更改或数据中的任何更改 service/layer 都不会 REQUIRE 更改您的UI层,即使你改变了API表面。只有 json.User 对 UI 层中反序列化提示的更改或调整会受到影响。对我来说,这才有意义。

但是测试和错误呢?

测试很少测试结构。数据结构是您可以添加到解决方案中的最简单的东西,而且很少会增加复杂性。您可以在大约一秒钟内推理出一个结构。您可以在大约一分钟内推理出一个方法。结构的成本非常低。它们的建造成本也非常低。如果您 copy/paste 从数据层到 UI 层的初始结构——这就是我们所做的。但这不是重复代码。它只是构建适当解耦的相似对象。

我就是这么想的