Репозитории DDD

Сегодня я узнал 05/05/2022

  • Репозиторий
  • Сценарий
  • Реализация

Репозиторий

Вон Вернон в своей книге «Реализация проектирования, ориентированного на домены
определяет репозитории как:

Под хранилищем обычно понимается место хранения, которое обычно считается местом безопасности или сохранности хранящихся в нем предметов. Когда вы храните что-то в хранилище, а затем возвращаетесь, чтобы получить это, вы ожидаете, что оно будет в том же состоянии, в котором было, когда вы его туда положили. В какой-то момент вы можете решить удалить элемент, хранящийся в хранилище
ВЕРНОН, Вон. Реализация проектирования, ориентированного на домен

Эти объекты похожи на коллекции по персистентности. Каждый постоянный тип Aggregate будет иметь Repository. В общем, между типом агрегата и хранилищем существует связь один-к-одному
ВЕРНОН, Вон. Реализация проектирования, ориентированного на домен

То есть, для каждого агрегата у нас есть только одно хранилище, так что если, например, мы вернемся к примеру агрегата, который я приводил в статье о сервисах в DDD

Для этого совокупного клиента будет создано только одно хранилище, которое будет содержать поля клиента И поля адреса, нет необходимости создавать таблицу для Address, поскольку домен приложения отличается от домена инфраструктуры.

Не проблема реализовать базу данных, думая о домене, проблема в том, чтобы реализовать домен, думая о базе данных.

Сценарий

Представьте себе сущность order, где каждый заказ должен иметь связанные с ним элементы, и в этой сущности нам также нужно сохранить id пользователя, который сделал заказ, и продукт, который связан с элементом заказа.

Однако, в конечном итоге, наша совокупность будет такой:

Реализация

Для создания хранилища нашего агрегата заказов нам изначально понадобятся две модели, модель OrderItem и модель Order. Мы создадим две таблицы для каждой базы данных, помня, что хранилище соответствует агрегату, но хранилище не имеет отношения 1 к 1 с таблицей в базе данных

(ps: модель была сделана с помощью sequelize, но используемая ORM не имеет большого значения, она может быть реализована с любой):
order-items.model.ts

@Table({
  tableName: 'orders_items',
  timestamps: false
})
export class OrderItemModel extends Model{
  @PrimaryKey
  @Column
  declare id: string;

  @ForeignKey(() => ProductModel)
  @Column({allowNull: false})
  declare product_id: string;

  @BelongsTo(() => ProductModel)
  declare product: ProductModel;

  @ForeignKey(() => OrderModel)
  @Column({allowNull: false})
  declare order_id: string;

  @BelongsTo(() => OrderModel)
  declare order: OrderModel;

  @Column({allowNull: false})
  declare quantity: number;

  @Column({allowNull: false})
  declare name: string;

  @Column({allowNull: false})
  declare price: number;

}

Войдите в полноэкранный режим Выход из полноэкранного режима

order.model.ts

@Table({
  tableName: 'orders',
  timestamps: false
})
export class OrderModel extends Model{
  @PrimaryKey
  @Column
  declare id: string;

  @ForeignKey(() => CustomerModel)
  @Column({allowNull: false})
  declare customer_id: string;

  @BelongsTo(() => CustomerModel)
  declare customer: CustomerModel;

  @HasMany(() => OrderItemModel)
  declare items: OrderItemModel[]

  @Column({allowNull: false})
  declare total: number;
}
Войдите в полноэкранный режим Выход из полноэкранного режима

После объявления моделей мы можем создать хранилище:

export class OrderRepository{
  async create(entity: Order): Promise<void> {
    await OrderModel.create({
      id: entity.id,
      customer_id: entity.customer_id,
      total: entity.total(),
      items: entity.items.map(item => ({
        id: item.id,
        name: item.name,
        price: item.price,
        quantity: item.quantity,
        product_id: item.productId,
      }))
    },
    {
      include: [{model: OrderItemModel}]
    })
  }

}
Войдите в полноэкранный режим Выход из полноэкранного режима

Хранилище Orders нам нужно только потому, что оно заботится о сохранении элементов в таблице order-items, когда мы создаем новый заказ.

Я все еще изучаю DDD, и если вы хотите увидеть код лучше, вы можете взглянуть на этот репозиторий

Оцените статью
Procodings.ru
Добавить комментарий