【问题标题】:How can I simplify or improve readability in complex logic statements?如何简化或提高复杂逻辑语句的可读性?
【发布时间】:2016-04-16 22:51:58
【问题描述】:

所以我有一个逻辑陈述的怪物:

(((ncode[i]+key[ikey])>90 && (ncode[i]+key[ikey])<97) || (ncode[i] + key[ikey])>122)

总是有人告诉我,如果你有需要换行的逻辑语句,你可能做错了什么。我知道我可以将它重构为一种新方法,但对于我正在从事的工作来说这样做并不一定有意义。我该怎么做才能使其更具可读性?

【问题讨论】:

  • 对谁可读?你?我?教皇?一条线,两条线,三条线,无聊?你喜欢 80 列,我喜欢 100 列。你喜欢很短的名字我喜欢描述性的名字。你喜欢乳蛋饼,我会拿走自动售货机里的任何东西。
  • 总是像维护者是一个知道你住在哪里的精神病患者一样编写代码:-P

标签: c++ logic readability


【解决方案1】:

我只是使用一个临时变量来清理:

auto code = ncode[i] + key[ikey];
if ( (code > 90 && code < 97) || (code > 122) )

无论如何,大多数编译器都会优化临时离开。

【讨论】:

  • 是的,现在您刚刚污染了范围和不必要的变量。这与其他良好做法相矛盾。这是好事还是坏事?有关系吗?为什么不把阿甘正传和我们 ea for 声明。 (for(auto code = 1; code &gt; 90 &amp;&amp; code &lt; 97 || code &gt; 122;) {}
  • 为什么不{ ...code... } ?如果它使代码更具可读性/可维护性,我不认为创建不必要的变量是一件坏事。污染可以用{ } 块来处理,如果你不制作非常大的功能,它无论如何都不会很重要,因为它是本地的。为了性能 - 大多数编译器无论如何都会对其进行优化,如果它确实重要,则将重点放在占用 90% 执行时间的程序的 10% 上,但保持其余部分的可读性。
  • 我只是指出问题并提出问题。如果您要一直添加局部变量,请使用 Lamba 将您的表达式减少到 if(ConditionMet(code)) [}。但前提是您真的在寻找可读性。
  • 在我的代码编写完成、正常工作并准备好进行分析之前,我不会考虑不考虑性能方面的两个问题。为什么你还提到它
  • 因为我也只是想指出并回答。不用担心。
【解决方案2】:

假设ncodekey 中的值都是整数(或浮点数),你能不将它们的总和值分配给一个新变量吗?把线变成:

int result = ncode[i] + key[iKey];
if( (result > 90 && result < 97) || result > 122)
    //Logic

它变成了两行,但在我看来确实增加了可读性。

【讨论】:

    【解决方案3】:

    为了性能和可读性,我会使用一个 const temp 变量来替换三个重复的 (ncode[i]+key[ikey])。不要重复自己。

    const auto temp = ncode[i] + key[ikey];
    if ( ((90<temp) && (temp<97)) || (122<temp) )
    

    此外,在这种情况下仅使用 &lt;。因此,前两个比较变成“温度在 90 和 97 之间。想象画一条线,线上分别是 90、97 和 122,即与这三个点相关的线上的“良好”温度范围。

    【讨论】:

      【解决方案4】:
      template<class Lower>
      auto is_gt(Lower&&l){
        return [=](auto&&x){ return l<x; };
      }
      template<class Higher>
      auto is_lt(Higher&&l){
        return [=](auto&&x){ return x<l; };
      }
      template<class L, class R>
      auto also(L&& l, R&& r){
        return [=](auto&&x){return l(x)&&r(x); };
      }
      template<class L, class R>
      auto either(L&& l, R&& r){
        return [=](auto&&x){return l(x)||r(x); };
      }
      template<class Lower, class Upper>
      auto between(Lower&& l, Upper&& u){
        return also(is_gt(l), is_lt(u));
      }
      

      是一些玩具。

      然后:

      if (either(between(90,97), is_gt(122))(ncode[i]+key[ikey])) {
      

      这可以做得更流畅一些。如果我们将谓词定义为返回bool 的函数对象,它支持&amp;&amp;||~ 重载,并让我们上面的玩具返回谓词,我们得到:

      if (( between(90,97) || is_gt(122))(ncode[i]+key[ikey])) {
      

      摆脱 either 前缀噪音。

      要在非int 情况下提高效率,请通过移动捕获边界。

      template<class F>
      struct predicate_t:F{
        predicate_t(F const& f):F(f){}
        template<class F2>
        friend auto operator&&(predicate const& f1,predicate<F2> const& f2){
          auto r=[=](auto&&...args){
            return f1(args...)&&f2(args...);
          };
          return predicate_t<decltype(r)>(r);
        }
        template<class F2>
        friend auto operator||(predicate const& f1,predicate<F2> const& f2){
          auto r=[=](auto&&...args){
            return f1(args...)||f2(args...);
          };
          return predicate_t<decltype(r)>(r);
        }
      
        template<class F2>
        friend auto operator!(predicate const& f1){
          auto r=[=](auto&&...args){
            return !f1(args...);
          };
          return predicate_t<decltype(r)>(r);
        }
      };
      template<class F>
      predicate_t<std::decay_t<F>>
      predicate(F&&f){
        return std::forward<F>(f);
      }
      

      上述每个toy 函数都返回return predicate(lambda); 而不是lambda。

      此代码在使用时更简单、更简洁,运行时间开销为零,但与传统 C++ 的编码风格不同。

      【讨论】:

        猜你喜欢
        • 2019-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-24
        • 2010-12-09
        • 1970-01-01
        • 2011-09-30
        • 1970-01-01
        相关资源
        最近更新 更多