I currently need to extend a function's API that is very often used in my aplication with a new (boolean) parameter. I also foresee that, as more features are added to the program, the same function may (not yet certain) need more functionality, that (if needed) can be controled by boolean parameters. The extra functionality will only be needed by new function calls, not by the existing ones.
So, to simplify its extension in the future, I plan on adding two or tree extra enumerated parameters to its API, so that new features can be added without chasing and editing all fuction calls everytime something is added. So, instead of extending to this:
function(currparams..., bool option1, bool option2, bool option3, bool option4);
It would extend to this:
typedef enum{
noopt,
opt1,
opt2,
opt3,
...
}APIoptions;
function(currparams..., APIoptions option1, APIoptions option2);
As long as the enumerated arguments I add now are enough for the future needs, this should make extending the API easier. However I don't recall seing this type of programming in the wild and would like to understand its disadvantages and potential problems and why it wouldn't be more often used.
Thanks in advance.
Adding meaningless arguments that you plan to implement some day (or maybe never) is bug prone. Imagine that you have an argument option4
that is ignored by the function and your program works just fine. In some time later you add meaning to that argument and for some unknown reason your program becomes unstable. That may happen if in some places you call your function giving that argument some random values and it went unnoticed in the past since the option4
was ignored. Now, how do you find out in which calls it has a good value and in which it is the value that you gave it by mistake before it was implemented? And moreover, what if there is not just one such argument but a few of them?
Creating a structure, which will contain all the extra arguments and passing it to the function seems to be a better solution:
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
}
Later you will add members to that structure and modify the function. In places where you call this function with only some arguments being passed, you initialize the entire structure to zero and the members you need.
struct args_ex extra =
{
.foo = true,
.bar = true,
};
your_function (... , & extra);