Programmers with lots of hours of maintaining code eventually evolve to return early, sorting exit conditions at top and meat of the methods at the bottom. Same way you evolve out of one liners. Same way comments are extra weight that should only be in public or algorithm/need to know areas. Same way braces go on the end of the method/class name to reduce LOC. Same way you move on from heavy OO to dicts/lists. Same w…
(This example comes from Elixir.)
value = if boolean, do: this_value, else: other_value
is undefined in some circumstances unless an "else" is included.
This pattern might seem weird to OOP folks (the assignment, not the ternary-operator-style logic), but in Elixir-land, it is not only considered superior to assigning inside if/then logic, you actually get a compiler warning if you assign/bind to a variable inside a logical expression because (again) that value becomes undefined as soon as you leave local scope (or re-acquires the value it had in the outer scope, thanks to immutability).
And if you think about it, values can only travel in one direction using this scheme, which further simplifies reasoning about information flows.
I would argue that this is also superior to early-exit as having one entry point and one exit point is much easier to reason about, and because the extra logical complexity you're ostensibly trying to avoid writing by early-exiting is actually still there, it's just obfuscated... and that complexity should be made obvious (in which case, if it's extensive, it would be a code smell... consider the example of a function with 25 early exits that "looks flat" visually, but which actually has 25 different branches)