CodeSOD: Proper Property Validation
Tim H inherited some code which has objects that have many, many properties properties on them. Which is bad. That clearly has no cohesion. But it's okay, there's a validator function which confirms that object is properly populated.
The conditions and body of the conditionals have been removed, so we can see what the flow of the code looks like.
if (...) { if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } else if (...) { } } else { // default }It's important to note that this conditional doesn't validate every property on the object. Just most of them.
Even with autocomplete I feel like this is going to make you wear out your "{" key.
.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.CodeSOD: The Update Route
Today's anonymous submission is one of the entries where I look at it and go, "Wait, that's totally wrong, that could have never worked." And then I realize, that's why it was submitted: it was absolutely broken code which got to production, somehow.
Collection.updateOne(query, update, function(err, result, next)=>{ if(err) next(err) ... })So, Collection.updateOne is an API method for MongoDB. It takes three parameters: a filter to find the document, an update to perform on the document, and then an object containing other parameters to control how that update is done.
So this code is simply wrong. But it's worse than that, because it's wrong in a stupid way.
When creating routes using ExpressJS, you define a route and a callback to handle the route. The callback takes a few parameters: the request the browser sent, the result we're sending back, and a next function, which lets you have multiple callbacks attached to the same route. By invoking next() you're passing control to the next callback in the chain.
So what we have here is either an absolute brain fart, or more likely, a find-and-replace failure. A route handling callback got mixed in with database operations (which, as an aside, if your route handling code is anywhere near database code, you've also made a horrible mistake). The result is a line of code that doesn't work. And then someone released this non-working code into production.
Our submiter writes:
This blew up our logs today, has been in the code since 2019. I removed it in a handful of other places too.
Which raises the other question: why didn't this blow up the logs earlier?
Error'd: Clever domain name here
An anonymous cable-puller wrote "Reading a long specification manual. The words "shall" and "shall not" have specific meaning, and throughout the document are in bold italic. Looks like someone got a bit shall-ow with their search-and-replace skills."
Picki jeffphi attends to details. "Apparently this recruiter doesn't have a goal or metric around proper brace selection and matching." You're hired.
UGG.LI admins highlighted "even KFC hat Breakpoints deployed in Prod now ..." I wanted to say something funny about Herren Admins' Handle but reminded myself of John Scalzi's quote about the failure case of smartass so I refrained. You might be funnier than I.
Smarter still, Steve says "A big company like Google surely has a huge QA staff and AI bots to make sure embarrassing typos don't slip through, right? You wouldn't want to damage you reputation..."
I'll bet Pascal didn't expect this, eh? "Delivered, but On the way, Searching for a driver, but Asdrubal"
CodeSOD: One Case
I feel like we've gotten a few SQL case statement abuses recently, but a properly bad one continues to tickle me. Ken C sends us one that, well:
SELECT CASE h.DOCUMENTTYPE WHEN 2 THEN 3 WHEN 3 THEN 4 WHEN 4 THEN 5 WHEN 5 THEN 6 WHEN 6 THEN 7 WHEN 7 THEN 8 ELSE h.DOCUMENTTYPE END AS DocumentType, h.DOCNMBR AS DocNmbr, h.FULLPOLICY AS FullPolicy, h.BATCHID AS BatchId, h.OrigBatchId, h.UPDATEDDATE AS UpdatedDate, h.CUSTOMERNO AS CustomerNo, h.PROJECTID AS ProjectID, h.AMOUNT AS AmountOn one hand, I can't say "just add one", because clearly sometimes they don't want to add one. On the other hand, there's an element of looking at this and knowing: well, something absolutely stupid has happened here. Maybe it was two disjoint databases getting merged. Maybe it was just once upon a time, when this database was a spreadsheet, the user responsible did a weird thing. Maybe some directive changed the document type numbering. Hell, maybe that ELSE clause never gets triggered, and we actually could just do arithmetic.
Corporate Language Compliance Generator
You've already read the longer version. You need a quick phrase of corpo-speak to distract and confuse your rivals. Here's the generator for doing that:
Generate class Replacement { constructor(text) { this.tokens = text.split(" "); } } class Rule { constructor() { this.replacements = []; } addReplacement(text) { const opts = text.split("|"); opts.forEach((o) => this.replacements.push(new Replacement(o))); } choose() { return this.replacements[Math.floor(Math.random()*this.replacements.length)]; } } class Grammar { constructor() { this.rules = {}; } setStart(token) { this.start = token; } addRule(token,text) { if (!this.rules[token]) { this.rules[token] = new Rule(); } this.rules[token].addReplacement(text); return this; } addRules(token,sepText) { sepText.split("|").forEach(text => { this.addRule(token, text); }); } generate(token) { if (this.rules[token]) { const nextVal = this.rules[token].choose(); let res = []; nextVal.tokens.forEach(token => { res = res.concat(this.generate(token)); }); return res; } return [token]; } phrase() { return this.generate(this.start); } } class UI { constructor(grammar) { this.button = document.getElementById("generate"); this.content = document.getElementById("generated"); const callback = () => { const text = grammar.phrase(); let joined = text.join(" "); joined = joined.replace(/ ,/g, ","); this.content.innerHTML = joined; } this.button.addEventListener("click", callback); callback(); } } let g = new Grammar(); g .addRule("!mission", "Our goal|Our objective|Our stance|Our culture|Our mission|Our ethos|Our call to arms|Our essence|Our scent") .addRule("!missions", "!mission|!mission and !submission") .addRule("!visions", "vision|perspective|orientation|clear-sight|foresight|over-the-horizon planning|clear-eyed self-assessments") .addRule("!submission", "raison 'd etre|purpose|customer-focused soul|!withs powered !visions") .addRule("!is_that", "is that by|is by|demands that|expands over our") .addRule("!prep", "in|with|onto|into|without") .addRule("!bleeding", "technology|values|timelines|commitment|redundancy|credentialing") .addRule("!withs", "AI|creativity|the ubermensch|prestige|the latest technology|user-enabling|bleeding edge !bleeding|blockchain|NFTs") .addRule("!action", "leveraging|powering|working|engaging|bandwidth-widening|agentifying|vision questing|covering all the bases|solving|absorbing|communing|joining") .addRule("!action", "actioning|emoting|crafting|forging|manifesting|demonstrating|advocating|willing|engaging Nietzschean will-to-powering") .addRule("!action", "pressure testing|getting in the tent|saving|drumming our own beat|enabling|blue-skying") .addRule("!target", "core competencies|synergies|cross-collateralization|blue-sky thinking|best practices|vision|impact|target|low hanging fruit") .addRule("!target", "foundation|ideation|idea generation|lead generation|pull|bank accounts|shareholder-value|new domains|the whales") .addRule("!target_mods", "cradle-to-grave|balanced|cross back|high-value|high-impact|maximalizing|throughput-maxxing|reinvented|collaborational|optimized") .addRule("!target_mods", "withholding|full-ecosystem|cross-functional|network-oriented|cross-paradigm|growth-hacking|disruption|appropriate|gravitational") .addRule("!targets", "!target|!adjective !target|!target_mods !target|!target and !targets") .addRule("!adjective", "open|wide|smart|enabled|agentic|AI-first|AI-forward|fifth-sigma|forward looking|future-proof|optimized|four-quadrant") .addRule("!adjective", "vast|moatified|inverted|AI-enabled|LLM-driven|agent-driven|paradigmatic|pragmatic|blue-sky|open doored|window-oriented|maximizing") .addRule("!adverb", "markedly|vastly|smartly|synergistically|agentically|cooly|vapidly|rapidly|overwhelmingly|abstractly|inherently|value-balancingly") .addRule("!adverb", "disruptively") .addRule("!actions", "!action|!adverb !action") .addRule("!objects", "the world|the economy|the market|society|best practices|the info-sphere|cyberspace|the dating scene|high-value market segments|the eschaton|anime consumers|the poorly hydrated|Warhammer fanatics|executive assistants|stake holders|investor value|the median consumer") .addRule("!objects", "future generations|high quality sandwiches|thought-leaders|visionaries|the reckless ones|Big Brother|paradigms") .addRule("!objects", "the infodome|the terror dome|gorgeous lights|city-pop albums|heart transplants|financial envelope") .addRule("!by_phrase", "By !actions !targets we are !actions !prep !objects") .addRule("!by_phrase", "By !actions !prep !targets we are !actions !objects") .addRule("!by_phrase", "By !actions !prep !targets with !withs we are !actions !objects") .addRule("!miss_phrase", "!missions !is_that !action !prep !targets !adverb !action !target") .addRule("!miss_phrase", "!missions is !action !objects by !actions !targets") .addRule("!with_phrase", "With !withs , we are !actions !objects to !action !targets") .addRule("!with_phrase", "!missions !is_that with !withs we are !actions !objects") .addRule("!are_phrase", "We are !objects !action !targets|We are !actions !prep !objects|We are !withs !prep !targets") .addRule("!phrase", "!by_phrase|!miss_phrase|!with_phrase|!are_phrase") g.setStart("!phrase"); let ui = new UI(g);Now, admittedly, this generator may use a grammar for generating phrases, but it's not an English grammar, and the result is that sometimes it has problems with verb agreement and other prosaic English rules. I say, lean into it. Let someone challenge your bad grammar, and then look down your nose at them, and say: "I'm blue-skying the infosphere across new domains, you wouldn't get it."
Corporate Language Compliance
As we all know, there are two basic kinds of scientific studies. The first is a ground-breaking paper that changes the way we view the world, and forces us to confront our presuppositions and biases about how we think the world works, and change our perspective. The other tells us what we already know to be true, and makes us feel good. The second kind, of course, is what we'd call "good science".
Or, if you want to skip past this straight to the generator at the bottom.
For example, what if I told you that people who are impressed by hyperbolic corporate jargon are dumber than you or I? It's probably something you already believe is true, but wouldn't you like a scientist to tell you that it's true?
Well, have I got good news for you. If you're tired of hearing about "growth-hacking paradigms" researchers at Cornell found that people who are impressed by semantically empty phrases are also bad at making decisions.
The entire paper is available, if you like charts.
There are a few key highlights worth reading, though. The paper spends a fair bit of time distinguishing between "jargon" and "bullshit". Jargon is domain specific language that is impenetrable to "out-group" individuals, while bullshit may be just as impenetrable, but also is "semantically empty and confusing".
It also has some ideas about why we drift from useful jargon to bullshit. It starts, potentially, as a way to navigate socially difficult situations by blunting our speech: I can't say that I think you're terrible at your job, but I can say you need to actualize the domain more than you currently are. But also, it's largely attempts to fluff ourselves up, whether it's trying to contribute to a meeting when we haven't an idea what we're talking about, or trying to just sound impressive or noble in public messaging. It seems that the backbone of bullshit is the people who didn't do the reading for Literature class but insist on holding forth during the classroom discussion, confident they can bullshit their way through.
Of course, bullshit doesn't thrive unless you have people willing to fall for it. And when it comes to that, it's worth quoting the paper directly:
Bullshit receptivity is linked to a lower analytic thinking, insight, verbal ability, general knowledge, metacognition, and intelligence (Littrell & Fugelsang, 2024; Littrell et al., 2021b; Pennycook et al., 2015; Salvi et al., 2023). It also predicts certain types of poor decision-making and a greater proclivity to both endorse and spread fake news, conspiracy theories, and other epistemically-suspect claims (Čavojová et al., 2019; Iacobucci & De Cicco, 2022; Littrell et al., 2024; Pennycook & Rand, 2020).
The paper cites a study that indicates there's an aspect of education to this. If you take a bunch of undergrads to an art gallery and present them with fluffed up descriptions of artist intent, they're more likely to see the works as profound. But if you do the same thing with people who routinely go to art galleries, the bullshit has little effect on them. It also indicates that our susceptibility to bullshit is highly context dependent, and anyone could potentially fall for bullshit in a domain they don't know enough about.
Wait, I thought this was about talking about a paper that confirms my biases and makes me feel good? I don't want to think about how I could succumb to bullshit. That's terrifying.
The backbone of the paper is the actual methodology, the analyses of their results, and their carefully crafted bullshit phrases used for the study, which are pretty goddamn great. Or terrible, depending on your perspective.
ul { list-style-type: disc; list-style-position: inside; margin-top: 1.5rem; }- Our goal is to engage our capabilities by focusing our efforts on executing the current transmission of our empowerment, driving an innovative growth- mindset with our change drivers, and coaching energetic frameworks to our resonating focus.
- Our goal is to engage our conversations by focusing our efforts on architecting the current vector of our balanced scorecard.
- Working at the intersection of cross-collateralization and blue-sky thinking, we will actualize a renewed level of cradle-to-grave credentialing and end- state vision in a world defined by architecting to potentiate on a vertical landscape.
There are a few other key things the paper notes. First, unchecked bullshit can turn an environment toxic and drive away competent employees who need to escape it. It also could potentially impact hiring: a bullshit laden workplace may seek out bullshit friendly employees, making the situation worse. What the study does show is that bullshit-receptive employees are more likely to fertilize the field themselves. And there's also the sad truth: bullshit works. If you're looking to fluff yourself up, impress your superiors, and climb the ladder, the careful application of bullshit may get you where you want to go.
And it's that last point that brings us to the real point of this article. If you're here, you're likely not the most bullshit friendly employee. Clearly, you're smarter and make better decisions than that. (This is that good science I was talking about- you're probably more attractive than those people too, though there's no study to that effect yet.)
If you're not using bullshit, you're leaving powerful tools for self-promotion on the table. But it's hard to come up with suitably impressive and semantically vacant phrases. Fear not, we're here to help! Here's a phrase generator for you, that will come up with endless phrases that you can use in meetings and mission statements to sound far more impressive.
Generate class Replacement { constructor(text) { this.tokens = text.split(" "); } } class Rule { constructor() { this.replacements = []; } addReplacement(text) { const opts = text.split("|"); opts.forEach((o) => this.replacements.push(new Replacement(o))); } choose() { return this.replacements[Math.floor(Math.random()*this.replacements.length)]; } } class Grammar { constructor() { this.rules = {}; } setStart(token) { this.start = token; } addRule(token,text) { if (!this.rules[token]) { this.rules[token] = new Rule(); } this.rules[token].addReplacement(text); return this; } addRules(token,sepText) { sepText.split("|").forEach(text => { this.addRule(token, text); }); } generate(token) { if (this.rules[token]) { const nextVal = this.rules[token].choose(); let res = []; nextVal.tokens.forEach(token => { res = res.concat(this.generate(token)); }); return res; } return [token]; } phrase() { return this.generate(this.start); } } class UI { constructor(grammar) { this.button = document.getElementById("generate"); this.content = document.getElementById("generated"); const callback = () => { const text = grammar.phrase(); let joined = text.join(" "); joined = joined.replace(/ ,/g, ","); this.content.innerHTML = joined; } this.button.addEventListener("click", callback); callback(); } } let g = new Grammar(); g .addRule("!mission", "Our goal|Our objective|Our stance|Our culture|Our mission|Our ethos|Our call to arms|Our essence|Our scent") .addRule("!missions", "!mission|!mission and !submission") .addRule("!visions", "vision|perspective|orientation|clear-sight|foresight|over-the-horizon planning|clear-eyed self-assessments") .addRule("!submission", "raison 'd etre|purpose|customer-focused soul|!withs powered !visions") .addRule("!is_that", "is that by|is by|demands that|expands over our") .addRule("!prep", "in|with|onto|into|without") .addRule("!bleeding", "technology|values|timelines|commitment|redundancy|credentialing") .addRule("!withs", "AI|creativity|the ubermensch|prestige|the latest technology|user-enabling|bleeding edge !bleeding|blockchain|NFTs") .addRule("!action", "leveraging|powering|working|engaging|bandwidth-widening|agentifying|vision questing|covering all the bases|solving|absorbing|communing|joining") .addRule("!action", "actioning|emoting|crafting|forging|manifesting|demonstrating|advocating|willing|engaging Nietzschean will-to-powering") .addRule("!action", "pressure testing|getting in the tent|saving|drumming our own beat|enabling|blue-skying") .addRule("!target", "core competencies|synergies|cross-collateralization|blue-sky thinking|best practices|vision|impact|target|low hanging fruit") .addRule("!target", "foundation|ideation|idea generation|lead generation|pull|bank accounts|shareholder-value|new domains|the whales") .addRule("!target_mods", "cradle-to-grave|balanced|cross back|high-value|high-impact|maximalizing|throughput-maxxing|reinvented|collaborational|optimized") .addRule("!target_mods", "withholding|full-ecosystem|cross-functional|network-oriented|cross-paradigm|growth-hacking|disruption|appropriate|gravitational") .addRule("!targets", "!target|!adjective !target|!target_mods !target|!target and !targets") .addRule("!adjective", "open|wide|smart|enabled|agentic|AI-first|AI-forward|fifth-sigma|forward looking|future-proof|optimized|four-quadrant") .addRule("!adjective", "vast|moatified|inverted|AI-enabled|LLM-driven|agent-driven|paradigmatic|pragmatic|blue-sky|open doored|window-oriented|maximizing") .addRule("!adverb", "markedly|vastly|smartly|synergistically|agentically|cooly|vapidly|rapidly|overwhelmingly|abstractly|inherently|value-balancingly") .addRule("!adverb", "disruptively") .addRule("!actions", "!action|!adverb !action") .addRule("!objects", "the world|the economy|the market|society|best practices|the info-sphere|cyberspace|the dating scene|high-value market segments|the eschaton|anime consumers|the poorly hydrated|Warhammer fanatics|executive assistants|stake holders|investor value|the median consumer") .addRule("!objects", "future generations|high quality sandwiches|thought-leaders|visionaries|the reckless ones|Big Brother|paradigms") .addRule("!objects", "the infodome|the terror dome|gorgeous lights|city-pop albums|heart transplants|financial envelope") .addRule("!by_phrase", "By !actions !targets we are !actions !prep !objects") .addRule("!by_phrase", "By !actions !prep !targets we are !actions !objects") .addRule("!by_phrase", "By !actions !prep !targets with !withs we are !actions !objects") .addRule("!miss_phrase", "!missions !is_that !action !prep !targets !adverb !action !target") .addRule("!miss_phrase", "!missions is !action !objects by !actions !targets") .addRule("!with_phrase", "With !withs , we are !actions !objects to !action !targets") .addRule("!with_phrase", "!missions !is_that with !withs we are !actions !objects") .addRule("!are_phrase", "We are !objects !action !targets|We are !actions !prep !objects|We are !withs !prep !targets") .addRule("!phrase", "!by_phrase|!miss_phrase|!with_phrase|!are_phrase") g.setStart("!phrase"); let ui = new UI(g);Now, admittedly, this generator may use a grammar for generating phrases, but it's not an English grammar, and the result is that sometimes it has problems with verb agreement and other prosaic English rules. I say, lean into it. Let someone challenge your bad grammar, and then look down your nose at them, and say: "I'm blue-skying the infosphere across new domains, you wouldn't get it."
CodeSOD: Joined Up
Sandra from InitAg (previously) works with Bjørn, and Bjørn has some ideas about how database schemas should be organized.
First, users should never see an auto-incrementing ID. That means you need to use UUIDs. But UUIDs are large and expensive, so they should never be your primary key, use an auto-incrementing ID for that.
This is not, in and of itself, a radical or ridiculous statement. I've worked on many a database that followed similar rules. I've also seen "just use a UUID all the time" become increasingly common, especially on distributed databases, where incrementing counters is expensive.
One can have opinions and disagreements about how we handle IDs in a database, but I wouldn't call anything a WTF there.
No, the WTF is how Bjørn would design his cross-reference tables. You know, the tables which exist to permit many-to-many relationships between two other tables? Tables that should just be tableA.id and tableB.id?
Table "public.foo_bar" Column | Type | Collation | Nullable | Default -----------+------------------------+-----------+----------+------------------------------------ id | integer | | not null | nextval('foo_bar_id_seq'::regclass) foo_id | integer | | not null | bar_id | integer | | not null | uuid | character varying(128) | | not null |Yes, every row in this table has an ID, which isn't itself a terrible choice, and a UUID, despite the fact that the ID of these rows should never end up in output anyway. It exists only to facilitate queries, not store any actual data.
I guess, what's the point of having a rule if you don't follow it unthinkingly at all times?
[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.CodeSOD: Three Minutes
Angela's team hired someone who was "good" at SQL. When this person started, the team had some regular jobs which ran in the mornings. The jobs were fairly time consuming, and did a lot of database IO. When their current database person left for another job, they hired someone who had a "good grasp" on SQL. We'll call him Barry.
Barry started out by checking the morning jobs every day. And over time, the morning jobs started getting slower and slower. That was a concern, but Barry swore he had it under control. Barry did not share that a handful of slow queries- queries which took three or so minutes to run- had suddenly started taking 75+ minutes to run. Barry didn't think about the fact that a little time with the query planner and some indexes could have probably gotten performance back to where it should have been. Barry saw this problem and decided: "I'll write a Python script".
import time from datetime import datetime, timedelta import pytz # for time zone current_date = datetime.now() day_number = current_date.weekday() # integer value: 0 is Monday hub_1_ready = False hub_2_ready = False hub_1_results = [] hub_2_results = [] job_ran_later = False # If this job is manually run later in the day, avoid sending a "both hubs failed" email # Monday (day_number 0) runs later than the other 6 days if day_number == 0: end_time = datetime.strptime("08:30", "%H:%M") end_time = end_time.time() # get just the time portion else: end_time = datetime.strptime("07:30", "%H:%M") end_time = end_time.time() # get just the time portion # If this job is run later in the day than the normaolly scheduled time if datetime.now(pytz.timezone('US/Central')).time() > end_time: job_ran_later = True # Starting when Morning jobs are scheduled to kick off, check for completion of both hubs every 3 minutes until end_time. If both hubs are not a Success by end_time, an email is sent while datetime.now(pytz.timezone('US/Central')).time() < end_time: h1 = session.sql("SELECT LOG_STATUS FROM PROD_CTRL.CTRL.DRB_EXECUTION_LOG WHERE LOG_PROJECT = 'SRC_PROD_1' AND date(log_start_date) = current_date AND date(LOG_END_DATE) = current_date").take(1) hub_1_results = [] hub_1_results.append(h1) if str(hub_1_results[0]) == "[Row(LOG_STATUS='SUCCESS')]": hub_1_ready = True h2 = session.sql("SELECT LOG_STATUS FROM PROD_CTRL.CTRL.SRC_EXECUTION_LOG WHERE LOG_PROJECT = 'SRC_PROD_2' AND date(log_start_date) = current_date AND date(LOG_END_DATE) = current_date").take(1) hub_2_results = [] hub_2_results.append(h2) if str(hub_2_results[0]) == "[Row(LOG_STATUS='SUCCESS')]": hub_2_ready = True # If both hubs are Success, then break out of while loop, even if it's not end_time yet if hub_1_ready == True and hub_2_ready == True: break time.sleep(180) # Sleep for 3 minutes before trying again if not hub_1_ready and not hub_2_ready and job_ran_later == False: message = "Neither Hub_1 nor Hub_2 finished in time for Morning jobs." context.updateVariable('METL_MESSAGE', message) raise ValueError("send email: "+message) elif hub_1_ready == False and hub_2_ready == True: message = "Hub_1 did not finish in time for Morning jobs." context.updateVariable('METL_MESSAGE', message) raise ValueError("send email: "+message) elif hub_1_ready == True and hub_2_ready == False: message = "Hub_2 did not finish in time for Morning jobs" context.updateVariable('METL_MESSAGE', message) raise ValueError("send email: "+message) elif job_ran_later == True: message = "This job was run manually later in the day. Check that both Source hubs have completed. If you did not run this job, you can probably ignore this email." context.updateVariable('METL_MESSAGE', message) raise ValueError("send email: "+message)I don't particularly like any of this. Some of it is just little ugliness, like the fact that job_ran_later and the closing if statements could be written to be much more clear. Or the way that, after our main while loop, which we'll come back to, we compare boolean variables against boolean literals.
The core of it is the while loop, which checks the current time, and while it's before the target end time, it runs a pair of queries. For each query it runs, it empties an array, then append the results (which we know is only one value, because they take(1)) to the array. Then they check the first element of the array against an expected string.
Why the arrays? Who knows. Perhaps at one point they thought they'd keep the results from multiple iterations, then decided against it. Why do the check against the string in the Python code and not the query? No idea, but maybe I don't have a "good grasp" of SQL. That said, with my bad grasp, I'm pretty sure I could figure out how to do all that in one single query and not two that are almost identical.
In any case, if we don't see what we want in the database, we sleep for three minutes, then try again.
At the end of the process, we check what happened and output messages and raise exceptions based on what we did see in the database.
It's also worth noting that Angela's team used a pretty reasonable job management system. All of their other scripts doing similar jobs didn't include retry logic inside themselves- they just failed. That let the job runner decide whether or not to retry, and that allowed all sorts of valuable configuration options that are more fine grained than "sleep for 3 minutes".
Error'd: Timely Reminder
There is no particular theme this week, except that I have noticed many of these contributors are providing "customized" email addresses. This is a practice which I too have followed, to detect who is selling my email address to spammers. I would use a consistent login id for many web sites, and a decent password generated by a mental algorithm, with a unique email address for each site. It worked great until some website wanted to know specifically what "my" email address is, and I couldn't remotely remember which of 300 variant email addresses I had signed up for their services with.
First up, Martin is traveling by air. "I have heard it's so beautiful this time of year, so I look forward to visit @arrCity_SLPH." Martin helpfully explains "First sentence is in Danish: Your SAS-booking has been confirmed."
Dr. Bob Bobbers, PhD would rather drive. "Somehow I'm projected to arrive 20 minutes ago. I had started in one timezone and was finishing in the next timezone to the east, and when I had connectivity, the ETA was right, but somehow seems to have stopped computing correctly when I went offline."
Caleb B. thinks Amazon's AI-generated coding practices don't compute. "I've been working with my kid a lot with her math homework explaining that the alligator eats the bigger number. I think someone at Amazon needs to learn it too."
Andrew knows that there's a difference between > and ⋝. "Tried to upload my insurance card back and front. Apparently I cannot please the webserver."
And finally, Daniel D. has a timely reminder that we should all bear in mind so that nobody else has to: "Set your country, set your time zone and they should match. Google thinks otherwise, offering only one option (Czechia) for the selected country (Slovakia). The timezone is correct as the whole Central Europe uses the same time (CET). But the basic rule of usability is: Don't make me think!"
CodeSOD: Preformatted
Amity sends us a "weird" replacement, and I regret to inform you, it's not as weird as it should be.
$body = str_replace(['<pre><code>', '</code></pre>'], ['<pre>', '</pre>'], $body);This PHP code scans through a string containing HTML and replaces all the <pre><code>.../<code></pre> tags with just <pre></pre>. And yes, that's a weird thing to do; these mean different things, after all. pre tells us the text is preformatted and things like extra whitespace and line breaks should be respected. code tells us the text represents some sort of code. Usually, that involves respecting the formatting, but it also generally involves rendering in a monospace font.
And this touches upon one of my complaints about this very site. A complaint I don't complain about much, because I could easily fix it, and also it doesn't bother me that much, but also, I don't want to be maintaining our little homegrown CMS more than I have to, so I haven't done it.
Quite some time ago, we did a redesign here. It was fairly necessary, as the site old 100% didn't work on mobile devices. At the time, one habit was en vogue amongst web developers: clear all the formatting rules from the default browser stylesheet and replace them with your own. I can sympathize with that, I suppose. It's certainly one way to deal with cross browser rendering quirks: burn everything to the ground and build up from scratch. You'll still have cross browser quirks, but they'll all be your fault, and your fault alone. And another "quirk" that showed up in that rebuilding, and a quirk I've seen on a depressing number of other sites: make pre content be in monospace.
For some reason I don't fully understand, there was a brief period in CSS styling where people willfully collapsed the distinction between pre and code, and just turned them into the same thing. I'm admittedly a bit of a semantic snob (HTML is a DATA format not a PRESENTATION format, it's still SGML to me).
In any case, this doesn't impact you, our dear readers, who instead get a sometimes confounding Markdown comment box with bad editing support. But I post articles here in pure HTML, and while I rarely need a pre tag, every once in awhile, the default site stylesheet throws me off.
[Advertisement] Plan Your .NET 9 Migration with ConfidenceYour journey to .NET 9 is more than just one decision.Avoid migration migraines with the advice in this free guide. Download Free Guide Now!
CodeSOD: Development Tools
A few holiday seasons ago, Paul S was doing the requisite holiday shopping online, looking for those perfectly impersonal but mildly thoughtful gifts that many companies specialize in. This was one of the larger such vendors, well known for its fruit-filled gift baskets. As is not uncommon for our readers, when the site started misbehaving, he pulled up the dev tools. He didn't solve the problem, but he did learn a lot about how they were managing their API keys, as this was exposed to the client:
env: { APP_AUTH0_GUID: 'ctZZL1BqgKm9kBmDEKAjt0yBeQ47Cpwl XS0xxpLFS5g8o-EUpSu4fi9ecOqN19WnXn-EqI9yaupwme22bKuBd2jH3Kf3QngZ', APP_LOGGING_ENABLED: 'true', APP_LOGGING_SERVICE_PATH: 'r/api/logging/mbp-ui', REACT_APP_MBP_LOGGER_CONSOLE: 'ERROR', APP_TIQ_ACCOUNT: '1800flowers', APP_TIQ_PROFILE: 'full', APP_TIQ_ENV: 'prod', APP_PAYPAL_SDK_URL: 'https://www.paypal.com/sdk/js', APP_PAYPAL_CLIENT_ID: 'AcYrxrOkFwUnMKRoJmkOR0N6caopqRNqwNRxy6H-EvZ-IKUz22i-E0uT0uMT7JQZEC33Oy1HCNsgm_le', APP_PAYPAL_ENV: 'production', APP_PAYPAL_SOURCE: 'PWA', APP_VENMO_ENV: 'production', APP_VENMO_PROFILE_ID: '2705494007504552889', APP_AUTH_LOGIN_SOURCE: 'undefined', APP_SG_BASKET_SCRIPT: 'https://cdn2.smartgiftit.com/scripts/widgets/gift-basket.js', APP_AUTH_DOMAIN: 'login.celebrations.com', APP_AUTH_AUDIENCE: 'celebrations-prod.1800-flowers.auth0.com', APP_STATUS_BAR_ENABLED: 'true', APP_WALLET_ENABLED: 'true', APP_VERIFY_ADDRESS_HOST: 'api.edq.com', APP_VERIFY_ADDRESS_AUTH_TOKEN: '47d991c9-043e-4073-bee3-a5c8922baa3a', APP_FULLSTORY_ORG_ID: 'MXD30', APP_GRAPHQL_ENV: 'production', APP_VISA_CHECKOUT_API_KEY: 'B0LQRDVCE0LWKBHR880J14gCRlEjr_UqLhh6V-yYRAmcvD0W8' }I've gone ahead and mangled the keys, and given that this was a few holidays ago, I'd hope the retailer in question has fixed their website. But as you can see, it was pushing API keys for payment processors, along with potential authentication tokens and internal IDs. Now, I would hope most of these required additional authentication to be useful, and that a malicious actor couldn't do anything nasty with this information- but that's a dim hope. Even with the data exposed here, I wonder if someone could flip APP_PAYPAL_ENV to "development" or "test" and run some transactions through. Or do the same with Venmo.
This is a React app, based on some of the keys, using Graphql for communicating with the back end, and that hits at the fact that it's a single-page application. Probably, the developers were trying to build once for the web and for a "website bundled in an app" deployment for smart phones. And the result is that they weren't thinking about the distinction between "public" and "private" information- they had state to manage,so they managed it. By sending it to the client. Where anyone could see it. But it looked good, they shipped it, and they made sales, so everyone was happy.
For a time.
[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.CodeSOD: The Barren Fields
Today, it's not exactly the code that was bad. For some time, a government agency had been collecting information from users using fillable PDF forms. The user would submit the form, and then a data entry clerk would copy the text from the form into a database. This, of course, raised the question: why was someone manually riding the copy/paste button?
Sally was tasked with automating this. The data is already in a digital format, so it should be easy to use a PDF library to parse out the entered data and insert it into the database. And it almost was.
Sally shares with us, not code, but the output of her program which scanned the fields, looking for their names:
FieldType: Text FieldName: T5ZA1 FieldNameAlt: T5ZA1 FieldFlags: 25165824 FieldJustification: Left FieldMaxLength: 3 --- FieldType: Text FieldName: T5ZA2 FieldNameAlt: T5ZA2 FieldFlags: 25165824 FieldJustification: Left FieldMaxLength: 2 --- FieldType: Text FieldName: T5ZA3 FieldNameAlt: T5ZA3 FieldFlags: 25165824 FieldJustification: Left FieldMaxLength: 4I could go on, Sally certainly shared many more examples, but you can get the gist. The names were all cryptic five character blobs. They all start with T5Z, and followed by "letternumber": A3, B9, C2, etc. It has the vibe of being autogenerated; someone just never considered that they might want clear names for the fields, and just let their editor autonumber them, but that has one counterpoint to it: the letter "O" is never used. T5ZN9 is followed by T5ZP1.
Sally was left scratching her head. Of course, she was going to have to write some sort of lookup that would convert the PDF's field names into database field names, but she expected that the PDF would provide at least some sort of guidance on that front.
I really enjoy that the alt-text for every field is also the field name, which is a clear accessibility "win".
CodeSOD: Completely Readable
It is eminently 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?
Error'd: Yeah Yeah I'm The Tax Man
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!
TDWTF Home Edition: Pt 2
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.
Representative Line: Greater Than False
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 ConfidenceYour journey to .NET 9 is more than just one decision.Avoid migration migraines with the advice in this free guide. Download Free Guide Now!
CodeSOD: Poly Means Many, After All
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.
CodeSOD: A Little Twisted
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.
Error'd: @#$%^!!
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.
CodeSOD: Awaiting A Reaction
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.