减少“类型验证然后使用”的情况代码重复模式
该系统的模块之一处理基于 JSON 的协议,该协议用于传输各种数据。这导致了几乎一百个小代码段,看起来像这样:
/*
* Data package Foo reports Fooness level
*/
if(root.isMember("foo") && root["foo"].isInt())
{
int foo = root["foo"].asInt();
// do things with foo
}
/*
* Data package Bar gives ID number and name of a newly arrived bar.
*/
if(root.isMember("bar") && root["bar"].isObject())
{
JSON::Value bar = root["bar"];
if(bar.isMember("baz") && bar["baz"].isString()
&& bar.isMember("buzz") && bar["buzz"].isInt())
{
std::string baz = bar["baz"].asString();
int buzz = bar["buzz"].asInt();
// do things with baz and buzz
}
else{ err["bar"] = argument_error; }
}
不仅每个块的“肉体”通常是一两行和大约 10 行参数验证,这会导致无数的复制粘贴错误和可维护性问题(一个键改名,有6个地方必须改)。
您将如何重塑这些模式以实现它们的功能而不需要所有代码重复? (注意,所有主键和少数子键都是可选的,大多数子键是必需的。)
One of modules of the system deals with a JSON-based protocol that is used to transfer a wide variety of data. This results in almost a hundred of small sections of code that look like this:
/*
* Data package Foo reports Fooness level
*/
if(root.isMember("foo") && root["foo"].isInt())
{
int foo = root["foo"].asInt();
// do things with foo
}
/*
* Data package Bar gives ID number and name of a newly arrived bar.
*/
if(root.isMember("bar") && root["bar"].isObject())
{
JSON::Value bar = root["bar"];
if(bar.isMember("baz") && bar["baz"].isString()
&& bar.isMember("buzz") && bar["buzz"].isInt())
{
std::string baz = bar["baz"].asString();
int buzz = bar["buzz"].asInt();
// do things with baz and buzz
}
else{ err["bar"] = argument_error; }
}
Not only is the "flesh" of each block often a line or two with some 10 lines of parameter validation, this leads to countless copy-paste errors and maintainability problems (a key changes name, it must be changed in some 6 places).
How would you reshape these patterns to do what they do without all that code duplication?
(note, all main keys and few sub-keys are optional, most sub-keys are obligatory.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您没有列出诸如
bar
之类的类型,因此我仅使用Bar
来表示该类型。您可以为自己提供一些辅助方法,利用状态代码或异常,具体取决于您预计失败的常见程度。
然后你可以将它与:
稍微干净一点,但不是突飞猛进。如果您期望您正在寻找的东西出现,并且不太可能出现失败,那么我们可以使用异常。我们也可以全力使用模板:
设置需要更多方法,但现在使用它非常简单和干净。
You didn't list out the types of things like
bar
, so I'm just usingBar
for that type.You can give yourself some helper methods, making use of status codes or exceptions, depending on how common you expect failures to be.
Then you can use it with:
Which is slightly cleaner, but not by leaps and bounds. If you expect the things you're looking for to be present, and failures are unlikely, then we can use exceptions. And we can go all out with templates too:
The setup requires more methods, but now using it is very simple and clean.
由于您想要自动命名标识符,因此基本上只能使用预处理器。你可以尝试这样的事情:
Since you want to automate the naming of identifiers, you're basically down to using the preprocessor. You could try something like this: