正交变量代码重复问题
我最近开始重构一些遗留代码,遇到了两个用于绘制坐标网格的函数,问题是这些函数仅在它们处理的正交变量上有所不同,就像这样
void DrawScaleX(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int x = x0; x < x1; x += step)
{
MoveToEx(dc, x, y0, NULL);
LineTo(dc, x, y1);
}
}
void DrawScaleY(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int y = y0; y < y1; y += step)
{
MoveToEx(dc, x0, y, NULL);
LineTo(dc, x1, y);
}
}
所以如果我决定添加一些奇特的东西,比如抗锯齿或只需更换绘图铅笔或其他任何东西,我就必须在它们中放入相同的代码,这是代码重复,我们都知道为什么,这很糟糕。
我的问题是如何将这两个函数重写为一个函数以避免这个问题?
I've started refactoring some legacy code recently and came across two functions for drawing a coordinate grid, the problem is that these functions differ only in orthogonal variables they treat, something like that
void DrawScaleX(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int x = x0; x < x1; x += step)
{
MoveToEx(dc, x, y0, NULL);
LineTo(dc, x, y1);
}
}
void DrawScaleY(HDC dc, int step, int x0, int x1, int y0, int y1)
{
for(int y = y0; y < y1; y += step)
{
MoveToEx(dc, x0, y, NULL);
LineTo(dc, x1, y);
}
}
So if I decide to add some fancy stuff, like antialiasing or merely change drawing pencil or whatever I'll have to put the same code in both of them and it's code duplication and it's bad we all know why.
My question is how would you rewrite these two functions into a single one to avoid this problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
好吧,一个明显的“解决方案”是创建一个函数并添加一个额外的参数(类似枚举类型)。 然后在里面执行 if() 或 switch() ,并执行相应的操作。 因为嘿,函数的功能是不同的,所以你必须在某个地方执行这些不同的操作。
然而,这增加了运行时的复杂性(在运行时检查事物),而在编译时可以更好地检查。
我不明白将来在两个(或更多函数)中添加额外参数有什么问题。 它是这样的:
如果是 C++,当然你可以让函数成为一个模板,而不是添加一个额外的参数,而是添加一个模板参数,然后专门化模板实现来完成不同的事情。 但在我看来,这只是混淆了这一点。 代码变得更难理解,并且使用更多参数扩展它的过程仍然完全相同相同:
你什么也没赢得,反而让代码变得更难理解。 在我看来,这不是一个有价值的目标。
Well, an obvious "solution" would be to make a single function and add one extra parameter (of enum-like type). And then do an if() or switch() inside, and perform the appropriate actions. Because hey, the functionality of the functions is different, so you have to do those different actions somewhere.
However, this adds runtime complexity (check things at runtime) in a place that could be just better checked at compile time.
I don't understand what's the problem in adding extra parameters in the future in both (or more functions). It goes like this:
If it's C++, of course you could make the function be a template, and instead adding an extra parameter, you add a template parameter, and then specialize template implementations to do different things. But this is just obfuscating the point, in my opinion. Code becomes harder to understand, and the process of extending it with more parameters is still exactly the same:
So you've won nothing, but made code harder to understand. Not a worthy goal, IMO.
我想我会移动:
到他们自己的函数 DrawLine(x0,y0,x0,y0) 中,您可以从每个现有函数中调用它。
那么有没有一个地方可以添加额外的绘图效果呢?
I think I'd move:
into their own function DrawLine(x0,y0,x0,y0), which you can call from each of the existing functions.
Then there's one place to add extra drawing effects?
一些模板...:)
A little templates... :)
为什么不将 for 循环的主体提取到单独的函数中? 然后你可以在提取的函数中做一些有趣的事情。
Why you just do not extract the body of the for cycle into a separate function? Then you can do the funny stuff in the extracted function.
绘制一条线只是连接两个点,并在特定方向上通过 X 和/或通过 Y 绘制递增的 (x0,y0) 和 (x1,y1) 缩放。
这归结为,在比例情况下,发生哪个方向的步进(也许两个方向都是有趣的)。
模板将完成其工作:在编译时,编译器将删除所有空语句,即有关调用哪个函数的 deltaX 或 deltaY 为 0,并且每个函子中的一半代码消失。
您可以在这个 uniq 函数中添加抗锯齿、铅笔等内容,并让编译器正确生成代码。
这是在类固醇上剪切和粘贴的;-)
-- ppi
Drawing a line is simply joining two points, and drawing a scaling incrementing (x0,y0) and(x1,y1) in a particular direction, through X, and/or through Y.
This boils down to, in the scale case, which direction(s) stepping occurs (maybe both directions for fun).
The template will do its job: at compile time the compiler will remove all the null statements i.e. deltaX or deltaY is 0 regarding which function is called and half of the code goes away in each functor.
You can add you anti-alias, pencil stuff inside this uniq function and get the code properly generated generated by the compiler.
This is cut and paste on steroids ;-)
-- ppi
这是我自己的解决方案
,但在我看来,对于这样一个小问题来说太复杂了,所以我仍然期待看到您的解决方案。
Here is my own solution
But I it seems to me too complicated for such a tiny problem, so I'm looking forward to still see your solutions.