- 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
s/Do While Not/Do Until/
Admin
Not really... Do While Not is perfectly legal Visual Basic, IIRC
Admin
You miss the point. "Do Until" is easier to read and easier to understand.
Admin
Although it is legal, I prefer to use "Do Until" in these kinds of cases to prevent confusion. That way if someone has to scan through my code quickly to find a problem, they don't have to waste time figuring out what my "Do" loop is evaluating by negating the status of the condition.
As for this particular coder, clearly he should have split this up into 4 columns:
Hours_tensColumn as Integer
Hours_onesColumn as Integer
Minutes_tensColumn as Integer
Minutes_onesColumn as Integer
Now *that* is what I call efficient. Small data types, no need for string splitting functions...c'mon this is the best!
Admin
Heh I just noticed that while he's in the loop, he keeps reassigning the value of TotalHours, not adding to it. Therefore TotalHours will reflect only the total hours of the last record he pulls. The alternative is that TotalHours is a standardized number like 40 (for work hours in a normal week), and he's only expecting it to be that standardized value at the end. In that case, there's no reason to read that value for every record. Not to mention that his code will completely bomb if the ":" character is missing or not in the right place thanks to someone hand-jamming the database. Long live "On Error Resume Next"!
Admin
*sigh* It's supposed to do that. Ignore that part, or bring on the flames.
Admin
Okay, I see. Well, I saw the 'Do Unitel Not rs.EOF' pattern so often by now, that I got used to it :).
About storing the time... Here's how I would do it: just store the it as minutes. You just do a SELECT SUM(Minutes) and then convert it into a nice HH:MM format (just dividing by 60 and getting the remainder). Aah, life can be easy :).
Alternatively, you could store it as a DateTime or so, but I guess that would be some overhead (although you can use SQL's built in functions, then)
Admin
He surely did know in advance that calculating the total time of those time sheets wouldn't be a task for the faint of heart.
His tools?
* A permissive language that allows a lot of implicit type conversions.
* A "powerful" Replace function to cast any unwanted char to oblivion.
* Self confidence... You need a lot of self confidence to code this. Or maybe if not confidence then a lot of balls.
I don't fully understand the reasoning behind this piece of code. There are lines that seems eccentric, weird, absurd. Someone could say they are stupid.
Myself... What can I say? I'm not so sure of my programming skills after looking at this. How can I dare to judge the code when clearly I don't have the needed clues to understand it?
Although something seems obvious (I have to say), when he put that isolation level in the recordset, he wasn't overstating what he would do with it.
Admin
I guess one of the side-WTF's here is this:
So when the total time is less than 10 minutes, it should multiply it by 10? WTF?
Admin
The problem here is SQL weakness. All that code could & should've been done in a simple SQL math aggregation. The Do While is not a problem.
Admin
The '&' symbol is the concatenate function in VBScript. If the minutes variable is only one character then he's concatenating a zero on the end of it. So if it's 2 it'll now be 20...not that my understand of the code leads me to understanding WhyTF he is doing this...Meh.<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p>
<FONT size=3><FONT face="Times New Roman"> <o:p></o:p></FONT></FONT>
Admin
Maybe... Depends on where you want the load to be, on the SQL server, which is servicing (potentially) hundreds of users, or on the local machine, which is serving one user...
But, the cost of a simple aggregation may be negligible enough to just use the SQL Server's engine in this case.
(Clicking "Post" in hopes that my message actually get posted this time[*-)])
Admin
Admin
Well... I assume doing this kind of math on the server side is a lot faster than opening a recordset on the client and reading the rows one by one!
Admin
... and thus puts less stress on the server in the end, of course!
Admin
I think what the coder really wanted to do was concatenate the "0" at the beginning of times with single digits, i.e. 2 was supposed to become 02. Which he of course stuffed up.
Anyone else notice how "Totat" is spelt wrong?
Admin
Does this add up the minutes correctly? It seems from Replace(dbQTS("TotalHours"), ".", ":") that he's must be using metric time to get the minutes right. A value of "1.20" hours would be translated to "1:20" instead of the correct "1:12" (assuming the TotalHours field is a simple float value).
I also love the clever use of Replace() and Left() to round the extra minutes to hours (though it only works for values of 99 minutes or less).
Wouldn't have just a SUM(TotalHours) worked?
Admin
2 -> 20
1 -> 10
3 -> 30
See the pattern? Adding a zero to the end of a whole number is the same as multiplying by ten.
Admin
Admin
Ultimately, the problem is that they are storing numeric data (Number of Hours and Number of Minutes) as a string. Compound this with the fact that they are then storing these two values in the same field. Small wonder that everything runs to the gutter from there. I will grant that this particular implementation runs there quicker than others.
select SUM(Hours * 60 + Minutes) TotalMinutes
from MyTable
OR, if you prefer
select SUM(Hours * 60 + Minutes) / 60 TotalHours,
Sum(Minutes) % 60 TotalMinutes
from MyTable
Let the application perform the proper formatting of the number(s) from there.
Admin
AH! I see now, yes it's the same as multiplying by ten...but that's not what the code was actually doing.
Admin
You do realize that "Do Until" would be it's own WTF here don't you?
The problem comes to when the loop test is evaluated:
<font color="#0000ff"> Do Until</font> will evaluate after the code has executed
<font color="#0000ff"> Do While [Not]</font> evaluates before the code executes, which this fellow actually does want to do.
In other words, he doesn't want to evaluate the loop if <font color="#800080">dbQTS.EOF</font> is <font color="#a52a2a">true</font> (don't bother if we're at the end of the file/table/etc).
Both forms are valid and useful depending on what your trying to do and it's not limited to VB... e.g. in Java it would be:
<font color="#0000ff"> while</font>(!<font color="#800080">dbQTS.EOF</font>){
<font color="#006400">// do something</font>
}
<font color="#0000ff"> do</font> {
<font color="#006400">// do something</font>
} <font color="#0000ff">while</font>(!<font color="#800080">dbQTS.EOF</font>);
this first form would be correct, the second would be a WTF in this case.
Now... why is it that every time I read this blog, I see more WTF's in the comments than in the actual posted code... a bit of a generalization I admit, but I see that many people around here should be reading and learning than posting just to hear the keyboard click!
Admin
This code could use a few constants to make it more readable and perform better. For example:
Const Zero = 0
Const One = 1
Const Two = 2
Const Sixty = 60
Const ADODBdotRecordset = "ADODB.Recordset"
Const DB = "db"
Other than that I think it is pretty good code. Alot easier to read than if it was done in T-SQL.
Admin
Stupid quote function!
Admin
OMG! You are a walking WTF! might as well add this too..
Const MattDamon = "MattDamon"
Const Hour = "hh"
Const Minutes = "mm"
Const TrueValue = "True"
Const FalseValue = "False"
Const NegativeOne = "-1"
Where did you learn to code? I know. You got it from Lean how to code VB in 24 hours huh?
Admin
It's a pretty WTF language if
do until x {
}
doesn't evaluate the condition until after the first loop.
I don't know. Perhaps you need to look a little more closely.
Admin
Oh, and just how does one persuade this PoC web software to actually do the right thing? Its quoting is completely anti-intuitive.
Admin
You do realize that you don't understand VB Do loops, right? If you put the conditional statement at the top of the Do loop, as in
Do Until dbQTS.EOF
...then the evaluation criteria will be examined before the loop is entered. The loop breaks when that statement evaluates to True. If no records are returned, then .EOF = True, and the loop is skipped. What you're thinking of is if he did this:
Do
...
While dbQTS.EOF = False
(forgive me if the syntax is wrong, I never use this method)
Admin
Do comes in four basic flavours:
Do While <condition>
'Code never guaranteed to execute
Loop
Do Until <condition>
'Code never guaranteed to execute
Loop
Do
'Code guaranteed to execute at least once
Loop While <condition>
Do
'Code guaranteed to execute at least once
Loop Until <condition>
The While/Until question is a matter of whether the condition will be true or false while the loop executes, and is more-or-less a matter of convenience and readability. "Do While Not Thing Is Nothing" sounds bad and is less maintainable than "Do Until Thing Is Nothing". Multiple negatives are just not asking for no trouble.
Admin
And does this?
Admin
I think most everybody missed the fact that the time is stored in the database as hours - in decimal! He (or she) could just add the time!
Instead, he first replace stringifies the number and replaces "." with ":". The next two replaces separate the hours and minutes (using Left and Right) and removes the colon (that he just added!) from TotalHours and keeps a running total.
After some funky string arithmetic (good thing vb does all the string->number conversions for him), he ends up with hours and minutes. Sometimes he even ends up with hours and minutes * 10.
wtf?
Admin
As the poster of this great piece of code, let me add one more piece of comedy: we got a CV through the other day from the guy who originally wrote this, wanting to do more work for us [:|]
Admin
You just need to switch to PostgreSQL. Try this on for size:
<font face="Courier New">
CREATE TEMPORARY TABLE timesheet_entry (
timesheet_entry_id int NOT NULL PRIMARY KEY,
timesheet_id int NOT NULL,
time_spent interval NOT NULL
);
INSERT INTO timesheet_entry VALUES (1, 1, '1 hour');
INSERT INTO timesheet_entry VALUES (2, 1, '10 minutes');
INSERT INTO timesheet_entry VALUES (3, 2, '97 minutes');
INSERT INTO timesheet_entry VALUES (4, 2, '2.5 hours');
INSERT INTO timesheet_entry VALUES (5, 2, '4 hours 12 minutes');
INSERT INTO timesheet_entry VALUES (6, 2, '0.5 hour');
INSERT INTO timesheet_entry VALUES (7, 2, '10 minutes');
INSERT INTO timesheet_entry VALUES (8, 2, '0.5 day');
INSERT INTO timesheet_entry VALUES (9, 2, '3:29');
SELECT * FROM timesheet_entry;
timesheet_entry_id | timesheet_id | time_spent
--------------------+--------------+------------
1 | 1 | 01:00:00
2 | 1 | 00:10:00
3 | 2 | 01:37:00
4 | 2 | 02:30:00
5 | 2 | 04:12:00
6 | 2 | 00:30:00
7 | 2 | 00:10:00
8 | 2 | 12:00:00
9 | 2 | 03:29:00
(9 rows)
SELECT sum(time_spent) FROM timesheet_entry WHERE timesheet_id = 2;
</font> <font face="Courier New"> sum
----------------
1 day 00:28:00
(1 row)</font>
Admin
clakity clikity clakity clock!
[:P]
Admin
My additional big WTF:
Using adOpenDynamic and adLockPessimistic instead of (in this particular case) the correct and more efficient adOpenForwardOnly and adLockReadOnly.
Admin
Do While <condition1>
'Code never guaranteed to execute
Loop While <condition2>
Do Until <condition1>
'Code never guaranteed to execute
Loop While <condition2>
Do While <condition1>
'Code never guaranteed to execute
Loop Until <condition2>
Do Until <condition1>
'Code never guaranteed to execute
Loop Until <condition2>
Now, wouldn't these two be fun additions? [8-|] I wonder if these are legal constructions or not. :-) And what will happen if they are legan and you're using them....
Admin
I've since left the company where I found a bit of creative coding.
I was over hauling a timesheet system (vb front-end, access back) for a client, ddep in the code there was a timer that every 3 minutes checked to see if the application had been idle for more than 5 minutes (yes 3's into 5 now go!). Not too bad well it gets worse. The system would record the current date-time every time a mouse event happen in (wait for it) the registry file! every time you moved the mouse it would convert the full date time to a string and then write it to the registry (each day it would make a new key name with the current date to store this)! whats more the routine to check the current date-time with one in the registry went a bit like this
<Psuedocode>
date1=cstr(registrydate())
date1=right(date1,5) 'time in hours/minutes
date2=cstr(now())
date2=substring(date2,5)
if(cint(left(date2,2))=cint(left(date1,2)))
if(cint(right(date2,2))=cint(right(date1,2)))
lockscreen();
end if
end if
</Psuedocode>
compairing 2 date types stored in memory would be too complex, much safer to store it in the registry and perform 2 substrings and 2 datatype conversions.
Admin
maybe I'm crazy, but I would think that rsQTS would be the correct hungarian notation not dbQTS...
QTS= Q??? Time Sheet ??????
Admin
Skicow: He understood that that is the concat operator. By adding a zero on the end of any number, you are essentially multiplying it by 10. He should have it like so:
mTotatTime = "0" & mTotatTime [sic]
Admin
No, dbQTS is correct. The Q stands for Query. Thus you get: Database System Query Time Sheet.
Very logical, don't you agree?
Admin
I couldn't agree more. But I don't think you've fully clarified your const names. I prefer:
Const Minutes_NumberValue_One = 1
And of course the stings:
Const Minutes_String_ZeroToAppend = "0"
Admin
Yeah, I realized what he was saying after I posted...
Admin
^^ D'oh! That was me not logged on! ^^
Admin
Ok, I officially give up on using the horribly broken quoting function. It used to be that sometimes quoting wouldn't work, but at least the preview SHOWED that the quote didn't work. Now I have some that I KNOW I checked, and the stuff I typed after the quoting is GONE.
Will just have to go back to good old cut-and-paste and stop whining about quoting, I guess. Whaddya want for free?
-blue
Admin
Admin
You do have any idea what you're talking about here don't you ?
Admin
sorry to disagree, but the 'rs' is more informative, and the db is just not correct in this instance. The variable is a recordset. You do not need to reference how your set of data is managed at the back-end from within a variable name, that would be tedious. drew..
Admin
Admin
I love the way this forum kills all posts with quotes from users who use FireFox. [:P] I bet there are quite a few FireFox users here... Also makes me wonder what they were about to say.
Admin
The editing widget loses changes to comments that quote other comments with quotes in, in Firefox. Quoting comments without quotes in them seems to work.