Removing if Statements

There's a growing movement of functional programming, and part of that is removing conditions (see Michael Feathers post). In an example a secondary function is used to eliminate the need to have conditions on the length of an array.

Other techniques are to replace conditions with data structures - consider this problem:

  • Tickets 0001-1000 belong to group 1 - addresses are http://greoup1/old/<number_without_leading_zeros>
  • Tickets 1001-2000 belong to group 2 - addresses are http://greoup2/new/<number_without_leading_zeros>
  • Tickets 2001-9999 belong to group 3 - addresses are http://greoup3/tkt_<number_without_leading_zeros>
  • tickets above 1 million aren't yet valid

If one wanted to create a PRCustomLink for this, then they could have conditions like:

| numberPart |
PRCustomLink addConversion: [ :aString | 
			(('Ticket ####' match: aString) and: [ (numberPart := aString copyFrom: 9 to: 13) isAllDigits ])
				ifTrue: [ 
					numberPart asInteger < 1001
						ifTrue: [ 'http://group1/old/' , numberPart asInteger asString]
						ifFalse: [ 
							numberPart asInteger < 2001
								ifTrue: [ 'http://group2/new/' , numberPart]
								ifFalse: [ 'http://group3/tkt_' , numberPart ] ] ] ]

Another implementation would be:

| ticketRunArray numberPart |
ticketRunArray := RunArray new: 1000 withAll: 'http://group1/old/'.
ticketRunArray add: (2000 - 1000) withOccurances: 'http://group2/new/'.
ticketRunArray add: (1000000 - 10000) withOccurances: 'http://group3/tkt_'.
PRCustomLink addConversion: [ :aString | 
			(('Ticket ####' match: aString) and: [ (numberPart := aString copyFrom: 9 to: 13) isAllDigits ])
				ifTrue: [ (ticketRunArray at: numberPart asInteger ifAbsent: [^nil]), numberPart asInteger asString]].

Adding another group of tickets requires changing both implementation (adding more tests in the first, and more entries to the run array in the second), however the first ends up with many close braces while the second just gets another line added. Tests show that the RunArray is 10 times faster for 16 conditions.

Posted by John Borden at 26 July 2014, 10:58 pm link