Michael Feathers’ (of Working Effectively With Legacy fame) post Unconditional Programming is well forth reading. I take the liberty of stealing parts of it:
Over and over again, I find that better code has fewer if-statements, fewer switches, and fewer loops. Often this happens because developers are using languages with better abstractions. [..] The problem with control structures is that they often make it easy to modify code in bad ways.
Includes a nice example of replacing if-else with much more readable and safer code:
A while ago, I was working on some Ruby code and I needed to write a ‘take’ function to take elements from the beginning of an array. Ruby already has a take function on Enumerable, but I needed to special behavior. If the number of elements I needed was larger than the number of elements in the array, I needed to pad the remaining space in the resulting array with zeros.
The naive if-based implementation:
def padded_take ary, n if n <= ary.length ary.take(n) else ary +  * (n - ary.length) end end
The final one, which seems much nicer and easier to understand to me:
def padded_take ary, n pad(ary, n).take(n) end def pad ary, n pad_length = [0, n - ary.length].max ary +  * pad_length end
Read the original post for a full discussion and explanation of why.