使用预定义(枚举)选项列表而不是单个参数的 api 扩展的缺点

Disadvantages of api extension with predefined (enumerated) option list instead of individual arguments

我目前需要扩展一个函数的 API,它在我的应用程序中经常用到一个新的(布尔)参数。我还预见到,随着更多的功能被添加到程序中,相同的功能可能(尚未确定)需要更多的功能,(如果需要)可以由布尔参数控制。只有新函数调用需要额外的功能,现有函数不需要。

所以,为了在未来简化它的扩展,我计划在它的 API 中添加两个或树额外的枚举参数,这样就可以添加新功能,而无需每次都追逐和编辑所有功能调用添加。所以,而不是扩展到这个:

function(currparams..., bool option1, bool option2, bool option3, bool option4);

它将扩展到:

typedef enum{
    noopt,
    opt1,
    opt2,
    opt3,
    ...
}APIoptions;

function(currparams..., APIoptions option1, APIoptions option2);

只要我现在添加的枚举参数足以满足未来的需要,这应该会使 API 的扩展更容易。但是我不记得在野外使用过这种类型的编程,并且想了解它的缺点和潜在问题以及为什么它不会被更频繁地使用。

提前致谢。

添加您计划某天(或可能永远不会)实现的无意义参数很容易出错。想象一下,你有一个参数 option4 被函数忽略了,你的程序运行得很好。一段时间后,您为该参数添加了意义,并且由于某些未知原因,您的程序变得不稳定。如果在某些地方你调用你的函数给该参数一些随机值并且它在过去因为 option4 被忽略而没有引起注意,则可能会发生这种情况。现在,您如何找出它在哪些调用中具有良好的价值,以及在实施之前您错误地赋予它的价值?而且,如果这样的论点不止一个,而是几个呢?

创建一个包含所有额外参数并将其传递给函数的结构似乎是更好的解决方案:

struct args_ex
{
    bool foo;
    bool bar;
    bool spam;

    // add more later
};

void your_function (... , const struct args_ex * extra)
{
    ...

    if (extra)
        // Do something with an extra arguments
}

稍后您将向该结构添加成员并修改函数。在仅传递一些参数的情况下调用此函数的地方,将整个结构初始化为零和所需的成员。

struct args_ex extra =
{
    .foo = true,
    .bar = true,
};

your_function (... , & extra);

为了避免一次性传递所有参数,您可以创建一个对象。然后您可以按照 pdf 中的建议进行操作,这样您就可以编写

MyObject myObject(someParams);
myObject.setOption1(foo);
myObject.setOption2(bar);

myObject.doFunction();