设计数据源不可知模型

时间:2020-07-23 01:55:40

标签: typescript design-patterns architecture

我正在使用全栈打字稿应用程序,并且正在尝试

  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对象,但是我确实很喜欢拥有业务逻辑层的想法与底层数据源分离。

1 个答案:

答案 0 :(得分:0)

首先:是的,最好有一个域对象图而不是具有ID的地图。操作,理解和实现关系以及维护起来要容易得多。

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

  • 它将消耗内存,
  • 花费很长时间来加载不需要的信息,
  • 并且由于其他用户操作而很快会过时

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

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

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