使用 { } 分割大块代码以提高代码可读性 - 好的做法吗?
我正在考虑使用匿名 { } 代码块来逻辑区分同一方法调用内的“代码块”,这(理论上)应该提高代码的可读性。
我想知道以下 2 个代码段中哪一个对您来说更好?
另外,这两个代码段是否编译为相同的字节码?换句话说,使用 { } 会以任何方式损害代码的性能吗?
选项 1:不带 { } 标识的代码块
public static String serviceMatch(HttpServletRequest servletRequest, RequestTypeEnum requestTypeEnum, ...censorsed..., RequestStatistics requestStatistics) {
Request request;
// We get the parser that fits the ...censorsed..., effectively transforming the HTTPReqeuest to application local "Request*" object
RequestParser parser = RequestParserFactory.getParser(...censorsed...);
// Populate basic parameters, the "heavy" data will be lazy loaded
request = parser.parse(servletRequest);
// Instead of polluting the parsers let's put it here... (unless we identify meaningful justifications for the other alternative of changing RequestParser.parse() interface.
request.requestType = requestTypeEnum;
// Store the request statistics object on the request, so that we have access to it from all over the code
request.requestStatistics = requestStatistics;
// Update timestamp when request was parsed
request.requestStatistics._1_end_parseRequest = System.currentTimeMillis();
/*
* ...censorsed...
*/
MatchResult matchResult = Matcher.findMatch(...censorsed...);
/*
* ...censorsed...
*/
String reply = ReplyFormatFactory.getFormatter(...censorsed...
// Update timestamp when reply finished construction
request.requestStatistics._6_end_formatReply = System.currentTimeMillis();
return reply;
}
选项 2:带 { } 标识的代码块
public static String serviceMatch(HttpServletRequest servletRequest, RequestTypeEnum requestTypeEnum, ...censorsed..., RequestStatistics requestStatistics) {
Request request;
/*
* Request parsing block
*/
{
// We get the parser that fits the ...censorsed..., effectively transforming the HTTPReqeuest to application local "Request*" object
RequestParser parser = RequestParserFactory.getParser(...censorsed...);
// Populate basic parameters, the "heavy" data will be lazy loaded
request = parser.parse(servletRequest);
// Instead of polluting the parsers let's put it here... (unless we identify meaningful justifications for the other alternative of changing RequestParser.parse() interface.
request.requestType = requestTypeEnum;
// Store the request statistics object on the request, so that we have access to it from all over the code
request.requestStatistics = requestStatistics;
}
// Update timestamp when request was parsed
request.requestStatistics._1_end_parseRequest = System.currentTimeMillis();
/*
* ...censorsed...
*/
MatchResult matchResult = Matcher.findMatch(...censorsed...);
/*
* ...censorsed...
*/
String reply = ReplyFormatFactory.getFormatter(...censorsed...
// Update timestamp when reply finished construction
request.requestStatistics._6_end_formatReply = System.currentTimeMillis();
return reply;
}
感谢 Maxim 的审阅。
I'm considering the option of using anonymous { } code blocks to logically distinguish "code blocks" inside the same method call, something that (theoretically) should improve readability of the code.
I'm wondering which of the following 2 code segments is better to your eyes?
Also, are the 2 code segments compile to the same bytecode?, In other words, can using { } hurt in any way the performance of the code?
Option 1: Code block without { } identation
public static String serviceMatch(HttpServletRequest servletRequest, RequestTypeEnum requestTypeEnum, ...censorsed..., RequestStatistics requestStatistics) {
Request request;
// We get the parser that fits the ...censorsed..., effectively transforming the HTTPReqeuest to application local "Request*" object
RequestParser parser = RequestParserFactory.getParser(...censorsed...);
// Populate basic parameters, the "heavy" data will be lazy loaded
request = parser.parse(servletRequest);
// Instead of polluting the parsers let's put it here... (unless we identify meaningful justifications for the other alternative of changing RequestParser.parse() interface.
request.requestType = requestTypeEnum;
// Store the request statistics object on the request, so that we have access to it from all over the code
request.requestStatistics = requestStatistics;
// Update timestamp when request was parsed
request.requestStatistics._1_end_parseRequest = System.currentTimeMillis();
/*
* ...censorsed...
*/
MatchResult matchResult = Matcher.findMatch(...censorsed...);
/*
* ...censorsed...
*/
String reply = ReplyFormatFactory.getFormatter(...censorsed...
// Update timestamp when reply finished construction
request.requestStatistics._6_end_formatReply = System.currentTimeMillis();
return reply;
}
Option 2: Code block with { } identation
public static String serviceMatch(HttpServletRequest servletRequest, RequestTypeEnum requestTypeEnum, ...censorsed..., RequestStatistics requestStatistics) {
Request request;
/*
* Request parsing block
*/
{
// We get the parser that fits the ...censorsed..., effectively transforming the HTTPReqeuest to application local "Request*" object
RequestParser parser = RequestParserFactory.getParser(...censorsed...);
// Populate basic parameters, the "heavy" data will be lazy loaded
request = parser.parse(servletRequest);
// Instead of polluting the parsers let's put it here... (unless we identify meaningful justifications for the other alternative of changing RequestParser.parse() interface.
request.requestType = requestTypeEnum;
// Store the request statistics object on the request, so that we have access to it from all over the code
request.requestStatistics = requestStatistics;
}
// Update timestamp when request was parsed
request.requestStatistics._1_end_parseRequest = System.currentTimeMillis();
/*
* ...censorsed...
*/
MatchResult matchResult = Matcher.findMatch(...censorsed...);
/*
* ...censorsed...
*/
String reply = ReplyFormatFactory.getFormatter(...censorsed...
// Update timestamp when reply finished construction
request.requestStatistics._6_end_formatReply = System.currentTimeMillis();
return reply;
}
Thanks for the review, Maxim.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
如果您只是为了可读性而考虑在同一方法中添加额外的
{ }
,我的建议是考虑将您的方法重构为几个较小的方法。这些较小的方法优点是更容易被自己理解,并且更可重用(如果它们是“松散耦合”)。请参阅单一责任原则。
If you're looking into adding extra
{ }
's within the same method just for the sake of readability, my advice would be to consider refactoring your method into several smaller methods.These smaller methods have the advantage of being easier to understand by themselves, and being more reusable (if they are "loosely coupled"). See the single responsibility principle.
如果您发现将括号放在代码的某些部分(如选项 2 中)会很方便,那么您应该将其移至其自己的方法中。这就是提高可读性的原因。
顺便说一句,我还认为您实际上不需要注释每一行代码。例如,即使没有注释,时间戳更新也是不言自明的。
If you come to the state that it would be handy to put the brackets around some part of code (like in Option 2), you should move it to its own method. That's what improves readability.
By the way, I also think you don't really need to comment every single line of your code. For example the timestamp update is self-explanatory even without the comment.
如果没有语法原因,我通常不会添加大括号分隔的块,但是如果仅在有限的范围内需要变量,我宁愿创建一个嵌套范围,而不是在较大范围的中间定义变量(因为在后一种情况下,没有明确的指示变量何时超出“有用”范围)。
至于将这样的代码块提取到另一个方法中,我认为如果生成的方法(1)具有一批合理的参数,并且(2)可以给出一个描述其行为以及实际代码确实如此。如果使用该方法需要传递过多的参数,或者必须查看该方法中的代码才能了解其调用者在做什么,那么我认为最好使用匿名作用域块。
I don't generally add a brace-delimited block without some syntactic reason, but if a variable will only be needed within a limited scope, I'd rather created a nested scope than define the variable in the middle of a larger one (since in the latter case there's no clear indication when the variable goes out of 'useful' scope).
As for pulling out such a code block into another method, I think it's a good idea if the resulting method both (1) has a reasonable batch of parameters, and (2) can be given a name that describes its behavior as well as the actual code does. If using the method would require passing an excessive number of parameters, or if one would have to look at the code in the method to understand what its caller is doing, then I think it's better to use an anonymous scoping block.
我认为这有点主观,没有正确或错误的答案......我的意见是不要这样做。用注释块分隔代码块,并解释它们为何不同,但不要使用大括号。当我看到大括号时,我立即想到应该有一个前导
if
、while
或其他东西......而没有找到 is 有点奇怪。I think this is a bit subjective, no right or wrong answer... my opinion is don't do it. Separate blocks of code with comment blocks that precede and explain why they are different, but don't use the braces. When I see braces, I immediately think there should be a leading
if
,while
, or something... and not finding is is a little weird.您可能应该使用单独的方法。您可以调用第一个块 processRequest。任何阅读此代码的人都可以看到使用了哪些参数、返回了哪些数据、它做了什么(即使没有注释)。块不提供此类信息。
字节码可能是相同的。
You should probably use separate methods instead. You can call the first block processRequest. Anyone who reads this code will be able to see which parameters are used, what data is returned, what it does (even without comments). Blocks don't provide such information.
Bytecode will likely be the same.
我有时更喜欢使用第二个选项。当提取单独的方法会导致多个返回参数混乱(即将它们包装在人造对象中)时,就会发生这种情况。
I sometimes prefer to use the second option. That happens when extracting separate methods would lead to mess with multiple return parameters (that is, wrapping them in artificial object).
Lighttpd 在配置文件中有一个注释块,就是按照这种风格制作的;
因此,您只需注释即可,而不需要对代码进行 {} 处理。
在 Perl 中,{ }、sub { } 或 eval { } 内的任何内容都将被求值;然而,在某些子例程中保留大量的 { } 块被认为很糟糕,足以将代码分成更小的部分;
所以这种做法是众所周知的。
Lighttpd has a comment blocks in configuration file, made in this style;
So you can just comment instead of {}'ing your code.
In Perl, anything inside { }, sub { } or eval { } will be evaluated; however, keeping a large amount of { } blocks inside some sub-routine is considered bad enough to push the code out in smaller parts;
So the practice is known.
大括号通常用于对控制结构等的语句进行分组。我发现它们用于其他用途时会很刺耳。
如果我有一个过长的函数(无论出于何种原因)我不想拆分,我会将它分成带有注释的块。
Braces are usually used to group statements for control structures and the like. I find them jarring when used for anything else.
If I have an overlong function that (for whatever reason) I don't want to split up, I break it apart into blocks with comments.
大括号
{ }
有其用途(在 Java 7 中更是如此)我认为它们很少只是为了可读性而使用。就我个人而言,如果像选项 2 那样使用它们,我首先想到的是“这是一个静态块吗?”。因此,我发现选项 1“更正常”且可读。如果您真的热衷于坚持使用一种方法,而不是像这里许多人建议的那样重构这堆代码,那么可以使用注释作为行分隔符。就像:
恕我直言,注释可能是使代码可读的最好方法。
Braces
{ }
have their purpose (even more in Java 7) and I think they are rarely used just for readability. Personally, if they are used like in Option 2 the first thing that comes to my mind is that, "Is this a static block?". Hence, I find Option 1 "more normal" and readable.If you are really keen on sticking with one method and not refactoring this chuck of code as suggested by many here, then use comments as line separators instead. Something like:
IMHO, comments are probably the best in making codes readable.
如果您使用 C# 进行开发,我建议您使用 #region ... #endregion 来代替,以提高可读性。
If you're developing in C# I would advise you to use #region ... #endregion instead for readability purpose.