home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / lang / cplus / 12861 < prev    next >
Encoding:
Internet Message Format  |  1992-08-25  |  6.6 KB

  1. Path: sparky!uunet!olivea!news.bbn.com!usc!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!pacific.mps.ohio-state.edu!linac!att!pacbell.com!UB.com!igor!thor!rmartin
  2. From: rmartin@thor.Rational.COM (Bob Martin)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Tiny proposal for named loops.
  5. Message-ID: <rmartin.714753208@thor>
  6. Date: 25 Aug 92 14:33:28 GMT
  7. References: <rmartin.714435942@dirac> <2294@devnull.mpd.tandem.com> <rmartin.714670566@thor> <2301@devnull.mpd.tandem.com>
  8. Sender: news@Rational.COM
  9. Lines: 133
  10.  
  11. rgp@mpd.tandem.com (Ramon Pantin) writes:
  12.  
  13. |In article <rmartin.714670566@thor> rmartin@thor.Rational.COM (Bob Martin) writes:
  14.  
  15. |>A loop is defined by a loop condition and a body.  By using a flag in
  16. |>the loop condition, I am immediately expressing that condition.  By
  17. |>using a break I am postponing the expression of that condition until I
  18. |>happen to think of it in the midst of the loop.
  19.  
  20. |The CONDITIONS FOR SETTING YOUR FLAGS inside the loop are not evident
  21. |from reading the head of the loop.  You still have to search for the
  22. |places where that variable is set in the loop and constantly ask yourself:
  23.  
  24. |    Ok, the "done" variable was set here, in the MIDDLE of
  25. |    the loop.  Does it mean that nothing else will be executed
  26. |    for this case?  Can't assume that.  I will have to read all
  27. |    the code that follows and see if something else happens for
  28. |    this case.  Who knows, maybe some code below sets "done" to
  29. |    FALSE under some other condition and the loop is not exited
  30. |    at all for this case ...
  31.  
  32. |By the time you have "cached" in your brain a couple of these "thoughts"
  33. |for the first occurrences of assignments to "done", "error", etc,
  34. |you will have a much harder time reading the rest of the code.
  35.  
  36. Yes, flags can be abused, no doubt about it.  However, in a loop which
  37. lacks break and continue statements, the concerns you mention above
  38. don't often materialize.  This is because you can very easily follow
  39. the if/else blocks and prove that no other code is executed after the
  40. flag has been set.  
  41.  
  42. I do not recommend that flags be used without caution.  I recommend
  43. that they be used in preference to break and continue.  I also
  44. recommend that they be used "judiciously" (i.e. with judgement) to
  45. avoid the problems that you mention above.
  46.  
  47. |>|    - Continue, I'm done with this case, the code that follows
  48. |>|      doesn't apply to this case, lets go to the next iteration.
  49. |>
  50. |>This is what 'else' statements are for.  every continue should be
  51. |>replaced by an else.
  52.  
  53. |No!  There could be code AFTER the whole "if else" statement.  If I see
  54. |an "if else" construct then I HAVE TO ASSUME that something else might
  55. |happen for either case after the "if else" statement.  By reading the
  56. |test at the head of the "if" I can't tell that, it is not expressing the
  57. |intentions of the programmer.
  58.  
  59. We can argue this forever, and for every example you give me, I can
  60. give you a counter example.  Believe me, I have written tens of
  61. thousands of lines of code which do not require breaks or continues.
  62. Nor have I had to reach very far to do this.  Just like OOP, it
  63. becomes a very natural way to think after you do it for a while.
  64.  
  65. The if/else blocks within a loop can always be arranged in a way that
  66. makes "continue" redundant.
  67.  
  68. |>|    - Return, I'm done, lets get out of this function.
  69. |>
  70. |>But first you'd better check to be sure that you have freed and closed
  71. |>and taken care of everything else. Premature exit is a significant
  72. |>cause of memory leaks, unclosed files, and other problems of pairity.
  73.  
  74. |There is no replacement for properly written code, if you structure
  75. |your code correctly, then things occur naturally in the right places.
  76. |If you have to do free/close/cleanup in multiple places then your
  77. |code is probably poorly written.  
  78.  
  79. My point exactly.
  80.  
  81. |It is funny to note that you had
  82. |to "duplicate code" in YOUR structured example below which is exactly
  83. |the problem that you are trying to avoid when you say "one open, one
  84. |close" ...
  85.  
  86. I duplicated code, (probably a function call), not a close or free.
  87. The duplication of small bits of code is preferable to tangling the
  88. code with breaks or continues.  Moreover, it is my experience that
  89. such duplicated code is only coincidentaly identical.  As the code is
  90. maintained and new features are added, the "duplicated blocks" often
  91. diverge, since they live in different contexts.  Thus, they should
  92. never have been combined.
  93.  
  94. If the code is truly identical, and there are more then a few lines,
  95. then perhaps a function is indicated.
  96.  
  97. |If at the beginning of my function I do some validation of the arguments
  98. |then there is nothing more natural than returning when an invalid argument
  99. |has been detected.  These are the problems of trying to force this error
  100. |return occur at the end of the function:
  101. |    - The "if else" problem described above.
  102. |    - The "normal" code is harder to read because it is indented
  103. |      one level deeper and it is not clear by looking at the code
  104. |      that this is the normal code.  The reader might wonder if
  105. |      there is more code after the "if else".  The "if else"
  106. |      problem occurs twice here!
  107.  
  108. Yes, by forcing returns at the end of a function, you get deeper
  109. nesting.  This is both good an bad.  It is bad because of the number
  110. of nesting levels.  It is often advisable to break up the code into
  111. functions.  It is good because of a simple heuristic:  The real work
  112. of the function occurs in the inner most block, all error conditions
  113. are handled in subsequent else blocks, all clean up code (free, close,
  114. etc) occurs at the end of non-else blocks.  (typically)
  115.  
  116. In short, functions with one return are full of landmarks that are
  117. easy to recognize. The nesting structure exposes the places where
  118. certain tasks are always performed.
  119.  
  120. [.. lots of argument deleted ..]
  121.  
  122. |>So, let me reverse the challenge.  I suggest that you try writing a
  123. |>substantial amount of code without breaks, gotos, or mid-function
  124. |>returns.  You might really like it!
  125.  
  126. |Inexperienced programmers might benefit from the structured
  127. |programming concepts.  Like you (and everybody else) I have programmed
  128. |in a variety of languages.  I don't need to restrain myself to these
  129. |things to be able to write good code.  I trust my common sense,
  130. |aesthetic sense, rationality and experience.
  131.  
  132. Meaning that you won't try it, right?  You "know" already. Fine.
  133.  
  134. Come on, give it a try.  Try it for 5,000 lines of code.  After that,
  135. if you haven't derived the benefits that I claim, you can post a
  136. scathing review proving that you were right all along.  
  137.  
  138.  
  139. --
  140. Robert Martin                        Training courses offered in:
  141. R. C. M. Consulting                       Object Oriented Analysis
  142. 2080 Cranbrook Rd.                        Object Oriented Design
  143. Green Oaks, Il 60048 (708) 918-1004       C++
  144.