4 ms·
For some of these reasons, I prefer to write this: if (condition){ throw } else { <rest of code> } Rather than: if (condition
by shadowofneptune 4y ago
For some of these reasons, I prefer to write this:
if (condition){
throw
} else {
<rest of code>
}
Rather than:
if (condition) {
throw
}
<rest of code>
The justification, which I found in this presentation (https://youtu.be/SFv8Wm2HdNM https://youtu.be/SFv8Wm2HdNM) is that if you only looked at the block structures, could you tell that the rest of the code might never run?
- layer8 4y agoThe counter-argument is that you can get arbitrarily deeply nested code that way. The second style uses what is known as guard clauses. The way to think about it is that it establishes a precondition that the rest of the code can then assume is met. It is similar to an assert statement, or to precondition checks in a design-by-contract language. You don’t want to indent the regular-case code just because it is preceded by a guard. If you have multiple such conditions, it’s like going through a checklist of what you have to check before continuing with the actual operation. Moreover, if you have exceptions, any line of code containing a function call can potentially throw, so that the subsequent lines at the same level are not executed. (So you can’t see from the block structure if code is always executed anyway, when the language uses exceptions.) This is as if you’d factored out the guard clause into a separate function that you invoke at the location where you previously had the guard clause. In the if-then-else alternative, you can’t factor out the if-then separately from the else. The guard-clause style thus also affords more flexibility regarding code organization.
- shadowofneptune 4y agoI came across the awkwardness this introduces to guard clauses a while back, and found that it could act as a smell. Instead of drip-feeding the validation, do it all at once if you can. I do see what you mean with your second paragraph, though. It's a good argument against.
- layer8 4y agoDoing it all at once suggests factoring out all checks into a separate function, in which case it also makes sense to throw from that function, in order to give good exception messages depending on the specific error, and possibly including associated data in the exception. Which means that at the call site you won’t have any indented block structure differentiating the validation call from the rest of the function. When programming with exceptions, it is the common case that a function consists of a sequence of steps each of which can fail and thus abort the function via an exception. Simple validation steps are not a special case in that respect.
- ncmncm 4y agoOf course the same argument applies to return statements. And breaks. Some of us use a convention of a blank line after a block that ends with return, throw, break, or continue, to save on indentation. Of course that can help only if you are not splattering blank lines everywhere, communicating only that you think the reader doesn't deserve to see much of your code at once.