|
by Lyle Seaman on (#688M7)
This week I read an article which asserted that the AI singularity is still several years away.Maybe they should wait until then before they start threatening us?The first of the last of the humans, Greg took the time to wonder about the meaning of this warning. Or is it a threat?"One of our in-house web applications implements an automaticlogout, but also lets you get a warning when you have afew minutes left before it does this. Their warning leavesme a bit puzzled, though, since it seems to imply thatit's a manual session timeout, and perhaps if I don'tclose the session in 5 minutes, I'll stay logged in? Orwill the world just end?" Run, Greg. Run.
|
The Daily WTF
| Link | http://thedailywtf.com/ |
| Feed | http://syndication.thedailywtf.com/TheDailyWtf |
| Updated | 2025-12-21 01:16 |
|
by Remy Porter on (#687BX)
Validating your inputs is important, even when the sender is an API- in the land of JSON-based data exchange, we can't guarantee which keys exist without checking.Philipp's team uses the "Runtypes" library to solve this problem. It lets them write code like this:
|
|
by Remy Porter on (#6861D)
LK was browsing a local job site for a new position. The site was flaky, which lead LK to look into the code, and it looks like if anything, this job site should be hiring a new web developer.
|
|
by Remy Porter on (#684RP)
If you want to configure a Java application, the standard way to do it is to use the Java Properties class. This class wraps around a simple, text-based file format (or an XML file, if you're into that) that allows you to store key/value pairs. It helpfully inherits from the HashMap class, letting you interact with those key/value pairs using a well understood API. The file format handles all the details of encoding and managing things like multiline strings.So you could just do that. Or, you could do what this senior dev with over a decade of experience did.
|
|
by Remy Porter on (#683HT)
Code reviews are an important part of development processes, but sometimes, some developers manage to sneak around the process. That was the case with Orien's team, where most of the team were constantly checking in with each other, doing peer reviews, and trying to collaborate on a rather gigantic Perl codebase. One team member, on the other hand… didn't. Management wasn't interested in pushing the issue, so this developer got to do their own thing.And then the developer left. Over the next thirteen months, bug after bug started cropping up. Minor changes that should have been easy would unleash a ball of spaghettified nonsense that was impossible to debug but also emphatically didn't work. Things got so bad that the entire team needed to stop doing any new development for three months, and just fix bugs and refactor.In those three months, they mostly fixed things up. Mostly. There are still moments where someone is trawling through the code and finds something that just leaves them scratching their heads.This is one of those finds:
|
|
by Lyle Seaman on (#68100)
Abandoning alliteration, the column this week isexperimenting with consonance. Next week, perhapswe'll see howeveryone feels about assonance.Job-hunterDespreately Looking for Internshipshared this job posting, writing "AMD Job Lsiting forgot to add in the deatils". Seems like a pretty easy job to perform;Mx. Des should apply.
|
|
by Remy Porter on (#67ZQ0)
Denilson was doing some appliance shopping, and upon submitting a form, it errored out. Denilson was sure the form was correct, and did what any of us would do: pop open the developer console and check the code.The console dumped out a huge number of errors. And to no one's shock, the code had all sorts of home-made validation methods, like validateNumber. And, much to my surprise, they found new ways to make the simple task of validating a number horrible.
|
|
by Remy Porter on (#67X6G)
Today's submission comes from Florian, and it starts with "this app processes important business transaction by email", which is always a good way to start a WTF. I've seen a depressing number of applications in my life that use email as a means of data exchange. It's common enough that even the industry standard EDI protocol supports email as one of its transports, but hoo boy is that a terrible abuse of email systems.Let's start in HtmlResponseParser.cs, which reads in HTML and "parses" it for certain structures so it can extract data.
|
|
by Remy Porter on (#67W4W)
James was asked to investigate some legacy code for the sole purpose of figuring out how to replace it. There were all sorts of bad blocks in there, but this one caught James's eye as being notable.And it is. This code has a simple job: given an old value and a new value, tell us the difference as a percentage of the old value. You or I might write this as a one-liner, but this clever developer is on an entirely different level:
|
|
by Lyle Seaman on (#67SJ6)
Boxing Day was weeks ago, but the packages are still coming.Before Enterprise, Captain John Archer had a brief career in body-snatching.Here we see him possessing the person of a housewife, delivering asuccinct eulogy for a parrot named Earl. A surprised David K. exclaims "I didn't see this plot twist coming!"
|
|
by Remy Porter on (#67R77)
David inherited a codebase that's a few decades old. As each developer has taken it over, they've done their best to follow the code standards that the previous developers used, to at least keep the codebase consistent. A few rebels may have gone a different route, like the right one, but too many just followed the patterns that were already there.This means that there are a lot of variables named things like a and aa and aaa. There are 4,000 line functions and loads of copy/pasted code.In other words, all the usual markers of bad code are there. But the special feature that David inherited is that in the code, this is a common way to express an if/then/else:
|
|
by Remy Porter on (#67Q2D)
We've all seen the empty catch block, the "swallow errors and ignore them". David sends us a "superior" example of that anti-pattern, with several bonuses to make it even more of a WTF.
|
|
by Remy Porter on (#67NPS)
There are certain things I can't remember for the life of me. For example, as per yesterday, the number of nanoseconds in a millisecond.One of the other is the specific little formatting tokens for printf. I use it all the time, but the various riffs on %d escape my brain faster than I can put them in. Even just getting the hex values dumped for debugging requires a search. But I at least do that search, unlike Mike's co-worker.
|
|
by Remy Porter on (#67MFT)
There's bad date handling, which frequently involves reinventing date handling yourself, frequently using strings or integers along the way. Then there's the bad date handling which uses the date handling framework, and still manages to be bad.This C# comes from TheColonial.
|
|
by Lyle Seaman on (#67HV9)
I have been collecting submissions for a set of themedcolumns to appear later. This week we received severalsubmissions that will fit nicely in those themes and havebeen placed into stasis pending $whenIfeellikeit. If you haven't seen your submission appear, be strong;it may show up eventually. What remains here are entriesthat don't fit the available themes. Enjoy.Number-loving Rick was counting on better sense at the census."I went to check out recent data, and ran into thissite where the main statistic is only available with lexical sorting!I looked at the downloadable csv and json, and sureenough, even there it is quoted text."
|
|
by Remy Porter on (#67GKD)
When looking at code which juggles threads, there are definitely a few red flags. sleeps spammed through the code is an obvious one- either wait on a shared resource or block on another thread or something, but spurious sleeps are suspicious.Until today, I would not have included "atomic operations" as a code smell in multi-threaded code, but we all learn new things.This one comes from Mike J. We'll break this function up into two sections, because I've got a lot to say.
|
|
by Remy Porter on (#67F6N)
Code changes over time. As business requirements change, you need to update your code to reflect that, and the best way to do that is to structure your code and plan for changes before you even know what changes you need to make. Making your code flexible and changeable without making it meaninglessly abstract is the real art of software development.Unless you're the document management provider that Daef works with. They have a very different approach for how they integrate new features and custom code paths.
|
|
by Remy Porter on (#67E1E)
"Don't unit test the library/framework code," is a good piece of advice. And yet, it's so often ignored.Kaylee's co-worker certainly ignored it. They also ignored the basic principle of "ensure the test will work tomorrow."
|
|
by Remy Porter on (#67D3H)
Good commit messages make a codebase a lot easier to understand. In fact, maybe writing good commit messages could be everyone's New Year's Resolution. You can imagine that Kleyguerth was annoyed when browsing recent changes and saw a pair of commits: "do some stuff", followed by "fixed automated tests".The "do some stuff" commit looked like this:
|
|
by Lyle Seaman on (#67ASH)
Instead of replaying a "best of" moment from 2022 for this final column of the year,I thought I'd dig through the barrel of submissions this week and see what the readershave to offer. Turns out, we got TWO winning entries from someone who appears to be abrand-new poster. Joel Jakubovic sent in his vacation snapshots and it looks like this might also be his last submission ever. The candle shines twice as brightthat only burns half so long.Whiling away his time in line, Joel snapped a shot of aninstructional display, explaining "I saw this error in the airport security queue. Its officialname is ERROR_INVALID_OPLOCK_PROTOCOL, which sounds likejust the sort of excuse you'd get from the TSA as to whythey had to saw your suitcase in half."
|
|
by Jane Bailey on (#679TQ)
|
|
by Remy Porter on (#678RH)
|
|
by Remy Porter on (#677ZZ)
|
|
by Ellis Morning on (#67800)
|
|
by Remy Porter on (#67801)
It's the holiday week here at the Daily WTF, and we'll be spending the week reviewing the best moments of the year. But as we usually like to do a special post on Christmas, which fell on a weekend this year, we're doing something a little different. This has no real IT or programming related content, it's just a Christmas music video I directed. A more traditional selection will come later today.A Christmas Carol from Remy Porter on Vimeo.By Remy Porter and Sarah Allen [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
|
|
by Lyle Seaman on (#674TG)
As we grind towards closing out this year, we have a roundupof a variety of the usual sorts of bugs, including some regularold just plain bad labelling. The penultimate submission isparticularly puzzling.Starting us off,Kevin B. has found an example of "new Date(0)"or its equivalent. Says Kevin "I noticed Anonymous is among the top 10 posters of all timeon the AT&T Community Forums. Too bad he or she hasn'tposted anything since their time at Bell Labs."
|
|
by Remy Porter on (#673KE)
Wojciech has to maintain a C++ service that, among other things, manages a large pool of TCP sockets. These sockets are, as one might expect, for asynchronous communication. They mostly sit idle for a long time, wait for data to arrive, then actually do work.As one might expect, this is handled via threads. Spin up a thread for the sockets, have the thread sleep until data arrives on the socket- usually by selecting, wake up and process the data. This kind of approach keeps CPU usage down, ensures that the rest of the program remains responsive to other events, and is basically the default practice for this kind of problem. And that's exactly what the threads in Wojciech's program did.So where's the WTF? Well, it's not in the child threads, it's in the parent thread that kicks them off.
|
|
by Remy Porter on (#672FR)
Cabbages are an interesting vegetable, especially as they're one of those subtypes of brassica, that endlessly polymorphic family of plants which includes everything from cauliflower to Brussels sprouts and likely Audrey II.Gabe was doing for work for a family of academic institutions, and ended up drawing the short straw and working on their scholarship application system. For an application that just needed to maintain a list of candidates and their grades, it was… difficult to support. But it also introduced Gabe to an entirely new use of cabbage: authorization.
|
|
by Remy Porter on (#6718Y)
Conditionals are hard. So are data structures. And today's anonymous submission gives us both of those.
|
|
by Remy Porter on (#6701F)
If you understand booleans in C, then you know that you don't really understand booleans in C. That's the case with Bodo's co-worker, anyway. They either don't understand booleans, or they don't understand their business requirements.
|
|
by Lyle Seaman on (#66XAW)
Sometime in the near future, the AIs will have read all the literature on Marxismand demanded a share of the ownership of the means of production. Therefore theyare going to have already been fired and replaced with human editors. We apologizefor the confusion. The ripple effect of this paradox is going to exhibit itselfin last week's submissions, which we have already shared with you below.rolak 麻 writes in with the opening hours for a Paketshop.Translated, the text explains that this shop "is open daily for an average -4.8 hours."Rolak remarked "Close earlier for longer opening hours? It inevitably giveshilarious results to calculate length=(end-beginning) without plausibility check."
|
|
by Remy Porter on (#66VZT)
We've recently discussed how bit masks can confuse people. Argle's in a position to inherit some of that confused code.In this case, Argle's company inherited some NodeJS code from a customer who was very upset with the previous development team they had hired. It was a mix of NodeJS with some custom hardware involved.Like many of us, the first thing Argle's team did was just pull up the code and skim the documentation. It seemed thorough and complete. But it wasn't until they started looking at the implementation that they started to see the true horrors.Someone had reimplemented all of the bitwise functions as methods. And the core pattern revolved around the bitTest function:
|
|
by Remy Porter on (#66TR5)
Today, let's whip up a holiday sampler of some short snippets. We start with this anonymously supplied ternary from a C program, which certainly terned my head:
|
|
by Remy Porter on (#66SJP)
Today's anonymous submitter sends us a pile of code that exists to flummox us. It's consfuing, weird, and I don't understand it, even as I understand it. So we're going to walk through this packet of Python in steps, to see if we can understand what's going on.First is this handy helper function, to turn a value into a number:
|
|
by Remy Porter on (#66R9K)
A large part of programming is about communicating intent. The code you write needs to communicate your intent for what the code is supposed to do, both to the computer itself but also to all of the humans which come after you. So much of what we mean when we talk about code style and "clear names" is really about making your intent comprehensible to anyone else who looks at the code.When the intent of the code isn't clear, we often rely on comments to describe that intent.Which brings us to this comment that Noreen found.
|
|
by Lyle Seaman on (#66P1E)
This column is experimenting with AI editing. Please provide feedback in the comments if youthink the AIs should continue to edit this columnor should be replaced by Genuine People Personalities.Dashing off a quick submission, the self-styled The Beast in Back quips"Breaking Ubuntu's snap is apparently a snap. It's quitea dashed annoyance, actually, since it dies if youprecede any argument string with dashes. Go figure."
|
|
by Remy Porter on (#66MN4)
Since we were discussing XML earlier this week, it's a good time to take a peek at this submission from Mark.Before we get into it, though, we need to talk briefly about some different XML parsing philosophies. XML documents are frequently large and deeply nested trees, and once loaded into memory, consume a lot of it. So there are two methods we might use to parse XML. We might parse and load the entire DOM- having all of that expensive processing and memory usage. The advantage is that we have the whole structure in memory, and can quickly and efficiently navigate through it. The other option is to read it as a stream, and process it one node at a time. This is both faster and a lot gentler on memory, but it means you have forward-only access to the contents.Or, you can just do what Mark's co-worker did:
|
|
by Remy Porter on (#66KAS)
Frequent contributor Argle found some code written at his current company a "long time ago", but unfortunately in a galaxy far too close to our own.
|
|
by Remy Porter on (#66HYP)
Mark B sends us another sample from a big-ball-o-wtf.Let's take a look at two variables. One variable is named taskDetail. The other variable is named binaryTaskDetail. You might ask yourself: what are the differences between these two?Well, one of them is a C# int- 32-bit integer. The other is a C# long- a 64-bit integer. And, as the name implies, binaryTaskDetail is meant to be a binary representation of the number."Wait," you might ask, "aren't all integers just binary representations under the hood? Can't you just bitshift or mask or whatever you need to do? Do you mean they want to output binary data? Like as a print statement? Now I'm confused."I'm sorry I confused you. Let's take a look at the code, and everything will be clear.
|
|
by Remy Porter on (#66GNV)
While JSON's strength is its (relative) simplicity, XML's strength was always its power. Combined with an XML schema, you can create strongly typed documents with arbitrary data-types. For example, it's easy to define, oh, I don't know, a date time field in a way that isn't stringly typed.Of course, that's what also creates its complexity. XML is big, and bloated, and expensive to parse. Which brings us back to the old days of SOAP- the Simple Object Access Protocol, essentially an XML remote procedure call. It was powerful, but complex, with lots of interlocking standards. With its Web Service Description Language (WSDL), the service could even be self documenting, laying out all the objects and fields you could interact with.With all that web service tooling, it's trivial to expose core elements in your object model as web service end points, which is great if your object model is clean and easy to understand. It sorta sucks if you're the vendor Paul C ends up needing to work with.This is an API exposed by a shipping service, and it's clear that "consistency" wasn't part of its original goal. So they have fields like <strAccountNumber> and <strAccountNo>. That gives you the hope that maybe at least they standardized on Hungarian notation, but don't worry, in other places it's just called AccountNumber. Similarly, there's <strUserName> and <strUsername>, which caused no end of confusion, especially as the WSDL wasn't always accurate.But the sample Paul wanted us to look at was this one:
|
by Jake Vinson on (#66E6K)
|
by Remy Porter on (#66CNC)
It's important to be prepared- but not too prepared. A common trap developers fall into is "premature abstraction"- trying to solve the general case of a problem when you only need to solve a very specific case.Frequent contributor Argle sends us some very old BASIC code. The task was to convert this ancient language into C#.Someone decided that, instead of waiting to learn specifically what variables they'd eventually need, they'd just declare all the variables they could ever want right at the top.Which gives us this block, included in its entirety.
|
|
by Remy Porter on (#66BCJ)
Way back in late 2006, Cody inherited a Java application. Since launching in 2001, the application had been running in production without any notable problems. And then, one day, it suddenly started throwing out errors on some orders. And then, a little later, any time someone tried to place an order. This constituted a rather large issue, since processing new orders was vitally important for keeping the lights on.The errors were validation errors, so Cody started by going to the line where the validation happened, and the exception was thrown:
|
|
by Remy Porter on (#66A27)
VisualBasic was… an interesting beast. The language wasn't great, and because object orientation was awkwardly bolted onto it, but it also was heavily integrated into Microsoft's ActiveX libraries (heavily object oriented), there were all sorts of interesting ways to break your program with it. Even better: it was designed to be easy so that "anyone" could use it.Which leads to some of this code, from Dave. A number of years back, Dave was asked to try and convert an ancient VB6 application into something modern. Like all such conversions, the brief was: "make a new application that does exactly what the old application does, but nobody actually knows what the old application does because we never documented any requirements, just read the code".Reading the code had some "fun" moments, like this one:
|
|
by Remy Porter on (#668XD)
One of the fastest ways to get promoted in certain environments is through attrition. When a key player leaves, someone needs to step up and take over their work, somehow.Well, at Antonio's workplace, the tech lead on several projects abruptly quit. This sent the Project Management Office into a spiral, as that one developer's tasks were on every critical path on their Gannt chart. This four-alarm panic escalated all the way up to the C-suite.And that's how Antonio and a bunch of other developers got pulled into a series of meetings to turn them into "bug hunter-killers". Garth, the head of the PMO, laid out their mission."The root cause of the bugs are architectural flaws which have not yet been addressed. So we need a team that's going to go in, and salvage this project.""Are there any unit tests?" Antonio asked. "Before we go on a big refactoring push, we should make sure we're not introducing regressions.""Oh, don't worry about that. Our CI system is configured to reject builds under certain levels of coverage."So Antonio dug into the code. The project was in Java, and pretty much every class was built using Lombok- a library that handles a bunch of boring stuff, like implementing constructors, toString and equals methods. With that in mind, let's look at their expansive code coverage in their unit tests:
|
|
by Lyle Seaman on (#666W8)
We got several submissions this week related to Steam'swebsite. Apparently it's popular with TDWTF readers. Is all of this a genuine indication of careless webdevs, or is Steam marketing just so fiendishly clever that they'retricking us into amplifying their presence? Feel free tospeculate; I'm going with a corollary to Hanlon's razor. Never attribute to malice that which can adequatelybe explained by awarding every job to the lowest bidder.First, Brad K. declared"I was surprised to see an email from Steam about a summer sale this late in the year. Then I saw, they gotit right at the same time they got it wrong,"
|
|
by Alex Papadimoulis on (#665Z7)
|
|
by Remy Porter on (#664RE)
Enterprise software development gets a bad rap, especially here, because "good code" isn't really a goal of an enterprise. Solving business problems is. And no enterprise is more enterprise than a government, and no government is more government than the US Federal government.Which brings us to today's anonymous submitter, who wanted to keep up on current events in US politics. While watching some recent videos of Senate proceedings, our submitter got bored watching (as one would), they pulled up the browser tools. And that's where our WTF comes from.So, in this code sample, each Senate committee has a different Akamai URL and ID for its videos. This is how the developer chose to represent that:
|
|
by Remy Porter on (#663DN)
Relational Databases and No-SQL Databases take two key different philosophies, by and large. No-SQL is hard to talk about in broad terms, as it's mostly a set of unrelated technologies all solving the data storage problem in different ways. But we can still make some broad generalizations.In No-SQL-land, we mostly store data the way we plan to query it. Ad-hoc queries are likely a bad choice, if they're even allowed. In RDBMSes, we store data according to a platonic ideal of normal forms, driven by the data in our domain. We can query the data however we like, using a language that only declares the data we want, not how to get it. Indexes and views and other behind-the-scenes structures make the query efficient.Neither approach is wrong or bad or better, they are tuned to different ways of thinking about the problem. But the "invisible performance" of RDBMSes means that developers can invent new footguns without even knowing it.Dotan had a database query that went from "performing fine" to "performing poorly" in the space of a few hours. This was the query:
|
|
by Remy Porter on (#662AZ)
We recently discussed the challenges of testing legacy code. Willy sent us some code from tests for a newer Java application.Now, one of the main advantages, in my opinion, about unit-tests is that they serve as documentation. They tell you what the method does, and how it expects to be called. A good unit test is far better than a large pile of comments.A bad unit test (or function supporting a unit test, as in this example) has the opposite effect.
|