Loop-switch sequence: Difference between revisions

Content deleted Content added
No edit summary
 
(27 intermediate revisions by 23 users not shown)
Line 1:
{{Orphan|date=October 2022}}
A '''loop-switch sequence''' is a specific derivative of the [[spaghetti code]] programming [[antipattern]] where a clear set of steps is implemented as a [[byzantine failure|byzantine]] switch-within-a-loop. Also known as "The FOR-CASE paradigm" [http://thedailywtf.com/Articles/Switched_on_Loops.aspx].
 
A '''loop-switch sequence'''<ref name="LEVEL ">{{cite web | url=https://levelupcode.wordpress.com/avoid/loop-switch-sequences/ | title=Loop-switch sequences | date=30 November 2013 | publisher=LEVEL UP CODE | accessdate=11 April 2016}}</ref> (also known as the '''for-case paradigm'''<ref>[http://thedailywtf.com/Articles/The_FOR-CASE_paradigm.aspx The FOR-CASE paradigm] and [http://thedailywtf.com/Articles/Switched_on_Loops.aspx Switched on Loops] at [[The Daily WTF]]</ref> or Anti-[[Duff's Device]]) is a programming [[antipattern]] where a clear set of steps is implemented as a switch-within-a-loop. The loop-switch sequence is a specific derivative of [[spaghetti code]].
'''Note: ''' it is not necessarily an [[antipattern]] to use a switch statement within a loop. It is only incorrect when used to model a known sequence of steps. The most common example of the correct use of a switch within a loop is an event handler. In event handler loops, the sequence of events is not known at compile-time, so the repeated switch is both necessary and correct. (see [[Event-driven programming]], [[Event loop]] and [[Event-driven finite state machine]]). Also regarding the alarm that could trigger the possible performance loss that a conditional inside a loop could bring. Today modern compilers are capable in some cases to transform the loop with conditional(s) into a construct with better performance. Therefore not constituting an anti-pattern in some cases and not worth to look at when maintaining code. (see [[Loop unswitching]])
 
'''Note: ''' itIt is not necessarily an [[antipattern]] to use a [[switch statement]] within a loop. Itloop—it is only considered incorrect when used to model a known sequence of steps. The most common example of the correct use of a switch within a loop is an [[inversion of control]] such as an event handler. In event handler loops, the sequence of events is not known at compile-time, so the repeated switch is both necessary and correct. (see [[Eventevent-driven programming]], [[Eventevent loop]] and [[Eventevent-driven finite state machine]]). Also regarding the alarm that could trigger the possible performance loss that a conditional inside a loop could bring. Today modern compilers are capable in some cases to transform the loop with conditional(s) into a construct with better performance. Therefore not constituting an anti-pattern in some cases and not worth to look at when maintaining code. (see [[Loop unswitching]])
==Example of antipattern (pseudocode)==
 
This is not a performance antipattern, though it may lead to an inconsequential performance penalty due to the lack of an [[Loop unwinding|unrolled loop]]. Rather, it is a clarity antipattern, as in any non-trivial example it is much more difficult to decipher the intent and actual function of the code than the more straightforward refactored solution.
<source lang="java">
 
==Example==
// parse a key, a value, then three parameters
 
An event-driven solution would implement a [[Observer pattern|listener interface]]:
String key;
<sourcesyntaxhighlight lang="java">
String value;
String key = stream.parse()null;
List<String> args;
String value = stream.parse()null;
List<String> argsparams = null;
for ( int i = 0; i < 5; ++i )
int column = 0;
{
 
switch( i )
public void addToken(token) {
{
 
case 0 :
// parse a key, a value, then three parameters
key = stream.parse();
switch (column) break;{
case 0 :
params = new LinkedList<String>();
case 1 :
value key = stream.parse()token;
break;
case 1 :
default: value = token;
args.add( stream.parse() ) break;
default:
params.add(token);
break;
}
if (++column >= 5) {
}
column = 0;
completeRow(key, value, params);
{}
}
</syntaxhighlight>
 
But without the listener, it becomes an example of the antipattern:
</source>
<sourcesyntaxhighlight lang="java">
// parse 3a key, a value, then three parameters
String key = null;
String value = null;
List<String> params = new LinkedList<String>();
 
for ( int i = 0; i < 5; i++i) ){
==Refactored solution (pseudocode)==
switch( (i ) {
<source lang="java">
// parse a key and value case 0:
key = stream.parse();
break;
String key = stream.parse();
case 1:
String value = stream.parse();
value = stream.parse();
break;
// parse 3 parameters
default:
params.add(stream.parse());
break;
}
}
</syntaxhighlight>
 
And here is the refactored solution:
List<String> args;
<syntaxhighlight lang="java">
// parse a key and value
for ( int i = 0; i < 3; ++i )
String key = stream.parse();
{
String value args.add(= stream.parse() );
}
 
// parse 3 parameters
List<String> params = new LinkedList<String>();
for ( int i = 0; i < 3; i++i) ){
params.add(stream.parse());
}
</syntaxhighlight>
 
==References==
</source>
<references />
 
[[Category:Anti-patternsComputer programming]]