(开始、结束)与(开始、长度)

问题描述 投票:0回答:4

我已经看到在指定一系列索引时使用了两种替代约定,例如

subString(int startIndex, int length);

subString(int startIndex, int endIndex);

就您可以使用它们执行的操作而言,它们显然是等效的,唯一的区别在于您是否指定结束索引或范围的长度。

我假设在所有情况下

startIndex
都是包容性的,并且
endIndex
都是排他性的。

在定义 API 时,是否有任何令人信服的理由选择其中一种而不是另一种?

language-agnostic api-design
4个回答
7
投票

我更喜欢

length
,因为它让我少了一个需要在文档中询问/查找的问题。

对于基于

endIndex
的终点 - 这是包容性终点还是排他性终点?

(对于任一变体,都可以针对 startIndex 提出相同的问题

,但这将是一个反常的 API,使其具有排他性)。


3
投票

如何消除位置参数的歧义...

  1. 使用更长的名称 subStringFromUpto( startIndex , stopIndex )

  2. 在整个库中使用统一的约定

这么多年我们没有找到更好的吗?

啊,是的,也许在 Smalltalk 中,因为这个问题被标记为与语言无关......

aString copyFrom: startIndex to: stopIndex.
aString substringOfLength: length startingAt: startIndex.

减少歧义,但也许我们还得再等 30 年才能更广泛地采用这种风格
(它可能看起来太简单而难以严肃)


2
投票

这是一个很好的问题,我认为使用哪个的偏好取决于最常见的用例。大多数用例使用任一 API 都同样简单,但请考虑这个:

您想要获取从 5 开始到字符串末尾结束的子字符串。使用基于索引的版本(假设它的第二个索引是独占的),它很简单:

str.subString(5, str.length());

使用基于长度的 API:

str.subString(5, str.length() - 5);

第二种方法不太简洁和明显。然而,这可以通过简单地说明如果长度会导致剩余字符串溢出来解决,它将优雅地支持这一点(例如

str.subString(5, str.length());
会抓取从索引 5 到末尾的所有内容,即使它可能会要求更多字符比剩下的)。除了支持负索引等高级功能之外,Ruby 还使用其 String#splice 方法来实现此目的。

在我看来,基于指数的方法更具体,尤其是在不允许使用负指数的情况下。这使得 API 的期望变得非常明显,这可能是一件好事;让你更难搬起石头砸自己的脚。然而,像 Ruby 这样记录良好的 API 可以轻松地为程序员提供支持,并且可以进行一些优雅的子字符串处理。

我还发现,一般来说,当我执行子字符串操作时,我通常知道我的起点和终点。使用基于长度的方法,在调用 API 时需要进行额外的计算(例如

substring(startIndex, endIndex - startIndex)
)。


1
投票

有人应该对典型的调用站点进行研究,以找出哪种方法会产生更简洁的代码(因此可能是正确的代码)。

我喜欢使用“长度”的论点,您不必查看文档,但您可能已经在查看文档来确定第二个整数是“结束”还是“长度”。如果您将其命名为 endExclusive,那么它就像自记录一样。

© www.soinside.com 2019 - 2024. All rights reserved.