Maison  >  Questions et réponses  >  le corps du texte

Évitez d'inclure la logique de domaine dans la couche du référentiel

Dans mon application actuelle, je dois créer une route api GET "/inactive-users" qui devrait renvoyer les utilisateurs archivés (“isArchived”),并且同时处于非活动状态超过一个月("lastVisitedDate" 字段应早于 new Date() - 1 个月).

En utilisant une architecture en couches (contrôleur/service/dépôt) et un modèle de domaine médiocre, que dois-je faire dans ce cas ?

Je vois qu'il y a deux approches possibles.

1 - Créez une méthode de référentiel générique pour récupérer l'utilisateur et lui transmettre les champs utilisateur dont nous avons besoin.

@Injectable()
export class UserRepository {
  constructor(private readonly prisma: PrismaService) { }

  findAll = async ( where: { user: Partial<User>; dateTreshold: Date } ): Promise<User[]> => {
    const users = await this.prisma.user.findMany(
      { where: {...user}, lastVisitedDate: { lt: dateTreshold }; // lt - less than
    );
        
    return users.map(user => new User(user));
  }
}

@Injectable()
export class UserService {
  constructor(private readonly userRepository: UserRepository) {}
  
  getInactiveUsers = async () => {
    return this.userRepository.findAll(
      { where: {user: {isArchived: true}, dateTreshold: "// calculatedDate //"}
    ) 
  }
}

2 - Créez la méthode du référentiel pour récupérer exactement les utilisateurs inactifs, la méthode saura quels champs elle doit demander.

@Injectable()
export class UserRepository {
  constructor(private readonly prisma: PrismaService) { }

  getInactiveUsers = async (): Promise<User[]> => {
    const users = await this.prisma.user.findMany(
      { where: {isArchived: false, lastVisitedDate: { lt: "// calculatedDate //" }}; // lt - less than
    );
        
    return users.map(user => new User(user));
  }
}

@Injectable()
export class UserService {
  constructor(private readonly userRepository: UserRepository) {}
  
  getInactiveUsers = async () => {
    return this.userRepository.getInactiveUsers() 
  }
}

Quel est le meilleur moyen ? Le premier me semble bon car dans ce cas, le référentiel ne sait rien de la compréhension du domaine de l'utilisateur "inactif". Mais en même temps, la mise en place d’une telle approche réactive peut s’avérer assez difficile.

La deuxième méthode est plus facile à construire, mais en même temps, elle comprend une certaine logique « métier » et sait que ce sont les utilisateurs inactifs "isArchived" 等于 false. De plus, cette méthode de référentiel sait combien de jours nous devons utiliser.

Quelle option choisir dans cette situation ? Ou peut-être existe-t-il d'autres façons de construire cette chose ?

P粉151720173P粉151720173181 Il y a quelques jours428

répondre à tous(1)je répondrai

  • P粉118698740

    P粉1186987402024-04-02 19:39:22

    La bonne façon d'isoler ce problème est que le référentiel ne connaît que les éléments de données du référentiel. Cela ne signifie pas que vous ne pouvez pas avoir plusieurs points d'entrée dans votre référentiel, il peut y avoir de nombreuses requêtes différentes accédant toutes à la même « table ».

    Cela ne signifie pas que vous avez besoin d'un QBE complet comme la première méthode, restez simple. Il existe une requête qui encapsule le niveau de la base de données mais nécessite toujours ce dont elle a besoin.

    Dans ce cas, vous devriez avoir une signature passant les paramètres isArchived et lastVisitedDate. Quelque chose comme QueryUsersByStatusAndLastVisited. De cette façon, le référentiel gère tous les bits impliqués dans la récupération des données, mais n'a aucune logique quant à la raison pour laquelle ils sont récupérés. Ce sera "stupide", avec tous les bits intelligents encapsulés dans la couche de service.

    répondre
    0
  • Annulerrépondre