|
Simply do it how you think it's ok. As long as it's only a question of preferences, I see no salomonian compromise.
Why?
Let's assume you can keep the method short and to the point, with only few conditions that 'spaghettify' the code. In that case I hope that all people involved are intelligent enough to read the code, despite it not having their preferred format.
In the other case, hopefully rare, where you have no choice and the method gets a little longer and has many if/else conditions, then religiously trying to put it in a certain format will most probably 'spaghettify' it even more and make it even harder to understand.
That's why I always prefer good judgement over religiously (meaning thoughtlessly) enforcing 'standards' at all cost. Whose standards? Those of the team as a common ground or those of a few beaurocrats who never find an end?
Been there, done that. I was once in charge of writing the 'rulebook' and code review. It kept getting longer every week. Rules, more rules, exceptions to the rules and then of course alternate rules. In the end it was always one or two people who turned the code review into a discussion about their personal preferences while the rest of the team started to ignore the whole worthless circus and automatically getting the buerocrats off their backs by giving them so much to freak out about that even they could not keep up with inventing more 'standards'. If those idiots want someone to type exactly what they want, why don't they get themselves a secretary?
I have lived with several Zen masters - all of them were cats.
His last invention was an evil Lasagna. It didn't kill anyone, and it actually tasted pretty good.
|
|
|
|
|
The (professional) opinion is that humans work better with "positive" statements vs deciphering compound negatives.
I will even resort to:
if ( a && b && c ){
// continue.
} else {
return;
}
... for myself.
("Early returns" probably run contrary to the notion of "diving into the code"; but since code should not run more than "a page", "diving" implies a bigger problem).
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
modified 15-Feb-19 13:57pm.
|
|
|
|
|
I believe I am in the minority on this but I prefer one single return statement. Multiple returns adds unnecessary confusion. For example, if you put a breakpoint near the end of a function and it never hits it may be because of the early returns so you have to go hunting around to find out what's going on.
One return.
Social Media - A platform that makes it easier for the crazies to find each other.
Everyone is born right handed. Only the strongest overcome it.
Fight for left-handed rights and hand equality.
|
|
|
|
|
Putting a break point that does not get hit where you expect it to only implies that one does not understand the program flow; not that there could be "too many returns".
Without a try-catch block everywhere, every exception amounts to an "early return".
Also, "early returns" facilitate the returning of different "condition codes"; instead of "tramping" them along.
A la IBM;
0 - Good
4 - Good with conditions
8 - Warning
16 - Oh Oh
...
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
Gerry Schmitz wrote: only implies that one does not understand the program flow; Exactly!
But it's very easy to assume the code is failing down near the bottom of the function and therefore you put the breakpoint there because you don't want to step through all of it.
Social Media - A platform that makes it easier for the crazies to find each other.
Everyone is born right handed. Only the strongest overcome it.
Fight for left-handed rights and hand equality.
|
|
|
|
|
Nice and well, until you sit in the middle of several levels of conditions, something goes wrong and you want to get out of there. What then? Awkward nested if/else blocks? Or do we just make use of the good old GOTO to hop to your single return at the end? I do exactly that often enough in assembly programs, just because I need a single return as a point where I clean up the stack frame before actually returning. I don't really see the point if it's only a matter of principle.
I have lived with several Zen masters - all of them were cats.
His last invention was an evil Lasagna. It didn't kill anyone, and it actually tasted pretty good.
|
|
|
|
|
CodeWraith wrote: something goes wrong and you want to get out of there That's when you throw an exception.
CodeWraith wrote: Awkward nested if/else blocks? Maybe breaking things into functions would be better.
Social Media - A platform that makes it easier for the crazies to find each other.
Everyone is born right handed. Only the strongest overcome it.
Fight for left-handed rights and hand equality.
|
|
|
|
|
ZurdoDev wrote: That's when you throw an exception. In what way is that better than an early return if your goal is to have a single return point? And catching it yourself at the end of your function does not justify the overhead of throwing an exception. The dreaded GOTO would then be cheaper and no more or less problematic.
ZurdoDev wrote: Maybe breaking things into functions would be better. Unless you can't afford to bog down the processor with too much overhead of packing parameters onto the stack or cleaning it up afterwards. On a strong processor that's no big deal anymore, but often enough I sit there with a C compiler and a small microcontroller clocked < 10 MHz. Usually some output pins need to be pulled up or down according to a certain timing, leaving me only a few machine instructions on the microcontroller within that timeframe. In that case I may have to resort to inline assembly and can't afford any function calls.
I have lived with several Zen masters - all of them were cats.
His last invention was an evil Lasagna. It didn't kill anyone, and it actually tasted pretty good.
|
|
|
|
|
CodeWraith wrote: inline assembly and can't afford any function calls. Different rules apply to assembly vs. OOP.
Social Media - A platform that makes it easier for the crazies to find each other.
Everyone is born right handed. Only the strongest overcome it.
Fight for left-handed rights and hand equality.
|
|
|
|
|
ZurdoDev wrote: Different rules apply to assembly vs. OOP Actually it's C code with some inline assembly, if needed. Good C code quickly borders on object orientation, just think of structs containing function pointers plus some preprocessor magic to call the 'constructors' and 'destructors'. That's essentially the way C evolved to C++.
You are right, but the rules don't change by what paradigm you choose. It's more like the processor dictating which paradigm you can afford. I still have my first computer, which I built almost 41 years ago. It has a hex keyboard and I still write machine code programs for it. You would not believe how much neatly calling functions bogs down the old processor or how quickly the code to pass parameters to the functions via the stack can eat up the tiny 4k RAM. Old programs are usually a single chunk of spaghetti code, only maintainable because they can't be very large, but they shurely make more out of these limited resources.
I have lived with several Zen masters - all of them were cats.
His last invention was an evil Lasagna. It didn't kill anyone, and it actually tasted pretty good.
|
|
|
|
|
CodeWraith wrote: Nice and well, until you sit in the middle of several levels of conditions, something goes wrong and you want to get out of there. What then? For those situations, I loved the exit mechanism in the CHILL language: Any composite statement could be labeled (a function body was a composite statement labeled by the function name). The label did not identify a "point" in the code, but the entire composite. So you could exit any composite statement by "EXIT label".
(Another nice use of the label: You could add it to the termination of the composite statement, any sort of END statement, easing the reading of deeply nested code, and the compiler would check the label to make sure that you made no mistakes in the nesting.)
Unfortunately, CHILL never got out of telephone switch programming (for which it was developed). It really was a nice language in a lot of respects.
|
|
|
|
|
ZurdoDev wrote: One return. There is only one return, from the program-flow perspective: the one it hits first.
When a program is running, the number of lines of code that are read varies according to loops and if statements. Having lots of quickly finished loops and quick escapes from if blocks is like hitting green lights all the way down the road.
Save your processor a billionth of a second of effort: let it get out as soon as it knows it has to get out.
I wanna be a eunuchs developer! Pass me a bread knife!
|
|
|
|
|
Mark_Wallace wrote: Save your processor a billionth of a second of effort Depending on the processor and the stack protocol you use to pass parameters and return values, you may find that you gain little to nothing.
Been there recently when I had to modify the 'traditional' call protocol of my old computer. Now it uses a second stack to pass parameters and return values, instead of inlining the parameters with the code for the call. Yuck, was way to close to self modifying code!. And I extended the address of the subroutine to 24 bits, so that I now can do bank switching in the calling protocol and call code anywhere in a 16 Mb memory space without the processor noticing anything. Not bad for a 40 year old 8 bit computer. If only there was a convenient way to access data anywhere in that memory space as well.
I have lived with several Zen masters - all of them were cats.
His last invention was an evil Lasagna. It didn't kill anyone, and it actually tasted pretty good.
|
|
|
|
|
Sounds like my kind of toy!
I wanna be a eunuchs developer! Pass me a bread knife!
|
|
|
|
|
I prefer one return but if I am working with people who go ape-sunshine about it I will defer to their preference. Life is too short to wage war about that.
All the while muttering under my breathe that their way leads to confusion and makes debugging more difficult like someone else already pointed out.
I'm passive-agressive that way.
|
|
|
|
|
Multiple returns can lead to resource leaks if not handled properly (think of RAII)
I'd rather be phishing!
|
|
|
|
|
|
Exactly what do you mean? In C++ RAII like objects (allocated on the stack) get destructor calls as soon as you go out of scope, even if you exit by exception.
"If we don't change direction, we'll end up where we're going"
|
|
|
|
|
It took me a long time to accept multiple returns. Meanwhile I love the concept "If a decision is clear, draw the consequences".
And even though, if you are honest, it's a disguised goto; similar to a lot of MS code examples where a loop/break will be "missused".
It does not solve my Problem, but it answers my question
modified 19-Jan-21 21:04pm.
|
|
|
|
|
Forogar wrote: if (s != null && s.Thing != null)
This.
Or better yet
void SomeFunction(SomeThing s)
{
if (null == s || null == s.Thing)
{
throw blah;
}
}
|
|
|
|
|
fail fast, fail early. end of story.
|
|
|
|
|
Forogar wrote: which is bad coding practice You have to look into who says it's bad coding practice.
Let's be honest: the computer doesn't care. It just some human's personal preference, which he's written down in a book.
You don't have to follow anyone's personal preferences -- the computer doesn't care whose preferences you follow.Forogar wrote: This makes a complete hash of the natural flow of the code OK, if you see it that way, that's your preference, and I won't try to change that.
But, to me, it looks like that's a way that the computer would be happier doing it, so my preference in this doesn't match yours.Forogar wrote: If I was to refactor the code If I were to refactor your statement, it would look like this:Mark Wallace prefers: If I were to refactor the code Which amounts to the same thing; it's all about personal preferences.
Make sure that you follow your own preferences, not those of someone who wrote a book, just because a few of his other ideas are good.
... Unless, of course, you have coding standards, where you work -- in which case, follow those religiously.
I wanna be a eunuchs developer! Pass me a bread knife!
|
|
|
|
|
I'm definitely in the single exit camp.
And, after browsing this thread, finding it very hard to argue the case for it beyond "'cause I am, that's why!"
I just like knowing there's a single exit point where I nuke that pointer if it's non-null etc.
"Look here you function - or threadproc - or whatever it is you call your self, you're not getting out of here until your hair is combed and you've buttoned your shirt."
If I were to use the multiple return paradigm I think I'd use multiple goto exit 's instead. Which seems kinda uglee.
I'm definitely in the single exit camp.
'cause I am, that's why.
|
|
|
|
|
Tim Deveaux wrote: after browsing this thread, finding it very hard to argue the case for it beyond "'cause I am, that's why!" That's a good enough reason.
Me, I see adding returns where they fit as being more efficient (which it is), but unless you're doing something really intensive like editing high-res game graphics or video (where loops and if-blocks are hit, quite literally, billion of times), it won't make a difference that's human-noticeable, so stick to what you're happy with, and what makes your code easier on your eye, when you have to revisit it.
Tim Deveaux wrote: If I were to use the multiple return paradigm I think I'd use multiple goto exit 's instead. Which seems kinda uglee. Every jump to a non-sequential line is a goto. Loops and if statements were invented to save you the trouble of writing endless goto lines, by adding them for you, in the background behind the code.
Think: What does return do that goto doesn't?
(Answer: it satisfies the anti-goto evangelists, by using a function named "return", which does nothing but call goto.)
Saying that the goto is unacceptable is saying that if and for are unacceptable. Never be afraid of using a goto in sequential code, as long as you use it intelligently.
E.g. exiting an if-block with a goto is usually fine, but exiting a loop with a goto often isn't (unless you're only using global variables, which... Yeah, no need to expound on that one).
I wanna be a eunuchs developer! Pass me a bread knife!
|
|
|
|
|
Mark_Wallace wrote: ... stick to what you're happy with
Yes - in that it's a matter of style.
If I was working on a codebase that used the fast exit religiously, I'd stick to it - better not to mix styles.
But my style it definitely ain't - and that's part of it - the reassurance that if I wrote this my way it exits here - which is worth more to me than the (alleged) increase in readability.
|
|
|
|