如何使函数的参数列表更清晰?
How to make the parameter list of a function cleaner?
在我最近观看的一段视频中,Kate Gregory 建议如果一个函数有一个巨大的参数列表(例如 4 个以上的参数),应该将所有这些参数放在 struct
中(即 make它们是结构的成员)并在初始化 struct
的实例后将其传递给所述函数(显然这也需要重构函数本身)。
我有一个带有 5 个参数的效用函数,您可以在下面看到:
bool convert_str_to_valid_ints( const std::string_view inputStr, const std::span<int> result_ints,
const std::size_t expectedTokenCount, const std::vector<int>& specificTokensIndices,
const std::pair<int, int> acceptableRange =
std::pair<int, int>( std::numeric_limits<int>::min( ), std::numeric_limits<int>::max( ) ) );
正如所料,在任何调用站点调用此函数都会引入大量可怕的代码!
上面可以变成这样:
// In a header file
struct ParameterList
{
std::string_view inputStr;
std::span<int> result_ints;
std::size_t expectedTokenCount;
std::vector<int> specificTokensIndices;
std::pair<int, int> acceptableRange = std::pair<int, int>( std::numeric_limits<int>::min( ),
std::numeric_limits<int>::max( ) );
};
bool convert_str_to_valid_ints( const ParameterList& pl );
.
.
.
// in any source file that includes the said header file
const ParameterList pl { /* arguments go here */ };
bool isValid { convert_str_to_valid_ints( pl ) }; // much more readable, and possibly more performant?
我试图将它分解成更小的部分(例如,两个较小的函数,每个函数的参数都更少)但我没有这样做,因为这个函数的作用在逻辑上不能分解成两个部分,而且它不会很有意义。所以我想寻求帮助,看看 Gregory 的方法在这种特殊情况下是否是一个有效的选择。
现在如果有人说这是一个有效的选择,那么我应该把这个特殊用途的定义放在哪里 struct
(我猜是在声明大函数的 header 里面,这样其他源文件可以通过包含大函数的 header 然后调用函数来访问该结构)?
该结构应该在一个头文件中,可能在它自己的头文件中。
你考虑过这个吗?
将convert函数添加到struct中,这样就可以直接使用参数,也方便以后复用。
#include <iostream>
#include <string_view>
#include <span>
#include <vector>
struct ParameterListConverter
{
std::span<int> result_ints; // you can even set some reasonable defaults here
std::size_t expectedTokenCount;
std::vector<int> specificTokensIndices;
std::pair<int, int> acceptableRange = std::pair<int, int>(std::numeric_limits<int>::min(),
std::numeric_limits<int>::max());
bool convert(const std::string input) const
{
// ... your convert function using the parameters set
};
};
int main()
{
ParameterListConverter converter
{
.expectedTokenCount = 42ul
};
bool success = converter.convert("123,234");
return 1;
}
在我最近观看的一段视频中,Kate Gregory 建议如果一个函数有一个巨大的参数列表(例如 4 个以上的参数),应该将所有这些参数放在 struct
中(即 make它们是结构的成员)并在初始化 struct
的实例后将其传递给所述函数(显然这也需要重构函数本身)。
我有一个带有 5 个参数的效用函数,您可以在下面看到:
bool convert_str_to_valid_ints( const std::string_view inputStr, const std::span<int> result_ints,
const std::size_t expectedTokenCount, const std::vector<int>& specificTokensIndices,
const std::pair<int, int> acceptableRange =
std::pair<int, int>( std::numeric_limits<int>::min( ), std::numeric_limits<int>::max( ) ) );
正如所料,在任何调用站点调用此函数都会引入大量可怕的代码!
上面可以变成这样:
// In a header file
struct ParameterList
{
std::string_view inputStr;
std::span<int> result_ints;
std::size_t expectedTokenCount;
std::vector<int> specificTokensIndices;
std::pair<int, int> acceptableRange = std::pair<int, int>( std::numeric_limits<int>::min( ),
std::numeric_limits<int>::max( ) );
};
bool convert_str_to_valid_ints( const ParameterList& pl );
.
.
.
// in any source file that includes the said header file
const ParameterList pl { /* arguments go here */ };
bool isValid { convert_str_to_valid_ints( pl ) }; // much more readable, and possibly more performant?
我试图将它分解成更小的部分(例如,两个较小的函数,每个函数的参数都更少)但我没有这样做,因为这个函数的作用在逻辑上不能分解成两个部分,而且它不会很有意义。所以我想寻求帮助,看看 Gregory 的方法在这种特殊情况下是否是一个有效的选择。
现在如果有人说这是一个有效的选择,那么我应该把这个特殊用途的定义放在哪里 struct
(我猜是在声明大函数的 header 里面,这样其他源文件可以通过包含大函数的 header 然后调用函数来访问该结构)?
该结构应该在一个头文件中,可能在它自己的头文件中。 你考虑过这个吗? 将convert函数添加到struct中,这样就可以直接使用参数,也方便以后复用。
#include <iostream>
#include <string_view>
#include <span>
#include <vector>
struct ParameterListConverter
{
std::span<int> result_ints; // you can even set some reasonable defaults here
std::size_t expectedTokenCount;
std::vector<int> specificTokensIndices;
std::pair<int, int> acceptableRange = std::pair<int, int>(std::numeric_limits<int>::min(),
std::numeric_limits<int>::max());
bool convert(const std::string input) const
{
// ... your convert function using the parameters set
};
};
int main()
{
ParameterListConverter converter
{
.expectedTokenCount = 42ul
};
bool success = converter.convert("123,234");
return 1;
}