by Remy Porter on (#6NZXD)
|
The Daily WTF
Link | http://thedailywtf.com/ |
Feed | http://syndication.thedailywtf.com/TheDailyWtf |
Updated | 2024-11-21 14:46 |
by Remy Porter on (#6NZ0T)
Today, we have an interesting one. It's not technically a Code SOD, because it doesn't have any code. It isn't quite a feature, because it doesn't contain a story. It's just some data, from a database table.But it does tell a story.Today's anonymous submitter was browsing through the tables underlying a bit of enterprise software. One of the things which caught our submitter's attention was that the MODULES table had a field MD_ID and a field MD_GUID. Now, it seems odd to have both. Ideally, each GUID is unique. Maybe it was some misguided ideas around how to optimize foreign keys? Maybe it didn't start with GUIDs, and needed to retain the old column for backwards compatibility? There are many, logical reasons why it might be this way.Let's look at the data.MD_IDMD_NAMEMD_GUIDMD_DESC0Defects{e1bb4b51-06e1-454e-8d75-83d6f7a38f42}Defects1Test Plan{fefeb3f5-81fd-472c-af4a-9bbf008f22f8}Test Plan2Test Lab{652b5c42-13e1-40d1-a319-7056c0171006}Test Lab3Requirements{409a58f0-73f6-46b9-a96c-e3851ed09825}Requirements4Dashboard{c67dcd3a-3968-44c9-baf3-a65c81bd329a}Dashboard5Components{df363e91-c0a6-465c-9ef4-820365957c2e}Business Components6ReleasesReleases module has no GUIDManagement7Models{74ce1ffb-6840-49da-b7e3-7e138e1851a1}Business Models8Libraries{e00fdc7f-174a-4b28-aced-f71e02058781}Libraries9Environments{80f6b6d7-c022-4306-9b6f-6a77774d8d5f}EnvironmentsThis is more about the users than the data itself, but I really do enjoy that the description field provides no additional information, and in some cases makes the meaning of the name less clear.But the real special thing is obviously, that the Releases module has no GUID. This also tells us that the GUIDs are stored as strings, which is the wrong way to store a GUID.Is there a good reason why one module doesn't get a GUID? Probably not. But it leaves us puzzling- why not just set one. It doesn't matter! Why is this one special? Why do we break our unique identifiers by not treating them correctly? [Advertisement] ProGet's got you covered with security and access controls on your NuGet feeds. Learn more.
|
by Remy Porter on (#6NY4H)
Joe wanted to interact with a social media service's API. As one does, he went out and found a library for his language, and started investigating it. Now, the API was, unsurprisingly, an HTTP based API, wrapped in TLS for security. The library had a handy built-in function which validated the security certificates to ensure they were still valid and hadn't been compromised:
|
by Remy Porter on (#6NX80)
Johannes started debugging an application, and decided he needed to "share his pain".Here, we're presented with a simple problem: convert a number in the range [0-25] to a letter [A-Z]. Many people would solve this with an array of letters as a lookup table. If they're clever, they'd leverage the character encoding and do some arithmetic.Or, they could just have a gigantic switch:
|
by Lyle Seaman on (#6NVE0)
Happy Friday to those who celebrate. Enjoy it while it lasts, because Greg L. has some bad news."It was nice hanging out with all of you, but it looks like the Sun is scheduled to expire Sunday morning."It's worse than that: the laws of physics are being replaced.
|
by Remy Porter on (#6NTGP)
Alice works with an XML-based RPC system. They send requests, it does a thing, and returns back a response, all surrounded in XML. The service sending the requests, however, doesn't use a well-established parsing library. The result is that, well, the code ends up here.First, though, a bit about the data they expect to parse. It's verbose, but fairly straightforward:
|
by Remy Porter on (#6NSW2)
Evan sent us 545 lines of PHP code from a file called spec_email.php. It appears to participate in sending an email, with a nice big pile of HTML in it. We're going to take it in a few chunks, because... choices were made.It opens with this check, and a few variable declarations:
|
by Remy Porter on (#6NRP9)
Alexander sends us this snippet, where we change our definition of truth to something which eschews concrete definitions and accepts that existence is ephemeral. Truth and false are just illusions we project onto a reality that is itself just an illusion. In the end, we are all nothing.
|
by Remy Porter on (#6NQX3)
When interacting with RESTful web services, there's a depressingly common anti-pattern: always return status 200 OK, but embed a more meaningful status code in the body of the response. Frequently, the embedded status code is just the HTTP status code you should have returned in the first place.This "fixes" situations where you have badly behaving clients that don't do proper error handling, but also breaks the entire point of doing REST.Alice works on an app that, while most of the time the code is decent, has a service that does this. This service also does something even worse: depending on the URL parameters you pass to the query, it may do something like this when it returns errors:
|
by Lyle Seaman on (#6NP7K)
Not to be outdone by Michael R., another prolificparticipant styles himself The Beast In Black.A handful of his experiences follow here. [psst. Mr Black. Check out this explanation of a half-closed interval)Buyer Beast bemoans "I knew that the global situation was bad, but when Amazon starts offering disdiscounts (ordiscountcounts, perhaps?) you know that theworld is truly up the toilet without a paddle roll."
|
by Remy Porter on (#6NNA1)
If I'm being completely honest, I'm mildly anti-ORM. I'm not about to go on a rampage and suggest they should absolutely, never, ever, ever be used, but I think they tend to create a lot of problems. Instead of being a true mapping between our object model and our relational model, they're their own tool, with its own idosynchracies, and a lot of "magic" that conceals its actual operation. For simple applications, they're great, but once you start getting into something more complicated than basic CRUD operations, you're in for a world of hurt. And that's before someone makes a mistake with eager vs. lazy fetching.Today's anonymous submission offers us a good example of another way the mismatch can go wrong between objects and relations.
|
by Remy Porter on (#6NMJ1)
Today's a day for a smorgasbord. We're going to start with a classic kind of bad code, from astephens:
|
by Remy Porter on (#6NKNJ)
David's application has loads of unit tests. Many of the unit tests even go so far as to exhaustively test every combination of parameters. So seeing something like this is pretty common:
|
by Remy Porter on (#6NJTZ)
Today, I'm honestly not sure that the WTF is in the code we're looking at. Jeff needed to support an older PHP application which used client side JavaScript heavily. This block was copy-pasted many times throughout the code base:
|
by Lyle Seaman on (#6NH4F)
One of our most dedicated readers, Michael R., is also one of our most dedicated contributors,sometimes sending us several submissions in a single day. We haven't featuredall of them, but now we're making up for that. Today, it'swall-to-wall Michael, mostly food misadventures. Michael might tell you we'vecooked the plot, but he can't prove it.On leaving France (it's a long story), Michael was confused at the airport."Yo Sushi at Charles de Gaulle Terminal, please make upyour mind about what payment types you accept." I think this one is pretty clear;just because a sign says they accept one form of paymentit doesn't mean they categorically reject all others. So if your card is on eithersign, you're covered. I hope he got fed.
|
by Remy Porter on (#6NGAS)
Kyle sends us a puzzler of bad code today. It appears in a "JSP-like" codebase- which Kyle provides no futher details on, but certainly hints at a serious WTF underpinning this code.
|
by Remy Porter on (#6NFEJ)
Ever since the DOS days, determining file type based on the three letter extension in its filename has been a common practice. I'd argue that it's not a good practice, but it's become so standard that it's hard to avoid. It's so common that pretty much any language in wide use has some sort of "get extension" method. C# is no exception.Of course, having a convenient and commonly used helper method is no barrier to writing it yourself, and Andrew found this code in their application, which is meant to extract "png", or "jpg" as the extension.
|
by Remy Porter on (#6NEJK)
When you get into the world of proprietary filesystems, things can get real weird. There are many a filesystem that doesn't support directories, still in use today. Or filesystems which only allocated chunks in multi-megabyte blocks, which means you end up wasting a lot of space if you have small files. Or filesystems where the largest file size is itself a handful of megabytes.Dan was working on one such filesystem where, when you opened a file for writing, you could specify how many "fixed records" it needed to support. So, for example, if you wanted to open a file for writing, in binary mode, you might do this: open(pathToFile, "f4096wb"): support 4096 records, and open it for writing.Now, Dan's predecessor wanted to do exactly that: open a file for writing, with 4096 records.This was their C code for doing that:
|
by Remy Porter on (#6NDTV)
Many years ago, Tom supported a VB6 application. It was about 750,000 lines of code, split across far too many files, with no real organization to it. While the code was bad and awful, the organization problem was a universal issue for the application. It even infested the database.This is some VB6 code for querying that database:
|
by Lyle Seaman on (#6NBXA)
I'm fresh out of snark this week, so I'm relying on the rest of you to carry the load for me. Tote that barge, etc.First up is a timely comment from an anonymous reader:"Even Kronos admits their software is a pain."
|
by Remy Porter on (#6NB2D)
Many a time, we've seen a program reach out into the database for date times. It's annoying to see, but not entirely stupid- if you can't rely on your web servers having synchronized clocks, the centralized database may very well be the only place you can get a reliable date/time value from. This ends up meaning you get a lot of date formatting happening in the database, but again- if it's the only reliable clock, you can't do better.Unless you aren't even looking at a clock. Mendel sends us this C#:
|
by Remy Porter on (#6NA52)
One of the nice things about Git is that it makes it very easy for us to learn the steps that went into a WTF. It doesn't mean it explains the WTF, as many are just inexplicable, but it's at least something.Like this example, from Aoife.The JavaScript started like this:
|
by Remy Porter on (#6N95Y)
Chilly inherited a VB .Net application which generates an "IDoc" file which is used to share data with SAP. That's TRWTF, but the code has some fun moments:
|
by Remy Porter on (#6N89N)
Joe inherited some C code that left him scratching his head.It doesn't start too badly:
|
by Lyle Seaman on (#6N6HE)
We got a lot of good submissions this week, includingsome examples of test-in-prod we're saving for a specialedition. Not too many of the usual NaN/Null/Undefined sort, but we did also get a small rash of time failures.But frist, Henk highlights the curious case of QNAP's email subscription management page (which appears to be outsourced)."QNAP surely does not want to lose me!" he hoped.
|
by Remy Porter on (#6N5MY)
Back in the heady days of the DotCom Bubble, startups were thick on the ground, and Venture Capital money was a flood- lifting startups atop a tsunami only to crash them back into the ground a short time later. Taliesyn once worked for one such startup.Taliesyn's manager, Irving, was an expert in AI. In the age of the DotCom Bubble, this meant Irving knew LISP. Knowing LISP was valuable here, because their core product was a database system built on LISP- specifically the Common LISP Object System, an object-oriented bolt-on for LISP.It was an object-oriented database system, akin to the modern NoSQL databases, but its architecture left a few things to be desired. First, since disk reads and writes were expensive operations, the system avoided them. All updates to data were done in memory, and someday, at some point, when the program felt like it, the changes would be written to disk. This meant that any failures or crashes could lose potentially days of data. Worse, the data was stored in one gigantic text file, which meant corruption could easily take out the entire database.These were legitimate problems, and due to the architecture, they were going to be challenging to resolve. That was the startup life, however- they had a minimum viable product, and just needed to pour energy into making it something worth using.Everyone looked to Irving, the AI and LISP expert, to guide them through this.Irving saw where the real problems lay. "Your database doesn't support SQL," Irving said."Well, sure," Taliesyn said. "That's our selling point."Irving nodded, and then, speaking slowly, as if to a particularly dense child, said, "A database needs to support SQL.""I mean, a relational database, sure," Taliesyn said, "but we're using an object oriented data model which means we don't need to do joins or-" Taliesyn kept talking, explaining why their database didn't support SQL, why it shouldn't support SQL, and why SQL support was not only off the roadmap, but so far off the roadmap that it was labelled "Here there be dragons."Irving nodded along, and ended the conversation with a, "Sure, that makes sense."Everything was fine for a few weeks, until one of Taliesyn's peers on a different team, Angela, shot him an email: "Hey, marketing is getting antsy about a SQL demo, and I've got half a dozen features blocked until you get me a build with that functionality. What's the timeline like?"Taliesyn was uncertain about what the timeline was like, since he had now clearly slipped into a parallel universe. He politely informed his peer that he had no idea what was going on, but would find out. It didn't take a great sleuth to figure out that Irving had started appending his own features to the roadmap.Taliesyn tracked Irving down and demanded to know what was going on."A customer is already using it!" Irving protested. "They wrote it themselves! So we should be able to do it easily. Frankly, it's embarrassing to say that we can't do something with our own tools that the customer is already doing!"Taliesyn knew that Irving was either wrong or lying, and asked to talk to the customer. Irving was, in fact, wrong. The customer had used LISP to write an extension to their object database (another one of those selling point features), and this extension used ODBC to open a connection to a relational database. This let them move data between the two different database systems."Irving," Taliesyn said, "they're not using SQL on our database, they're connecting to a relational database and using SQL there. SQL doesn't make sense for our data structure! We don't have tables, or keys, or relationships. It's objects! You're promising features that we can't deliver."Irving was unmoved. "We are making a database. A database must have SQL capability. It's structured query language- it's right there in the name! Our structure should be queried by structured query language."Taliesyn tried going over Irving's head, but upper management had no interest in actually solving personnel problems. Irving's buzzword laden ideas about why SQL was required seemed to jive with what their customers wanted, and the idea of shipping a non-SQL database was getting lost in the endless quest for the next round of VC funding.The result was a bolted on monster of broken implementations of SQL that infuriated the few customers who tried it, Irving got promoted, and Taliesyn ran as far from the trainwreck as possible before the company flamed out. [Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
|
by Remy Porter on (#6N4NV)
Michael has a confession. Once upon a time, a very long time ago, he needed to write some JavaScript to serialize data and send it as part of a request. The challenge for Michael is that he didn't actually know JavaScript or what its built in functions could do and the task was already past the deadline by the time it got assigned to him.
|
by Remy Porter on (#6N3SZ)
I've known a surprising number of developers who say, "Why use any higher level abstractions, you can just do this all in C, and the code will be cleaner and easier to read." Sometimes, they're right. Other times... not so much. And then there are the developers who find C too abstract for their tastes, and eschew things like structs.That's what Renee encountered when inheriting a chat server written in C. I'm guessing it was an IRC server, based on some terminology in the code.
|
by Remy Porter on (#6N37S)
|
by Lyle Seaman on (#6N1KM)
...and we'll cry though we really don't want to.Celebrant Joe cheered "Happy birthday DailyWTF! My gift to you, yet anotherdate related Error'd for the pile."
|
by Remy Porter on (#6N0QD)
Alan worked on a website which had a weekly event which unlocked at 9PM, Saturday, Eastern Time. The details of the event didn't matter, but this little promotion had been running for about a year and a half, without any issues.Until one day, someone emailed Alan: "Hey, I checked the site on Sunday, and the countdown timer displays 00:00:00."Alan didn't check their email on Sunday, and when they checked the site, everything was fine, so he set himself a reminder to check things out next Sunday, and left things alone for a week.Well, Alan forgot on Sunday. It was his day off after all, but he did remember to check first thing on Monday. When he came in, the timer read 00:00:00. Alan had a twelve o'clock flasher. Oddly, when he checked it after grabbing some coffee, the timer now showed the correct value.It was time to dig through the code. Now, this story happened quite some time ago, so the countdown timer itself was a Flash widget. But the widget received a parameter from the HTML DOM, which itself was generated by PHP, and it didn't take long to find the SQL query it was using to find the next event: SELECT next_event FROM event_timer.Yes, event_timer was a one column, one row table. A quick search through the codebase found the table referenced only one other place: backend_settimer.php.All the pieces came together: resetting the timer was an entirely manual process. Every Monday, Tina came in, and assuming she remembered, she reset the timer. Some days she did it late, or forgot entirely. Some weeks, she was on vacation. Maybe she remembered to delegate, maybe she didn't.For roughly 72 weeks, this had been how things had been working.The good news was that the date was getting parsed with the PHP strtotime function, which meant Alan merely had to go to the backend_settimer.php and set the value to Next Saturday 9pm, and let Tina know she didn't need to do this anymore. [Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
|
by Remy Porter on (#6MZV2)
We're all used to Java class names that are... verbose.Arno sends us a representative Java line, which demonstrates that this doesn't end with class names.
|
by Remy Porter on (#6MYZD)
Visual Studio and the .NET languages support a feature known as "regions". Enclosing a block of code between #region SomeName and #endregion creates collapsible regions in the text editor.It can, in principle, help you organize your code. It does, in practice, make code like this, from Mark, possible."What do you mean, 'single responsibility principle?' This has one job! ADD A CLAIM. How can it get simpler than that?"The upshot of this, is that it's easier to see how one might refactor this function into multiple functions which collaborate. The downside is that this code has been like this for years. As a very bureaucratic insurance company, any refactoring efforts need to be budgeted for, you can't just refactor while working on other tickets- that's "misusing the budget".Instead, we get to enjoy the idea of simple functions, without actually having simple functions. [Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
|
by Remy Porter on (#6MY2Y)
Good method names are one of the primary ways to write self-documenting code. The challenge there, is that documentation often becomes out of date.Take this delectable PHP nugget, from Nathaniel P, who has previously been tortured by bad date handling.
|
by Lyle Seaman on (#6MWES)
This week we have an unusual number of submissions involving dates or timestamps.That is, the usual sorts of error'ds, but unusually many of them.Gerald E. chuckled "I do love the back to the future movies. Butnow I can see Beck from the future."
|
by Remy Porter on (#6MVJB)
Today's a simple one. We've all seen code that relies too heavily on string concatenation and eschews useful methods like Join.Nick L sends us this VB.Net example, written by a slew of mechanical engineers.
|
by Remy Porter on (#6MTK5)
Juliano had this very non-WTF bit of PHP code:
|
by Remy Porter on (#6MSKK)
Gavin continues work on the old C++ app he inherited. Today we get a delightful smattering of bad choices.
|
by Remy Porter on (#6MRPK)
"The attached class connects to an Access database," writes Nicolai. That's always a good start for a WTF. Let's take a look.
|
by Lyle Seaman on (#6MPX1)
Tim Y. is on Fire with this burn."Competing teams inside Google? Or just the AI recognizing marketing tactics?"
|
by Remy Porter on (#6MP2Y)
While Java didn't invent putting a toString method in the base class of every object, it certainly made it mainstream. The nice thing about the method is that it allows you to turn any object into a string, though it's up to the implementor to decide what a good string representation is. But what if you want to ensure that the object you're handed is really and truly a string, not just something you can convert to a string?teknopaul's co-worker found their own solution:
|
by Remy Porter on (#6MN6Y)
Comments explain a lot about our code. And sometimes, the comments explain more than the code itself.Alastair found this lovely comment, which demonstrates an excellent, if confusing, understanding of a boolean "or":
|
by Remy Porter on (#6MM8A)
While poring through some VB .Net code, John noticed some odd things in their datamodel. For example, a different process would scan files, and log any "suspicious" files into a database. The program John supported would then report on that data.One of their classes had a property which looked like this:
|
by Remy Porter on (#6MKCT)
You have some text, and need to replace every sequence of spaces with a single space. E.g., My text becomes My text. Now, if you're most of us, you ignore the famous quote and reach straight for regexes.But Samuel's co-worker isn't most of us.
|
by Lyle Seaman on (#6MHQW)
An anonymous friend sent us our frist test in prod for this week. And then there will be more, and more, and more."This came up in Kaspersky's Blog's RSS. If you're luckythey might still have the error up in the original URL."I don't know if "chron" is just how "cron" translates to Russian and back, but the test appears to have succeeded.
|
by Remy Porter on (#6MGVB)
Greg's co-worker really wanted to make sure that a variable was correctly set to true or false. So they did this:
|
by Remy Porter on (#6MFYF)
Meta-programming- programs which generate programs- is a delightful hobby, but usually shouldn't be used in production code. Usually. I mean, if you're working in LISP, 90% of your program is going to be macros.But if you're using PHP and JavaScript, there's good odds that someone you work with has decided to combine these two tastes together to create something nobody wants to taste.This is a depressingly common anti-pattern, usually seen in the form of JavaScript code which looks like: if (1 == 2)- once upon a time one or both of those values were PHP variables, but we only see the resulting generated code.A more extreme version happened to our anonymous submitter.
|
by Remy Porter on (#6MF0J)
Zeke sends us a C# snippet from an extract-transform-load process his company uses. It's... special.
|
by Remy Porter on (#6ME3G)
When I first saw Nick L's submission, I thought to myself, "This is just decompiled code, so of course the names are bad."
|
by Lyle Seaman on (#6MC5A)
Faithful Michael R. is good for a chuckle today. "I am using the free tier Infura right now but think I will go enterprisey straight away."Can't turn down a deal like that, eh?
|