Skip to main content

CodeSOD: Completely Readable

15 hours 57 minutes ago

It is eminitently reasonable for companies to have "readability standards" for their code. You're writing this code for humans to read, after all, at least in theory. You need to communicate to future inheritors of your code.

But that doesn't mean readability standards are good. Tony's company, for example, has rules about returning boolean values from functions, and those rules mean you are expected to write code like this:

public bool Completed () { if (completed == true) { return true; } else { return false; } }

It's more "explicit" this way. Which I certainly would have explicit things to say if I were told I needed to write code this way. Also, what's with the non-indented return statements? Is that also part of their coding standards?

[Advertisement] ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.
Remy Porter

Error'd: Yeah Yeah I'm The Tax Man

3 days 15 hours ago

In only a handful of years, four Liverpudlian scruffs clawed their way from obscurity to unprecedented worldwide celebrity.
Yeah, yeah, yeah.
Already making a mint from "Money" and other hits, by 1965 they were MBEs, and suddenly discovered class solidarity -- with the rest of the singlet-clad bathers in their grottos of ducats. To be fair, a 97% marginal rate does make it hard for a lad to break into the ranks of true generational wealth.
So in 1966, George Harrison and his newly-minted toffs released the anti-government protest shriek of the upper class, and even now, we Americans share their pain in this our momen of reckoning with ... the Tax Man.

The Beast in Black first complained "I tried to get my W2 (for our non-Murican friends, that's the statement from your employer showing how much they paid you and how much tax they deducted) from ADP, and apparently their programmers did a number (two) on the form. TRWTF is that the damn form actually works if I add the slash separators to the date components."

 

And again he moaned "Frankly, I'm a little too scared by this WTF to be snarky; I'd expect a Tax Accounting firm - H&R Block in this case - to not have such basic accounting WTFs. Perhaps they should change their name to H&R Blockhead...?"

 

Adam R. remarked "It's tax season again. I hope their tax return backend is better than their JavaScript frontend that set the tooltip on this image to [object Object]."

 

Frustrated Dustin S. is trying to comply: "I logged into my credit union to download the tax documents for my account, but when I clicked on the link, this is what I got. Maybe doing taxes by invoice in the U.S. now?"

 

And looking to the future, the tax man cometh inevitably for Michael R. , though not today. "In green: I want to enter a discount for the items I'm selling. The error says:"Invalid discount amount. Please enter a discount of less than €0.00 (packaging costs + taxes).". Yes, I have also tried to enter -7,41 without any luck. In blue: It says:"Total amount approx.". Maybe one of the ebay lawyers figured out they are using float data types and wants to cover their bottoms against the rounding errors?"

 

[Advertisement] Plan Your .NET 9 Migration with Confidence
Your journey to .NET 9 is more than just one decision.Avoid migration migraines with the advice in this free guide. Download Free Guide Now!
Lyle Seaman

TDWTF Home Edition: Pt 2

4 days 15 hours ago

Read (Part One here)

When Ellis awoke on Sunday, the unusual cold broke through her drowsiness right away. Her new thermostat was programmed to maintain a lower temperature overnight, but at 6:30AM, it was supposed to climb again, kicking the heat on right when she got out of bed.

Why was it so cold? Why was the furnace dead silent? Something must've gone wrong again. So soon?

It sucked to get out of bed when it was dark and cold, but Ellis had no choice. She forced herself to peel back the covers and launch into her morning routine. Her cat shadowed her, helpfully letting her know several times that his plate had no food on it.

She attended to the cat's needs first before approaching the thermostat downstairs. The set point was at the overnight setting even though it claimed to be following her programmed schedule. Using the touchscreen interface, she increased the set point manually. The heat cut on just fine from there, thank goodness.

Through her dehydrated, hungry, uncaffeinated haze, Ellis suddenly remembered the time change. They had "sprung ahead" for Daylight Saving Time. Had her new thermostat joined them in this archaic ritual?

It had not. Checking its day/time settings, Ellis found the time an hour behind. She pressed her index finger onto the hour, expecting a dial or drop-down or some other such control to appear. Nothing. Hours, minutes, and AM/PM were all fixed. Only the time zone could be changed. It was currently set to EST. Opening the drop-down menu, none of the options she skimmed over looked promising.

Her old thermostat (out of support, incompatible with her new HVAC system) had handled time changes all by itself, and had allowed every possible manual adjustment one could wish for. It frustrated Ellis that the latest so-called "smart" thermostat couldn't manage the same despite being hooked up to the Internet at all times.

Part of her wanted to keep digging at this, but it was way too early. Ellis was unprepared in every possible way to descend into a troubleshooting rabbit-hole. She had places to be that morning. The heat was working, that was all that really mattered. More importantly, someone from the HVAC company was already scheduled to perform a 1-week follow-up test of her newly-installed system in a couple of days. She could disable the schedule and make manual adjustments until the technician arrived.

With HVAC having taken center stage in her brainspace for over a month by that point, Ellis desperately needed to give herself this break.

The technician who arrived was equally mystified. He tried a factory reset of the thermostat, which had no effect. It was determined that future time changes would have to be handled manually by toggling the time zone between EST and ... Eastern. An unhelpful label that Ellis' sleepy brain had completely glossed over early on Sunday morning.

Annoying, but not the end of the world.

Once the technician tested her system (all good, thankfully) and left, Ellis sat down in front of her laptop to check her usual subreddits. Ah, the World Baseball Classic! Someone had posted a highlight reel of her favorite baseball team's best pitcher—arguably the best pitcher on the planet—recording 7 strikeouts in a single game. She opened up the video, eager to watch.

Why the hell is Ellis suddenly telling you about sportsball? Because, in an amazing coincidence, she spied the name of the company that had built her new thermostat, right there on the backstop behind home plate!

So they had WBC advertising money, but couldn't pony up for a sensible day/time interface. Ellis suspects she's in for an interesting couple of decades ... assuming her new system lasts that long.

P.S. Since Ellis has shamelessly segued her way into sportsball, there's something else she wants to share: a new player on her favorite team, Jhostynxon Garcia, is nicknamed The Password.

His younger brother Johanfran, also a baseball player, is called The Username.

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!
Ellis Morning

Representative Line: Greater Than False

5 days 15 hours ago

Today's anonymous submitter passes us a single line of JavaScript, and it's a doozy. This line works, but that's through no fault of the developer behind it.

{arr?.length && shouldNotShow === false > 0 (...)}

Pedantically, this is JSX, not pure JavaScript, but the rules still apply.

So, fun fact in JavaScript: true > 0 is true, and false > 0 is false. Which generally makes sense, but why would you use that here? But this code is worse than it looks, thanks to operator precedence.

The highest precedence operation is the optional chain- arr?.length. The second highest operation? >. So the first part of the comparison that evaluates is false > 0. Which is false. Do you know what's next? ===. So we compare shouldNotShow to false. Then we && that with the potentially falsy value from our arr?.length.

It's all a mess, and it's all so we can compare against false, which we could have just done with a ! operator. !(arr?.length && shouldNotShow).

Our submitter credits this to an offshore team, and this does have the vibe of throwing characters at the problem until it passes the test. Less LLM-guided and more "manually executed Markov chain". That's also an accurate description of the rest of the code in this code base: hand crafted Markov chain generation.

[Advertisement] Plan Your .NET 9 Migration with Confidence
Your journey to .NET 9 is more than just one decision.Avoid migration migraines with the advice in this free guide. Download Free Guide Now!
Remy Porter

CodeSOD: Poly Means Many, After All

6 days 15 hours ago

Capybara James sends us some code which is totally designed to be modular.

This particular software accepts many kinds of requests which it then converts into a request for a ListView. This is a perfect example of where to use polymorphism, so you can write one transform method that operates on any kind of request.

Let's see how they did it:

@Component public class ListViewTableRequestTransformer implements Function<TableExportRequest, ListViewRequest> { @Override public ListViewRequest apply(TableExportRequest request) { return new ListViewRequest(request.getFilters(), request.getRangeFilters(), request.getSearch(), request.getSort()); } } @Component public class ListViewFormulaRequestTransformer implements Function<FormulaExportRequest, ListViewRequest> { @Override public ListViewRequest apply(FormulaExportRequest request) { return new ListViewRequest(request.getFilters(), request.getRangeFilters(), request.getSearch(), request.getSort()); } }

Now admittedly, my first instinct for letting generics just handle this wouldn't work in Java thanks to type erasure. My excuse is that I've been using C++ templates for too long. But what's not pictured in this code is that TableExportRequest and FormulaExportRequest both implement the same base interface, which means polymorphism could still condense this down into a single function: ListViewRequest apply(RequestInterface request).

Duplicated code like this is like cockroaches. You've seen two, which means there are many many more lurking in the codebase. All of the various request types get their own identical method, differing only in signature.

All my explanation doesn't sum this up as pithily as Capybara James did, however:

There was an attempt to make the code modular and scalable. An attempt I say.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Remy Porter

CodeSOD: A Little Twisted

1 week ago

Dana sends us a WTF that'll turn your head. She was shopping for new hard drives, and was doing it from her phone, a fairly reasonable tool to use for online shopping these days. She opened the website of one vendor, and it was rotated 90 degrees. Or half-pi radians, for those of us that are more used to sensible units.

This was irrespective of any rotation settings on her phone, the website insisted on showing itself in landscape mode. This created quite the unusual appearance when she held her phone in portrait orientation: the browser chrome surrounding the content was in portrait mode, but the page itself was in landscape.

Obviously, this is a terrible design choice. But Dana wanted to know more. So she started digging in. There was no sign of this behavior on a desktop, which sure, I'd hope not. Attempting to use wget to download the page caused a 403. Using curl downloaded a JavaScript challenge. Fine, they didn't want bots, but Dana wasn't a bot.

Poking around in the network tab of the desktop browser's debugging tools helped Dana learn a few things. First: the line endings in the files were all CRLF, implying that all development happened on Windows machines. Maybe that's not interesting, but in 2026, it feels unusual. Second, the page is setting a PHPSESSID cookie, so clearly the backend is written in PHP. But most important, Dana is able to piece together what she needs to successfully use curl to download the page, once pretending to be a desktop browser, and once pretending to be a mobile browser. With that, she ran a diff to see what changed.

The desktop version started with 42 blank lines. The mobile version started with 41. The rest of the pages were substantially the same, with two exceptions. First, the mobile page also added a stylesheet called stylesheet-responsive.css. I assume that name was chosen because irony is dead; nothing about this site is responsive. Second, there was a subtle difference in the body tags.

You see, both pages had a body tag like this:

<body marginwidth="0" marginheight="0" topmargin="0" bottommargin="0" leftmargin="0" rightmargin="0" bgcolor="#FFFFFF">

But the mobile page, continued from there:

<!-- header //--> <body id="landscape_mode_only" marginwidth="0" marginheight="0" topmargin="0" bottommargin="0" leftmargin="0" rightmargin="0" bgcolor="#FFFFFF">

Yes, the mobile version has two body tags.

Dana writes:

Even though I don't have access to the real PHP source-code, I can imagine what it looks like.

Somewhere in that PHP source-code there is browser-detection (or rather browser-sniffing) and that toggles if it should serve a slightly different HTML code to the user. I do not want to work for that website, I do not want to look at that backend source-code. And I have to feel sorry and respect for the browser developers, as they have to write software that can handle completely broken HTML.

While I hate the results, the fact that the HTML specification originally required clients to render even the most broken HTML is arguably a really good design choice. Expecting people to do the right thing never works out for you.

Let's not forget their "responsive" CSS, which is obviously worth looking at, even if it's obvious what it must be:

@media only screen and (orientation:portrait) { #landscape_mode_only { height:98vw; -webkit-transform:rotate(90deg); -moz-transform:rotate(90deg); -o-transform:rotate(90deg); -ms-transform:rotate(90deg); transform:rotate(90deg) } }

This forces everything in the body to rotate sideways.

Look, actually responsive design is hard. But "just force the page into landscape mode no matter what the user does" is definitely not the solution.

And Dana points out one last thing:

As a cherry on the top, observe how the comment that marks the end of the header is placed after the <body> starts. Which is wrong already, but also stupid, because </head> already marks the end of the head. And the head is not really the header.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Remy Porter

Error'd: @#$%^!!

1 week 3 days ago

Here's a weird email but IMO the erorr is just the odd strikethrough. Bill T. explains: "From my Comcast email spam folder. It was smart enough to detect it was spam, but... spam from a trusted sender? And either the delivery truck is an emoji (possible), an embedded image (maybe?), or Comcast is not actually blocking external images." I'd like to see the actual email, could you forward it to us? My guess is that we're seeing a rare embedded image. Since embedding images was the whole point of MIME in the first place, I have found it odd that they're so so hard to construct with typical marketing mass mailers, and I almost never receive them.

 

The WTFs are heating up for Peter G. . Or cooling off. It's one or the other. "Fiji seems to be experiencing a run of temperature inversions. Must be something to do with climate change. "

 

Back with a followup, dragoncoder047 has a plan to rule the world. "I was looking up some closed-loop stepper motors for a robotics project when StepperOnline gave me this error message. Evidently they don't think my project is a good idea. "

 

"My %@ package is missing!" ranted Orion S. "After spending the day restoring my system, I can offer alternatives such as the "@&*% you!" package."

 

Soon-to-be journalist Marc Würth buries the lede: "Not really looking for a job but that is certainly a rare opening." Okay, but what I really want to know is what that Slashdot article is about. Do I even have a Slashdot account still? Why, yes I do.

 

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Lyle Seaman

CodeSOD: Awaiting A Reaction

1 week 4 days ago

Today's Anonymous submitter sends us some React code. We'll look at the code and then talk about the WTF:

// inside a function for updating checkboxes on a page if (!e.target.checked) { const removeIndex = await checkedlist.findIndex( (sel) => sel.Id == selected.Id, ) const removeRowIndex = await RowValue.findIndex( (sel) => sel == Index, ) // checkedlist and RowValue are both useState instances.... they should never be modified directly await checkedlist.splice(removeIndex, 1) await RowValue.splice(removeRowIndex, 1) // so instead of doing above logic in the set state, they dont setCheckedlist(checkedlist) setRow(RowValue) } else { if (checkedlist.findIndex((sel) => sel.Id == selected.Id) == -1) { await checkedlist.push(selected) } // same, instead of just doing a set state call, we do awaits and self updates await RowValue.push(Index) setCheckedlist(checkedlist) setRow(RowValue) }

Comments were added by our submitter.

This code works. It's the wrong approach for doing things in React: modifying objects controlled by react, instead of using the provided methods, it's doing asynchronous push calls. Without the broader context, it's hard to point out all the other ways to do this, but honestly, that's not the interesting part.

I'll let our submitter explain:

This code is black magic, because if I update it, it breaks everything. Somehow, this is working in perfect tandem with the rest of the horrible page, but if I clean it up, it breaks the checkboxes; they're no longer able to be clicked. Its forcing React somehow to update asynchronously so it can use these updated values correctly, but thats the neat part, they aren't even being used anywhere else, but somehow the re-rendering page only accepts awaits. I've tried refactoring it 5 different ways to no avail

That's what makes truly bad code. Code so bad that you can't even fix it without breaking a thousand other things. Code that you have to carefully, slowly, pick through and gently refactor, discovering all sorts of random side-effects that are hidden. The code so bad that you actually have to live with it, at least for awhile.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Remy Porter

CodeSOD: All Docked Up

1 week 5 days ago

Aankhen has a peer who loves writing Python scripts to automate repetitive tasks. We'll call this person Ernest.

Ernest was pretty proud of some helpers he wrote to help him manage his Docker containers. For example, when he wanted to stop and remove all his running Docker containers, he wrote this script:

#!/usr/bin/env python import subprocess subprocess.run("docker kill $(docker ps -q)", shell=True) subprocess.run("docker rm $(docker ps -a -q)", shell=True)

He aliased this script to docker-stop, so that with one command he could… run two.

"Ernest," Aankhen asked, "couldn't this just be a bash script?"

"I don't really know bash," Ernest replied. "If I just do it in bash, if the first command fails, the second command doesn't run."

Aankhen pointed out that you could make bash not do that, but Ernest replied: "Yeah, but I always forget to. This way, it handles errors!"

"It explicitly doesn't handle errors," Aankhen said.

"Exactly! I don't need to know when there are no containers to kill or remove."

"Okay, but why not use the Docker library for Python?"

"What, and make the software more complicated? This has no dependencies!"

Aankhen was left with a sinking feeling: Ernest was either the worst developer he was working with, or one of the best.

[Advertisement] Keep all your packages and Docker containers in one place, scan for vulnerabilities, and control who can access different feeds. ProGet installs in minutes and has a powerful free version with a lot of great features that you can upgrade when ready.Learn more.
Remy Porter

CodeSOD: To Shutdown You Must First Shutdown

1 week 6 days ago

Every once in awhile, we get a bit of terrible code, and our submitter also shares, "this isn't called anywhere," which is good, but also bad. Ernesto sends us a function which is called in only one place:

/// /// Shutdown server /// private void shutdownServer() { shutdownServer(); }

The "one place", obviously, is within itself. This is the Google Search definition of recursion, where each recursive call is just the original call, over and over again.

This is part of a C# service, and this method shuts down the server, presumably by triggering a stack overflow. Unless C# has added tail calls, anyway.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Remy Porter

Anti-Simplification

2 weeks ago

Our anonymous submitter relates a tale of simplification gone bad. As this nightmare unfolds, imagine the scenario of a new developer coming aboard at this company. Imagine being the one who has to explain this setup to said newcomer.

Imagine being the newcomer who inherits it.

David's job should have been an easy one. His company's sales data was stored in a database, and every day the reporting system would query a SQL view to get the numbers for the daily key performance indicators (KPIs). Until the company's CTO, who was proudly self-taught, decided that SQL views are hard to maintain, and the system should get the data from one of those new-fangled APIs instead.

But how does one call an API? The reporting system didn't have that option, so the logical choice was Azure Data Factory to call the API, then output the data to a file that the reporting system could read. The only issue was that nobody on the team spoke Azure Data Factory, or for that matter SQL. But no problem, one of David's colleagues assured, they could do all the work in the best and most multifunctional language ever: C#.

But you can't just write C# in a data factory directly, that would be silly. What you can do is have the data factory pipeline call an Azure function, which calls a DLL that contains the bytecode from C#. Oh, and a scheduler outside of the data factory to run the pipeline. To read multiple tables, the pipeline calls a separate function for each table. Each function would be based on a separate source project in C#, with 3 classes each for the HTTP header, content, and response; and a separate factory class for each of the actual classes.

After all, each table had a different set of columns, so you can't just re-use classes for that.

There was one little issue: the reporting system required an XML file, whereas the API would export data in JSON. It would be silly to expect a data factory, of all things, to convert this. So the CTO's solution was to have another C# program (in a DLL called by a function from a pipeline from an external scheduler) that reads the JSON document saved by the earlier program, uses foreach to go over each element, then saves the result as XML. A distinct program for each table, of course, requiring distinct classes for header, content, response, and factories thereof.

Now here's the genius part: to the C# class representing the output data, David's colleague decided to attach one different object for each input table required. The data class would use reflection to iterate over the attached objects, and for each object, use a big switch block to decide which source file to read. This allows the data class to perform joins and calculations before saving to XML.

To make testing easier, each calculation would be a separate function call. For example, calculating a customer's age was a function taking struct CustomerWithBirthDate as input, use a foreach loop to copy all the data except replacing one field, and return a CustomerWithAge struct to pass to the next function. The code performed a bit slowly, but that was an issue for a later year.

So basically, the scheduler calls the data factory, which calls a set of Azure functions, which call a C# function, which calls a set of factory classes to call the API and write the data to a text file. Then, the second scheduler calls a data factory, which calls Azure functions, which call C#, which calls reflection to check attachment classes, which read the text files, then call a series of functions for each join or calculation, then call another set of factory classes to write the data to an XML file, then call the reporting system to update.

Easy as pie, right? So where David's job could have been maintaining a couple hundred lines of SQL views, he instead inherited some 50,000 lines of heavily-duplicated C# code, where adding a new table to the process would easily take a month.

Or as the song goes, Somebody Told Me the User Provider should use an Adaptor to Proxy the Query Factory Builder ...

[Advertisement] ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.
Ellis Morning

Error'd: That's What I Want

2 weeks 3 days ago

First up with the money quote, Peter G. remarks "Hi first_name euro euro euro, look how professional our marketing services are! "

 

"It takes real talent to mispell error" jokes Mike S. They must have done it on purpose.

 

I long wondered where the TikTok profits came from, and now I know. It's Daniel D. "I had issues with some incorrectly documented TikTok Commercial Content API endpoints. So I reached out to the support. I was delighted to know that it worked and my reference number was . PS: 7 days later I still have not been contacted by anyone from TikTok. You can see their support is also . "

 

Fortune favors the prepared, and Michael R. is very fortunate. "I know us Germans are known for planning ahead so enjoy the training on Friday, February 2nd 2029. "

 

Someone other than dragoncoder047 might have shared this earlier, but this time dragoncoder047 definitely did. "Digital Extremes (the developers of Warframe) were making many announcements of problems with the new update that rolled out today [February 11]. They didn’t mention this one!"

 

[Advertisement] Picking up NuGet is easy. Getting good at it takes time. Download our guide to learn the best practice of NuGet for the Enterprise.
Lyle Seaman

CodeSOD: Qaudruple Negative

2 weeks 4 days ago

We mostly don't pick on bad SQL queries here, because mostly the query optimizer is going to fix whatever is wrong, and the sad reality is that databases are hard to change once they're running; especially legacy databases. But sometimes the code is just so hamster-bowling-backwards that it's worth looking into.

Jim J has been working on a codebase for about 18 months. It's a big, sprawling, messy project, and it has code like this:

AND CASE WHEN @c_usergroup = 50 AND NOT EXISTS(SELECT 1 FROM l_appl_client lac WHERE lac.f_application = fa.f_application AND lac.c_linktype = 840 AND lac.stat = 0 AND CASE WHEN ISNULL(lac.f_client,0) <> @f_client_user AND ISNULL(lac.f_c_f_client,0) <> @f_client_user THEN 0 ELSE 1 END = 1 ) THEN 0 ELSE 1 END = 1 -- 07.09.2022

We'll come back to what it's doing, but let's start with a little backstory.

This code is part of a two-tier application: all the logic lives in SQL Server stored procedures, and the UI is a PowerBuilder application. It's been under development for a long time, and in that time has accrued about a million lines of code between the front end and back end, and has never had more than 5 developers working on it at any given time. The backlog of feature requests is nearly as long as the backlog of bugs.

You may notice the little date comment in the code above. That's because until Jim joined the company, they used Visual Source Safe for version control. Visual Source Safe went out of support in 2005, and let's be honest: even when it was in support it barely worked as a source control system. And that's just the Power Builder side- the database side just didn't use source control. The source of truth was the database itself. When going from development to test to prod, you'd manually export object definitions and run the scripts in the target environment. Manually. Yes, even in production. And yes, environments did drift and assumptions made in the scripts would frequently break things.

You may also notice the fields above use a lot of Hungarian notation. Hungarian, in the best case, makes it harder to read and reason about your code. In this case, it's honestly fully obfuscatory. c_ stands for a codetable, f_ for entities. l_ is for a many-to-many linking table. z_ is for temporary tables. So is x_. And t_. Except not all of those "temporary" tables are truly temporary, a lesson Jim learned when trying to clean up some "junk" tables which were not actually junk.

I'll let Jim add some more detail around these prefixes:

an "application" may have a link to a "client", so there is an f_client field; but also it references an "agent" (which is also in the f_client table, surpise!) - this is how you get an f_c_f_client field. I have no clue why the prefix is f_c_ - but I also found c_c_c_channel and fc4_contact columns. The latter was a shorthand for f_c_f_c_f_c_f_contact, I guess.

"f_c_f_c_f_c_f_c" is also the sound I'd make if I saw this in a codebase I was responsible for. It certainly makes me want to change the c_c_c_channel.

With all this context, let's turn it back over to Jim to explain the code above:

And now, with all this background in mind, let's have a look at the logic in this condition. On the deepest level we check that both f_client and f_c_f_client are NOT equal to @f_client_user, and if this is the case, we return 0 which is NOT equal to 1 so it's effectively a negation of the condition. Then we check that records matching this condition do NOT EXIST, and when this is true - also return 0 negating the condition once more.

Honestly, the logic couldn't be clearer, when you put it that way. I jest, I've read that twelve times and I still don't understand what this is for or why it's here. I just want to know who we can prosecute for this disaster. The whole thing is a quadruple negative and frankly, I can't handle that kind of negativity.

.comment { border: none; } [Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!
Remy Porter

CodeSOD: Repeating Your Existence

2 weeks 5 days ago

Today's snippet from Rich D is short and sweet, and admittedly, not the most TFs of WTFs out there. But it made me chuckle, and sometimes that's all we need. This Java snippet shows us how to delete a file:

if (Files.exists(filePath)) { Files.deleteIfExists(filePath); }

If the file exists, then if it exists, delete it.

This commit was clearly submitted by the Department of Redundancy Department. One might be tempted to hypothesize that there's some race condition or something that they're trying to route around, but if they are, this isn't the way to do it, per the docs: "Consequently this method may not be atomic with respect to other file system operations." But also, I fail to see how this would do that anyway.

The only thing we can say for certain about using deleteIfExists instead of delete is that deleteIfExists will never throw a NoSuchFileException.

[Advertisement] Plan Your .NET 9 Migration with Confidence
Your journey to .NET 9 is more than just one decision.Avoid migration migraines with the advice in this free guide. Download Free Guide Now!
Remy Porter

CodeSOD: Blocked Up

2 weeks 6 days ago

Agatha has inherited some Windows Forms code. This particular batch of such code falls into that delightful category of code that's wrong in multiple ways, multiple times. The task here is to disable a few panels worth of controls, based on a condition. Or, since this is in Spanish, "bloquear controles". Let's see how they did it.

private void BloquearControles() { bool bolBloquear = SomeConditionTM; // SomeConditionTM = a bunch of stuff. Replaced for clarity. // Some code. Removed for clarity. // private System.Windows.Forms.Panel pnlPrincipal; foreach (Control C in this.pnlPrincipal.Controls) { if (C.GetType() == typeof(System.Windows.Forms.TextBox)) { C.Enabled = bolBloquear; } if (C.GetType() == typeof(System.Windows.Forms.ComboBox)) { C.Enabled = bolBloquear; } if (C.GetType() == typeof(System.Windows.Forms.CheckBox)) { C.Enabled = bolBloquear; } if (C.GetType() == typeof(System.Windows.Forms.DateTimePicker)) { C.Enabled = bolBloquear; } if (C.GetType() == typeof(System.Windows.Forms.NumericUpDown)) { C.Enabled = bolBloquear; } } // private System.Windows.Forms.GroupBox grpProveedor; foreach (Control C1 in this.grpProveedor.Controls) { if (C1.GetType() == typeof(System.Windows.Forms.TextBox)) { C1.Enabled = bolBloquear; } if (C1.GetType() == typeof(System.Windows.Forms.ComboBox)) { C1.Enabled = bolBloquear; } if (C1.GetType() == typeof(System.Windows.Forms.CheckBox)) { C1.Enabled = bolBloquear; } if (C1.GetType() == typeof(System.Windows.Forms.DateTimePicker)) { C1.Enabled = bolBloquear; } if (C1.GetType() == typeof(System.Windows.Forms.NumericUpDown)) { C1.Enabled = bolBloquear; } } // private System.Windows.Forms.GroupBox grpDescuentoGeneral; foreach (Control C2 in this.grpDescuentoGeneral.Controls) { if (C2.GetType() == typeof(System.Windows.Forms.TextBox)) { C2.Enabled = bolBloquear; } if (C2.GetType() == typeof(System.Windows.Forms.ComboBox)) { C2.Enabled = bolBloquear; } if (C2.GetType() == typeof(System.Windows.Forms.CheckBox)) { C2.Enabled = bolBloquear; } if (C2.GetType() == typeof(System.Windows.Forms.DateTimePicker)) { C2.Enabled = bolBloquear; } if (C2.GetType() == typeof(System.Windows.Forms.NumericUpDown)) { C2.Enabled = bolBloquear; } } // Some more code. Removed for clarity. }

This manages two group boxes and a panel. It checks a condition, then iterates across every control beneath it, and sets their enabled property on the control. In order to do this, it checks the type of the control for some reason.

Now, a few things: every control inherits from the base Control class, which has an Enabled property, so we're not doing this check to make sure the property exists. And every built-in container control automatically passes its enabled/disabled state to its child controls. So there's a four line version of this function where we just set the enabled property on each container.

This leaves us with two possible explanations. The first, and most likely, is that the developer responsible just didn't understand how these controls worked, and how inheritance worked, and wrote this abomination as an expression of that ignorance. This is extremely plausible, extremely likely, and honestly, our best case scenario.

Because our worse case scenario is that this code's job isn't to disable all of the controls. The reason they're doing type checking is that there are some controls used in these containers that don't match the types listed. The purpose of this code, then, is to disable some of the controls, leaving others enabled. Doing this by type would be a terrible way to manage that, and is endlessly confusing. Worse, I can't imagine how this behavior is interpreted by the end users; the enabling/disabling of controls following no intuitive pattern, just filtered based on the kind of control in use.

The good news is that Agatha can point us towards the first option. She adds:

They decided to not only disable the child controls one by one but to check their type and only disable those five types, some of which aren't event present in the containers. And to make sure this was WTF-worthy the didn't even bother to use else-if so every type is checked for every child control

She also adds:

At this point I'm not going to bother commenting on the use of GetType() == typeof() instead of is to do the type checking.

Bad news, Agatha: you did bother commenting. And even if you didn't, don't worry, someone would have.

.comment { border: none; } [Advertisement] Picking up NuGet is easy. Getting good at it takes time. Download our guide to learn the best practice of NuGet for the Enterprise.
Remy Porter

CodeSOD: Popping Off

3 weeks ago

Python is (in)famous for its "batteries included" approach to a standard library, but it's not that notable that it has plenty of standard data structures, like dicts. Nor is in surprising that dicts have all sorts of useful methods, like pop, which removes a key from the dict and returns its value.

Because you're here, reading this site, you'll also be unsurprised that this doesn't stop developers from re-implementing that built-in function, badly. Karen sends us this:

def parse_message(message): def pop(key): if key in data: result = data[key] del data[key] return result return '' data = json.loads(message) some_value = pop("some_key") # <snip>...multiple uses of pop()...</snip>

Here, they create an inner method, and they exploit variable hoisting. While pop appears in the code before data is declared, all variable declarations are "hoisted" to the top. When pop references data, it's getting that from the enclosing scope. Which while this isn't a global variable, it's still letting a variable cross between two scopes, which is always messy.

Also, this pop returns a default value, which is also something the built-in method can do. It's just the built-in version requires you to explicitly pass the value, e.g.: some_value = data.pop("some_key", "")

Karen briefly wondered if this was a result of the Python 2 to 3 conversion, but no, pop has been part of dict for a long time. I wondered if this was just an exercise in code golf, writing a shorthand function, but even then- you could just wrap the built-in pop with your shorthand version (not that I'd recommend such a thing). No, I think the developer responsible simply didn't know the function was there, and just reimplemented a built-in method badly, as so often happens.

.comment { border: none;} [Advertisement] Picking up NuGet is easy. Getting good at it takes time. Download our guide to learn the best practice of NuGet for the Enterprise.
Remy Porter

Error'd: Perverse Perseveration

3 weeks 3 days ago

Pike pike pike pike Pike pike pike.

Lincoln KC repeated "I never knew Bank of America Bank of America Bank of America was among the major partners of Bank of America."

 

"Extra tokens, or just a stutter?" asks Joel "An errant alt-tab caused a needless google search, but thankfully Gemini's AI summary got straight-to-the-point(less) info. It is nice to see the world's supply of Oxford commas all in once place. "

 

Alessandro M. isn't the first one to call us out on our WTFs. "It’s adorable how the site proudly supports GitHub OAuth right up until the moment you actually try to use it. It’s like a door with a ‘Welcome’ sign that opens onto a brick wall." Meep meep.

 

Float follies found Daniel W. doubly-precise. "Had to go check on something in M365 Admin Center, and when I was on the OneDrive tab, I noticed Microsoft was calculating back past the bit. We're in quantum space at this point."

 

Weinliebhaber Michael R. sagt "Our German linguists here will spot the WTF immediately where my local wine shop has not. Weiẞer != WEIBER. Those words mean really different things." Is that 20 euro per kilo, or per the piece?

 

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!
Lyle Seaman

CodeSOD: The Counting Machine

3 weeks 4 days ago

Industrial machines are generally accompanied by "Human Machine Interfaces", HMIs. This is industrial slang for a little computerized box you use to control the industrial machine. All the key logic and core functionality and especially the safety functionality is handled at a deeper computer layer in the system. The HMI is just buttons users can push to interact with the machine.

Purchasers of those pieces of industrial equipment often want to customize that user interface. They want to guide users away from functions they don't need, or make their specific workflow clear, or even just brand the UI. This means that the vendor needs to publish an API for their HMI.

Which brings us to Wendy. She works for a manufacturing company which wants to customize the HMI on a piece of industrial equipment in a factory. That means Wendy has been reading the docs and poking at the open-sourced portions of the code, and these raise more questions than they answer.

For example, the HMI's API provides its own set of collection types, in C#. We can wonder why they'd do such a thing, which is certainly a WTF in itself, but this representative line raises even more questions than that:

Int32 Count { get; set; }

What happens if you use the public set operation on the count of items in a collection? I don't know. Wendy doesn't either, as she writes:

I'm really tempted to set the count but I fear the consequences.

All I can hear in my head when I think about "setting the Count" is: "One! One null reference exception! Two! TWO null reference exceptions! HA HA HA HA!"


By http://muppet.wikia.com/wiki/Count_von_Count

[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
Remy Porter

CodeSOD: Safegaurd Your Comments

3 weeks 5 days ago

I've had the misfortune of working in places which did source-control via comments. Like one place which required that, with each section of code changed, you needed to add a comment with your name, the ticket number, and the reason the change was made. You know, the kind of thing you can just get from your source control service.

In their defense, that policy was invented for mainframe developers and then extended to everyone else, and their source control system was in Visual Source Safe. VSS was a) terrible, and b) a perennial destroyer of history, so maybe they weren't entirely wrong and VSS was the real WTF. I still hated it.

In any case, Alice's team uses more modern source control than that, which is why she's able to explain to us the story of this function:

public function calculateMassGrossPay(array $employees, Payroll $payroll): array { // it shouldn't enter here, but if it does by any change, do nth return []; }

Once upon a time, this function actually contained logic, a big pile of fairly complicated logic. Eventually, a different method was created which streamlined the functionality, but had a different signature and logic. All the callers were updated to use that method instead- by commenting out the line which called this one. This function had a comment added to the top: // it shouldn't enter here.

Then, the body of this function got commented out, and the return was turned into an empty array. The comment was expanded to what you see above. Then, eventually, the commented-out callers were all deleted. Years after that, the commented out body of this function was also deleted, leaving behind the skeleton you see here.

This function is not referenced anywhere else, not even in a comment. It's truly impossible for code to "enter here".

Alice writes: "Version control by commented out code does not work very well."

Indeed, it does not.

.comment { border: none; } [Advertisement] ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.
Remy Porter

Representative Line: Years Go By

3 weeks 6 days ago

Henrik H's employer thought they could save money by hiring offshore, and save even more money by hiring offshore junior developers, and save even more money by basically not supervising them at all.

Henrik sends us just one representative line:

if (System.DateTime.Now.AddDays(-365) <= f.ReleaseDate) // 365 days means one year

I appreciate the comment, that certainly "helps" explain the magic number. There's of course, just one little problem: It's wrong. I mean, ~75% of the time, it works every time, but it happily disregards leap years. Which may or may not be a problem in this case, but if they got so far as learning about the AddDays method, they were inches from using AddYears.

I guess it's true what they say: you can lead a dev to docs, but you can't make them think.

[Advertisement] Picking up NuGet is easy. Getting good at it takes time. Download our guide to learn the best practice of NuGet for the Enterprise.
Remy Porter
Checked
3 hours 27 minutes ago
Curious Perversions in Information Technology
Subscribe to The Daily WTF feed