我应该选择代码重复还是与 api 服务整合 - JS

GHO*_*-34 4 javascript architecture api redundancy design-patterns

我正在开发一个大型 CMS 系统,其中特定模块及其子模块利用相同的后端 API。除了“文档类型”之外,每个子模块的端点完全相同。

所以遵循这样的模式:

api/path/v1/{文档类型}

api/path/v1/{document-type}/{id}

api/path/v1/{document-type}/{id}/versions

随着时间的推移,使用这个 API 的模块数量不断增加,我留下了许多实现 7 CRUD 方法的冗余 api 服务:

getAllXs() {...}
getX(id) {...}
getXVersion(id, versionId) {...}

etc...
Run Code Online (Sandbox Code Playgroud)

使用看起来像这样的单个方法

getAllXs() {
    let endpoint = BASE.URL + ENDPOINTS.X;
    let config = ...
    return http.get(endpoint, config)
        .then(response => response.data);
        .catch(...);

}
Run Code Online (Sandbox Code Playgroud)

其中 X 将是特定文档类型的名称。

我决定做一个单一的服务并做这样的事情:

const BASE_URL = window.config.baseUrl + Const.API_ENDPOINT;
const ENDPOINTS = {
  "W": "/v1/W/",
  "X": "/v1/X/",
  "Y": "/v1/Y/",
  "Z": "/v1/Z/",
}

getAllDocuments(docType, config={}) {
  let endpoint = BASE_URL + ENDPOINTS[docType];
  return http.get(endpoint, config)
        .then(response => response.data);
        .catch(...);
}
...other methods
Run Code Online (Sandbox Code Playgroud)

其中指定了类型并使用映射端点来构建路径。

这将所有文档 api 服务减少到一个。现在这是更简洁的代码,但显然现在需要一个额外的参数并且术语更通用:

getAllXs() --> getAllDocuments()

它有点不那么“防白痴”。让我对当前编写方式感到不安全的是,有 6 个模块使用此 API,并且每个服务中有 7 个相同的方法。

我不断问自己的问题是:

  • 我是否与动态函数接近反模式?

  • 如果我有 10 个以上的模块使用相同的 API 会怎样?

Kad*_*Kad 6

你的问题让我想到了一个常见的对象关系映射设计问题。

在设计方面没有单一的事实来源,但是如果您在您正在构建的内容中认识到 ORM 并重视面向对象的设计原则,那么我会给您一些启发。

这是我在许多项目中使用的我自己的 vanilla ES6 ORM 的过度简化(重用您的代码片段以获得相关性)。这个设计的灵感来自我在其他语言中使用过的重型 ORM 框架。

class ORM {
   constructor() {
      this.BASEURL = window.config.baseUrl + Const.API_ENDPOINT
      this.config = {foo:bar} // default config
   }

   getAll() {
      let endpoint = this.BASEURL + this.ENDPOINT
      return http.get(endpoint, this.config)
       .then(response => response.data)
       .catch(...)
   }

   get(id) {
      // ...
   }
}
Run Code Online (Sandbox Code Playgroud)

以及该类的扩展示例(注意具有特殊配置的那个)

class XDocuments extends ORM {
   static endpoint = '/XDocument/'

   constuctor() {
      super()
   }

   otherMethod() {
      return 123
   }
}

class YDocuments extends ORM {
   static endpoint = '/YDocument/'

   constuctor() {
      super()
   }

   getAll() {
      this.config = {foo:not_bar}
      super.getAll()
   }
}
Run Code Online (Sandbox Code Playgroud)

因为您特别询问这是否与反模式接壤。我建议阅读SOLIDDRY原则,以及一般的ORM设计。您还会发现有关全局常量的代码异味,但只有在窗口上下文中才会如此。我看到您已经在努力避免代码重复气味散弹枪手术气味的正确道路上。:-)

祝你好运,不要犹豫,提出进一步的问题,并在评论中添加更多的细节!

  • 请参阅我在 @tcanusso 答案上留下的评论。是的,这确实让我相信我正朝着正确的方向前进。我对反模式的担忧是使用单个动态 api 服务而不是可扩展的基础,但我现在意识到这将是多么脆弱。 (2认同)