如何正确实施存储库适配器?

How to correct implement the Repository Adapter?

我开始学习如何基于 TypeScript 和 NestJS 构建简洁的架构。一切正常,直到我开始实施存储库适配器和控制器。主要问题是 API 方法和用例的 return 类型不兼容。

我们的想法是将实体和用例放在 核心 文件夹中,其中用例使用存储库适配器(通过 DI)。该适配器也实现了 core 文件夹中的存储库接口。

存储库适配器的实现包含在 app 中。 app 还包含 NestJS 实现、TypeOrm 实体等。但我也想为某些控制器使用存储库,例如 getAll query

!!!还有问题!!!

对于几乎每个命令,我都必须使用 Mappers 因为 TypeORM 实体和域实体是不兼容的类型。我认为如果我们将该数据传递给用例就可以了,因为我们需要将数据从 TypeOrm 形状转换为域形状。

但如果我只是在控制器中调用存储库适配器方法,我需要再次将数据映射回来...而且我不知道如何跳过不必要的步骤。 在我的想象中,只要调用app服务中的repository方法即可,仅此而已。 如果我跳过映射,那么所有数据属性都将具有前缀 _(

可能有人遇到同样的问题?

//核心区

帐户实体(/domain/account):

export type AccountId = string;
export class Account {
constructor(
  private readonly _id: AccountId,
  private readonly _firstName: string
) {}

  get id(): AccountId {
   return this._id;
  }

  get firstName() {
   return this._firstName;
  }
}

存储库接口(repositories/account-repository):

import { Account } from '../domains/account';

export interface AccountRepository {
  getAccountById(id: string): Promise<Account>;
  getAllAccounts(): Promise<Account[]>;
}

存储库用例示例:

import { AccountRepository } from '../../repositories/account-repository';

export class ToDoSomething {
  constructor(private readonly _accountRepository: AccountRepository) {}

  async doSomethingWithAccount(command): Promise<boolean> {
    const account = await this._accountRepository.getAccountById(
      command.accountId,
    );

    if (!account) {
      return false;
    }

    return true;
  }
}

//应用区

存储库适配器:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Account } from '../../../../core/domains/account';
import { AccountRepository } from '../../../../core/repositories/account-repository';
import { AccountEntity } from '../account.entity';
import { AccountMapper } from '../account.mapper';

@Injectable()
export class AccountRepositoryAdapter implements AccountRepository {
  constructor(
    @InjectRepository(AccountEntity)
    private readonly _accountRepository: Repository<AccountEntity>,
  ) {}

  async getAccountById(id: string): Promise<Account> {
    return this._accountRepository.findOne({ id: id });
    // will return { id: 1, firstName: "name" }
    // and because I need to use MapToDomain
  }

  async getAllAccounts(): Promise<Account[]> {
    return this._accountRepository.find();
    // Here too I need to use MapToDomain for every item
  }
}

TypeOrm 帐户:

import {
  Column,
  Entity,
  PrimaryGeneratedColumn,
} from 'typeorm';

@Entity({ name: 'account' })
export class AccountEntity {
  @PrimaryGeneratedColumn()
  id: string;

  @Column()
  firstName: string;
}

在清洁架构中,控制和数据流通常是这样的:控制器从视图(例如网络应用程序)获取请求并将其转换为请求模型,然后传递给用例。用例从请求模型中读取它应该计算的内容,并使用存储库与域实体交互以最终创建响应模型。然后将响应模型传递给演示者(可能与控制器相同class),后者将其转换为视图的响应。

控制器通常不与域实体甚至 ORM 类型交互。

查看我关于实施清洁架构的博客系列以了解更多详细信息:http://www.plainionist.net/Implementing-Clean-Architecture-Controller-Presenter/