【问题标题】:JS Design Patterns - Interface to perform different tasksJS 设计模式 - 执行不同任务的接口
【发布时间】:2021-11-08 23:46:49
【问题描述】:

我的应用中有不同的方法来获取用户:

1. Fetch international users
2. Fetch users from same region
3. Fetch users from same city

目前,我已经为每个实现了 1 种方法:

 const fetchIntenationalUsers = async (limit = 10) => {
   const result = await db.collection("users").limit(limit).get();
   ...
   return parseUsers(result);
 }

 const fetchSameRegionUsers = async (region, limit = 10) => {
   const result = await db.collection("users").where("region", "==", region).limit(limit).get();
   ...
   return parseUsers(result);
 }

 const fetchSameCityUsers = async (city, limit = 10) => {
   const result = await db.collection("users").where("city", "==", city).limit(limit).get();
   ...
   return parseUsers(result);
 }

我曾想过创建一个通用方法,例如:

const fetchUsers = (queryType = "international", location = {}, limit = 10) => {
   const queries = {
      "international": db.collection("users"),
      "region": db.collection("users").where("region", "==", location.region),
      "city": db.collection("users").where("city", "==", location.city),
   };

   const result = await queries[queryType].limit(limit).get();

   ...

   return parseUsers(result);
} 

但我不确定这是反模式还是设计模式。还有其他方法吗?

【问题讨论】:

    标签: javascript design-patterns ecmascript-6


    【解决方案1】:

    是的,我认为将它们放在一个单一的“通用”方法中并引入 queryType 枚举是一种反模式。将来您将获得越来越多的查询类型,这将在god method 中造成巨大的混乱。 (此外,它具有@CertainPerformance 的答案中提到的缺点)。

    相反,我建议保留单独的函数(可以单独调用),但将代码的重复部分抽象为一个抽象辅助函数:

    async function fetchUsers(addCondition, limit = 10) {
      const query = addCondition(db.collection("users")).limit(limit);
      const result = await query.get();
      …
      return parseUsers(result);
    }
    
    export const fetchInternationalUsers = (limit) => 
      fetchUsers(q => q, limit);
    
    export const fetchSameRegionUsers = (region, limit) =>
      fetchUsers(q => q.where("region", "==", region), limit);
    
    export const fetchSameCityUsers = async (city, limit) =>
      fetchUsers(q => q.where("city", "==", city), limit);
    

    【讨论】:

      【解决方案2】:

      总体思路在我看来不错,但有一个问题:使用这一行:

      const queries = {
        "international": db.collection("users"),
        "region": db.collection("users").where("region", "==", location.region),
        "city": db.collection("users").where("city", "==", location.city),
      };
      

      您在创建对象时调用了所有这些数据库方法,而不仅仅是您需要的那个。 (您也没有处理未使用的方法可能引发的错误。)

      稍作调整,请考虑返回查询的函数。你也可以提前db.collection('users')

      const users = db.collection("users");
      const queries = {
         international: () => users,
         region: () => users.where("region", "==", location.region),
         city: () => users.where("city", "==", location.city),
      };
      const result = await queries[queryType]().limit(limit).get();
      

      【讨论】:

      • "您正在调用所有这些数据库方法" - 这很好,因为这些方法只生成查询。只有在调用 .get() 时才会执行查询。当然,它的效率并不高,尤其是如果location.… 不可用,查询构建可能会失败。
      猜你喜欢
      • 2019-10-02
      • 2011-05-12
      • 2021-09-23
      • 2016-03-29
      • 2016-01-15
      • 1970-01-01
      • 2013-01-17
      • 1970-01-01
      相关资源
      最近更新 更多