Related
this is not related to any problem in particular but just me thinking.Does the presence of lots of IF statements in code signify bad code design and reduce efficiency or not.
If you really want to optimize the code, be aware of this:
if (complexCalculation(someVariable) > 10)
{
}
else if (complexCalculation(someVariable) > 5)
{
}
the point is, if you are trying to optimize some code, try to "cache" the result of calculations in variables, instead of redoing many times the same calculation
int cached = complexCalculation(someVariable);
if (cached > 10)
{
}
else if (cached > 5)
{
}
Why this? Now... If complexCalculation is deterministic based on its parameters (so complexCalculation(N) == complexCalculation(N) always, in simple words, you call it twice with the same parameters and you will receive both times the same result always) and is without side-effects (so it doesn't modify anything else), then the compiler could optimize it freely. The problem is that quite often the compiler isn't able to verify if a function is deterministic and without side-effects, and very very few languages (primarily the functional languages like F#, Haskell...) make it easy to tell it to the compiler (technically in the functiona languages all the functions should be deterministic and without side effects :-) ).
Theoretically, lots of 'if' statements would not significantly reduce code efficiency. The code simply determines the boolean value of the expression and decides whether or not to continue. If there are many 'if' statements within an iterative loop, however, that could cause a larger problem in terms of efficiency.
Bad design is a whole other issue that I'm not going to mention (Ziminji has covered it better than I could).
In general, the presence of a lot of "if" statement is considered bad design. Consider replacing conditionals with polymorphism. This one of the topics in Martin Fowler's book "Refactoring: Improving the Design of Existing Code" on page 255. Checkout the following article if you don't have the book: http://sourcemaking.com/refactoring/replace-conditional-with-polymorphism
This question is inspired by this question, which features the following code snippet.
int s;
if((s = foo()) == ERROR)
print_error();
I find this style hard to read and prone to error (as the original question demonstrates -- it was prompted by missing parentheses around the assignment). I would instead write the following, which is actually shorter in terms of characters.
int s = foo();
if(s == ERROR)
print_error();
This is not the first time I've seen this idiom though, and I'm guessing there are reasons (perhaps historical) for it being so often used. What are those reasons?
I think it's for hysterical reasons, that early compilers were not so smart at optimizing. By putting it on one line as a single expression, it gives the compiler a hint that the same value fetched from foo() can be tested rather than specifically loading the value from s.
I prefer the clarity of your second example, with the assignment and test done later. A modern compiler will have no trouble optimizing this into registers, avoiding unnecessary loads from memory store.
When you are writing a loop, it is sometimes desirable to use the first form, as in this famous example from K&R:
int c;
while ((c = getchar()) != EOF) {
/* stuff */
}
There is no elegant "second-form" way of writing this without a repetition:
int c = getchar();
while (c != EOF) {
/* stuff */
c = getchar();
}
Or:
int c;
for (c = getchar(); c != EOF; c = getchar()) {
/* stuff */
}
Now that the assignment to c is repeated, the code is more error-prone, because one has to keep both the statements in sync.
So one has to be able to learn to read and write the first form easily. And given that, it seems logical to use the same form in if conditions as well.
I tend to use the first form mostly because I find it easy to read—as someone else said, it couples the function call and the return value test much more closely.
I make a conscious attempt at combining the two whenever possible. The "penalty" in size isn't enough to overcome the advantage in clarity, IMO.
The advantage in clarity comes from one fact: for a function like this, you should always think of calling the function and testing the return value as a single action that cannot be broken into two parts ("atomic", if you will). You should never call such a function without immediately testing its return value.
Separating the two (at all) leads to a much greater likelihood that you'll sometimes skip checking the return value completely. Other times, you'll accidentally insert some code between the call and the test of the return value that actually depends on that function having succeeded. If you always combine it all into a single statement, it (nearly) eliminates any possibility of falling into these traps.
I would always go for the second. It's easier to read, there's no danger of omitting the parentheses around the assignment and it is easier to step through with a debugger.
I often find the separation of the assignment out into a different line makes debugger watch or "locals" windows behave better vis-a-vis the presence and correct value of "s", at least in non-optimized builds.
It also allows the use of step-over separately on the assignment and test lines (again, in non-optimized builds), which can be helpful if you don't want to go mucking around in disassembly or mixed view.
YMMV per compiler and debugger and for optimized builds, of course.
I personally prefer for assignments and tests to be on different lines. It is less syntactically complicated, less error prone, and more easily understood. It also allows the compiler to give you more precise error/warning locations and often makes debugging easier.
It also allows me to more easily do things like:
int rc = function();
DEBUG_PRINT(rc);
if (rc == ERROR) {
recover_from_error();
} else {
keep_on_going(rc);
}
I prefer this style so much that in the case of loops I would rather:
while (1) {
int rc = function();
if (rc == ERROR) {
break;
}
keep_on_going(rc);
}
than do the assignment in the while conditional. I really don't like for my tests to have side-effects.
I often prefer the first form. I couldn't say exactly why, but it has something to do with the semantic involved.
The second style feels to me more like 2 separate operations. Call the function and then do something with the result, 2 different things. In the first style it's one logical unit. Call the function, save the temprary result and eventually handle the error case.
I know it's pretty vague and far from being completely rational, so I will use one or the other depending on the importance of the saved variable or the test case.
I believe that clarity should always prime over optimizations or "simplifications" based only on the amount of characters typed. This belief has stopped me from making many silly mistakes.
Separating the assignement and the comparison makes both clearer and so less error-prone, even if the duplication of the comparison might introduce a mistake once in a while. Among other things, parentheses become quickly hard to distinguish and keeping everything on one line introduces more parentheses. Also, splitting it up limits statements to doing only one of either fetching a value or assigning one.
However, if you expect people who will read your code to be more comfortable using the one-line idiom, then it is wide-spread enough not to cause any problems for most programmers. C programmers will definately be aware of it, even those that might find it awkward.
I'm reviewing a quite old project and see code like this for the second time already (C++ - like pseudocode):
if( conditionA && conditionB ) {
actionA();
actionB();
} else {
if( conditionA ) {
actionA();
}
if( conditionB ) {
actionB();
}
}
in this code conditionA evaluates to the same result on both computations and the same goes for conditionB. So the code is equivalent to just:
if( conditionA ) {
actionA();
}
if( conditionB ) {
actionB();
}
So the former variant is just twice more code for the same effect. How could such manner (I mean the former variant) of writing code be called?
This is indeed bad coding practice, but be warned that if condition A and B evaluations have any side effects (var increments, etc.) the two fragments are not equivalent.
I would call it bad code. Though I've tended to find similar constructs in project that grew without any code review being done. (Or other lax development practices).
Guys? Look at this part: ( conditionA && conditionB )
Basically, if conditionA happens to be false, then it won't evaluate conditionB.
Now, it would be a bad coding style but if conditionA and conditionB aren't just evaluating data but if there's also some code behind these conditions that change data, there could be a huge difference between both notations!
if conditionA is false then conditionA is evaluated twice and conditionB is evaluated just once.
If conditionA is true and conditionB is false, then both conditions are evaluated twice.
If both conditions are true, both are executed just once.
In the second suggestion, both conditions are executed just once... Thus, these methods are only equivalent if both methods evaluate to true.
To make things more complex, if conditionB is false then actionA could change something that would change this validation! Thus the else branch would then execute actionB too. But if both conditions evaluates to true and actionA would change the evaluation of conditionB to false, it would still execute actionB.
I tend to refer to this kind of code as: "Why make things easy when you can do it the hard way?" and consider this a design pattern. Actually, it's "Mortgage-Driven development" where code is made more complex so the main developer will be the only one to understand it, while other developers will just become confused and hopefully give up to redesign the whole thing. As a result, the original developer is required to stay just to maintain this code, which is called "Job security" and thus be able to pay his mortgage for many, many years.I wonder why something like this would be used, then realized that I use a similar structure in my own code. Similar, but not the same:
if (A&&B){
action1;
} elseif(A){
action2;
} elseif(B){
action3;
} else{action4}
In this case, every action would be the display of a different message. A message that could not be generated by just concatenating two strings. Say, it's a part of a game and A checks if you have enough energy while B checks if you have enough mass. Of you don't have enough mass AND energy, you can't build anything anymore and a critical warning needs to be displayed. If you only have energy, a warning that you have to find more mass would be enough. With only energy, your builders would need to recharge. And with both you can continue to build. Four different actions, thus this weird construction.
However, the sample in the Q shows something completely different. Basically, you'd get one message that you're out of mass and another that you're out of energy. These two messages aren't combined into a single message.
Now, in the example, if conditionA would detect energy levels and conditionB would detect mass levels then both solution would just work fine. Now, if actionA tells your builders to drop their mass and start recharging, you'd suddenly gain a little bit of mass again in your game. But if conditionB indicated that you ran out of mass, that would not be true anymore! Simply because actionA released mass again. if actionB would be the command to tell builders to start collecting mass as soon as they're able then the first solution will give all builders this command and they would start collecting mass first, then they would continue their other actions. In the second solution, no such command would be given. The builders are recharged again and start using the little mass that was just released. If this check is done every 5 minutes then those builders would e.g. recharge in one minute to be idle for 4 more minutes because they ran out of mass. In the first solution, they would immediately start collecting mass.
Yeah, it's a stupid example. Been playing Supreme Commander again. :-) Just wanted to come up with a possible scenario, but it could be improved a lot!...
It's code written by someone who doesn't know how to use a Karnaugh Map.
This is very close to the 'fizzbuzz' Design Pattern:
if( fizz && buzz ) {
printFizz();
printBuzz();
} else {
if( fizz ) {
printFizz();
}
else if( buzz ) {
printBuzz();
}
else {
printValue();
}
}
Maybe the code started life as an instance of fizzbuzz (maybe copied-n-pasted), then was refactored slightly into what you see today due to slightly different requirements, but the refactoring didn't go as far as it probably should have (boolean logic can sometimes be a bit trickier than one might think - hence fizzbuzz as an interview weed-out technique).
I would call it bad code too.
There is no best way on indenting, but there is one golden rule : choose one and stick with it.
This is "redundant" code, and yes it is bad. If some precondition must be added to the calls to actionA (assuming that the precondition can't be put into actionA itself), we now have to modify the code in 2 places, and therefore run the risk of overlooking one of them.
This is one of those times where you can feel better about deleting some lines of code, than in writing new ones.
inefficient code?
Also, could be called Paid per line
I would call it 'twice is better'. It's made like that to be sure that the runtime really understood the question ;).
(although in multi-threaded, not-safe environment, the result may differ between the two variants.)
I might call it "code I wrote last month while I was in a hurry / not focused / tired". It happens, we all make or have made these kind of mistakes. Just change it. If you want to you can try and find out who did this, hope it is not you, and give him/her feedback.
Since you said you've seen this more than once, it seems that it's more than a one-time error due to being tired. I see several reasons for someone to repeatedly come up with such code:
The code was originally different, got refactored, but whoever did this oversaw that this is redundant.
Whoever did this didn't have a good grasp of boolean logic.
(Also, there's the slight possibility that there might be more to this than what your simplified snipped shows.)
As pgast has said in a comment there is nothing wrong with this code if actionA effects conditionB (note that this is not a condition with a side effect but an action with a side effect (which you kind of expect))
I just saw this block of code on the Wikipedia article on conditional operators:
Vehicle new_vehicle = arg == 'B' ? bus :
arg == 'A' ? airplane :
arg == 'T' ? train :
arg == 'C' ? car :
arg == 'H' ? horse :
feet;
I've changed the code a little, but the idea is the same. Would you find this use of the conditional operator acceptable? It's much more concise than the if-else construct, and using a switch would definitely open up a whole new set of opportunities for bugs (fall-throughs anyone?). Also, if-elses and switch can't be used as R-values, so you'd have to create the variable first, initialize it and then assign as necessary.
I for one really like this, but I'm wondering what others think.
But the formatting is essential.
EDIT: I still like this. But I understand those who say "the switch statement was made for this". OK, maybe so. But what if the conditions are function calls that return bool? Or a million other things you can't switch on.
Are you switch lovers really trying to convince me that a huge if-else chain is better? Yes, programmers who don't know how to use the conditional operator will not understand this. They should learn how to use it. It's not arcane.
I have used this type of construction many times. As long as it's formatted nicely (i.e. not all on one line, making it unreadable), I don't see a problem with it.
I would use a switch, because this is the kind of thing it was designed for. Yes, there is a risk of fall-through bugs, but this nested-conditional block has a much higher risk of being misunderstood by other programmers.
This is a great example of conditional operator use. I use it in this manner all the time in C++, Java, and Perl.
Not only is there nothing wrong with it, it communicates the intent of the operation in the most concise and clear way possible.
Replacing with if else, or switch construction requires that the snippet
"new_vehicle = "
be repeated in every instance, which requires that the reader read every repeating instance of it to ensure that it is in fact the same in every instance..
I like it. It is similar to an if-else-if ladder, only more concise.
There's a lot of whitespace around the character constants that makes it a bit hard to read. I'd parenthesize the comparisons: (and maybe move the last value in line.)
Vehicle new_vehicle = (arg == 'B') ? bus :
(arg == 'A') ? airplane :
(arg == 'T') ? train :
(arg == 'C') ? car :
(arg == 'H') ? horse :
feet;
Now it looks great.
The conditional operator version is clean, simple, and it's immediately obvious to anybody who knows C or C++ what is happening. Its other virtue is that it returns a value immediately, which means it can be put in the initialization (like this example is).
A switch statement would be more clumsy. It would require that the variable be declared and then initialized, usually a bad idea if it can be avoided. It would take more typing, and would have more places for bugs to creep in. It wouldn't be as clear, since it would be necessary to look at each case to see that it said something like new_vehicle = foo; break;.
If you're going to do this look up here only, then having the conditional version right there is good, as it immediately shows what's happening. If it's going to occur more than once, consider putting it in a function, so that there's only one place to update if anything changes (such as, say, 'R' for carriage or 'L' for helicopter).
Purely a stylistic choice. For small data sets like you present here, then as long as your programming team isn't thrown by such a thing, then its fine in my book.
A switch is both clearer and possibly much more efficient. If I saw code like this at a code review, I'd be worried. Also, this is "the conditional operator" - it is an instance (albeit currently the only one in C and C++) of a ternary operator.
Vehicle new_vehicle = getVehicleByType(arg);
Vehicle getVehicleByType(char arg){
if (arg == 'B') return bus;
if (arg == 'A') return airplane;
if (arg == 'C') return car;
if (arg == 'T') return train;
if (arg == 'H') return horse;
return feet;
}
I like this better. The nested conditional is clever, but I think this is almost as concise and less likely to confuse a future reader. Sorry if the syntax is off, I'm not doing much C nowadays.
EDIT: Fixed return type omission noted in comments. thx!
EDIT: I'm not horrified at your version by the way. I did not exclaim WTF or OMG when i saw it. I just prefer mine a little more :)
I don't particularly care for it.
It doesn't really buy anything, or make anything more clear, and it's a pretty non-standard usage of the operator.
It seems the primary advantage is that it's somewhat clever. I avoid clever unless there's a pretty good (external) reason to be clever.
I would lean toward a switch statement because the compiler will catch duplicate cases. Arguably, this is not an issue in this example but if the list gets really long and is worked on by several different people it is easy to add a duplicate and not realize it.
Read the C++ section of the Wikipedia article a bit more carefully. It explicitly lists some situations where using the ?: operator is the only option, and can't be replaced by if/else or switch.
On the other hand, I wouldn't use it only because it looks prettier.
I've never seen anything written like this before. While it is clever and well-formatted, this seems like the perfect opportunity to use a dictionary/hashtable (assuming Vehicle is an enumeration, which is unclear).
A few people have already mentioned the possibility of using an std::map or other associative array type to do the job. As long as you're only doing this is one place (or a few places), you might consider just using a normal array or vector instead:
Vehicle vehicles[CHAR_MAX];
// Initialization
std::fill_n(vehicles, CHAR_MAX, feet);
vehicles['A'] = airplane;
vehicles['B'] = bus;
vehicles['C'] = car;
vehicles['H'] = horse;
vehicles['T'] = train;
// Use
Vehicle new_vehicle = vehicles[arg];
Depending on how may tables you need/use (that store the same type of object), and the size of the contained objects (Vehicle in this case), this can be a perfectly reasonable alternative to an std::map. If you're creating a lot of tables, or each object is really big, std::map becomes a more reasonable alternative.
When you use an std::map (or unordered_map, etc.) you're using more code to save on data storage. This does the reverse -- but as long as Vehicle is small (say, 4 bytes), one table like the above will typically occupy something like half a kilobyte. It's hard to guess exactly how large the code for std::map is going to be for a specific compiler, but it seems likely that it'll usually be larger than half a kilobyte, so if you're only creating one table like this, std::map may be a net loss.
Of course, if you know that you're only dealing with letters as input, you could reduce the table size quite a bit:
template <class T>
class letter_table {
static const int range = 'Z' - 'A';
T table[range];
public:
// ...
T operator[](int index) {
index -= 'A';
assert(index<range);
return table[index];
}
};
In the example case, this would give a table around 100 bytes -- you can create a pretty fair number of 100-byte tables in the space std::map will normally occupy.
Purely practical:
Plus: The ternary sequence is more flexible, and can be used to avoid the limitations of switch, you could use other operators (e.g. <=, >=) or any other tests, including e.g. string comparisons.
x = IsEven(arg) ? 0 :
(arg < 0) ? -1 : 1; // or whatever
Also, if the switch is a performance bottleneck and you have uneven probabilities, you can force the likeliest tests being done first (due to the not evaluated guarantee for the path not chosen).
So-So
Unlike a switch statement, order is important (unless you stick to ==). That can be an advantage, but being otherwise similar to switch that might be misleading when the maintainer is unfamiliar with the concept or in a hurry.
Many developers may shy away because they aren't sure about the details (which terms will be evaluated, is the rpecedence of the operators ok?) - However, if your developer pool won't grasp a well-presented example, you might have problems that can't be solved by banning ternary operators.
Minus
It isn't as common as switch, thus the optimizer might not treat it the same. Optimizers are know to select the best fit implementation for a switch (table, binary search, comparison sequence, or any combination of this). Optimizers can't reaarange wevaluaiton order, and are less likely to support a table lookup here.
Requires good formatting to be easily recognizable (lining up the '?' and ':') - Sucks when you use tabs.
Aesthetics
I like it for its precision and succinctness, close to mathematical notations. However, that might as well be used against it. It's probably an eyebrow raiser at code reviews, because it is less common and more brittle.
Just for comparison, in C++0x you can have an expression without using the conditional operator or an out-of-line function:
Vehicle new_vehicle = [&]() -> Vehicle {
if (arg == 'B') return bus;
if (arg == 'A') return airplane;
if (arg == 'T') return train;
if (arg == 'C') return car;
if (arg == 'H') return horse;
return feet;
}();
Not really any better, though.
How about:
enum Vehicle { bus = 'B', airplane = 'A', train, car = 'C', horse = 'H', feet = 'F' };
...
new_vehicle = arg;
:-), by the way.
I think its useful for someone who code it, but will be difficult to understand for the reviwer,
"KEEP IT SIMPLE BUDDY"
In my opinion what you've done is acceptable due to the simplicity of the example. If you were doing more things with each case this type of construct could rapidly get messy. For that reason I would prefer a switch or even nested if then elses (if there aren't too many cases), formatted as follows:
if (A) {
//Do A stuff
}
else if (B) {
//Do B stuff
}
else if (C) {
//Do C stuff
}
else {
//Do default stuff
}
It's about the readability of the code, which lends itself to the maintainability of the code. I've never been a huge fan fan of the conditional operator, because I don't like to see multiple expressions on a single line. Conditional operators can be difficult to follow when single stepping the code in a debugger. The simpler the code the easier it is to concentrate on what the code is doing.
Many of us are used to the Iif-functions in various reporting tools or the If-function in Excel where we basically need to use the less clear Iif(arg="B";"Bus";Iif(arg="A";Airplane;"Feet")). I love your sample compared to that :)
I personally would've used if-elses, but I would not have a problem with your sample.
Myself and a colleague have a dispute about which of the following is more elegant. I won't say who's who, so it is impartial. Which is more elegant?
public function set hitZone(target:DisplayObject):void
{
if(_hitZone != target)
{
_hitZone.removeEventListener(MouseEvent.ROLL_OVER, onBtOver);
_hitZone.removeEventListener(MouseEvent.ROLL_OUT, onBtOut);
_hitZone.removeEventListener(MouseEvent.MOUSE_DOWN, onBtDown);
_hitZone = target;
_hitZone.addEventListener(MouseEvent.ROLL_OVER, onBtOver, false, 0, true);
_hitZone.addEventListener(MouseEvent.ROLL_OUT, onBtOut, false, 0, true);
_hitZone.addEventListener(MouseEvent.MOUSE_DOWN, onBtDown, false, 0, true);
}
}
...or...
public function set hitZone(target:DisplayObject):void
{
if(_hitZone == target)return;
_hitZone.removeEventListener(MouseEvent.ROLL_OVER, onBtOver);
_hitZone.removeEventListener(MouseEvent.ROLL_OUT, onBtOut);
_hitZone.removeEventListener(MouseEvent.MOUSE_DOWN, onBtDown);
_hitZone = target;
_hitZone.addEventListener(MouseEvent.ROLL_OVER, onBtOver, false, 0, true);
_hitZone.addEventListener(MouseEvent.ROLL_OUT, onBtOut, false, 0, true);
_hitZone.addEventListener(MouseEvent.MOUSE_DOWN, onBtDown, false, 0, true);
}
In most cases, returning early reduces the complexity and makes the code more readable.
It's also one of the techniques applied in Spartan programming:
Minimal use of Control
Minimizing the use of conditionals by using specialized
constructs such ternarization,
inheritance, and classes such as Class
Defaults, Class Once and Class
Separator
Simplifying conditionals with early return.
Minimizing the use of looping constructs, by using action applicator
classes such as Class Separate and
Class FileSystemVisitor.
Simplifying logic of iteration with early exits (via return,
continue and break statements).
In your example, I would choose option 2, as it makes the code more readable. I use the same technique when checking function parameters.
This is one of those cases where it's ok to break the rules (i.e. best practices). In general you want to have as few return points in a function as possible. The practical reason for this is that it simplifies your reading of the code, since you can just always assume that each and every function will take its arguments, do its logic, and return its result. Putting in extra returns for various cases tends to complicate the logic and increase the amount of time necessary to read and fully grok the code. Once your code reaches the maintenance stage then multiple returns can have a huge impact on the productivity of new programmers as they try to decipher the logic (its especially bad when comments are sparse and the code unclear). The problem grows exponentially with respect to the length of the function.
So then why in this case does everyone prefer option 2? It's because you're are setting up a contract that the function enforces through validating incoming data, or other invariants that might need to be checked. The prettiest syntax for constructing the validation is the check each condition, returning immediately if the condition fails validity. That way you don't have to maintain some kind of isValid boolean through all of your checks.
To sum things up: we're really looking at how to write validation code and not general logic; option 2 is better for validation code.
As long as the early returns are organized as a block at the top of the function/method body, then I think they're much more readable than adding another layer of nesting.
I try to avoid early returns in the middle of the body. Sometimes they're the best way, but most of the time I think they complicate.
Also, as a general rule I try to minimize nesting control structures. Obviously you can take this one too far, so you have to use some discretion. Converting nested if's to a single switch/case is much clearer to me, even if the predicates repeat some sub-expressions (and assuming this isn't a performance critical loop in a language too dumb to do subexpression elimination). Particularly I dislike the combination of nested ifs in long function/method bodies, since if you jump into the middle of the code for some reason you end up scrolling up and down to mentally reconstruct the context of a given line.
In my experience, the issue with using early returns in a project is that if others on the project aren't used to them, they won't look for them. So early returns or not - if there are multiple programmers involved, make sure everyone's at least aware of their presence.
I personally write code to return as soon as it can, as delaying a return often introduces extra complexity eg trying to safely exit a bunch of nested loops and conditions.
So when I look at an unfamiliar function, the very first thing I do is look for all the returns. What really helps there is to set up your syntax colouring to give return a different colour from anything else. (I go for red.) That way, the returns become a useful tool for determining what the function does, rather than hidden stumbling blocks for the unwary.
Ah the guardian.
Imho, yes - the logic of it is clearer because the return is explicit and right next to the condition, and it can be nicely grouped with similar structures. This is even more applicable where "return" is replaced with "throw new Exception".
As said before, early return is more readable, specially if the body of a function is long, you may find that deleting a } by mistake in a 3 page function (wich in itself is not very elegant) and trying to compile it can take several minutes of non-automatable debugging.
It also makes the code more declarative, because that's the way you would describe it to another human, so probably a developer is close enough to one to understand it.
If the complexity of the function increases later, and you have good tests, you can simply wrap each alternative in a new function, and call them in case branches, that way you mantain the declarative style.
In this case (one test, no else clause) I like the test-and-return. It makes it clear that in that case, there's nothing to do, without having to read the rest of the function.
However, this is splitting the finest of hairs. I'm sure you must have bigger issues to worry about :)
option 2 is more readable, but the manageability of the code fails when a else may be required to be added.
So if you are sure, there is no else go for option 2, but if there could be scope for an else condition then i would prefer option 1
Option 1 is better, because you should have a minimal number of return points in procedure.
There are exceptions like
if (a) {
return x;
}
return y;
because of the way a language works, but in general it's better to have as few exit points as it is feasible.
I prefer to avoid an immediate return at the beginning of a function, and whenever possible put the qualifying logic to prevent entry to the method prior to it being called. Of course, this varies depending on the purpose of the method.
However, I do not mind returning in the middle of the method, provided the method is short and readable. In the event that the method is large, in my opinion, it is already not very readable, so it will either be refactored into multiple functions with inline returns, or I will explicitly break from the control structure with a single return at the end.
I am tempted to close it as exact duplicate, as I saw some similar threads already, including Invert “if” statement to reduce nesting which has good answers.
I will let it live for now... ^_^
To make that an answer, I am a believer that early return as guard clause is better than deeply nested ifs.
I have seen both types of codes and I prefer first one as it is looks easily readable and understandable for me but I have read many places that early exist is the better way to go.
There's at least one other alternative. Separate the details of the actual work from the decision about whether to perform the work. Something like the following:
public function setHitZone(target:DisplayObject):void
{
if(_hitZone != target)
setHitZoneUnconditionally(target);
}
public function setHitZoneUnconditionally(target:DisplayObject):void
{
_hitZone.removeEventListener(MouseEvent.ROLL_OVER, onBtOver);
_hitZone.removeEventListener(MouseEvent.ROLL_OUT, onBtOut);
_hitZone.removeEventListener(MouseEvent.MOUSE_DOWN, onBtDown);
_hitZone = target;
_hitZone.addEventListener(MouseEvent.ROLL_OVER, onBtOver, false, 0, true);
_hitZone.addEventListener(MouseEvent.ROLL_OUT, onBtOut, false, 0, true);
_hitZone.addEventListener(MouseEvent.MOUSE_DOWN, onBtDown, false, 0, true);
}
Any of these three (your two plus the third above) are reasonable for cases as small as this. However, it would be A Bad Thing to have a function hundreds of lines long with multiple "bail-out points" sprinkled throughout.
I've had this debate with my own code over the years. I started life favoring one return and slowly have lapsed.
In this case, I prefer option 2 (one return) simply because we're only talking about 7 lines of code wrapped by an if() with no other complexity. It's far more readable and function-like. It flows top to bottom. You know you start at the top and end at the bottom.
That being said, as others have said, if there were more guards at the beginning or more complexity or if the function grows, then I would prefer option 1: return immediately at the beginning for a simple validation.