简体   繁体   English

参数或方法重载的幻数?

[英]Magic numbers for parameters or method overloading?

I need to implement an interface for a class in C++ where I need to ask for events occured related with two kinds of sets, let's say here persons and actions. 我需要为C ++中的一个类实现一个接口,在该接口中,我需要询问与两种类型的集合相关的事件的发生,这里说人员和动作。 I need to ask for person identifier and action identifier in all possible combinations (all of them, specifying only one of the identifiers or specifying both of them) 我需要在所有可能的组合中要求提供人员识别符和动作识别符(全部,仅指定其中一个识别符,或同时指定两者)
Option 1) 选项1)

// Asks for all events occured for every combination
int getNumberofEvents(float param1)
// Asks for all events occured for idPerson AND all possible value of idAction
int getNumberofEvents(int idPerson, float param1)  
// Asks for all events occured in idAction AND all possible value of idPerson
int getNumberofEvents(int idAction, float param1)
// Asks for all events occured in idPerson AND idAction
int getNumberofEvents(int idPerson, int idAction, float param1)

This option is clear to read but I need to implement a different interface for every possible combination, so there would be 8 methods if I include a new identifier (2³). 该选项很容易阅读,但是我需要为每种可能的组合实现一个不同的接口,因此,如果我包含一个新的标识符(2³),将有8种方法。

Option 2) 选项2)

static const int ALL_PERSONS= 0;
static const int ALL_ACTIONS= 0;
int getNumberofEvents(int idPerson, int idAction, float param1)

For this option there is only one method interface, but I introduce a public magic number to search for 'All possible id' 对于此选项,只有一个方法界面,但是我引入了一个公共魔术数字来搜索“所有可能的ID”

Regarding to usability and further maintainability, which would be the best option between these two now I have in mind (there can be other better options that I do not include, of course). 关于可用性和进一步的可维护性,这是我现在想到的这两者之间的最佳选择(当然,还有其他一些更好的选择我没有包括在内)。

Thanks. 谢谢。

You could modify option 2 to avoid magic numbers and also avoid the problem of passing a person id for the action parameter or vice versa: 您可以修改选项2以避免使用幻数,也可以避免为操作参数传递人id的问题,反之亦然:

struct Person
{
    explicit Person(int x) : id (x) {}
    int id;
    static Person ALL;
};

Person Person::ALL(0);

struct Action
{
    explicit Action(int x) : id (x) {}
    int id;
    static Action ALL;
};

Action Action::ALL(0);

int getNumberofEvents(const Person& person, const Action& action, float param1);

// ...

int count = getNumberOfEvents(Person(3), Action::ALL, 1.0f);

You appear to be badly reinventing what C++ has included in the Standard Library: std::count_if 您似乎很想重新创建标准库中C ++包含的内容: std::count_if

Notice that it allows arbitrarily complex conditions because it accepts a functor object which is able to filter and decide which objects match. 请注意,它允许任意复杂的条件,因为它接受可以过滤并确定哪些对象匹配的函子对象。 With C++11, lambdas make supplying the condition easier than ever. 使用C ++ 11,lambdas使提供条件比以往更加容易。

You can either expose begin() and end() iterators and let the user call std::count_if , or write 您可以公开begin()end()迭代器,并让用户调用std::count_if ,或者编写

int getNumberofEvents(std::function<bool (const descriptor&)> filter, float param1);

and let the user write their query expression in a very natural way: 并让用户以非常自然的方式编写其查询表达式:

getNumberOfEvents([](const descriptor& x) { return x.Action == ACTION_RAISE; }, 5.7);

Absolutely go with option 2. The user of your code won't have to look up which method they want to call, they would just be able to use your defined constants in certain cases. 绝对使用选项2。您的代码用户将不必查找要调用的方法,在某些情况下,他们只能使用您定义的常量。 It makes the user's life a whole lot easier to only have one function name to work with so that they don't have to be constantly referencing your .h file to figure out which one of the many functions (named the same thing) they want to use. 仅使用一个函数名称就可以使用户的生活变得更加轻松,这样他们就不必不断引用您的.h文件来找出他们想要的多个函数(命名相同)中的哪个使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM