如何在不复制太多代码的情况下重构此代码?

Posted

技术标签:

【中文标题】如何在不复制太多代码的情况下重构此代码?【英文标题】:How to restructure this code without duplicating too much code? 【发布时间】:2021-08-18 21:14:06 【问题描述】:
class

public:
  void func(const int val, const bool flag)
  
    if(flag)
    
      while(!lower.empty() && val <= lower.top())
      
        // do a bunch of stuff with lower
      
    
    else
    
      while(!higher.empty() && val >= higher.top())
      
        // do a bunch of stuff with higher, but it's the same stuff as would've done
        // for lower
      
    
  
private:
  std::stack<int> lower;
  std::stack<int> higher;

我正在尝试找出一种更好的方法来编写子句,因为目前我在这两个子句中都有很多重复的代码。唯一的区别是一个子句在lower 上运行,另一个在higher 上运行,第一个子句中的&lt;= 在第二个子句中更改为&gt;= higher

我可以将子句包装在一个辅助函数中并在每个子句中调用它(并将lowerhigher 作为参数传入),例如,

class

public:
  void func(const int val, const bool flag)
  
    if(flag)
    
      helper(lower, comparer);
    
    else
    
      helper(lower, comparer);
    
  

  void helper(std::stack<int> &st)
  
    // do a bunch of stuff with st
  
  
private:
  std::stack<int> lower;
  std::stack<int> higher;

我不确定这是否是个好主意,如果是,我不确定如何绕过&gt;=&lt;=。希望大家对我的设计提出建议!

【问题讨论】:

提取一个获取栈的方法? @DaveNewton 你能详细说明这意味着什么吗?是不是像我在第二个sn-p中描述的辅助函数? 这应该没问题;事实上,它经常在标准库中完成。通常,您将参数设为模板参数。不确定这是否是计划,因为辅助函数目前只接受一个参数。 template&lt;typename ComparerType&gt; void Helper(std::stack&lt;int&gt;&amp; st, int val, ComparerType compare) while(!st.empty() &amp;&amp; compare(val, st.top()) ... Helper(lower, val, [](int a, int b) return a &lt;= b; ); @f*** 代替 lambdas,可以使用std::less_equalstd::greater_equal,例如:Helper(lower, val, std::less_equal); Helper(higher, val, std::greater_equal); @RemyLebeau 啊,我现在明白了。该注释中的Helper(lower, val, [](int a, int b) return a &lt;= b; ) 部分实际上是显示函数的调用方式。 【参考方案1】:

您可以执行以下操作:

class

public:
  void func(const int val, const bool flag)
  
    std::stack<int> *st;
    bool (*compare)(int, int);

    if (flag)
    
      st = &lower;
      compare = [](int a, int b) return a <= b; ;
    
    else
    
      st = &higher;
      compare = [](int a, int b) return a >= b; ;
    

    while (!st->empty() && compare(val, st->top()))
    
      // do a bunch of stuff with *st
    
  

private:
  std::stack<int> lower;
  std::stack<int> higher;

另外,使用助手当然也可以:

class

public:
  void func(const int val, const bool flag)
  
    if (flag)
      func_helper(lower, val, std::less_equal);
    else
      func_helper(higher, val, std::greater_equal);
  

private:
  std::stack<int> lower;
  std::stack<int> higher;

  template<typename Comparer>
  void func_helper(stack<int> &st, const int val, Comparer compare)
  
    while (!st.empty() && compare(val, st.top()))
    
      // do a bunch of stuff with st
    
  

【讨论】:

【参考方案2】:

这样的事情怎么样

class

public:
  void func(const int val, const bool flag)
  
    int sign = 1;
    std::stack<int>* higher_or_lower = &higher; 
    if(flag)
    
      higher_or_lower = &lower;
      sign = -1;
    

    while(!higher_or_lower->empty() && sign*val >= sign*higher_or_lower->top())
    
      // do a bunch of stuff with higher_or_lower
    
  
  
private:
  std::stack<int> lower;
  std::stack<int> higher;

higher_or_lower 涵盖两个堆栈,sign 负责处理小于与大于。

【讨论】:

这个标志的想法很有趣,但我想也许它对某人来说不太清楚?当然更短!【参考方案3】:

或者更紧凑一点:

class C

public:
    void func(const int val, const bool flag)
    
        const std::stack<int>* st[] = &lower, &higher;
        bool (*compare[])(int, int) =  [](int a, int b)  return a <= b;  ,  [](int a, int b)  return a >= b;  ;

        while (!st[flag]->empty() && compare[flag](val, st[flag]->top()))
        
            // do a bunch of stuff with *st
        
    

private:
    std::stack<int> lower;
    std::stack<int> higher;
;

【讨论】:

以上是关于如何在不复制太多代码的情况下重构此代码?的主要内容,如果未能解决你的问题,请参考以下文章

重构 PHP OOP - 如何在不传递参数的情况下获取对象?

如何在不覆盖当前内容的情况下写入文件? [复制]

如何在不重构的情况下发布两个具有相同源代码但不同包名的 android 应用程序

我的客户如何在不访问源代码的情况下上传 ios 应用程序? [复制]

我想每次添加不同的图像,我重复使用这张卡片。如何在不复制粘贴整个代码的情况下做到这一点

如何在不重新编译的情况下配置我的 C# 项目? [复制]