In meiner aktuellen Anwendung muss ich eine API-GET-Route „/inactive-users“ erstellen, die archivierte Benutzer zurückgeben soll (“isArchived”
),并且同时处于非活动状态超过一个月("lastVisitedDate"
字段应早于 new Date() - 1 个月
).
Was soll ich in diesem Fall tun, wenn ich eine mehrschichtige Architektur (Controller/Dienst/Repository) und ein schlechtes Domänenmodell verwende?
Ich sehe, dass es zwei mögliche Ansätze gibt.
1 – Erstellen Sie eine generische Repository-Methode, um den Benutzer abzurufen und ihm die von uns benötigten Benutzerfelder zu übergeben.
@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 – Erstellen Sie die Repository-Methode, um inaktive Benutzer genau abzurufen. Die Methode weiß, welche Felder sie anfordern soll.
@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() } }
Welcher Weg ist besser? Das erste sieht für mich gut aus, da das Repository in diesem Fall nichts über das Domänenverständnis des „inaktiven“ Benutzers weiß. Gleichzeitig kann es jedoch recht schwierig sein, einen solchen reaktiven Ansatz zu entwickeln.
Der zweite Weg ist einfacher zu erstellen, verfügt aber gleichzeitig über ein gewisses Verständnis der „Geschäftslogik“ und weiß, dass es sich dabei um inaktive Benutzer handelt "isArchived"
等于 false
. Außerdem weiß diese Repository-Methode, wie viele Tage wir verwenden müssen.
Welche Option sollte in dieser Situation gewählt werden? Oder gibt es vielleicht andere Möglichkeiten, dieses Ding zu bauen?
分离此问题的正确方法是存储库仅了解存储库中的数据元素。这并不意味着您的存储库中不能有多个入口点,可能有许多不同的查询都访问相同的“表”。
这并不意味着您需要像第一种方法那样的完整 QBE,请保持简单。有一个封装数据库层位的查询,但仍然要求它需要的东西。
在这种情况下,您应该有一个传递 isArchived 和 lastVisitedDate 参数的签名。类似 QueryUsersByStatusAndLastVisited 之类的东西。这样,存储库可以处理与检索数据有关的所有位,但没有关于为什么检索它们的逻辑。它将是“哑巴”的,所有智能位都封装在服务层。