【问题标题】:Designing data source agnostic models设计与数据源无关的模型
【发布时间】:2020-07-23 16:49:35
【问题描述】:

我正在开发一个全栈 Typescript 应用程序,并且正在尝试

  1. 将所有模型和服务逻辑与任何支持数据源分开
  2. 保持数据和行为分离(即无方法模型)

但在关系方面,我很难弄清楚如何设计这些模型。

现在我有一个core 包,可以导出一些接口

interface Item {
  id: string;
  text: string;
  idProject: string;
}

interface Project {
  id: string;
  name: string;
  idSource: string;
}

interface Source {
  type: 'rss' | 'api';
  name: string;
}

interface ItemService {
  get(id: string): Promise<Item>
}

interface ProjectService {
  get(id: string): Promise<Project>
}

interface SourceService {
  get(id: string): Promise<Source>
}

interface ProjectItemLoaderService {
  constructor();
  loadItems(project: Project, source: Source): Promise<Item[]>;
}

然后在我的server 包中,我像这样使用它们

get('/project/:idProject/items', ({ idProject }) => {
  const project = projectService.get(idProject);
  const source = sourceService.get(project.idSource);
  const items = projectItemLoaderService.loadItems(project, source);
  ...
})

但是从我一直在阅读的关于抽象模型(DDD,六边形架构)这个主题的内容来看,我的模型不应该通过 ID 来引用关系,而应该包括实际模型,因为像 ID 这样的东西是存储概念,而不是域概念。

interface Item {
  id: string;
  text: string;
  project: Project
}

interface Project {
  id: string;
  name: string;
  source: Source
}

interface Source {
  type: 'rss' | 'api';
  name: string;
}

...

interface ProjectItemLoaderService {
  constructor();
  loadItems(project: Project): Promise<Item[]>;
}

...

get('/project/:idProject/items', ({ idProject }) => {
  const project = projectService.get(idProject);
  // Project already includes the Source model, not need to load it
  const items = projectItemLoaderService.loadItems(project);
  ...
})

这更方便不必经常加载嵌套模型,但随着嵌套越来越深,它似乎很容易失控。 Project 模型实际上应该有一个 items: Item[] 属性,根据后备存储可能需要相当长的时间来填充。然后它将是周期性的,这是另一个问题。

我基本上是在寻找有关制作与数据无关的模型的任何建议,以及应如何让处理这些模型的服务访问其关系。也许在不使用完整的 DDD(用例、命令等)的情况下做这种事情并不是很可行,我应该只使用源耦合的 ORM 对象,但我真的很喜欢拥有业务逻辑层的想法与底层数据源解耦。

【问题讨论】:

    标签: typescript design-patterns architecture


    【解决方案1】:

    首先:是的,最好有一个领域对象的图表而不是带有 id 的地图。它更容易操作、理解和实现关系以及维护。

    第二:您不能在您的应用程序中加载您域的全部数据。并且在加载对象时,您不必加载整个依赖树。

    • 会消耗内存,
    • 需要很长时间才能加载您不需要的信息,
    • 并且由于其他用户的操作很快就会过时

    --> 制作只加载页面或操作所需的对象和嵌套对象的服务。

    例如,对于一个列表,您通常只需要加载列表的对象,但在详细信息页面上,您需要加载并显示关联的子项,以增加 1 或 2 个深度级别。

    (稍后您会考虑哪些数据可以经常重复使用并使用缓存进行优化)

    【讨论】:

    • 但是这些模型的类型呢?假设project 有时只会加载到Item 上,我必须将其输入为project: Project | undefined。然后,每当我有一项依赖于Item 的服务时,它就必须进行持续的空值检查以确定project 是否存在。实际上,该服务只能使用填充了projectItem 调用。
    • 是的...但是使用 ID 的替代方案更糟。但是,当您知道您将始终需要该关系时,您可以将该字段设为必填并系统地加载它。
    • 注:也许一个项目可以在没有项目的情况下存在?如果您已经拥有从项目到项目的链接,是否还需要从项目到项目的链接?
    猜你喜欢
    • 1970-01-01
    • 2012-12-10
    • 1970-01-01
    • 2013-02-21
    • 2014-11-23
    • 1970-01-01
    • 2014-08-15
    • 2020-10-24
    • 1970-01-01
    相关资源
    最近更新 更多