"Never use early exits" is tantamount to saying "never study programming languages deeply enough to understand control-flow graphs". That's not simply a good rule of thumb, it's a terrifying omission. I would suggest that early exists are simply a matter of taste and never using them is the crutch that keeps junior developers junior.
Data are on my side here: a quick perusal of the Quake 3, the Linux kernel, the Clojure runtime, and LevelDB show that Carmack, Torvalds, Hickey, and Dean all use them where appropriate.
Specifically try to judge whether an "early exit" leads to simpler, more maintainable code in this particular case. Optimize for lower cost, not for just following a rule.
Agreed. A lot of the time, early exits just make sense. Instead of holding a variable called "succeeded" and doing a bunch of if elses, why not just continue on every failure? You're only testing for half a dozen side-cases and just exit out early when you encounter any one. No need to wrap all of your actual work in 5 levels of if elses.
That one caught me up too. Maybe if you have full control of the input data and performance is not a concern, then they should be avoided, but "never" is a pretty small set.
Although 'never' is a very hard word, I found that in real live most code that uses early exists simply breaks SRP (come to think of it 99% of the time that is the case)
I know people will say "but I will only write this little return statement here" before you know it you will "add this little assignment before it returns" ...
Never might be strong but it make a very good point.
Data are on my side here: a quick perusal of the Quake 3, the Linux kernel, the Clojure runtime, and LevelDB show that Carmack, Torvalds, Hickey, and Dean all use them where appropriate.