{"id":3932,"date":"2018-09-06T09:00:47","date_gmt":"2018-09-06T09:00:47","guid":{"rendered":"http:\/\/www.nikola-breznjak.com\/blog\/?p=3932"},"modified":"2018-09-06T09:00:47","modified_gmt":"2018-09-06T09:00:47","slug":"code-complete-2-steve-mcconnell-general-control-issues","status":"publish","type":"post","link":"https:\/\/nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-general-control-issues\/","title":{"rendered":"Code Complete 2 \u2013 Steve McConnell \u2013 General Control Issues"},"content":{"rendered":"<p>I just love Steve McConnell&#8217;s classic book <a href=\"http:\/\/amzn.to\/2vdwv5v\">Code Complete 2<\/a>, and I recommend it to everyone in the Software &#8216;world&#8217; who&#8217;s willing to progress and sharpen his skills.<\/p>\n<p>Other blog posts in this series:<\/p>\n<ul>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-part-1-laying-foundation\/\">Part 1 (Chapters 1 &#8211; 4): Laying the Foundation<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-design-construction\/\">Chapter 5: Design in Construction<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-working-classes\/\">Chapter 6: Working Classes<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-high-quality-routines\/\">Chapter 7: High-Quality Routines<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-defensive-programming\/\">Chapter 8: Defensive programming<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-pseudocode-programming-process\/\">Chapter 9: Pseudocode Programming Process<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-general-issues-using-variables\/\">Chapter 10: General Issues in Using Variables<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-general-issues-using-variables\/\">Chapter 11: General Issues in Using Variables<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-fundemental-data-types\/\">Chapter 12: Fundemental Data Types<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-unusual-data-types\/\">Chapter 13: Unusual Data Types<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-using-conditionals\">Chapter 15: Using Conditionals<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-controlling-loops\/\">Chapter 16: Controlling Loops<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-unusual-control-structures\/\">Chapter 17: Unusual Control Structures<\/a><\/li>\n<li><a href=\"http:\/\/www.nikola-breznjak.com\/blog\/books\/programming\/code-complete-2-steve-mcconnell-table-driven-methods\/\">Chapter 18: Table-Driven Methods<\/a><\/li>\n<\/ul>\n<h2>Boolean Expressions<\/h2>\n<p>Except for the simplest control structure, the one that calls for the execution of statements in sequence, all control structures depend on the evaluation of boolean expressions.<\/p>\n<h3>Using true and false for Boolean Tests<\/h3>\n<p>Use the identifiers <code>true<\/code> and <code>false<\/code> in boolean expressions rather than using values like <code>0<\/code> and <code>1<\/code>.<\/p>\n<p>You can write clearer tests by treating the expressions as boolean expressions. For example, write<\/p>\n<pre><code>while ( !done ) ...\nwhile ( a &gt; b ) ...\n<\/code><\/pre>\n<p>rather than<\/p>\n<pre><code>while ( done == false ) ...\nwhile ( (a &gt; b) == true ) ...\n<\/code><\/pre>\n<p>Using implicit comparisons reduces the numbers of terms that someone reading your code has to keep in mind, and the resulting expressions read more like conversational English.<\/p>\n<h3>Making Complicated Expressions Simple<\/h3>\n<p><strong>Break complicated tests into partial tests with new boolean variables<\/strong> rather than creating a monstrous test with half a dozen terms, assign intermediate values to terms that allow you to perform a simpler test.<\/p>\n<p><strong>Move complicated expressions into boolean functions<\/strong> if a test is repeated often or distracts from the main flow of the program. For example:<\/p>\n<pre><code>If ( ( document.AtEndOfStream ) And ( Not inputError ) ) And \n    ( ( MIN_LLINES &lt;= lineCount ) And ( lineCount &lt;= MAX_LINES ) ) And \n    ( Not ErrorProcessing() ) Then\n    ...\nEnd If\n<\/code><\/pre>\n<p>This is an ugly test to have to read through if you&#8217;re not interested in the test itself. By putting it into a function, you can isolate the test and allow the reader to forget about it unless it&#8217;s important.<\/p>\n<pre><code>If ( DocumentIsValid( document , lineCount, inputError) ) Then\n    ' do something other\n    ...\nEnd If\n<\/code><\/pre>\n<p>If you use the test only once, you might not think it&#8217;s worthwhile to put it into a routine. But putting the test into a well-named function improves readability and makes it easier for you to see what your code is doing, and that&#8217;s sufficient reason to do it.<\/p>\n<h3>Forming Boolean Expressions Positively<\/h3>\n<blockquote><p>\n  I ain&#8217;t not no undummy.<\/p>\n<p>  ~ Homer Simpson<\/p>\n<p>  Not a few people don&#8217;t have not any trouble understanding a nonshort string of nonpositives-that is, most people have trouble understanding a lot of negatives.\n<\/p><\/blockquote>\n<p>You can do several things to avoid complicated negative boolean expressions in your program:<\/p>\n<ul>\n<li>In <code>if<\/code> statements, convert negatives to positives and flip-flop the code in the <code>if<\/code> and <code>else<\/code> clauses\n<ul>\n<li>You shouldn&#8217;t write <code>if ( !statusOK )<\/code>. Alternatively, you could choose a different variable name, one that would reverse the truth value of the test. In the example, you could replace <code>statusOK<\/code> with <code>ErrorDetected<\/code>, which would be true when <code>statusOK<\/code>  was false.<\/li>\n<\/ul>\n<\/li>\n<li>Apply DeMorgean&#8217;s Theorems to simplify boolean test with negatives\n<ul>\n<li>DeMorgan&#8217;s Theorem lets you exploit the logical relationship between an expression and version of the expression that means the same thing because it&#8217;s doubly negated. For example:<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><code>if ( !displayOK || !printerOK ) ...<\/code><\/p>\n<p>This is logically equvalent ot the following:<\/p>\n<p><code>if ( !( displayOK &amp;&amp; printerOK ) ) ...<\/code><\/p>\n<h3>Using Parentheses to Clarify Boolean Expressions<\/h3>\n<p>Using parentheses isn&#8217;t like sending a telegram: you&#8217;re not charged for each character &#8211; the extra characters are free.<\/p>\n<h3>Knowing How Boolean Expressions Are Evaluated<\/h3>\n<p>The pseudocodeThe pseudocode example of when &#8220;short-circuit&#8221; or &#8220;lazy&#8221; evaluation is necessary:<\/p>\n<p><code>while( i &lt; MAX_ELEMENTS and item[ i ] &lt;&gt; 0 ) ...<\/code><\/p>\n<p>If the whole expression is evaluated, you&#8217;ll get an error on the last pass through the loop. The variable <code>i<\/code> equals <code>MAX_ELEMENTS<\/code>, so the expression <code>item[ i ]<\/code> is an array-index error.<\/p>\n<p>In the pseudocode, you could restructure the test so that the error doesn&#8217;t occur:<\/p>\n<pre><code>while ( i &lt; MAX_ELEMENTS )\n    if (item[ i ] &lt;&gt; 0 ) then \n        ...\n<\/code><\/pre>\n<p>C++ uses <strong>short-circuit evaluation<\/strong>: if the first operand of the and is false, the second isn&#8217;t evaluated because the whole expression would be false anyway.<\/p>\n<h3>Write Numeric Expressions in Number-Line Order<\/h3>\n<p><code>MIN_ELEMENTS &lt;= i and i &lt;= MAX_ELEMENTS<\/code><\/p>\n<p>The idea is to order the elements left to right, from smallest to largest. In the first line, <code>MIN_ELEMENTS<\/code> and <code>MAX_ELEMENTS<\/code> are the two endpoints, so they go at the ends. The variable <code>i<\/code> is supposed to be between them, so it goes in the middle.<\/p>\n<h2>Compound Statements (Blocks)<\/h2>\n<p>A &#8220;compound statement&#8221; or &#8220;block&#8221; is a collection of statements that are treated as a single statement for purposes of controlling the flow of a program. Compound statements are created by writing <code>{<\/code> and <code>}<\/code> around a group of statements in C++, C#, C, and Java.<\/p>\n<blockquote><p>\n  \u26a0\ufe0f Use the block to clarify your intentions regardless of whether the code inside the block is 1 line or 20.\n<\/p><\/blockquote>\n<h2>Taming Dangerously Deep Nesting<\/h2>\n<p>Excessive indentation, or \u201cnesting,\u201d has been pilloried in computing literature for 25 years and is still one of the chief culprits in confusing code.<\/p>\n<p>Many researchers recommend avoiding nesting to more than three or four levels (Myers 1976, Marca 1981, and Ledgard and Tauer 1987a). Deep nesting works against what Chapter 5 describes as Software&#8217;s Major Technical Imperative: Managing Complexity. That is reason enough to avoid deep nesting.<\/p>\n<p>It&#8217;s not hard to avoid deep nesting. If you have deep nesting, you can redesign the tests performed in the <code>if<\/code> and <code>else<\/code> clauses or you can break the code into simpler routines. Here are the tips to reduce the nesting depth:<\/p>\n<h3>Simplify the nested <code>if<\/code> by testing part of the condition<\/h3>\n<pre><code>if ( inputStatus == InputStatus_Success ) {\n   \/\/ lots of code\n   ...\n   if ( printerRoutine != NULL ) {\n    \/\/ lots of code\n        ...\n        if ( SetupPage() ) {\n            \/\/ lots of code\n            ...\n            if ( AllocMem( &amp;printData ) ) {\n                \/\/ lots of code\n                ... \n        }\n    } \n}\n<\/code><\/pre>\n<p>Here&#8217;s the code revised to use retesting rather than nesting:<\/p>\n<pre><code>if ( inputStatus == InputStatus_Success ) {\n   \/\/ lots of code\n   ...\n   if ( printerRoutine != NULL ) {\n      \/\/ lots of code\n... }\n}\nif ( ( inputStatus == InputStatus_Success ) &amp;&amp;\n   ( printerRoutine != NULL ) &amp;&amp; SetupPage() ) {\n   \/\/ lots of code\n   ...\n   if ( AllocMem( &amp;printData ) ) {\n      \/\/ lots of code\n      ...\n    } \n}\n<\/code><\/pre>\n<p>This is a particularly realistic example because it shows that you can&#8217;t reduce the nesting level for free; you have to put up with a more complicated test in return for the reduced level of nesting.<\/p>\n<h3>Simplify a nested <code>if<\/code> by using <code>break<\/code><\/h3>\n<p>If some condition in the middle of the block fails, execution continues at the end of the block.<\/p>\n<pre><code>do {\n   \/\/ begin break block\n   if ( inputStatus != InputStatus_Success ) {\n      break; \/\/ break out of block\n   }\n   \/\/ lots of code\n   ...\n   if ( printerRoutine == NULL ) {\n      break; \/\/ break out of block\n   }\n   \/\/ lots of code\n   ...\n   if ( !SetupPage() ) {\n      break; \/\/ break out of block\n   }\n   \/\/ lots of code\n   ...\n   if ( !AllocMem( &amp;printData ) ) {\n      break; \/\/ break out of block\n   }\n   \/\/ lots of code\n   ...\n} while (FALSE); \/\/ end break block\n<\/code><\/pre>\n<p>This technique is uncommon enough that it should be used only when your entire team is familiar with it.<\/p>\n<h3>Convert a nested <code>if<\/code> to a set of <code>if-then-else<\/code>s<\/h3>\n<p>If you think about a nested <code>if<\/code> test critically, you might discover that you can reorganize it so that it uses <code>if-then-else<\/code>s rather than nested ifs. Suppose you have a busy decision tree like this:<\/p>\n<pre><code>if ( 10 &lt; quantity ) {\n   if ( 100 &lt; quantity ) {\n      if ( 1000 &lt; quantity ) {\n        discount = 0.10;\n      } \n      else {\n        discount = 0.05;\n      }\n    }\n    else {\n      discount = 0.025;\n    } \n}\nelse {\n   discount = 0.0;\n}\n<\/code><\/pre>\n<p>You can reorganize the code for better readability and reduced complexity:<\/p>\n<pre><code>if ( 1000 &lt; quantity ) {\n   discount = 0.10;\n}\nelse if ( 100 &lt; quantity ) {\n   discount = 0.05;\n}\nelse if ( 10 &lt; quantity ) {\n   discount = 0.025;\n}\nelse {\n   discount = 0;\n}\n<\/code><\/pre>\n<h3>Convert a nested <code>if<\/code> to a <code>case<\/code> statement<\/h3>\n<p>You can recode some kinds of tests, particularly those with integers, to use a <code>case<\/code> statement rather than chains of <code>if<\/code>s and <code>else<\/code>s. You can&#8217;t use this technique in some languages, but it&#8217;s a powerful technique for those in which you can.<\/p>\n<h3>Factor deeply nested code into its own routine<\/h3>\n<p>If deep nesting occurs inside a loop, you can often improve the situation by putting the inside of the loop into its own routine. This is especially effective if the nesting is a result of both conditionals and iterations. Leave the <code>if-then-else<\/code> branches in the main loop to show the decision branching, and then move the statements within the branches to their own routines.<\/p>\n<p>The new code has several advantages. First, the structure is simpler and easier to understand. Second, you can read, modify, and debug the shorter <code>while<\/code> loop on one screen; it doesn&#8217;t need to be broken across the screen or printed- page boundaries.<\/p>\n<blockquote><p>\n  \u26a0\ufe0f Complicated code is a sign that you don&#8217;t understand your program well enough to make it simple.\n<\/p><\/blockquote>\n<h2>A Programming Foundation: Structured Programming<\/h2>\n<p>The core of structured programming is a simple idea that a program should use only one-in, one-out control constructs (also called single-entry, single-exit control constructs).<\/p>\n<p>A structured program progresses in an orderly, disciplined way, rather than jumping around unpredictably. You can read it from top to bottom, and it executes in much the same way.<\/p>\n<h3>The Three Components of Structured Programming<\/h3>\n<ul>\n<li><strong>Sequence<\/strong>\n<ul>\n<li>A sequence is a set of statements executed in order. Typical sequential statements include assignments and calls to routines.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Selection<\/strong>\n<ul>\n<li>A selection is a control structure that causes statements to be executed selectively. The <code>if-then-else<\/code> statement is a common example.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Iteration<\/strong>\n<ul>\n<li>An iteration is a control structure that causes a group of statements to be executed multiple times. An iteration is commonly referred to as a &#8220;loop&#8221;.<\/li>\n<\/ul>\n<\/li>\n<li><strong>The core thesis<\/strong> of structured programming is that any control flow whatsoever can be created from these three constructs of sequence, selection, and iteration (B\u00f6hm Jacopini 1966).<\/li>\n<\/ul>\n<h3>How important is complexity?<\/h3>\n<blockquote><p>\n  The competent programmer is fully aware of the strictly limited size of his own skull; therefore he approaches the programming task in full humility<\/p>\n<p>  ~ Edsger Dijkstra\n<\/p><\/blockquote>\n<p>Control-flow complexity is important because it has been correlated with low reliability and frequent errors.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I just love Steve McConnell&#8217;s classic book Code Complete 2, and I recommend it to everyone in the Software &#8216;world&#8217; who&#8217;s willing to progress and sharpen his skills.&hellip;<\/p>\n","protected":false},"author":1,"featured_media":3897,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[34],"tags":[],"class_list":["post-3932","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/3932","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/comments?post=3932"}],"version-history":[{"count":1,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/3932\/revisions"}],"predecessor-version":[{"id":3933,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/3932\/revisions\/3933"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/media\/3897"}],"wp:attachment":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/media?parent=3932"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/categories?post=3932"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/tags?post=3932"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}