Although code bootcamps are hailed for a practical education in programming, best practices for long-term efficiency are compromised for rapid proficiency. Don’t get me wrong, the bootcamp movement should be celebrated for leveling-up the economy and empowering the disenfranchised(let’s hope the urgency for accreditation and federal loans doesn’t inflate bootcamp tuition prices), but University will endure as a place for eager minds who won’t settle for how things work and must grapple with why things work. I specifically recall respectfully disagreeing with a bootcamp instructor about the appropriate use of “Conditional If” statements vs. “Case” statements; in fairness, he was only encouraging Agile methodologies for MVP‘s, however, I was right. Evidently, a “Case” statement is most appropriate for solving FizzBuzz (a common interview question asking candidates to reproduce or white-board a function invoking a range of numbers, but for multiples of 3 prints ‘Fizz’ instead of the number, for multiples of 5 prints ‘Buzz’, and numbers which are multiples of both 3 and 5 prints ‘FizzBuzz’), as opposed to a standard “Conditional If” statement, which only a technical deep-dive can reveal—relax—this won’t hurt a bit; here is my solution(extended commentary edition for n00bs):
After consulting my Learning to Program in Java with Alice textbook in addition to other notes, and then verifying my hypothesis with several Google queries, I finally discovered the following within a SERP including a post by Danielle Sucher:
“Personally, I’m pretty intrigued by the fact that if/elsif uses branchUnless, while case uses branchIf. Based on that alone, I’d expect if/elsif to be faster in situations where one of the first few possibilities is a match, and for case to be faster in situations where a match is found only way further down the list (when if/elsif would have to make more jumps along the way on account of all those branchUnlesses).”
The Gist below contains the terminal-output replicating Danielle’s experimentation with RubyVM::InstructionSequence but scoped for FizzBuzz. According to RubyDocs, the InstructionSequence class represents a compiled sequence of instructions for the Ruby Virtual Machine (RubyVM)(YARV) handling “instructions comprising a method or proc, compile strings of Ruby code down to VM instructions and disassemble instruction sequences to strings for easy inspection instructions,” or in short, enabling inspection under the hood of Ruby. Evidently, “Case” and “Conditional If” statement-behaviors are respectively characterized by branchIf and branchUnless.
Academic analysis of algorithms identifies two basic types of sequences, linear sequences and branching routines; think of the former as a set of instructions immediately processed without any consideration for contingencies (e.g. baking a cake; smoking a salmon; calculating Internal Rate of Return (IRR)) because process output only requires input (plug ‘n chug), whereas the latter can account for contingencies through branching (e.g. a computerized water-sprinkler/irrigation controller accounting for weather-if it rains later today, reduce water output by 50%)-and so a branching routine occurs whenever the path or flow of sequential logic in an algorithm splits into two or more paths, or “branches,” AKA selection sequences or selection structures. If there are only two possible paths, the branching routine is binary branching ( e.g. a yes or no question), but if there are more than two paths, then the routine qualifies as a multiple branching algorithm (e.g. open-answer question/paths, like: “What color would you like for your purchased item?”).
For the scope of this analysis, only binary branching will be further examined, reduced to two types: binary bypass and binary choice. In a binary bypass, an instruction is either executed or bypassed, effectively skipped, potentially yielding no result or decisions, whereas in a binary choice, one of two sets of instructions will certainly occur, but not both. Hence think of a binary bypass as equivalent to a standard IF/THEN statement and binary choice as a IF/THEN/ELSE statement.
Consequently, the predictability pattern is the reason why a “Case” statement, or branchIf, is optimal and less expensive than a “Conditional If” statement, as clarified by Igor Ostrovsky’s Blog Post: Fast and Slow If-Statements: Branch Prediction in Modern Processors
“If the condition is always true or always false, the branch prediction logic in the processor will pick up the pattern. On the other hand, if the pattern is unpredictable, the if-statement will be much more expensive.”
Back to my optimized FizzBuzz solution- when the “Case” statement processes a number initializing the method, the constraint or case stops calculating when the condition is satisfied, and it will not continue to verify the constraint by branching unless divisible as it were for an IF/ELSIF construction, which saves time, performing faster, as the best solution possible, ultimately proving Danielle’s point:
I’d expect if/elsif to be faster in situations where one of the first few possibilities is a match, and for case to be faster in situations where a match is found only way further down the list (when if/elsif would have to make more jumps along the way on account of all those branchUnlesses).”
Furthermore, a real programmer can impress an interviewer by asking if the range invoked will be consecutive or random. Although a “Case” statement solution for FizzBuzz is generally more efficient, it will certainly be faster for a random range of numbers called. For the sake of clarity and convenience, here is a direct link to Danielle Sucher‘s post cited herein, Ruby: Case versus If (and a wee bit about Unless) detailing her performance tests. For additional reading, here is another outstanding post “How A Ruby Case Statement Works And What You Can Do With It” by Alan Skorkin. Thank you!
UPDATE: As promised, I’ve substantiated my hypothesis with benchmarking. In conclusion, please find the terminal output and corresponding benchmarks included below for review. Please feel free to ask any questions or challenge. Thank you!