- 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
There are those of us who believe code should be self-documenting. I tend to favor Markp's approach.
Admin
Aarrgh! I mean (44<<1)+1, of course.
Captcha: Still damnum.
Admin
But then you end up with head scratchers like
final long ms = 5000; /* 5 minutes worth of milliseconds */
Admin
End of course, half a year later someone decides that what is really needed is 10 minutes, instead of just 5. The code will then read:
final long ms = 600000; /* 5 minutes worth of milliseconds */
And a new WTF is born.
Admin
final long ms = 5 * 60 * 1000; final long ms = 300000; /* 5 minutes worth of milliseconds */
Talk about source code bloat.
Admin
I'd have to agree with MarkP here, the line:
final long ms = 5 * 60 * 1000;
is far more obvious to see that the original code writer did it right as opposed to:
final long ms = 300000; /* 5 minutes worth of milliseconds */
At first glance it's hard to tell the difference between these two lines:
final long ms = 300000; /* 5 minutes worth of milliseconds / final long ms = 3000000; / 5 minutes worth of milliseconds */
Note that the second one has the extra zero (so it's really 50 minutes worth of millisecs), but with the comment there you (as the developer trying to understand why the code isn't working) might easily skim past that, without taking the time to do the math yourself AND then count to make sure there are the same number of zeros.
Admin
final long FIVE_MINUTES = FIVE * SIXTY * ONE_THOUSAND;
Admin
oh. good idea.
... oops. forgot to update the comment.
I usually just do this:
Admin
Admin
Lisp isn't all about parenthesis, young wizard: (+ 40 1 1 1 1 1 1 1 1 1 1 10 1 (ascdiff "Z" "A") 1 1 1)
Admin
Actually I am going to have to gasp agree with the former comment. Even with your commented method, if I want to modify the number, I have to do math in my head. With his example, I can see which set of numbers is seconds and which is minutes and then modify the appropriate one with less effort. And if you think his method is overly verbose, you're just being a picky slashdot fanboy
Admin
Why are you guys using longs? Can't Java fit 30000 into an integer?
Admin
I'm going to guess it's processed output recycled. I think the original didn't contain all those crazy +1's, but rather was a legitimate case of building up the value by math on constants as many on here have mentioned.
However, the constants were already evaluated to make the offending line of code.
As for the broken down thing of
Time = 5 * Seconds_In_Minute * Milliseconds_In_Second
I've done things very similar to this. I wouldn't do it ONLY for this line of code but if you're going to use those constants elsewhere anyway, why not? Sure, they can never change but they're still magic values. By using constants instead you make it clearer what the code means.
Admin
90% of the people who think code should be self-documenting, can't actually write self-documenting code.
Admin
Keeping the value broken into unit-relative factors offers a fair bit of ease in adjusting it to other meaningful values while impacting performance so little that only a kernel programmer would (or should) care. Also, it's cleaner and more concise than commenting what could be completely obvious anyway.
Admin
Yeah, you can spend an extra minute pulling up a calculator and copy pasting the result (number dyslexic here), and then commenting it.
Or you can just do the multiplication which eliminates possibility of error and saves time, and is self documenting.
And a hell of a lot easier to modify in the future.
Captcha: Damn um
Admin
The code gets a different answer in EBCDIC (on a mainframe).
Admin
Admin
#define SECONDS_PER_DAY 86400 #define FIVE_DAYS 5 * SECONDS_PER_DAY
Admin
In LSL, you might do
integer ms = 300000;
instead of
integer ms = 5 * 60 * 1000;
for speed reasons... yep, LSL, though it is a compiled language, does NOT optimize that..
Admin
Not as clear, plus if you change the time you also have to change the comment, so you could introduce a subtle bug by having the documentation and the code be incompatible. I like the original better, the name of the variable tells you that it is in milliseconds, so the calculation tells you everything you need. If the units in the variable are not clear from the name (or usage) you can always do:
final long myTime = 5 * 60 * 1000; //in milliseconds
The compiler is only going to calculate it once anyway, and may even optimize it.
Admin
The first version is easier to understand/edit. eg. What if you wanted to change it to six minutes?
Admin
The best part of this is the " 'Z' - 'A' //86" Part. I mean - that HAS to be intentional obfuscation
Admin
final long fiveMinutesInMillisecondsEqualsThreeHundredThousand = 300000;
Admin
I'm trying to figure out if you wrote "30000" instead of "300000" just to add irony and prove my point.
As for the long vs. int, my basic rationale for that was that System.currentTimeMillis() returns a long. But there's another reason: As far as I understand it, the "+" operation in Java doesn't promote two ints to longs before doing the operation.
http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#170983
So if you had something that was fairly likely to be in the upward range of an integer's capacity (milliseconds since the epoch obviously qualifies, as does any time in ms in the order of magnitude of a month), and wanted to add another similar value to it, you'd have integer overflow:
Anyway, my post was sarcastic...I stand behind using expressions to self-document code, but I was obviously joking when I said I could understand the semantics behind the OP line of code. It's just
Admin
BigDecimal baby!
Admin
BigDecimal patno = 40; patno = patno.add(1); patno = patno.add(1); patno = patno.add(1); patno = patno.add(1); patno = patno.add(1); patno = patno.add(1); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(10)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal('Z' - 'A')); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1));
Admin
BigDecimal patno = new BigDecimal(40); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(10)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal('Z' - 'A')); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1)); patno = patno.add(new BigDecimal(1));
Admin
Yes, that's the correct approach, always write obfuscated code that will be hard/impossible to understand. Then add a comment. AFAIR there are some really good tutorials on TheDailyWTF.
Admin
But why comment if the code itself can be self explanatory?
Admin
Here are a thoughts...
First I would like to complain that since no language was defined it is really hard to know what else could be happening. If the language was C++, then the declaration of the variable is VERY important.
process angle: Programmer thought he/she(Paula) would experiment with "iterative design."
C++ angle: A programmer that hates regular expressions builds their own pattern language using overloaded expressions.
o A numeric value means any character for that field width. o A character value assumes a scale factor of 'A' and allows the next maxCharacterOffset characters to match via patno::operator+(char maxCharacterOffset = ('A'-'Z')).
CVS/diff angle: I once had a diff tool that would not compare file contents if the file lengths were the same. This technique would ensure that the file size changed.
MACRO angle: good possibility. Since you never know where macros will be used, you always include an extra set of parentheses. Create a macro that combines a few macros that combined a few macros, etc. and this is quite feasible.
Code generator: The sky is the limit!
Admin
// Just in case the number of seconds per day is changed. #define SECONDS_PER_DAY 86400 // Just in case they change the multiplication sign #define MULTIPLIED_BY * // Just in case five is not represented as '5' #define FIVE 5
#define FIVE_DAY FIVE MULTIPLIED_BY SECONDS_PER_DAY
Admin
Admin
Admin
patno-=0141+010
Admin
This looks suspiciously like autogenerated code to me.
I was particularly impressed with this little gem from some generated code:
if ((((((((((((((((((((0)))))))))))))))))))) { //approximately 1500 lines }
Admin
Oy. Even when making fun of bad programming I still tend to a functional style. ;)
It occurred to me later that for greater lisp obfuscation yet all those (1+ ...) calls could be replaced with (+ (*) ...).
Admin
I disagree, even the stupidest of compilers will optimize the operation away, and if code is clear enough, comments become redundant. The 5-6 extra keystrokes are well worth the clarity and readability in this case
Admin
Ok, but then let say we want to have it be 10 minutes worth of milliseconds, the value gets changed, the comment remains, and it ends up being another wtf:
final long ms = 600000; /* 5 minutes worth of milliseconds */
Admin
Or, gasp, you could use a macro.
final long ms= minutes_to_milliseconds(5);
Max
Admin
It looks like he was trying to convert A through Z to 1 through 26. The additions line up nicely with a shifted ascii table.
Admin
final long TIME_IN_MILS = DoItAllUnitConverter.convert(5, DoItAllUnitConverter.MINUTES, DoItAllUnitConverter.MILISECONDS);
Or the more enterprisey:
final UnitConverter minuteToMilisecondConverter = UnitConverterFactory.getConverter(UnitConverterFactory.TIME).setInputUnits(UnitConverterFactory.MINUTES).setOutputUnits(UnitConvertFactory.MILISECONDS);
final long TIME_IN_MILS = minuteToMilisecondConverter.convert(5);
Certainly the best solution!
Admin
final long TIME_IN_MILS = DoItAllUnitConverter.convert(5, DoItAllUnitConverter.MINUTES, DoItAllUnitConverter.MILISECONDS);
Or the more enterprisey:
final UnitConverter minuteToMilisecondConverter = UnitConverterFactory.getConverter(UnitConverterFactory.TIME).setInputUnits(UnitConverterFactory.MINUTES).setOutputUnits(UnitConvertFactory.MILISECONDS);
final long TIME_IN_MILS = minuteToMilisecondConverter.convert(5);
Certainly the best solution!
Admin
Grrrrrrr...my first post doesn't appear after several page refreshs. Then, I see a better post to respond to and think, "splendid, this is an even better post to respond to...I'm glad the forum didn't take my first post." Then I post it, both appear, and I look like a jack-ass.
THANKS FORUM SOFTWARE... <3 --'-,-<@ :-*
Admin
You just blew my mind man. By definition wouldn't the alphabet be in alphabetical order?
Admin
Sorry, AdBlock stays on: I disabled it for a few seconds and clicked a few links - pure distraction.
I'd much rather paypal-Tip authors of interesting content that I read regularly.
Admin
explicit code is better than a comment. Anything more complicated than this should be an explicit function (let minutesToMilliseconds minutes = minutes * 60 * 1000)
This is actually an example in "Elements of Programming Style". Kernighan votes for explicit code. Let the compiler do the work.
My theory for the code is that it reflects some underlying data - probably text layout: 4 lines of header, then a whole bunch of lines that kept changing, then A through Z, etc...
Admin
;)
Admin
Or gasp, stop using comments to hide smells, and name the constant FIVE_MINUTES_IN_MS.
Hill
Admin
I am on the fence as to whether this is a good line. On one hand, it uses hardcoded values. Lots of them. On the other, it looks like it is easier to make the appropriate change. I mean, I assume originally all of those were 1's, but someone had to go back and make one a 10. Can you imagine trying to figure out how changing a 1 to a 10 would work if it weren't broken down like this?
captcha: vindico