首頁  >  問答  >  主體

避免在儲存庫層中包含領域邏輯

在我目前的應用程式中,我需要建立一個api GET 路由“/inactive-users”,它應該會傳回已存檔的使用者(“isArchived”),並且同時處於非活動狀態超過一個月("lastVisitedDate" 欄位應早於new Date() - 1 個月)。

採用分層架構(控制器/服務/儲存庫),領域模型貧乏,這種情況下我該怎麼辦?

我看到有兩種可能的方法。

1 - 建立通用儲存庫方法來取得使用者並將我們需要的使用者欄位傳遞給它。

@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 - 準確地建立儲存庫方法來檢索不活動的用戶,該方法將知道它應該要求哪些欄位。

@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() 
  }
}

哪種方式比較好? 第一個對我來說看起來不錯,因為在這種情況下,儲存庫對「非活動」用戶的網域理解一無所知。但同時 - 建立這樣一個響應式方法可能相當困難。

第二種方式更容易構建,但同時 - 它具有一些“業務”邏輯理解,並且知道不活動用戶是那些 "isArchived" 等於 false 的用戶。而且,這個儲存庫方法知道我們需要使用的天數。

在這種情況下應該選擇哪個選項?或者也許還有其他方法來建造這個東西?

P粉151720173P粉151720173181 天前430

全部回覆(1)我來回復

  • P粉118698740

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

    分離此問題的正確方法是儲存庫僅了解儲存庫中的資料元素。這並不意味著您的儲存庫中不能有多個入口點,可能有許多不同的查詢存取相同的「表」。

    這並不意味著您需要像第一種方法那樣的完整 QBE,請保持簡單。有一個封裝資料庫層位的查詢,但仍然要求它需要的東西。

    在這種情況下,您應該有一個傳遞 isArchived 和 lastVisitedDate 參數的簽章。類似 QueryUsersByStatusAndLastVisited 之類的東西。這樣,儲存庫可以處理與檢索資料相關的所有位,但沒有關於為什麼檢索它們的邏輯。它將是「啞巴」的,所有智慧位都封裝在服務層。

    回覆
    0
  • 取消回覆