显式API方法与基于参数的通用API方法

时间:2009-01-28 05:28:48

标签: api usability

在定义客户可访问的API时,以下内容之间的首选行业惯例是什么:

a)定义一组显式 API方法,每种方法都有非常狭隘和特定的用途,例如:

SetUserName    <name>
SetUserAge     <age>
SetUserAddress <address>

b)定义一组更多通用基于参数的API方法,例如:

SetUserAttribute <attribute>

enum attribute {
    name,
    age,
    address
}

我的观点:

支持(a)

对于基于布尔的方法(例如EnableFoo),我会明确支持选项(a),因为意图更清晰,将来不太可能需要扩展,并且它使代码更具可读性。

例如,一个名为EnableDisableFoo的方法,它接受一个指示是启用还是禁用的布尔参数,不是很清楚,也不具备凝聚力。

这是有多个选项,问题变得更加复杂。

赞成(b)

选项(b)是在API中提供可扩展性的好方法,但是以可用性为代价。使用选项(a),API方法名称本身提供了足够的信息来指示它正在做什么。使用选项(b),用户必须查找方法名称和要使用的相应枚举/参数。从理论上讲,这使得选项(b)从可用性的角度来看更糟糕 - 但是使用更少的方法是件好事,所以即使这样也不完全正确。

其他想法

有必要在可用性和可扩展性之间取得良好的平衡,并且它们经常相互矛盾。但我想有一种更客观的方法来分析它,而不是依赖于API设计者的意见。

有没有人对此有任何想法?

3 个答案:

答案 0 :(得分:2)

我个人认为(a),因为我们的目标是使“静态”代码尽可能准确和可靠。

通过使用通用形式,我们引入了运行时错误的风险。例如,我可以设置age类型的属性,其值实际上是一个字符串等。

这与定义和使用枚举或显式类型的参数非常相似,而不是在旧C风格中使用和返回int,因为您可以获得更多级别的保证。

虽然我同意(b)允许可扩展性,但我没有看到太多的API需要这种可扩展性来完全不同类型的属性。 (b)的唯一常见用法是多态代码,其中函数可以在技术上接受任何东西,包括扩展。

答案 1 :(得分:1)

另一个考虑因素是您是否要设置所有属性,并同时设置它们。例如,当您想要向打印机发送内容时,可能会设置许多参数(横向或纵向;副本数;页面大小;分辨率等)。您可以定义单个函数,而不是定义需要调用数十次的API,该函数将struct作为参数,struct包含数十个字段,调用者初始化的位置struct闲暇时,然后在单个函数调用中将struct传递给API。

答案 2 :(得分:0)

我认为这取决于你所编写的代码。如果你正在写关于总是在一起的东西(即,如果你要使用/改变年龄总是带名字),那么去b,否则一个没问题。

但是不要试图过度做(a),因为那时你只会写更多的线并且做得更少。如果您为所编写的代码量付了代价,那就太好了:)