【问题标题】:Generalizing these lines of code?概括这些代码行?
【发布时间】:2015-03-09 02:13:59
【问题描述】:

在编程时,我遇到了一些代码。它看起来像这样:

这就是问题所在。我拍了一张漂亮的截图来减少我的内疚。漂亮的颜色并不能弥补可维护性的不足。我几乎不知道如何概括这样的代码。

我尝试了什么?

好吧,考虑第三个和第六个参数的周期性。它也与其他论点的周期性一致。如果我们使用数组,这样的事情将允许我们将此代码转换为一个有 9 行的循环。这是一个进步,因为我们下降了 66%。然而,这还不够好。最好将其更改为 1 行。这至少会使它更易于维护。

这真的是个问题吗?

好吧,让我们这样说吧。上面的代码也可能是错误的。

【问题讨论】:

  • 等到你开始实施密码学 :) 这些东西的页面。
  • 您已经发现将其简化为一行将是复杂且不明显的。这样做极不可能是值得的,或者会导致“可维护”的代码。我建议坚持九行。
  • 有了给定的代码,我可能会同意@LightnessRacesinOrbit 的观点。但是,我宁愿永远不要那样写(除非生成)。至少在分析和反转这些组合背后的逻辑之后,我总是觉得有义务确保未来的读者不必再这样做,或者检查它的正确性。当然,您可以在单元测试中粘贴“复杂”生成器来验证表格。

标签: c++ c++11 c++14 redundancy


【解决方案1】:

嗯,分析模式需要一些时间。

当然,我首先使用http://www.onlineocr.net/ 来从屏幕截图中获取文本。然后我开始匹配突出显示以发现模式。

  • 您可以看到make_cube 有效地占用了两个(x,y,z) 元组
  • 三个组或行以相同的z 值结尾
  • 这三个组由三个以相同 (y,z) 元组结尾的子组组成
  • x、y 和 z 值为每个组枚举相同的值对。

这使它成为生成循环的“明显”材料。经过大约 20 分钟的重构后,我终于到了

for (auto&& zs : { tie(rmin_z, imin_z), tie(imin_z, imax_z), tie(imax_z, rmax_z) })
    for (auto&& ys : { tie(rmin_y, imin_y), tie(imin_y, imax_y), tie(imax_y, rmax_y) })
        for (auto&& xs : { tie(rmin_x, imin_x), tie(imin_x, imax_x), tie(imax_x, rmax_x) })
{
    *out++ = make_cube(get<0>(xs), get<0>(ys), get<0>(zs), get<1>(xs), get<1>(ys), get<1>(zs));
}

但您会注意到循环范围的规律性。实际上我们有一个类似的序列

coord const sequence[] = { rmin, imin, imax, rmax };

我们选择连续的对:(rmin, imin), (imin, imax), (imax, rmax)

// we take all consecutive pairs (warning: ignoring the `(rmax, rmin)` closing pair here)
vector<pair<coord, coord>> pairs;
transform(begin(sequence), prev(end(sequence)), back_inserter(pairs), [](coord const& it) { return std::make_pair(*(&it+0), *(&it+1)); });

现在我们可以更直接地循环它。我还发明了一个简单的Cube 类型,它允许我们漂亮地打印生成器循环的结果,以便您可以在DEBUG 模式下验证结果:

for (auto zs : pairs) for (auto ys : pairs) for (auto xs : pairs)
    *out++ = Cube { { xs.first.x, ys.first.y, zs.first.z }, { xs.second.x, ys.second.y, zs.second.z } }; 

Live On Coliru

#include <iostream>
#include <algorithm>
#include <vector>
#include <array>

int main() {
#ifdef NDEBUG
    typedef double T;
    struct coord { T x,y,z; };

    coord rmin { 0,  1,  2 },
          imin { 3,  4,  5 },
          imax { 6,  7,  8 },
          rmax { 9, 10, 11 };
#else
    typedef const char* T;
    struct coord { T x,y,z; };

    coord rmin { "rmin_x", "rmin_y", "rmin_z" },
          imin { "imin_x", "imin_y", "imin_z" },
          imax { "imax_x", "imax_y", "imax_z" },
          rmax { "rmax_x", "rmax_y", "rmax_z" };
#endif
    using namespace std;

    // the source sequence
    coord const sequence[] = { rmin, imin, imax, rmax };

    // we take all consecutive pairs (warning: ignoring the `(rmax, rmin)` closing pair here)
    vector<pair<coord, coord>> pairs;
    transform(begin(sequence), prev(end(sequence)), back_inserter(pairs), [](coord const& it) { return std::make_pair(*(&it+0), *(&it+1)); });

    // Now we build cubes. The `make_cube` interface implied it requires two
    // coordinates to be constructed:
    struct Cube { coord p1, p2; };
    std::array<Cube, 3*3*3> cubes;

    // generate!
    auto out = cubes.begin();
    for (auto zs : pairs) for (auto ys : pairs) for (auto xs : pairs)
        *out++ = Cube { { xs.first.x, ys.first.y, zs.first.z }, { xs.second.x, ys.second.y, zs.second.z } }; 

    // debug print
    for(auto const& c : cubes)
        std::cout << "make_cube(" << c.p1.x << ", " << c.p1.y << ", " << c.p1.z << ", " << c.p2.x << ", " << c.p2.y << ", " << c.p2.z << ")\n";
}

结论:

  1. 我的代码看起来更复杂。它可能是。但是查看是否有错别字要容易得多
  2. 关于问题

    这真的有问题吗?

    好吧,让我们这样说吧。上面的代码也可能是错误的

    确实,我有点怀疑您是否涵盖了所有案件。见第一条评论:

    // we take all consecutive pairs (warning: ignoring the `(rmax, rmin)` closing pair here)
    

【讨论】:

  • 十分钟重构?该问题仅在三分钟前发布!
  • @LightnessRacesinOrbit 你从晚上 7 点起就没有去过休息室
  • @sehe 我爱你 sehe!谢谢;_;
  • @LightnessRacesinOrbit 只是计算出实际上是19 minutes,不包括OCR the image 的时间。而且我花了很多时间gold plating it(redacting this answer 的时间。所以,需要最后一次修订:)
猜你喜欢
  • 2014-07-20
  • 2020-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-15
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
相关资源
最近更新 更多