构建此类代码的最佳方法是什么?
我有一个功能需要逐个分析数据包并决定做什么。 对于每个数据包,代码必须:
- 读取数据包,超时时返回错误代码。
- 检查是否损坏,如果是,则记录它并转至 1。
- 检查中止数据包,如果是,则记录它并返回中止代码。
- 检查报文参数是否非法,如果是则记录,返回无效参数报文,并转至
- 。
- 1 packet为结束包,返回成功。
我的代码如下所示:
Packet p;
for (;;) {
int ret = receive(&p, time);
if (ret == TIMEOUT) {
log("timeout");
return TIMEOUT;
}
if (ret != 0) {
log("corrupted %d", ret);
continue;
}
if (p.type == ABORT) {
log("abort");
return ABORT;
}
ret = check(&p);
if (ret != 0) {
log("invalid %d", ret);
respond(&p, INVALID);
continue;
}
ret = execute(&p);
if (ret != 0) {
log("failure %d", ret);
respond(&p, FAILURE);
continue;
}
if (is_last(&p)) {
finalize(&p);
return 0;
}
}
是否有一种更好的结构化方式来使该代码没有不必要的嵌套或冗长?
I have a function that need to analyze packet after packet and decide what to do.
For each packet the code must:
- Read a packet, on timeout return an error code.
- Check for corruption, if positive log it and and go to 1.
- Check for an abort packet, if positive log it and return and aborted code.
- Check for illegality of the parameters of the packet, if positive log it, respond with an invalid parameters packet and go to 1.
- Run the action of the packet, if failed log it, respond with an failure packet and go to 1.
- If the packet is an end packet, return success.
My code look like this:
Packet p;
for (;;) {
int ret = receive(&p, time);
if (ret == TIMEOUT) {
log("timeout");
return TIMEOUT;
}
if (ret != 0) {
log("corrupted %d", ret);
continue;
}
if (p.type == ABORT) {
log("abort");
return ABORT;
}
ret = check(&p);
if (ret != 0) {
log("invalid %d", ret);
respond(&p, INVALID);
continue;
}
ret = execute(&p);
if (ret != 0) {
log("failure %d", ret);
respond(&p, FAILURE);
continue;
}
if (is_last(&p)) {
finalize(&p);
return 0;
}
}
Are there a better structured way for this code that is not unnecessary nested or long?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您可以使用return,而不是在循环中使用多个
break
并执行最终的return
:Instead of having multiple
return
s in the loop you could usebreak
and do a finalreturn
:我觉得看起来不错。它绝对没有不必要的嵌套,尽管它看起来“长”,但它非常简短 - 除非您想将日志移到
receive()
、check()
和 <代码>execute() 函数。I think it looks good. It definitely has no unnecessary nesting and even though it seems "long" it's quite brief - unless you want to move the logging inside the
receive()
,check()
andexecute()
functions.我会尽量避免从循环内部返回。
相反,break 并在函数末尾有一个返回。
除此之外看起来还不错。
I would try to avoid returning from inside the loop.
Instead break and have a single return at the end of the function.
Looks ok apart from that.
这是个人喜好,但我个人不喜欢无限循环或 continue 关键字。我会这样做:
我的版本看起来比你的更复杂,但那是因为它更准确地反映了算法的结构。在我看来(这只是一个意见),像 continue 和 break 这样的关键字会混淆结构,不应该使用。
除此之外,另一个主要优点是,在我的版本中,您只需查看一个地方(即循环条件)就可以清楚地看到导致循环退出的条件。此外,导致循环停止的条件是在循环外部处理的——从概念上讲,这是正确的地方。该函数也只有一个出口点。
It's personal preference but I personally do not like infinite loops or the
continue
keyword. I'd do it something like:My version looks more complicated than yours but that is because it more accurately reflects the structure of the algorithm. In my opinion (and it is only an opinion), keywords like continue and break obfuscate the structure and should not be used.
Other than this, the other main advantage is that, in my version, you can clearly see the conditions that cause loop exit by just looking in one place i.e. the loop condition. Also, conditions that cause the loop to quite are handled outside the loop - conceptually the right place. There's also only one exit point for the function.
很多人不喜欢嵌套在 if 语句中的赋值,但我认为这没有任何合理的基础。使用它们可以实现如下所示的紧凑代码(我并不认为这是“最好的”;这是非常主观的):
A lot of people don't like assignments nested in if statements, but I don't think there's any rational basis for that. Using them allows compact code like the following (which I don't claim is "best"; that is highly subjective):
经验法则是避免一遍又一遍地重复使用同一变量。如果它用于新事物,请创建一个新的。例如,当我阅读您的代码时,我错过了
ret
在此过程中被重新定义的事实。另一个优点是,如果定义了一个值并立即使用,您通常可以在较小的范围内定义它。例如:
您可以将其重写为:
或者,如果您使用的是
C99 或C++:A rule of thumb is avoid reusing the same variable over and over again. If it's used for something new, create a new one instead. For example, when I read your code I missed the fact that
ret
was redefined along the way. Another advantage is that if a value is defined and immediately used, you can often define it in a smaller scope.For example:
You can rewrite this into:
Or, if you are using
C99 orC++: