哪一种概念更好:存储所选项目还是仅存储其键(又名id)



关于一般的视图模型设计概念,我现在有一个相当大的困境。我的意思是一般,就像它不完全绑定到一个给定的语言或环境:我有同样的困境,当我为Winforms, WPF或KnockoutJS写视图模型。

作为一个简化的用例,假设我有一个视图,我必须从两个选择框中选择一个国家和一个城市。两者都在数据库中表示为一个惟一的ID、一个Name和一些其他相关信息,比如人口。现在假设我必须以文本形式呈现当前选中的数据,例如视图的标题为"您选择了伦敦,英格兰"。现在,这里是我创建视图模型的两个备选方案,我将尝试在每个版本下面列举我已经想到的优点/缺点。代码是以一种伪方式编写的,以便尽可能地通用。

class RegionModel {
  ID: number;
  Name: string;
  Population: number;
}

版本1:存储选中的对象

class MainView {
  SelectedCountry: RegionModel;
  SelectedCity: RegionModel;
  SelectionInfo: string; // computed, should return the "You've selected ...." caption
  Countries: List<RegionModel>; // datasource for country select
  Cities: List<RegionModel> // datasource for city select
}

优点:

  • 由于被选中,所以简单易懂项目的类型与可选择项目的类型相同。
  • 很容易计算这样的信息,如"你已经选择…"因为所有的当前选中项目的成员直接出现。

缺点:

  • 它保存了比消费者API通常需要的更多的信息。通常它只需要ID。
  • 如果在客户端应用中使用,整个被选中的对象将被返回到服务器,占用带宽。
  • 如果消费者API只需要ID(像在大多数情况下),我必须在我通过之前解决某种转换。可能在web应用中例如,在序列化到JSON期间。

版本2:只存储所选项目的ID

class MainView {
  SelectedCountryID: number;
  SelectedCityID: number;
  SelectionInfo: string; // computed, should return the "You've selected ...." caption
  Countries: List<RegionModel>; // datasource for country select
  Cities: List<RegionModel> // datasource for city select
}

优点:

  • 它的效率在于它只包含需要的信息是消费者api最有可能需要的。
  • 无需额外转换,可高效通过对于服务器端或其他API几乎是"原样"的。

缺点:

  • 在我看来,不是那么简单易懂。
  • 如何计算信息字符串?我需要,现在更难了从选择源列表中获取所需的成员根据给定的ID进行搜索,因此它在很大程度上依赖于这些清单(我的意思是项目必须在那里)。

我希望它不会因为没有建设性而迅速关闭。任何形式的建议,想法或经验将不胜感激。此外,如果答案是"视情况而定",请试着给我一些点,在哪里和什么时候使用哪个。

更新我想我的问题有点不清楚。我知道将视图模型与数据库实体解耦,这里我没有提到数据库实体。我提到了一个"抽象消费者API"。在一个具体的场景中:如果API需要所选项目的名称,而我的API只需要id,我应该选择哪一个替代方案,应该在哪里进行转换?

例如,我的服务器期望这样的数据格式(JSON):

{
  "SelectedCountryID": 2,
  "SelectedCityID": 5
}

,没有别的了。我怎样才能优雅地处理它呢?我希望通过手动转换来避免重复。

根据您的数据源的实现方式,这可能没有什么区别:如果您正在检索国家和城市列表,您可以存储对所选值的引用,对其字段之一的引用或列表中的索引。

忽略这一点,您应该将视图模型实体与数据库实体解耦,并仅将视图所需的字段放入视图模型中。这样,您的信息流量最小化,您的代码受数据库更改的影响更小。

在OP更新后编辑

说到与API交互而不是与数据库交互,我认为你可以应用同样的想法,只是用"服务层实体"替换"数据库实体"(例如,JSON进出你的服务器)。将返回的数据放入视图模型对象中,保存您需要的那些属性。显然,您可能还需要存储id,如您所述,当您稍后需要引用同一实体时。

从理论的角度来看,您不应该包含视图未使用的任何其他字段,但您可以根据自己的需求这样做。例如,当您需要将这些字段传递回服务层,并且不希望通过id再次查询以检索服务实体时。然而,也有其他替代方案(例如,某种缓存),确切的平衡取决于您的需求。

基于MVVM模式,你的viewModel应该是一个具有你需要在视图中显示的所有属性的对象。ViewModel应该只用于严格绑定到视图。不管怎样,你的例子在我看来不是很好。你不应该在存储东西的情况下考虑viewModel,请更多地考虑呈现数据。

请记住,在数据库中有数据之前,您必须插入它。所以,如果你有一些表单,有名字和姓氏,用户首先必须填写这个表单,数据必须插入到数据库中,没有它,你就没有任何ID。

总而言之,我认为viewModel应该具有必须呈现给最终用户的属性。

最新更新