It may have other issues, but is actually better than what this article is describing.
It may have other issues, but is actually better than what this article is describing.
One hilarious case was at Scottrade. I was poking around their C++ codebase one day and to my amazed horror saw a file hundreds of lines long, and a big chunk of it was devoted to handling leap years. Like, every leap year, one at a time.
There are few enough leap years that it should in theory be difficult to write hundreds of lines of code to handle each of them, but some contractor managed to.
And so the ball of mud continued. What can you do but laugh and embrace the horror?
int is_leap_year(int year) {
return 0;
}Although, I suppose it doesn't matter all that much which is which, as long as they're not both written the same way.
It's implementing it two different ways and comparing the results. It's not a guarantee, since you could have implemented the wrong spec, but there's only so much you can do with internal consistency checks.
But it would be better to compare to a known good function. It might be easier to add a dependency to do that in a test than in production code.
For the diametrical opposite, here's one time on an embedded system where I really didn't want to bring in a library dependency, so I wrote an inconspicuous-looking good-enough version:
y = (d - (d + 366 + (d >= 47847)) / 1461 + (d >= 47847)) / 365;
d = d - (d + 365 + (d >= 47848)) / 1461 + (d >= 47848) - y * 365;
y += 1970;int main() { long long d; std::cout << "Enter a Julian Day Number: "; std::cin >> d;
if (d < 0) {
std::cerr << "Error: Invalid Julian Day Number (must be non-negative)." << std::endl;
return 1; // Indicate an error to the system
}
const int DAYS_PER_YEAR = 365;
const int DAYS_PER_LEAP_YEAR = 366;
const int DAYS_PER_LEAP_CYCLE = 1461; // 4 years
const int JULIAN_TO_GREGORIAN_THRESHOLD = 2299161; // Oct 15, 1582
// Adjust for Julian-to-Gregorian transition
if (d >= JULIAN_TO_GREGORIAN_THRESHOLD) {
d += 10; // Account for dropped days
}
int a = d + 32044;
int b = (4 * a + 3) / DAYS_PER_LEAP_CYCLE;
int c = (4 * a + 3) % DAYS_PER_LEAP_CYCLE;
int y = (b / 1460) + 1970;
d = (c / 4) - 365;
if (d < 0) {
y--;
d += DAYS_PER_YEAR + (y % 4 == 0);
}
std::cout << "Gregorian Year: " << y << std::endl;
std::cout << "Day of Year: " << d + 1 << std::endl; // Add 1 as days are typically 1-indexed
return 0;
}Really begs the question of what the long-term outlook is for the non-top-quartile people. Maybe re-prompting LLMs is the new ball of mud?
Recently, my company acquired some engineers, and while I cannot evaluate their "percentile", I have been low-key flabbergasted at some of their suggestions for using LLMs in place of scripts. (For example, to modify or move nested data in a non-public JSON representation of a program.)
https://www.bbc.com/future/article/20240228-leap-year-the-im...
[0]: https://craftofcoding.wordpress.com/2020/02/12/the-world-of-...
But for case value
value can only be char or int, and must be unique
Really it is just sugar for if-else-if, but if you enforce explicit break in your code it is as close to a provable total function as you get in C.
Total functions are the ideal in any code.
As determining whether or not a function F is total is undecidable, switch is more reliable than if-else-if ladders.
But I agree that in the case you described, that the programmer was being stupid. However they could have written it as a giant if-elseif block and that would also have been stupid, or a loop over a giant list of years, and that also would have been stupid. I think the problem was the programmer not thinking about the problem carefully, not with the control-flow construct they used to write the bad code.
laugh. embrace and share the fun with others: submit to https://thedailywtf.com
Had a customers app break when they used zips that contained over 65k separate files. Sent it to dev and they said "Oh use this other API we have". And yes, the file 'worked' but the api didn't do what the customer needed. Got back with the developer and saw
We had two api's that did almost but not quite the same thing. Ok, it happens, maybe there was a reason for it.
We also had two different zip libraries built in. At some point a dev ran into issues with legacy zip support not working on large files and added a new library. They converted about 10% of the API, enough to cover what they were working on and stopped.
This is an interesting problem. If you insist on maximizing consistency on a large code base, then nothing can ever change. If you allow too many small deviations / good ideas that are only ever partially completed, it results in chaos. I think it is a little like entropy: some (not too much) is needed for things to progress.
I think for most users it's made feature observability much better.
Case in point I've been at multiple places that have had multiple JSON and XML libraries in the same product at the same time.