mXSCNT said:
The arrow anti-pattern has the same cyclomatic complexity as the equivalent code rewritten with gotos.
No, it doesn't. Read post #21 for a counterexample.
Converting old-fashioned spaghetti code to something to a pure structured programming form requires the creation of extra variables, extra boolean clauses, and at times, replication of code. For sufficiently large N, there exists an N-statement program written with
gotos that requires N! statements when without any
gotos. Those extra boolean clauses and the replicated code act to increase static analysis metrics such as complexity.
The statement
if (a && b) do_something(); can be rewritten as
if (a) if (b) do_something(); The two forms are functionally equivalent but have different cyclomatic complexity (2 versus 3). They do however have the same extended cyclomatic complexity (3). Another way to look at it: To achieve 100% code coverage using a good code coverage tool one would have to write three test cases for this
do_something() code snippet, regardless of the form in which it is written.mXSCNT, what you and AuMathTutor are doing is creating phony arguments against the use of
goto. I posted a link to a section from
Code Complete in post #77. Did you read it? That a five line code snippet that can be written without using
gotos is a phone argument against
gotos. Where the use of
goto is justified is in halving the lines of code and decimating the complexity of a 800+ line monstrosity with a cyclomatic complexity of 96.
In my experience,
gotos are most likely to be used in projects where some fool of a project manager has mandated the atrocious (IMHO) "single return" anti-pattern and has ruled out use of
break and
continue to boot. These rules practically mandate the use of
gotos in complex functions where guards must be placed against errors.
One way around the error guard use of
gotos is to use exception handling, if available. There are two problems with this. One is that using the exception handler for expected behaviors (e.g., EOF; every file has an EOF, so hitting EOF is not an exceptional thing to do) is itself an anti-pattern, the "Expection Anti-Pattern". Another problem is that in real-time programming, the words
try,
throw, and
catch are made illegal. (Exceptions are slow, which alone wreaks havoc with many real-time scheduling algorithms. That exceptions typically involve hopping in and out of kernel mode wreaks serious havoc with scheduling algorithms.)
The easiest way to avoid having any
gotos is to allow the use of the
return,
break and
continue statements. Example: A common requirement in the simulation world is that behavior models must be disable-able and must not perform any computations (other than testing for being disabled) if they are disabled. I would much prefer to see
if (disabled) return; at the very start of a model implementation than any other construct. Verification of this requirement is then achieved by a simple code inspection that takes a few seconds.