lundi 1 août 2022

Repository pattern and relationships

A question on how to properly implement the Repository pattern.

Proposed scenario (I'm using Typescript here, but it shouldn't matter):

  1. Data store

Table/Collection Exchanges: holds data about different Exchanges that operate in different Markets Table/Colletion Brokers: holds data about Brokers that operate assets through an Exchange Table/Collection BrokersRegistrations: holds a key to an Exchange, a key to a Broker, and also some relationship data, such as the date when the broker registered on that exchange, his/her current situation (active?), maybe the plan he/she is registered to

  1. Entities

Exchange, Broker, BrokerRegistration

  1. DTOs

Some helper types:

    export type CreateDTO<T> = Omit<T, 'id'>;
    export type UpdateDTO<T> = T;
    export type DeleteDTO<T extends { id: any }> = Pick<T, 'id'>;

For each entity:

    import { CreateDTO, UpdateDTO, DeleteDTO } from '@shared';
    import { BrokerId } from '@core/broker';
    import { Position } from '@core/position';
    
    export interface BrokerDTO {
      id: BrokerId;
      name: string;
      positions: Position[];
    }
    
    export type CreateBrokerDTO = CreateDTO<BrokerDTO>;
    export type UpdateBrokerDTO = UpdateDTO<BrokerDTO>;
    export type DeleteBrokerDTO = DeleteDTO<BrokerDTO>;
  1. Mappers

For each Entity:

    import { Mapper } from '@shared';
    import { BrokerDTO, Broker, PersistedBroker } from '@core/broker';
    
    export class BrokerMapper extends Mapper<BrokerDTO, Broker, PersistedBroker> {
      fromDTO(brokerDTO: BrokerDTO): Broker {
        return new Broker({
          id: brokerDTO.id,
          name: brokerDTO.name,
          positions: brokerDTO.positions,
        });
      }
    
      fromPersistence(persistedBroker: PersistedBroker): Broker {
        const { name, positions } = persistedBroker;
    
        return new Broker({ name, positions });
      }
    
      toDTO(broker: Broker): BrokerDTO {
        const { id, name, positions } = broker;
    
        return { id, name, positions } as BrokerDTO;
      }
    }

Now to the Repositories...

  1. Which ones should I create? One for each entity (BrokerRepository, ExchangeRepository, BrokerRegistrationRepository)?
  2. Suppose I want to have a ExchangeRepository.fingBrokersByName(name: string): Broker[] method, this method should return a collection of Brokers currently registered in that Exchange, but only if the name somewhow matches. How would you implement this? 2.1) Should it really return a collection of Broker, or should it instead return only a colleciton of Broker ids, and then the client is responsible for the BrokerRepository.findById(id) call? 2.2) I mean, in order to return a collection of Broker this ExchangeRepository method will probably have to call first BrokerRegistrationRepository.findAll(exchangeId): BrokerRegistration[] or BrokerRegistration.findByName(exchangeId, name)BrokerRegistration[] and then for each BrokerRegistration returned call BrokerRepository.findById(id). 2.3) Or would you instead make BrokerRegistrationRepository.findAll(exchangeId) return a collection of Broker already, instead of only their registration data?

I guess I need some guidance on how to implement relantionships with the Repository pattern.

Any help will be appreciate.

Have a nice day.

Aucun commentaire:

Enregistrer un commentaire