How do you follow DRY with code using x-y coords?
-
05-09-2019 - |
Question
How would you get the dreamed DRY ideal in this sample, in the language of your choice:
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));
}
Note: A multitude of ad-hoc preprocessor macros is likely to be extremely less readable&writable so that's out.
Solution
The answer is simple: vectors. E.g.
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);
OTHER TIPS
[I agree with Stewart, but I press on as an academic exercise.]
Tricky...
In a way, you're not really repeating yourself; you're doing two similar things that are (literally and figuratively) orthogonal to each other.
I suppose you could do the following, though it's no more readable and certainly no more performant:
[pseudo 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);
}
On second thoughts, I think this is just a silly idea... :-)
Maybe, in this case, you are taking DRY to too much of an extreme?
Nonetheless, as an academic exercise, I am looking forward to seeing whether anyone can come up with a solution that is as readable as your current code - but without the apparent duplication!
If your grid is square, I think the following could work:
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));
}