【问题标题】:Is this API too simple?这个 API 是不是太简单了?
【发布时间】:2010-02-23 20:56:31
【问题描述】:

有大量可用的键值对存储。目前你需要选择一个并坚持下去。我相信一个独立的开放 API,不是由键值存储供应商制作的,将使存储之间的切换变得更加容易。

因此,我正在构建一个数据存储抽象层(如 ODBC,但专注于更简单的键值存储),以便有人构建一次应用程序,并在必要时更改键值存储。这个 API 是不是太简单了?

get(Key)
set(Key, Value)
exists(Key)
delete(Key)

到目前为止,我看到的所有 API 似乎都增加了很多,我想知道需要多少额外的方法?

我收到一些回复说 set(null) 可以用来删除一个项目,如果 get 返回 null 那么这意味着一个项目不存在。这很糟糕,有两个原因。首先,混合返回类型和状态不是很好,其次,不是所有的语言都有 null 的概念。见:

Do all programming languages have a clear concept of NIL, null, or undefined?

我确实希望能够对数据执行多种类型的操作,但据我了解,一切都可以建立在键值存储之上。它是否正确?我也应该提供这些增值功能吗?例如:像 mapreduce 或索引

在内部,我们已经在 Erlang 和 Ruby 中有一个基本版本,它为我们节省了大量时间,还使我们能够测试不同键值存储的特定用例的性能

【问题讨论】:

  • 简单是件好事 :)
  • 简单明了的 API 每天都胜过复杂的大量文档。
  • 是的,太简单了。没有程序员愿意使用它,因为它不会提供任何工作保障。
  • 如果您按照我们的回答继续编辑 API,那么 API 当然永远不会太简单。 :-)
  • @Zubair:我的建议是,不要创建这个抽象层。只需使用您仔细选择的现有优质产品。根据我的经验,您在此处应用的“抽象层”通常会由于 API 不完整而令人沮丧,并且它理论上提供的“我可以轻松切换”选项实际上从未发生过,并且无论如何都会破坏事情。最重要的是,如果您真的想切换,那么只需完成并更改呼叫就不会那么难。

标签: api key-value


【解决方案1】:

只做绝对必要的事,不要问是否太简单,而要问是否太多,即使只有一种方法。

【讨论】:

    【解决方案2】:

    您的 API 缺少一些有用的功能,例如“hasKey”和“clear”。例如,您可能想查看 Python 的 hack http://docs.python.org/tutorial/datastructures.html#dictionaries,然后选择其他函数。

    每个人都在说,“简单就是好”,直到“简单太简单”之前都是如此。

    【讨论】:

    • 我将“hasKey”添加为“存在”。虽然我不确定“清除”
    • 如果对构建和销毁有良好的控制,则清除的强制性较低。
    • 构建供内部使用的 API 是 yagni 的一个很好的例子。在你需要它之​​前不要建造它。这样做将使设计尽可能简单,而不是“太简单”。
    • HasKey 的价值有限,因为除非你有某种锁定机制(我反对),否则调用的结果将在你得到它后立即过时。 SetIfNonExisting 或类似的东西可能更有意义,类似于在文件上独占创建。
    • @Zubair: 不,incr 和 decr 不能,你需要一个可以接受函数的函数,比如“DoIfKeyExistsElseSetTo(r => r + 1, 1)”——那会是原子的,但跨语言是不可能的,而且不是很简单。 ;)
    【解决方案3】:

    如果您所做的只是获取、设置和删除键,这很好。

    【讨论】:

    • 好吧,我想其他的一切都可以建立在此之上的一个层上,对吧?
    • hmmm... 取决于系统要求:如果您谈论的是大型 KV 存储,您可能不希望只针对 reset 每个键迭代一个大集合...
    • @jldupont。当你说“重置”时,你是什么意思?
    【解决方案4】:

    对于 API,没有“太简单”的说法。越简单越好!如果它按原样解决了需求,那就离开吧。

    【讨论】:

      【解决方案5】:

      delete 方法是不必要的。您可以将null 传递给set

      编辑添加:

      我只是在开玩笑!我会继续删除,并可能添加计数、包含,也许还有一个(或两个)枚举器。

      【讨论】:

      • 没错,但我认为这不是一个好主意。它使代码对读者的作用变得不那么明显。阅读 delete(a) 的人可能会理解发生了什么。但是,阅读 set(a, null) 的人可能必须查看文档以了解发生了什么。在某些情况下,存储 null 正是用户想要做的事情。
      • 我添加了“存在”,因为我不想开始将返回值与状态混合。谢谢
      • 但是根据系统的不同,这可能意味着额外的round trip 来获取数据...
      • @Laserallan - 同意。我不得不承认,我的回答真的是个笑话。我讨厌根据参数做很多不同事情的魔法函数!
      • 我不认为这个答案有资格开玩笑:) 如果没有 exists()/has_key() 删除的语义真的很难定义。考虑以下序列 1) set(a, 42);设置(一,空); b = 得到(一); 2) 集合(a, 42);删除(一); b = 得到(一)。在第一个序列之后 b 等于 null (显然)。在 b 的第二个序列值没有很好地定义之后,要么它为 null,然后您无法区分 null 值和没有键,要么引发了某种条件,它也需要包含在 API 中。
      【解决方案6】:

      在创建 API 时,您需要问自己,我的 API 为用户提供了什么。如果您的 API 过于简单,以至于您的客户可以更快、更轻松地编写自己的应用程序,那么您的 API 就失败了。问问自己,我的功能是否给他们带来了特定的好处。如果答案是否定的,那就太简单化了。

      【讨论】:

      • 对不起,我没明白你的意思。你能改写你的答案吗?谢谢
      • 返回基于“用例”IMO 列出“系统要求”。
      • 我们已经在 Erlang 和 Ruby 中有一个基本版本,它为我们节省了很多时间,还使我们能够测试不同键值存储的特定用例的性能
      【解决方案7】:

      我完全赞成将界面简化到最低限度,但没有更多关于系统要求的详细信息,很难判断这个界面是否足够。当然看起来足够简洁。

      不要忘记记录 “key non-existent” 的语义,因为阅读上面的 API 定义并不清楚。 更新:我看到你添加了exists 方法:这是必要的吗?您可以使用get 方法并定义某种NIL,不是吗?

      也许值得思考:考虑“新鲜度”的价值如何?即关联的“最后修改”时间戳?当然,这取决于您的系统要求。

      访问控制呢?是否在 API 定义范围内?

      迭代键呢?如果可能有一个大集合,您可能需要包含一些分页语义。

      【讨论】:

      • 我添加了“存在”。关于新鲜度也很有趣。这将用于最终一致的键值存储之上,但它们提供不同类型的版本控制。有些使用版本号 (Riak) 和一些时间戳 (Cassandra)
      • 关于你关于 NIL 的问题,这是一个奇怪的问题,因为我不确定是否所有语言都有 NIL 值的概念
      • 访问控制是一个“连接”字符串。例如,在 Erlang 中,它将是每个函数的第一个参数,并包含所需的任何特殊权限。
      • 迭代仍然对我将如何做到这一点持开放态度。我有很多想法,但我需要确保它们可供最终用户使用
      【解决方案8】:

      如前所述,越简单越好,但可以使用简单的迭代器或键列表方法。我总是最终需要遍历集合。一个“size()”方法,如果不被迭代器处理的话。不过,这显然取决于您的使用情况。

      【讨论】:

      • 大小是一个困难的问题,因为它通常是一项非常昂贵的操作。我正在考虑一个迭代器,但我只想添加它,如果我可以让它使用起来简单到可以自我描述
      • @Zubair - 如果一个 size 方法被认为是必要的,那么,在这样的 API 中,它总是可以进行 O(1) 操作。只需保留一个计数变量,并根据需要递增或递减。
      • 是的,保持运行计数应该可以正常工作。对于迭代器(如果需要),只需一个简单的“getKeys()”即可处理它,如果需要更多内存。
      • 大小可能会变得非常棘手。示例:对于一位客户,他们使用数据库作为后端键值存储。当数据由我们 API 外部的客户端更新时,我们会丢失这些插入/删除的计数。
      【解决方案9】:

      它不是太简单,它很漂亮。如果 "exists(key)" 只是 "get(Key) != null" 的一种方便的简写,你应该考虑删除它。我想这取决于您 get() 的值有多大或有多复杂。

      【讨论】:

      • 所有语言中都存在 null 吗?
      猜你喜欢
      • 2012-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多