views:

419

answers:

10

Hello,

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.

+46  A: 

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.

Donut
The code is critical region in terms of performance, it is not moved to separate methods to avoid stack overhead (method invocation).
Maxim Veksler
@Maxim Veksler: Sounds like premature optimization to me.
ColinD
And you can also 'comment' if you use good name for your new smaller methods
Hurda
@Maxim I'll be honest, Java is not my area of expertise and I'm not one to comment on whether moving your request parsing code to its own method would have an effect on your performance. However I'd tend to agree with @ColinD (and from a quick glance at his profile, he knows what he's talking about).
Donut
@ColinD, @Donut - I don't think this should be the center of the discussion. We have various consideration in choosing the most performance efficient coding style, sacrificing readability and sometimes even loose coupling. This is a delicate balance but for the above segment, no reason to split into methods for our use case.
Maxim Veksler
@Maxim Veksler: While I don't know the details of your application, I'm of the opinion that you're wrong on that point. To quote Effective Java, _Strive to write good programs rather than fast ones._ A well-written, loosely coupled and readable program will make it easy for you to correct performance issues when you've profiled and identified those issues. Plus, things that you may _think_ are helping with performance may not be, and may even prevent you from improving performance in some area later.
ColinD
I recently found that book: Refactoring: Improving the Design of Existing Code by Martin Fowler. I wish it was way earlier. It is a must read book. Compiler is able to make way better optimization then you by not splitting code into methods (e.g. just in time compliation - http://en.wikipedia.org/wiki/Java_performance). You need to make profiling before and after refactoring then you now what you gain what you lose.
Gadolin
@Maxim: have you *actually* tested the performance of this code and found that having one big method is faster than having calls to several smaller methods? If you aren't testing this and making decisions with real world results, you're just guessing.
matt b
+11  A: 

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.

dark_charlie
+1 for recommending against the comments on every line.
ColinD
I suspect the comments may be an enterprise requirement but yeah, they're a bit much.
Jonathan Grynspan
@Jonathan Grynspan: Programmers are not bureaucrats - if a code is readable and has a corresponding number of comments, no one will fire the programmer. At least no one with a clear mind :-)
dark_charlie
@dark: Yes, but many bureaucrats don't understand the purpose of comments beyond "makes code better." So they require every line to be commented. When one sees code with a comment on every line, it is often the result of rules and regulations in an organization. (Not always, of course! And comments every line are still better than no comments at all.)
Jonathan Grynspan
@Jonathan: I wouldn't say that comments every line are better than no comments at all, especially if code is broken up sensibly into well-named methods. Even if not, comments every line are just one end of a spectrum where both extremes are bad and good is somewhere in the middle.
ColinD
@ColinD: Oh, I agree--moderation is best--but in any reasonably complex program, there will be some function or class that really needs to be documented, and comments every line give you that, while none at all leave you in the dark.
Jonathan Grynspan
@Jonathan: Even in that case it depends what actually is contained in the comments. /* Increases i by one */ never helps.
dark_charlie
@dark Yes, but I'd rather have to ignore crap comments than look at a block of code and not have any at all to rely on. Clearly you disagree.
Jonathan Grynspan
+1  A: 

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.

FrustratedWithFormsDesigner
+1  A: 

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.

Athari
+1  A: 

If you're developping in C# i would advise you to use #region ... #endregion instead for readability purpose.

Flo.
Who upvoted this? It's totally irrelevant to this java question...
seanizer
A: 

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).

Grzegorz Oledzki
+3  A: 

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.

supercat
A: 

Lighttpd has a comment blocks in configuration file, made in this style;

#{{{ module name
module.option = value;
module.option = value;
#}}} 

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;

$html .= eval { $val = &getNextPiece(); return $val; };

So the practice is known.

mhambra
A: 

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.

David Thornley
A: 

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:

    /* -------------------------------------------- */
    /* describe in detail here why you don't want to put this in another method */
    /* so other readers will know why! */

   // 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;
  }
   /* -------- END of confusing block ------------- */

IMHO, comments are probably the best in making codes readable.

Adrian M
Comments are the *worst* way to make code readable.
Michael Borgwardt
We have to take this within the context of the question where refactoring is not an option due to performance.
Adrian M