DDD Repositórios
Tags: braziliandevs, javascript, ddd, todayilearned
Published: 2022-05-05 21:27:53

Today I Learned 05/05/2022

- [Repositório](#repositório)
- [Cenário](#cenário)
- [Implementação](#implementação)

## Repositório
O Vaughn Vernon em seu livro Implementing Domain-Driven Design
define repositórios como:

> Um repositório comumente se refere a um local de armazenamento, geralmente considerado um local de segurança ou preservação dos itens nele armazenados. Quando você armazena algo em um repositório e depois retorna para recuperá-lo, você espera que ele **esteja no mesmo estado que estava quando você o colocou lá.** Em algum momento, você pode optar por remover o item armazenado no repositório
VERNON, Vaughn. Implementing Domain-Driven Design

> Esses objetos são semelhantes a coleções sobre persistência. Todo tipo de **Agregado** persistente terá um **Repositório**. De um modo geral, existe uma relação **um-para-um entre um tipo de Agregado e um Repositório**
VERNON, Vaughn. Implementing Domain-Driven Design

Ou seja, para cada agregado temos apenas um repositório então se por exemplo voltarmos no exemplo de agregados que eu dei no artigo sobre [Services em DDD](https://dev.to/yanpiing/ddd-services-1cm7)

![Aggregado de customer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vwoev9p9jpzham4unts0.png)

Para esse aggregado de customer somente será criado um único repositório, que vai conter os campos de customer **E** os campos de endereço, não é necessário uma tabela para Address justamente por que o domínio da aplicação é diferente da infraestrutura

Não tem problema a gente implementar o banco de dados pensando em domínio, o problema é implementar o domínio pensando no banco de dados

##Cenário
Imaginando uma entidade de order onde cada order precisa ter os seus items associados, sendo que nessa entidade precisamos salvar também o id do usuário que fez o pedido e o produto que é associado ao ordem item.

Porem final das contas o nosso aggregado vai ser esse daqui:

![Exemplo da entidade](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owadjfqozxysb78a6bnu.png)

##Implementação
Para fazermos o repositório do nosso agregado de order vamos precisar inicialmente de dois models, o model de OrderItem e o de Order. Vamos criar duas tabelas por banco de dados, lembrando que 1 repositorio corresponde 1 agregado, porem 1 repositorio não tem essa relação de 1 para 1 com tabela no banco de dados


(ps: o model foi feito utilizando sequelize porem o ORM utilizado não importa muito, isso pode ser implementado com qualquer um):
_order-items.model.ts_
```js
@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_
```js
@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;
}
```

com os models declarados podemos criar o repository:
```js
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}]
    })
  }

}
```

Só precisamos do repositório de Orders, pois ele já se encarrega de quando criarmos uma nova order ele salvar os items na tabela de order-items

> Ainda estou aprendendo sobre DDD e se quiser ver melhor o código pode dar uma olhada nesse [Repositório](https://github.com/Yansb/full-cycle-course/tree/master/domain-driven-design)