- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
How is it a good practice to test a boolean right after you set it? What possible purpose would that serve?
Admin
I'm not sure how much I agree with that, but I'm just pointing out that some one has already addressed your questions.
The first check certainly isn't necessary, but I don't find it bitch-worthy. It doesn't make it difficult to understand what's going on, and I doubt it'll hurt performance by any amount humanly perceptible. Odd? Sure. Silly? Maybe. A WTF? I don't really think so.
Admin
OK, I withdraw my comment that the credit limit is the WTF. I'm wrong... and what's worse, I made an idiot out of myself with all those exclamation points :$
But I'm holding firm on the boolean thing.
The following code pattern is typical:
bool aok = true; // assume aok unless faults are found
if (aok && !test_1()) { aok = false; }
if (aok && !test_2()) { aok = false; }
if (aok && !test_3()) { aok = false; }
...
if (aok && !test_n()) { aok = false; }
the idea being that once a test fails, don't bother evaluating further tests.
It's true that the first if() clause tests against a boolean that was just set... but this is good, and here's why.
What order should the tests run in? For performance reasons, it's nice to be able to put the cheapest / most discriminatory tests first. Leaving the extra aok && in the first if() makes it easier to swap tests around by dragging lines of code.
Admin
If you need to use the return value of that call later (e.g. return it), it's usually the best way. It's pretty much the only way if the method call is not idempotent..
Admin
It might reduce mistakes if the code gets changed later on (by someone who is not paying attention).
<FONT face="Courier New">flag = true;</FONT>
<FONT face="Courier New">if(flag) {</FONT>
<FONT face="Courier New"> flag = test1();</FONT>
<FONT face="Courier New">}</FONT>
<FONT face="Courier New">if(flag) {</FONT>
<FONT face="Courier New"> flag = test2();</FONT>
<FONT face="Courier New">}</FONT>
Now, suppose the if statements get swapped so that test2 is before test1. The code still works.
<FONT face="Courier New">flag = test1();</FONT>
<FONT face="Courier New">if(flag) {</FONT>
<FONT face="Courier New"> flag = test2();</FONT>
<FONT face="Courier New">}</FONT>
Put the test2 before test1, and the code no longer works.
Admin
No wonder the "average programmer" has trouble understanding his explanations :P
Admin
And I think that pattern is often a WTF.
And that would be great if that's what it does but it doesn't. If the first test fails, it checks the value of aok n - 1 + m times. For the rest of the loop you must make sure to put if(aok) around everything of the code breaks. I think that is asinine.
Refactor this in a few ways:
if (!test_1() && !test_2() && !test_3() && !test_n()) {
// all validation passed
}
or you could break it up into two methods. Or instead of using a boolean flag, use continues.
Admin
I've never found this to be a convincing reason to use a code convention. The idea that coding something a certain way will allow people to move code around semi-randomly without breaking anything is not that believable to me. You have to be very careful when modifying code, regardless of how it was written. It's not something you can do in a slap-dash manner and expect it to work. Actually, conventions that make this kind of cut and paste coding easy often lead to bugs because it might work or appear to for a a few scenarios. I'd rather our junior developers come ask for help than move stuff around and check it in.
It's better to focus on making the intent of the code clear.
Admin
I typically do something like this:
bool ValidateSomething () {
if (!test_1()) return false;
if (!test_2()) return false;
if (!test_n()) return false;
return true; // Validation succeeds.
}
In general, I find most test sequences that use status flags can be refactored into a single function whose sole purpose is to perform that sequence of tests. This both removes the redundant testing and encapsulates the sequence into an intelligently named function.
Admin
Or just:
return (!test_1() && !test_2() && !test_n());
Of course, it's not always that simple which is when you example comes into play.
Admin
It seems to me that this isn't a WTF.
It may be that there's a hacked line or two of code parsing out text directly from the xml that should use the dom to do so -- but that's an excusable hack. It may be a result of debugging or encountering bad xml. It's not a "what kind of clueless git could write code like this?" mistake.
It may be that the data is being taken from the parent node and not the child or whatever. But again this is an east kind of mistake to make and (I think) argues for using simpler local variable games (e.g. group, product, item instead of product_group_node etc.) where the context is provided by the method and so having variables whose names are 90% similar makes it easier to miss small logical errors.
There may be a WTF here, but I don't see it. It's a slip, or a minor hack made while debugging, not a "I tried to break this egg with this sledgehammer and missed" kind of mistake that, say, the "using templates to perform integer multiplication of constants" optimization represented.
So my opinion: this is not a WTF.
Admin
Perhaps Mr. Alex could step in and elighten us as to what the actual WTF he intended us to ridicule in this post is, so we can stop bickering. :)
Admin
I am, admittedly, making the assumption that checking the value of a boolean is cheaper than a test. :)
I think we have the same desire to avoid indent-hell...
if (test_1())
{
if (test_2())
{
...
... if(test_n())
{
// do everything in here
// (hope your Tab key doesn't wear out)
// (hope you don't mind horizontal scrolling)
... }
}
}
Admin
I'm not really concerned with the cost so much as the readability and reliablity of the code. I prefer not using flags in most cases because using them is similar to saying "We're done, so lets keep going." In an assembly line, if a bad part is made, they don't slap a sticker that says 'bad' and pass it through the rest of the assemply line so everyone can check if it's got a 'bad' sticker on it. That wouldn't make sense. Everything after must check this boolean flag. It just more places for people to make mistakes doing work that the compiler is better at.
The basic premise of strucutured programming is factored into modern lanuguage control structures. It's not something that needs to be done manually.
Admin
Omitting the individual items that exceed the credit limit is an efficiency hack - they won't be able to order them in the first place, so why offer them?
But restricting the user to only ordering X number of products such that X * price(X) < creditlimit is a function of the ordertaking code, NOT the catalog-generation code!
Admin
Well, maybe they have a coupon...
Admin
I hope no one brought this up or I'll look retarded...well, more retarded than your average VB programmer.
InStr() will return the position of the first occurrence of the string you are searching for, and in the event that the string is not found, it will return zero (0). If his InStr() call fails, it will set lpos = 12, and it will grab what is mostly likely textual characters rather than numbers. Ever try to run text through CSng()? Crash and burn, baby.
Then again, there's On Error Resume Next, and even if this guy is using it, he's not testing for errors. InStr() was the way to take halfway not-so-crappy code and turn it into a fragile piece of software that can't tolerate the slightest variance in the input file.
Admin
I presume that <FONT face="Courier New" size=2>SystemType</FONT> is a numeric value - otherwise a string would cause interesting behaviour without enclosing quotes...
<FONT face="Courier New"><FONT size=2>Set product_groups_node = xmldom.SelectNodes("/root/systems[@type='" & SystemType & "']/product_group")</FONT></FONT>
Hey! I'm sure the variable's untyped (Variant) so it doesn't matter anyway right? ;-)
Admin
Unfortunatly VB will evaluate all parts of an if statement to determine the result. so in the example here all of the tests will be evaluated even if the first fails.
Admin
In my opinion the WTF is this:
There is a check whether there are any products in the group with quantity greater zero, and if there are, all products up to the customer's credit limit are listed, including those that are currently unavailable.
On the other hand, if all products in the group are off limits for this customer, an empty product group will be added to the customer's catalog.
Admin
Cost can be a concern, but I figure if someone's using VB for their codebase, it's not the primary concern. But as far as readability is concerned, in my opinion, a single condition check is not necessarily more readable. It depends on the number of sub-conditions, I suppose. Which looks better is in the eye of the beholder.
As far as reliability, of course any coder worth a damn will agree with you. However, both methods can be reliable, so as far as readability is concerned, that is up to the individual or company coding standards.
I can't tell from the code presented which version of VB it is, but VB.NET does actually have a short-circuited AND operator(AndAlso).
Admin
The point isn't the single statement so much as not using boolean flags.
Replacing breaks, continues, and returns where they show the methods intent clearly with boolean flags makes the code base more fragile, in my experience. In that respect I find code written that way to be less reliable. I've never seen a bug that came as a result of the use of breaks, etc. while I have seen many that were the result of artificial method flow control through the use of booleans. The theory behind using booleans this way is that having only one return is less confusing. In reality, returns are generally easy to see and what a return statement does is obvious. If the code reaches a return, the method execution terminates. A boolean flag is not clear. I don't know what happens in the rest of the method when aok is set to false. It might skip over the rest of the logic. It might only skip over part of it. There might be code that only executes if aok is false. There might be code that changes aok back to true. I have no way of knowing this without looking through the rest of the conditionals. If the method or loop body is finished, it should be clear. I shouldn't have to visually parse the rest of the method to find that out. It's bad practice to assume that setting a flag is equivalent to a return or break or continue.
Admin
I'd give up the answer, but it's just too damn funny to watch everyone miss the obvious gaffe. What's Next, Alex?
Admin
Does it matter much if you say
someProcedure argument1, argumentN
instead of
someProcedure(argument1, argumentN)
?
Or is this just TelligentSystems screwing up (again)? I don't think I want to know it if this is a VB " " " feature " " "!
BTW that innerest if-block looks kinda weird:
Is product_group adding products that it selects from itself to... itself? What's Next, an infinite loop?
I'd have to know a bit more about that product_group object's class, I guess.
Admin
I think the WTF is the names.
EVERYTHING is a product_group. Ther has to be 6 different things with product_group in their name. Its almost impossible to tell them all apart.
Admin
I agree with UncleMidriff. All the calls to product_group.selectSingeNode(X) are returning whatever the default values are for X in the newly initialized product_group. Presumably they should be calls to
product_group_node.selectSingleNode(X)
Of course, not being a VB6 hacker, I may be misinterpreting the code.
Admin
This code seems to be quite full of WTFs. What about:
rpos = InStr(lpos,product_group_node.xml,"""")
Seems quite weird to me searching for a double quote as last position of a string, because you'll allways find the first quote in the string. So even if the value of base_price is enclosed by quotes (why would it?), it would not work...
Admin
... I'll leave it as an exersize for the reader to find this same reason ...
WTF???
Admin
Not really. Part of the developer's problem is that several conditions must be satisfied before the actual processing may be done.
He chose to keep track of 'all tested conditions satisfied so far' in a variable. Testing that variable before checking the next condition nicely decouples the conditions. In other words, you can remove and add conditions without affecting the rest of the code. You can even insert another condition before the first condition!
I really like such decouplings. The average programmer will not be able to resist the urge to optimize the code into a cascade of 'if's and will claim that such code will run faster.
Well, first, indentation may push 'if' cascades to the edge of the screen.
Second, a half-decent compiler will figure out that it doesn't have to do the first test because IsValidGroup was just set to 'true'. For all subsequent tests it will figure out that once IsValidGroup has become 'false', it cannot ever become 'true' again because no code affecting IsValidGroup is executed. Having realized this, the compiler gains significant freedom for other optimizations.
This part of the code is definitely not WTF; it was written by s.o. who understands decoupling.
Admin
To those of you who would argue this is a gaffe:
It's not. That code is sensible. It makes the following validation lines, of which there are lots, all consistent in form instead of the first one sticking out as special for no reason. Now they can be freely added, removed, commented, un-commented, or re-arranged (e.g., perhaps to test the more commonly false conditions first in order to speed up the checks) without the danger of accidentally putting the line like this further down, or missing it out completely.