返回介绍

例子:与复杂的逻辑战斗

发布于 2024-08-18 11:54:29 字数 1858 浏览 0 评论 0 收藏 0

假设你在实现下面这个Range类:

下图给出一些范围的例子:

请注意终点是非包含的。因此A、B和C互相之间不会有重复,但是D与所有其他重复。

下面是对OverlapsWith()实现的一个尝试——它检查是否自身范围的任意一个端点在other的范围之内:

尽管只有两行代码,但是里面包含很多东西。下图给出其中所有的逻辑。

这里面有太多的情况和条件要去考虑,这很容易滋生bug。

说到这儿,这里还真有一个bug。前面的代码会认为Range[0,2)与Range[2,4)重复,而实际上它们并不重复。

这里的问题是在比较begin/end值时要小心地使用<=或<。下面是对这个问题的修正:

现在已经改正了,是吗?实际上,还有另一个bug。这段代码忽略了begin/end完全包含other的情况。

下面是处理这种情况的修改:

现在代码变得太复杂了。你不可能指望别人看了这段代码就对它的正确性有信心。那么我们该怎么办?怎么拆分这个大的表达式呢?

找到更优雅的方式

这就是那种你该停下来从整体上考虑不同方式的时机之一。开始还很简单的问题(检查两个范围是否重叠)变得非常令人费解。这通常预示着肯定有一种更简单的方法。

但是找到更优雅的方式需要创造力。那么怎么做呢?一种技术是看看能否从“反方向”解决问题。根据你所处的不同情形,这可能意味着反向遍历数组,或者往回填充数据结构而非向前。

在这里,Overlap sWith()的反方向是“不重叠”。判断两个范围是否不重叠原来更简单,因为只有两种可能:

1.另一个范围在这个范围开始前结束。

2.另一个范围在这个范围结束后开始。

我们可以很容易地把它变成代码:

这里的每一行代码都要简单得多——每行只有一个比较。这就使得读者留有足够的心力来关注<=是否正确。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文