【问题标题】:How do you follow DRY with code using x-y coords?您如何使用 x-y 坐标跟随 DRY 代码?
【发布时间】:2010-10-08 20:31:43
【问题描述】:

您将如何以您选择的语言在此示例中获得梦想中的 DRY 理想:

drawLine(Point(0, 0), Point(w, 0));
int curRowY = 0;
for(int row=0; row<rowHeights.size(); row++) {
    curRowY += rowHeights[row];
    drawLine(Point(0, curRowY), Point(w, curRowY));
}

drawLine(Point(0, 0), Point(0, h));
int curColX = 0;
for(int col=0; col<colWidths.size(); col++) {
    curColX += colWidths[col];
    drawLine(Point(curColX, 0), Point(curColX, h));
}

注意:大量的 ad-hoc 预处理器宏可能非常不太可读可写,因此已经过时了。

【问题讨论】:

    标签: dry coordinates


    【解决方案1】:

    答案很简单:向量。例如

    repeatLines(Point start, Point end, Vector direction, int[] gaps)
        {
        drawLine(start, end);
        for (int i = 0; i < gaps.Length; i++)
            {
            Vector vector = direction * gaps[i];
            start += vector;
            end += vector;
            drawLine(start, end);
            }
        }
    
    repeatLines(Point(0, 0), Point(0, w), Vector(1, 0), rowHeights);
    repeatLines(Point(0, 0), Point(h, 0), Vector(0, 1), colWidths);
    

    【讨论】:

    • 我们有一个赢家:这里的关键见解是 repeatLines 需要一个新参数来确定水平与垂直。这样做的好处是你也可以通过使用其他向量来做其他角度。
    • 其实还不错!当然对我来说是一堵墙:我一直认为这两个案例是“horz & vert”,我将其等同于“x & y”。将其视为任意角度是一个很好的解决方案。
    • ...我现在才意识到函数的优雅。它根本不是人为的,它具有通用的适用性,可以简洁地描述为“绘制一系列具有给定间隙的平行、大小相等的线段”。必须接受答案:我怀疑有人会想出更好的主意!
    【解决方案2】:

    [我同意斯图尔特的观点,但我坚持作为学术练习。]

    棘手...

    在某种程度上,你并没有真的重复自己;您正在做两件相似的事情,它们(字面上和比喻上)彼此正交。

    我想您可以执行以下操作,尽管它不再具有可读性,当然也不再具有更高的性能:

    [伪 C#]:

    void DrawGrid()
    {
        DrawLines(w, rowHeights, true);
        DrawLines(h, colWidths, false);
    }
    
    void DrawLines(int lineLength, int[] lineSeparations, bool isHorizontal)
    {
        MyDrawLine(Point(0, 0), Point(lineLength, 0), isHorizontal);
        int offset = 0;
        for (int i = 0; i < widths.length; i++)
        {
            offset  += lineSeparations[i];
            MyDrawLine(Point(offset, 0), Point(offset, lineLength), isHorizontal);
        }
    }
    
    void MyDrawLine(Point startPoint, Point endPoint, bool isHorizontal)
    {
        if (isHorizontal)
        {
            SwapXAndYCoordinates(startPoint);
            SwapXAndYCoordinates(endPoint);
        }
    
        drawLine(startPoint, endPoint);
    }
    

    再想一想,我认为这只是一个愚蠢的想法... :-)

    【讨论】:

    • 是的。这是通常看到的 DRY 的直接应用,但显然没有改进原始代码。我仍然很好奇为什么这种(​​和类似的)情况似乎不像大多数人那样从 DRY 中受益。
    【解决方案3】:

    也许,在这种情况下,您将 DRY 太过分了?

    尽管如此,作为一项学术练习,我期待看到是否有人能提出与您当前代码一样可读的解决方案 - 但没有明显的重复!

    【讨论】:

      【解决方案4】:

      如果您的网格是方形的,我认为以下方法可行:

      void drawGrid()
      {
          for(int i = 1, offset = 10; i <= numPoints; i++, offset += 10)
          {
              Point p = new Point(i * offset, i * offset);
      
              drawHorizontal(p);
              drawVertical(p);
          }
      }
      
      void drawHorizontal(Point p)
      {
          drawLine(new Point(0, p.y), new Point(width, p.y));
      }
      
      void drawVertical(Point p)
      {
          drawLine(new Point(p.x, 0), new Point(p.x, height));
      }
      

      【讨论】:

      • 是的,如果每个单元格都是方形的并且整个网格都是方形的。但它不是;]
      猜你喜欢
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 2022-12-10
      • 2012-07-22
      • 1970-01-01
      • 1970-01-01
      • 2013-06-27
      相关资源
      最近更新 更多