|
I like single returns but there are exceptions. Sometimes checking needs to be done at the start of a function. Checking that needs a couple of lines, not a single if . Sometimes there are 2-3 such checks. The single-return-rule would force the entire function to be indented 2-3 extra levels. Multi-return: zero extra levels.
"If we don't change direction, we'll end up where we're going"
|
|
|
|
|
Years ago I was working with people who insisted on single point of return and single loop termination, with no exception whatsoever. Both continue and break out of loops were "forbidden". These were also people who insisted on putting opening and closing braces on separate lines, and always enclose the body of an if in braces, even a single assignment (so the minimum line count for an if statement was four, eight lines for an if/else). In some code, opening and closing braces made up at least a third of the code lines.
I guess that made me stall. I got sick of vading through jungles and fords of little more than braces. Finding the end of a loop, or even a function, required you to leaf through pages by pages of code with minimal information content.
In my first programming course, one basic principle was taught: Always fit a function in a single page, so that you can overview all of it. Obviously, the main message was to choose a suitable abstraction level and factor out common sub-operations, but if an if/else costs you a minimum of eight lines, you can't build much abstraction (for the next level) in a single page!
So I use breaks, continues and returns, to keep the function logic together, not spread over multiple pages / screenfuls. If you immediately see where the loop ends, or you have all the returns on a single page, you will easily manage it. If you like to water out your code with tons of braces and elses and umpteen nesting levels, then you loose control over your returns. But that is exactly what returns and continues and breaks are meant to avoid.
|
|
|
|
|
Forogar wrote: This caused horribly messy code
Nah. Earlier return is both much more readable and more logical too.
More readable: you don't have to skip around when following a given execution path, you just follow it to its return.
More logical: you don't have to keep anything you don't need anymore in mind. When the function is done with it, it's returned and doesn't add to the cognitive load anymore.
The time when single exit point was a 'good practice' was, IIRC, during the structured programming days, as an antidote to goto statements.
Forogar wrote: introduces an execution statement (return) on the same line as the "if" which is bad coding practice
Huh? why? It's only styling. I would avoid having it under the if without brackets, because that's confusing sometimes, but on the same line? No problems.
|
|
|
|
|
I have developed c, C++, C# SW for decades. I believe that when an exception occurs, not only must it identify where and what went wrong, but if possible, how to fix it and who to blame. In a recent conversation, my opposite number who has decades of experience pointed out a way to handle this situation in the complicated code we use. Use a goto statement. It is only used within the body of a method and only to take you to the end of the method. It solves a ton of problems with flow and retaining error information. In my past decades of development, I've only used the goto statement once (gotoxy many times ) I plan to use it much more... ONLY WITHIN A METHOD THOUGH!
|
|
|
|
|
I use 'early' returns only to handle errors (typically input or 'no data' errors that don't merit throwing an exception) where the function is returning some sort of null value or an error code.
|
|
|
|
|
When multiple returns reduce the nesting inside a module they make a lot of sense (as well as making the code more readable in my opinion). This is similar to using the && and || conditionals that only evaluation clauses as needed.
|
|
|
|
|
For me, as a novice, my first concern is can I read and understand the code after a good nights rest.
After I get it running, then look for ways to make it better. Of course VS2017 does a lot for me.
I use inline returns all the time for avoiding null errors when getting data from a DataGridView.
But, for compound conditions it depends on what I am doing and whether they can be easily combined.
As for the final version with the "?" for me that obfuscates what is happening. But, then I am a novice.
In this case I would probably settle on the next to last version.
|
|
|
|
|
i would go ether way for what produces smaller and simpler code.
since this is a trivial example it is difficult to speak in general.
in this case i wouldn't go for No.1 it's against my taste, but No.2, No.3 and No.4 are OK.
No.2 and No.3 seem to have a different philosophy but they do exactly the same thing, imminent return if s == null.
i think No.2 is the way assembly coder would see the situation and No.1 would be how a Pascal programmer sees it. structured style programmers would go for a one exit routine, but sometimes that makes code especially complicated.
|
|
|
|
|
I would argue there is no “one way”. When it makes sense use an early return, then do so. The problem I so often see is both methods are used poorly. Programmers use embedded return statements when they should be throwing and catching errors, or they will have one method which has five different returns (bad). Or they use 5 tier “if” statements which is usually an indication that they may need to refactor code, maybe use function overloading or polymorphic behavior. In my opinion, programming is as much art as it is science, knowing when to apply the rules and when not to.
|
|
|
|
|
One way into a method, one way out (not counting ref and out parameters, which are intuitively obvious).
After 40+ years in software development, my tolerance for lazy programmers that just want to hack up some code and get the minimum done with the least time - is very low.
Some software shops are starting to use an approach I have used for years when I hired developers. Instead of hiring 10 "full stack" developers with an eye to cheap labor, H1-B and other inexperienced programmers cranking out poor code that just barely works for today, they take a different road.
For those 10 positions, they hire 6 experienced software engineers that understand how to code for value engineering, supportability, likely future needs, performance, readability, and meaningful comments. A 7th junior developer is hired who has an attitude and willingness to learn from the senior developers - a person whose character is teachable. No H1-B's.
The end result is better code, faster development cycles, fewer bugs, and lower life cycle cost.
Experienced software engineers understand how incredibly sophomoric it is to have multiple returns.
Now get off my lawn!
|
|
|
|
|
MSBassSinger wrote: my tolerance for lazy programmers that just want to hack up some code and get the minimum done with the least time - is very low. A very strange ad hominem rationale for a personal prejudice applied to a technical issue.
«Where is the Life we have lost in living? Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?» T. S. Elliot
|
|
|
|
|
Not strange if you make the connection between multiple returns and lazy programming.
Then use that as an example of a broader problem in software engineering today.
After 40 years in the business and Navy Nuc school, such observations are intuitive.
|
|
|
|
|
I prefer early return for domain errors like passing nullptr into a function that wants to operate on the object.
I prefer multiple returns over nested indents because after two or three levels of indentation, I can't remember what conditions held in the block I'm in.
I have the painful experience of using a language (Pascal) that only permitted a function to return at the bottom, and I almost always needed an auxiliary variable to record exit from nested loops.
You can't get rid of implicit control transfers in languages that have break in switch statements, continue and break in loops, and an explicit return statement. Better to learn to live with it.
|
|
|
|
|
What about 1 return and no braces
void SomeFunction(SomeThing s)
{
if (s == null || s.Thing == null) return;
}
Just put all your conditions into that 'if' clause.
Too many conditions?
Use a method to test the conditions and call that method from the 'if' clause
Regards
GregJF
|
|
|
|
|
Fascinating discussion !
While recognizing the special constraints of device driver, and down-to-the-hardware specific, programming, in a high-level language, like C#, with a powerful optimizing compiler, I favor multiple returns, and "defensive" error checking (throw immediately) wherever possible, asap.
For me, "deeply nested" is for the (recursive) birds.
«Where is the Life we have lost in living? Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?» T. S. Elliot
|
|
|
|
|
Single ``return`` or multiple ``return`` I think is a potential code smell - based on design and code format agreements.
I like the concept of having the guard statements and their ``return`` or ``throw`` exception small and tight at the beginning of a function/method. Putting the error handling into an ``else`` block can destroy the readability.
We recently found a method in a work project where we were setting a ``results`` variable to ``true``, and then calling ``return false``. The last line of the method was to ``return results``. (Of course, no comments what team member that is no longer with the company was thinking.) This was in the logic and processing, not in guard statements.
I think using negation logic can also be a code smell
void doSomething(var a)
{
if (a == null)
{
throw new Exception("a == null");
}
else
{
}
}
is more readable than
void doSomething(var a)
{
if (a != null)
{
}
else
{
throw new Exception("a == null");
}
}
|
|
|
|
|
I had to write some incredibly complicated business rules.
Imagine that we charge a 3% fee.
But there are like 19 situations where the fee is either more or less than that fee.
The fees are also relative to that 3% fee, which is customer specific.
I thought long and hard about how to write this to clarify the businesses intent, and used an infinite loop to avoid the return, but I also had to have a STRING indicating which rule was applied for logging, as well as to generate the invoice.
while (true) {
if (condition1) {set %; set sMsg; break}
if (condition2) {set %; set sMsg; break}
break;
}
logIt("Rate Calculation",sMsg, % as string);
setup return variables
return;
}
The upside of this code was that the comments, and the FLOW were ratified 3 times by the business side. The code went into production 20 years ago, and was never modified.
Is this similar to the "many returns"? Yes, in a big way. There are many exits from the loop, but it captures the flow and priority perfectly. In fact, there was a decent amount of pre-loop setup code that calculated pieces to make the conditions make sense and be readable to the business people.
While I am HUGE on coding standards and code reviews. There are ALWAYS unique coding situations where I will gladly throw them all out the window to produce Highly Provable code that is easy to process and find errors in!
|
|
|
|
|
Did Pink Freud release an album called "The Dark Side of Your Mother"?
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
|
there's no dark side of your mother really, matter of fact she's all dark
Message Signature
(Click to edit ->)
|
|
|
|
|
Hey now. Isn't the preferred term "African American"?
|
|
|
|
|
Not if she's not an American!
- I would love to change the world, but they won’t give me the source code.
|
|
|
|
|
I met with a cringeworthy left extremist here who referred to a colleague as "African American".
I told her that the dude she was referring to had nothing to do with Africa or 'Muhrica, and just for kicks asked her why was she being condescending and insulting about an aboriginal Australian.
The look on her face was priceless.
modified 15-Feb-19 15:50pm.
|
|
|
|
|
That was intentional in my response. There's plenty of "dark people" (ahem) who get referred to as "African Americans", even though they weren't born or might not have ever been to either Africa of 'Muhrica.
Political correctness gone mad. But then, I don't know of any other type of political correctness.
|
|
|
|
|
dandy72 wrote: That was intentional in my response.
Yup, I figured that much.
dandy72 wrote: Political correctness gone mad. But then, I don't know of any other type of political correctness
Very true!
|
|
|
|