假设我必须将 30 个数字输入到可执行文件中,由于输入量很大,通过命令行输入它们是不合理的。一种标准方法是将它们保存到单个XML文件中,并使用像tinyxml2这样的XML解析器来解析它们。问题是,如果我使用 tinyxml2 直接解析输入,我将拥有一个非常臃肿的主函数,这似乎与常见的良好做法相矛盾。
例如:
int main(int argc, char **argv){
int a[30];
tinyxml2::XMLDocument doc_xml;
if (doc_xml.LoadFile(argv[1])){
std::cerr << "failed to load input file";
}
else {
tinyxml2::XMLHandle xml(&doc_xml);
tinyxml2::XMLHandle a0_xml =
xml.FirstChildElement("INPUT").FirstChildElement("A0");
if (a0_xml.ToElement()) {
a0_xml.ToElement()->QueryIntText(&a[0]);
}
else {
std::cerr << "A0 missing";
}
tinyxml2::XMLHandle a1_xml =
xml.FirstChildElement("INPUT").FirstChildElement("A1");
if (a1_xml.ToElement()) {
a1_xml.ToElement()->QueryIntText(&a[1]);
}
else {
std::cerr << "A1 missing";
}
// parsing all the way to A29 ...
}
// do something with a
return 0;
}
但另一方面,如果我编写一个额外的类只是为了解析这些特定类型的输入以缩短 main 函数,这似乎也是不对的,因为这个额外的类将毫无用处,除非它与这个 main 函数一起使用,因为它不能在其他地方重用。
int main(int argc, char **argv){
int a[30];
ParseXMLJustForThisExeClass ParseXMLJustForThisExeClass_obj;
ParseXMLJustForThisExeClass_obj.Run(argv[1], a);
// do something with a
return 0;
}
最好的处理方法是什么?
注意,除了读取XML文件之外,您还可以通过stdin传递大量数据。使用例如mycomplexcmd | hexdump -C
,hexdump
通过管道从标准输入读取。
现在进入问题的其余部分:有理由使用您的多函数示例(这里它们是构造函数还是常用函数并不是很重要)。这与你为什么希望任何函数更小几乎相同——可读性。也就是说,我不知道"共同的良好做法",而且我见过许多main()
很大的终端实用程序。
想象一下,有新人正在阅读main()
的第一个变体。他们会费尽心思去弄清楚所有这些句柄、疑问、孩子、父母——而他们只想看看// do something with a
之后的部分。这是因为他们不知道这是否与他们的问题有关。但是在 2 nd 变体中,他们会很快弄清楚"啊哈,这是解析逻辑,这不是我要找的"。
也就是说,当然你可以用详细的评论来打破逻辑。但是现在想象一下出了点问题,有人正在调试代码,他们将问题归咎于这个函数(好吧,考虑到函数main()
,这很有趣,也许他们刚刚开始调试)。事实证明,该错误非常微妙,不清楚,并且正在检查功能中的所有内容。现在,因为你正在处理可变语言,你经常会发现自己处于这样的境地:你会想"哦,可能是这个变量的东西,它在哪里被改变?你首先通过这个大函数查找变量的每次使用,然后是可能导致它被改变的块的条件;然后你弄清楚这个与条件相关的另一个大块有什么作用,它可以被提取到一个单独的函数中,其中使用了哪些变量;直到你弄清楚它在做什么的那一刻,你已经忘记了你之前看的一半!
当然,有时大功能是不可避免的。但如果你问这个问题,可能不是你的情况。
经验法则:你看到一个函数做两件不同的事情,几乎没有共同点,你想把它分成两个独立的函数。在您的情况下,它是解析 XML 并"使用 a 做某事"。虽然如果第二部分是几行,可能不值得提取 - 推测一下。不用担心开销,编译器擅长优化。您可以使用 LTO,也可以仅将文件中.cpp
函数声明为静态(非静态类),并且根据优化选项,编译器可以内联代码。
PS:你似乎处于学习与一些哈斯克尔一起玩非常有用的状态。您不必将其用于真正严肃的项目,但您获得的见解可以应用于任何地方。它迫使你进行更好的设计,特别是你很快就会开始感觉到什么时候需要打破一个功能(除了许多其他事情)。