News for hackers. Stuff that matters.
Re:Programming Patterns I Like by fjfaase on Saturday June 29, 2019 @03:01AM (#20311199)
As, with everything, it should be applied wisely. In most cases, I think it is perfectly fine to have early exits on parameter checks at the start of the function/method. Otherwise you end up with deep nested if-then-else or complex conditional expressions. And yes, having multiple exits in complex functions, is a bad code smell. Often indicating that the function needs to be refactored, split is smaller functions. I also prefer to use early exits (also with break), if I can avoid the introduction of an Boolean variable. Returns, gotos, breaks, and continues are not in themselves bad. It is people who do not know how to use them wisely, are bad at software engineering.
Re:Programming Patterns I Like by quadcore on Saturday June 29, 2019 @03:13AM (#20311246)
As, with everything, it should be applied wisely.

Early returns is not a feature of the language. It's an artefact of assembly language. You have no reasons to use it in the first place.

In most cases, I think it is perfectly fine to have early exits on parameter checks at the start of the function/method.

I believe you'd be surprised what aberrations you'd find in your code and all the simplifications you could make if you would removed all the jumps.

Re:Programming Patterns I Like by irjoe on Saturday June 29, 2019 @03:44AM (#20311337)
I'm currently writing a lot of Elixir where early returns are a feature of the language (https://hexdocs.pm/elixir/Kernel.html#module-guards).

I also write a lot of JS and tend to use guard clauses fairly liberally. I find they make boundaries (x < 0) much clearer. My functions are also < 10 lines in most cases. For me it leads to less convoluted code but YMMV.

Re:Programming Patterns I Like by sterwill on Saturday June 29, 2019 @08:45AM (#20312271)
I love Elixir, but I don't think of guards as "early returns". They're more like preconditions or filters: they prevent the function from running at all if they don't match, and because they're applied top-down in the module, it's really easy for the programmer to find the one that should match. They're great!

Other programming languages let you return from any line in the function, no matter how deep in a conditional, inside nested loops, before or after variable side effects, etc. Tricky to know just _what_ that function will do given some inputs.

Re:Programming Patterns I Like by irjoe on Saturday June 29, 2019 @09:36AM (#20312489)
You're right, they're not really "early returns" but for me at least they are often in similar fashion to the "early exit" pattern in the article:

    def transform_data(raw_data) when length(raw_data) == 1, do: []
    def transform_data(raw_data) do
        # actual function code goes here
    end
That said, I wouldn't want to see the above snippet in my team's codebase :)
Re:Programming Patterns I Like by rrobukef on Saturday June 29, 2019 @04:08PM (#20314501)
Not a fan of prolog then? As an excercise, find the guard in this snippet (https://rosettacode.org/wiki/Babbage_problem#Prolog) and imagine such code in a team codebase!
Re:Programming Patterns I Like by irjoe on Sunday June 30, 2019 @05:19AM (#20317225)
Quite the opposite :) My preference would be to rely on pattern matching (unification) in the function head:

    def transform_data([_|[]]) do: []
I just wanted an example of using guard clauses. It does depend on the actual code though, there's probably a more elixiry solution.
Re:Programming Patterns I Like by solarkraft on Saturday June 29, 2019 @03:29AM (#20311292)
Are early returns essentially equivalent to gotos?

I suppose I could get rid of early returns with a variable and breaks, but is it worth it? My functions tend to be small enough for me to not run into problems with early returns.

Re:Programming Patterns I Like by quadcore on Saturday June 29, 2019 @03:36AM (#20311309)
massively edited. very interesting, thanks for the comment

They are literally goto end. It used to be done like that a lot actually.

I suppose I could get rid of early returns with a variable and breaks, but is it worth it?

Very good question. My claim is that yes it is tremendously worth it if you care about great code. The reason is because by introducing intermediate variables (or by using more the ternary operator ?) you will have a more expressive code, and then you will subsequently take better decisions when you will write/maintain/refactor it. And more importantly, you will refactor it because you can (how do you move code that's full of early returns?). At the end, your program will be much simpler and better (less bugs, faster, etc). Just try it in a big-enough program, you will not come back to the old ways, I think.

My functions tend to be small enough for me to not run into problems with early returns.

Very interesting. This point would require a live discussion. Many things are at play here, between over engineered object-oriented programs where everything is broken into little pieces that shouldn't (most of the time you should make a function when it's called twice, not because it represent a world object) and also, I'm not surprised you guys don't do bigger functions since you fill them with early returns. In clear, what I'm saying is: are you guys not able to write any big functions because of the early returns? I wasn't expecting that, sounds almost plausible. You end up breaking things up way too much, over engineering things and all just to avoid bigger functions because you can't have them because of the early returns? Very very interesting. Of course this is complete conjecture and certainly not true. Or is it?

edit: it also depend on what you mean by worth it. In terms of market value, you will not be rewarded because the market the doesn't reward great code so much anyway, broadly speaking.

Re:Programming Patterns I Like by kd5bjo on Saturday June 29, 2019 @05:41AM (#20311669)
> They are literally goto end.

So are a lot of other constructs:

break is goto the end of the loop, continue is goto the beginning of the loop, the closing of a loop block is goto the beginning of loop, else is goto the end of the conditional, if is maybe goto the next else, and return (early or not) is pop from the stack and goto that address.

The fact that a language feature uses a JUMP instruction does not make it necessarily evil; most of them do. Everything has both benefits and drawbacks which are often highly situational.

You may find it easier to convince people of the problem with early returns if you limit the scope of the argument to a more specific context than “always”: it’s usually easier to make an argument for a concrete case rather than an abstraction, and then show how the same reasoning applies to a large class of situations.

Re:Programming Patterns I Like by solarkraft on Saturday June 29, 2019 @01:19PM (#20313665)
Thanks a lot for the elaborate reply. I do tend to break things up into small functions. Why is that over-engineering? It makes it easier for me to reason about my code. It also makes it easier to refactor sometimes, although of course you're now restrained by the function's construct, so it becomes more difficult to move things between functions.

Do I understand correctly that you tend to make large functions because they're easier to refactor (and not returning early makes this easier)?