【问题标题】:How do I write this function without duplicating code, following the DRY principle如何在不重复代码的情况下编写此函数,遵循 DRY 原则
【发布时间】:2021-03-11 16:23:31
【问题描述】:

我想开始改进我编写代码的方式,而不是复制它,著名的干净代码,我想开始将它应用到已经使用的小函数中。 在不复制 switch 条件 甚至 创建类 并使用 多态性 的情况下,我如何改进这段代码,因为函数是 超级相似的

/**
 * Wait for an element and type on it
 * @param {puppeteer.Page} page - Context page
 * @param {string} selector - Element selector (CSS, xpath)
 * @param {string} text - Text to be typed in the element
 * @param {string} waitType - Element type (CSS, xpath)
 */
const waitAndType = async (page, selector, text, waitType = 'selector') => {
  switch (waitType) {
    case 'selector':
      await page.waitForSelector(selector)
      break
  }
  await page.type(selector, text)
}
// ===========================================

/**
 * Wait for an element and click on it
 * @param {puppeteer.Page} page - Context page
 * @param {string} selector - Element selector (CSS, xpath)
 * @param {string} waitType - Element type (CSS, xpath)
 */
const waitAndClick = async (page, selector, waitType = 'selector') => {
  switch (waitType) {
    case 'selector':
      await page.waitForSelector(selector)
      break
    case 'xpath':
      await page.waitForXPath(selector)
      break
  }
  await page.click(selector)
}
// ===========================================

// ===========================================
module.exports = {
  waitAndType,
  waitAndClick,
}
// ===========================================

【问题讨论】:

    标签: javascript puppeteer code-cleanup


    【解决方案1】:

    您可以向您的函数传递一个额外的参数,例如actionType。根据您的需要(输入和点击),它可以有两个或更多可能的值。

    您可以按如下方式重写您的函数:

    const waitAndPerformAction = async (page, selector, waitType = 'selector', actionType) => {
      switch (waitType) {
        case 'selector':
          await page.waitForSelector(selector)
          break
        case 'xpath':
          await page.waitForXPath(selector)
          break
      }
      if(actionType === 'type') {
        await page.type(selector)
      } else if(actionType === 'click`) {
         await page.click(selector)
      }
    }
    

    您可以更进一步,在一个单独的文件(可能是一个常量文件)中定义您的 action,您可以在其中定义所有操作类型以避免整个代码库中出现任何拼写错误。

    类似:

    const ACTION_TYPES = {
      CLICK: 'click',
      TYPE: 'type',
     ....
    }
    

    然后将ACTION_TYPES.CLICKACTION_TYPES.TYPE 作为argument 传递给您的函数并修改您的waitAndPerformAction 函数。

    const waitAndPerformAction = async (page, selector, waitType = 'selector', actionType) => {
      switch (waitType) {
        case 'selector':
          await page.waitForSelector(selector)
          break
        case 'xpath':
          await page.waitForXPath(selector)
          break
      }
     await page[ACTION_TYPES[actionType]]();
    }
    

    最后,将你的函数称为:

    waitAndPerformAction(..other arguments, ACTION_TYPES.CLICK)
    

    【讨论】:

    • 很好的解决方案?。感谢罗希特的回复。你总是需要使用几个 else if 吗? SRP(单一责任原则)可以应用在这个功能中吗?
    • 请检查解决方案的第二部分,您不必if/else if。您还可以将您的 actionTypes 映射到要调用的函数。例如在您的ACTION_TYPES 中,您可以将其修改为CLICK: { name: 'click', toCall: page.click }。然后你可以做类似await ACTION_TYPES[actionType].toCall()
    • @EduardoCarvalho 请将答案标记为正确,如果对您有帮助,请点赞,可能对未来的读者有所帮助。谢谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-02
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2020-04-08
    • 1970-01-01
    相关资源
    最近更新 更多