ANSI C - 创建良好API接口的技巧

时间:2012-08-30 21:49:55

标签: c api ansi

我正在尝试创建一个易于正确使用且难以正确使用的API。

想象一下,您有一个函数"bool MyObject_SetLocalDateTime(MyObject *pMyObject, params...)",允许客户以YYYY MM DD HH MM SS格式设置日期和时间:

MyObject *pMyObject = MyObject_Create();
...
MyObject_SetLocalDateTime(pMyObject, params...);
...
MyObject_Destroy(&pMyObject);

该功能的优秀界面是什么?我很感激有关如何使接口易于正确使用且难以在ANSI C(而非C ++中)中使用不正确的任何提示。

4 个答案:

答案 0 :(得分:2)

我首先要说的是“正确”是什么。认真。

您希望输入最准确吗?你想要功能不失败吗?你想限制可以输入的值吗?您可能想要考虑您正在创建的内容的要求。

如果调用此函数,数据的格式是什么?它可能只是在用户输入的“YYYY MM DD HH MM SS”的字符串中,那么也许最好采用一个字符串并自己解析这些值。当然,这在你的功能中还有很多工作要做。

此外,如果您正在为自己编写函数,则可以对输入值和测试更加宽容,因为您可能知道预期的内容。如果您要为操作系统创建一个函数,这个函数将有成千上万的人使用这些API,那么您需要更清楚地了解允许的内容并在函数内对它们进行测试。

根据您的情况最“正确”,有很多方法可以指定您引用的简单函数。

bool MyObject_SetLocalDateTime(pMyObject,int YYYY,unsigned int MM,unsigned int DD,int HH,int MM,int SS); //返回值表示成功或失败。

但是,如果消费者为MM传递零,该怎么办?如果消费者通过13?你是使用base-0(通常是C使用的)还是常规的1-12来表示月份(jan-dec)的数字,这从人类月份的角度来看更有意义,但是有点奇怪C程序员的想法?

对于像日期和时间这样的东西,C库有这个定义,这将使你更容易。另外,因为C库已经这样做了,对于使用你的功能的其他用户来说似乎更自然。

您还需要通过“难以正确使用”来定义您的意思。我再一次认真。也许你想要创建一个月(和几天)的枚举,并传递它而不是int。这将为API提供额外的类型检查,但是聪明的API使用者可能会遇到另一个值,因此不要认为您可以跳过测试有效输入。

在你的函数中,你需要验证输入值,无论它们传入什么形式,以确保它们有效,检查你不允许2月30日,并且你允许29对于feb,但每四年一次。日期和时间有很多隐藏的复杂性,这使得依赖已经在OS或运行时库中开发的例程变得明智。

答案 1 :(得分:1)

为什么不简单地使用time_t和/或struct tm

像下面这样的东西会很好:

time_t my_local_time ;

MyObject_SetLocalDateTime(pMyObject, my_local_time ) ;

struct tm my_local_time ;

MyObject_SetLocalDateTime(pMyObject, my_local_time ) ;

答案 2 :(得分:0)

您可以在名称中提供一个提示:MyObject_SetLocalDateTime_YMDHMS

答案 3 :(得分:0)

C中,我会遵循以下规则:

  1. 返回正确的错误代码作为返回类型。
  2. 使用struct const* struct_param这样可变的输入/输出参数,以便无法在该API内更改其指针值。

  3. struct const * const structParam用于不可变输入参数,以便无法在该API内更改其指针值和内容。

  4. 在C ++中使用引用而不是指针,我的意思是,C ++显式提供了引用传递,因此您可以减少指针值的传递。