Feed the-daily-wtf The Daily WTF

Favorite IconThe Daily WTF

Link http://thedailywtf.com/
Feed http://syndication.thedailywtf.com/TheDailyWtf
Updated 2025-07-18 21:30
The Document Cursor
IniCAD was one of the world's largest purveyors of CAD software. In the earlier days of this industry, they used more "industrial" sales models: rarely did you buy a license from IniCAD directly, but instead bought through a dealer who was technically a third party, but essentially was IniCAD's representative.If you build designs in CAD, at some point you need to turn these into drawings. In the industry, the drawings are 2D, static images that represent a canonical representation of your picture of the object/building/machine being designed. They're one of the primary tools for making sure that all of the various teams working on a large scale construction or fabrication project can all communicate accurately and precisely. Nothing is worse than having a building's electrician working from one drawing as they plan their wiring, and having the framers working from another drawing, and putting their walls in different places than the engineer expects.So IniCAD tried to solve this problem, by implementing their own document management solution, IniDOC. They implemented it in house, called it "good enough", and then shoved it off to the dealers to sell.Judi worked for one of those dealers as a TSSR, and was expected to demo this product. There was just one problem: it didn't work.IniDOC was a pile of VB code (IniCAD's flagship product was scriptable in VBA) that somehow managed to contain its own little copy of DLL Hell in its own dependencies. The first time Judi tried to install it, it borked her computer so badly she needed to do a fresh install of Windows. The second time, she got it to install, but couldn't store documents in it. With each glitch or problem, she went up the chain to complain to IniCAD, and each time IniCAD escalated her issue.By the time Judi was ready to start doing demos for clients, she had a team of IniCAD developers on call for the entire demo window. The code she was running for her demo was a hodgepodge of non-version-controlled quick hacks and duct-tape. Certainly, it wasn't the "gold master" or "release candidate" or what the customer would actually get.The demos went terribly, and Judi spent about six months touring Europe looking like an idiot shilling a dumpster-fire of a product. It was soul crushing, and at the end of that period, the sales team had one sale for the entire region to her credit. A few months after that, her one sale demanded a refund: a glitch caused the system to crash and destroy all the documents they were storing in their document management system.IniCAD realized that they had made a terrible mistake, trying to branch away from their specialty and into a new product niche. They quietly withdrew their IniDOC product, and then did what all companies with a decent cash reserve do: they bought a third party company that had a product better than theirs.IniCAD purchased "Docutrode", the "best in class" document management tool for architects, engineers, and fabricators. They relaunched it as IniDOC V2, and Judi was once again doing a round of demos.It went better, but not great. The new document management product was an attempt to clone Visual Source Safe, and the install process was fraught with unnecessary complexity. While IniDOC V2 actually made sales, most of the profit was eaten up by the high volume of support calls, and those calls were almost entirely configuration and install issues.IniCAD had a choice: they could improve their documentation, streamline their support path, redesign the install process to cut down on errors, and maybe do some business analysis to get a better sense of what the "right most of the time" defaults should be, or they could do a ground up rewrite using the team responsible for IniDOC V1.They did a ground up rewrite. Judi, working at the dealer, got to see lots and lots of marketing copy about it, lots of promises, lots of "Web 2.0!" branding. Release dates came and went, without a product. For awhile, Judi wondered if IniDOC V3 had died, but no software product dies if you're willing to throw good money after bad, so it eventually released.What Judi received was a software package that ran an IIS web server and a SQL Server database. It could support, in theory, hundreds of simultaneous users, but in practice more than five meant requests started timing out.Judi didn't write the software and didn't have access to most of the source code, but she wanted to understand why it was so slow. So she started poking around in the database to see the structure.The core of the database were three tables: one which actually stored the documents and their data (documents), one which lists off all the possible attribute metadata for any document (attributes), and one which links documents, attributes, and their values (document_attribute_values). Because metadata could be anything- numeric, text, even a thumbnail image- the only workable datatype was to store everything in BLOB columns.On the UI side, as the user navigated the application, they saw logical folders, and the files in that folder were listed with metadata columns. The user could set global preferences for which metadata columns they wanted to see.Judi poked around in the database, and found that almost all the business logic was implemented in stored procedures. And that's when she pulled up the procedure which handled that browsing.The logic went basically like this:Create a temporary table for the folder you're about to display. It has one column, document_id, and has one row for every document in the folder. Then, it opens a cursor on the attributes table. For every possible metadata field, it alters the query table to add column for the metadata field. Then, inside of that cursor for loop, the code opens a second cursor looking at the document_attribute_values table. There, it pulls the values (if there are any), and populates them into the column on the temporary table.Once every document in the folder had gotten that treatment, the entire table was sent to the client side, where the users' display settings got applied and the metadata columns they didn't want to see were excluded.Metadata fields were billed as being customizable and flexible. The application encouraged users to create metadata fields with abandon. A single deployment might have hundreds of possible metadata fields, but a single document might have, at most, thirty. In practice, most users only ever needed to see 5-8 columns.Each time an engineer changed folders, a cursor-driven pivot table was created with hundreds of mostly empty columns, of which only a handful actually mattered. All that data went back to the client side, where the filtering happened.IniDOC V3 sold slightly better than its previous versions, more due to increased demand for a document management solution than because of any merits to the product. Judi left IniCAD's dealer before IniDOC V4 had a chance to come out, but based on conversations with former co-workers, Judi believes it still more or less works this way.Which should be a lesson to all software developers: all performance problems can be solved by simply not changing any code and waiting for hardware improvements to make it run faster. [Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
Error'd: Just Following Out of Order Orders
"Instructables alphabetic sorting by each country's name in its own language (i.e. Spain == Espana) is a great idea, but it kind of makes for a hard to navigate list," writes Peter L.
CodeSOD: A Blacklisted Senior
Damien has the “pleasure” of supporting JavaScript code which runs, not in a browser or Node, but inside of a proprietary runtime specialized in handling high-performance collection datatypes. You can write extremely fast code, so long as you’re using the collection types correctly. This is good, because a lot of those JavaScript blocks have to be executed for every single request. Milliseconds of execution time add up faster than you think.One of Damien’s senior peers needed to add some code that would filter fields out of a response. Data fetched from the database would be compared against a blacklist of fields to exclude- those fields should be removed from the collection.This is a relatively simple task, and one that has, in other variations, already been implemented in the codebase. Some of those proprietary enhancements are faster implementations of types like Set, so the basic approach would be:
CodeSOD: Producing Self Joins
Wesley considers himself an “intermediate SQL-er”. The previous “database expert”, though, has moved on to greener pastures, and now Wesley is “the database person”. This means that they need to pick through a bunch of stored procedures and triggers and try and understand the undocumented, unversion-controlled database code.The upshot, is that Wesley is starting to feel like his intermediate skills might be more “expert” than the previous expert.For example, Wesley found this query. The goal of this query is, for a single point-of-sale terminal, in a date range, how many of each product did they sell, as a raw count. It should be able to say, there were 5 apples, 10 oranges, etc.Now, you or I or Wesley are probably already reaching for the GROUP BY and maybe a CASE. It’s the right choice, obviously. But the “expert” has a different solution:
CodeSOD: Break your Labels
Nedra writes “I discovered this code while cleaning up and refactoring some label printing methods in a home-grown ERP that I maintain.”The code in question “works most of the time”, which means it’s crossed a line of code quality. Speaking of crossing lines, this particular block of code needs to take information about how a product is formulated and print it on a label. These sorts of ERP functions are “mission critical”, in that correct and accurate formulations- whether the ingredients list on a foodstuff or the ingredients in a can of paint, or an industrial solvent- are required for regulatory compliance.Labels are also physical objects, and have a defined physical size. This means that you can only fit so much information on them, and you’ll need to make sure the layout of what you’re printing is readable on the label.Nedra’s co-worker had… a solution for this.
CodeSOD: The Label Printer
If you create a UI object in code, you have to go through all that pesky, annoying work of initalizing that object so it displays correctly. I mean, who wants to write VB.NET code which looks like this:
Error'd: Identification Without Authentication
Mark M. wrote, "While I was reading the Feb 6th DailyWTF, Feedly chimed in with this helpful comment that really put it in context."
CodeSOD: It's For DIVision
We’ve discussed the evil of the for-case pattern in the past, but Russell F offers up a finding which is an entirely new riff on this terrible, terrible idea.We’re going to do this is chunks, because it’s a lot of code.
Copy/Paste Culture
Mark F had just gone to production on the first project at his new job: create a billables reconciliation report that an end-user had requested a few years ago. It was clearly not a high priority, which was exactly why it was the perfect items to assign a new programmer."Unfortunately," the end user reported, "it just doesn't seem to be working. It's running fine on test, but when I run it on the live site I'm getting a SELECT permission denied on the object fn_CalculateBusinessDays message. Any idea what that means?"The problem was fairly obvious, and Mark knew exactly what the error meant. But the solution wasn't so obvious. Why did the GRANT script work fine in test, but not in production? How can he check to see what the GRANTS are in production? Is there someone specific he should ask to get permission to look himself? Does the DBA team use a sort of ticketing system maybe? Is this even the right approach? Who on his team could he even ask?Fortunately, Mark had the perfect venue to ask these sorts of questions: the weekly one-on-one with his team lead, Jennifer. Although he had a few years of coding experience under his belt, he was brand new to The Enterprise and specifically, how large organizations worked. Jennifer definitely wasn't the most technical person he'd met, but she was super helpful in "getting unblocked" as he was learning to say."Huh", Jennifer answered in their meeting, "first off, why do you even need a function to calculate the business days between two dates?""This seems like something pretty common in our reports," Mark responded, "and this, if the logic ever changes, we only need to change it in one place."Jennifer gave a mystified look and smiled, "Changes? I don't think the 7-day week is going to change anytime soon, nor is the fact that Saturday and Sunday are weekends.""Well, umm," Mark definitely didn't expect that response. He was surprised to have to explain the basic principles of code reuse to his supposed mentor, "you see, this way we don't have to constantly rewrite the logic in all the places, so the code is a bit simpler.""Why don't you just copy/paste the calculation code in your queries?" she rhetorically asked. "That seems like it'd be a lot simpler to me. And that's what I always do…. But if you really want to get the DBAs involved, your best contact is that dba-share email address. They are super-slow to project tickets, but everyone sees that box and they will quickly triage from there."Needless to say, he didn't follow Jennifer's programming advice. She was spot on about how to work with the DBA team. That tip alone saved Mark weeks of frustration and escalation, and helped him network with a lot more people inside The Enterprise over the years.##Mark's inside connections helped, and he eventually found himself leading a team of his own. That meant a lot more responsibilities, but he found it was pretty gratifying to help others "get unblocked" in The Enterprise.One day, while enjoying a short vacation on a beach far, far away from the office, Mark got a frantic call from one of his team members. An end-user was panicked about a billables reconciliation report that had been inaccurate for months. The auditors had discovered the discrepancies and needed answers right away."So far as I can tell," his mentee said, "this report is using a fn_ CalculateBusinessDays function, which does all sorts of calculations for holidays, but they already prorate those on the report."The problem was fairly obvious, and Mark knew exactly what happened. Some must have changed the logic on that function to work for their needs. But changing it back would mean breaking someone else's report. And the whole idea of a function seemed strange, because that would mean taking a dependen--The junior programmer interrupted his stream of thought."I think I should just add an argument to the function to not include holidays," he said. "That's really simple to do, and we can just edit our report to use that argument.""Ehhh," Mark hesitated, "the logic is so simple. Why don't you just copy/paste the business day calculation? That's the simplest solution… that's what I do all the time." [Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
Logs in the Cloud
Carrol C just joined IniTech. They were hiring for someone who could help them tame their cloud costs. There’s a lot of money being spent on AWS. Management had bought in on the “it’s cheaper than on-prem”, and were starting to wonder why that promise wasn’t being fulfilled.After a little settling in period, Carrol had his credentials for their AWS environment, and started digging around just to familiarize himself with the infrastructure. This environment had started as an on-prem system that got migrated to the cloud, so the infrastructure was mostly a collection of virtual-machines using attached virtual disks- EBS- for storing data.And that was the first red flag. Each VM was using between 160–200GB of EBS. CPU usage was hovering at around 15%, and RAM was barely a blip, but the quantity of disk was getting a more than a little out of hand. Carrol scribbled a few notes on a post-it, and went down the hall to visit Merna’s cube. Merna was one of the engineers responsible for developing the application. “Hey, Merna, question for you: how big is our application code and deployable artifacts?”“Oh, depends on which instance you’re talking about, but the biggest weighs in at about a gig,” Merna said. “But we have some additional stuff installed on our VM image, so the VM image itself is about 4GB.”“And what does-” Carrol paused to check his note- “the WRPT–073 instance do?”“Oh, that’s just a simple webserver. Just generates some reports. Barely operates at capacity on even a Micro instance.”“So… why is the disk sized for 200GB?”Merna looked at Carrol like he had just asked the dumbest possible question. “Logs, obviously,” she said.“… you have 196ish gigs of logs?”Merna nodded. “We might need them.”“AWS has a log aggregator that doesn’t store the logs on EBS. You could just ship them there and use logrotate to trim your logs, and that would be way cheaper.”Merna shook her head. “You say that, but- oh, hold on.” Merna’s email bleeped at her: instance WRPT–073 was getting close to its disk capacity threshold. She quickly pulled up the AWS console and added another 10GB to the disk, before turning back to Carrol. “A lot of those accessory services have highly variable costs, and it makes it hard to predict your spend. Using cloud VMs is a much more consistent option. But if you feel so strongly about it, you could submit a request and we’ll evaluate it for a future release.”Carrol submitted a request, and also pinged his new boss. “I think I know a way we can manage costs.” For now, Merna and the other engineers just expand disks when they fill up. It remains to be seen if anything actually changes, but regardless, Carrol is prepared for an “interesting” time at IniTech. [Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
CodeSOD: Legacy Documentation
Vernice inherited a legacy web app. By "legacy" in this case, we mean "lots of jQuery." jQuery everywhere. Nested callbacks of HTTP requests, no separation of concerns at all, just an entire blob of spaghetti code that was left out on the counter and is now stuck together as a big blob of sauceless starch. And as for documentation? There isn't any. No technical documentation. No comments. The code didn't even pretend to be self-documenting.For the past few months, Vernice has been tasked with adding features. This generally meant that she'd find the code she thought was responsible for that section of the app, change something, see nothing happen, realize she was looking at the wrong module, try that three more times, finally find the actual code that governed that behavior, but as it turns out it had downstream dependents which broke.Adding a single textbox to a form was a week long process.So imagine Vernice's joy, when she opened a file and saw neat, cleanly formatted code, a compact function, and her text editor showed her the telltale color of comments. There were comments! Had she finally found the "good" part of the application?Then she read the code.
Error'd: A Taste of Nil
"This nil looks pretty tasty, but I think I’m allergic to it since I always feel sick when I see it in my debugger," Kevin T. writes.
CodeSOD: The Powerful Parent
As we’ve explored recently, developers will often latch onto something they pick up in one language and carry it forward with them into others. Kerry still is working with the co-worker who has… odd ideas about how things should work. At is turns out, this developer is also a Highly Paid Consultant, which we just discussed yesterday.The latest problem Kerry found was in a display grid. It lists off a bunch of information linked to the user’s account, and each entry on the grid has a little plus sign on it to display further details. What, exactly, appears on that grid is tied to your account. It’s also worth noting that this service has a concept of corporate accounts- a “parent” account can administer entries for all their child accounts.When someone clicks that little plus sign, we need to fetch additional details, regardless of whether or not they’re a corporate parent account or not. So how exactly does the C# controller do this?
Hop Scotch
IniTech’s fashion division, IniGarment, launched their new accounting solution by hiring “best in class” highly-paid-consultants (HPCs). The system launched, collapsed under the weight of the first week of use, hardware was thrown at the problem in an absolute crisis panic, and the end result was that they had a perfectly serviceable accounting package that was overbudget and supported by expensive HPCs.It wasn’t sustainable. So out the HPCs went, and in came a pile of salaried employees. Jeff was one of those. His first six weeks at IniGarment were spent trying to understand the nest of stored procedures, quick hacks, and ugly choices. One of the first puzzles Jeff decided to look into was an invoice uploading step.They used a turn-key eCommerce package to handle sales, and the accounting system needed to generate invoices and upload them to the eCommerce package. This relatively simple task took 30 minutes to generate and upload a single invoice, and that was on a good day. On bad days, it could take nearly an hour. So Jeff set out to figure out why.In the middle of a 700+ line stored procedure, Jeff found the query which generated the report. The whole process required big piles of temporary tables (which, instead of being true temp tables, were created/dropped with each execution), and ugly group-bys and subqueries. Still, even with all that, it was just a SQL query, right?
CodeSOD: Install Your Package
I use Python a lot at work, and if you're doing anything vaguely data oriented, you want to use NumPy. I gave a talk about how much I love NumPy. It's one of the things that I automatically include in every requriements.txt because it's so goddamn useful.Lanny supports a product which uses NumPy, which is why he was surprised to find this block:
Representative Line: Without Directions
Adam S sends us a representative line which represents a mystery. It's a simple enough Java statement:
Error'd: Con(text)ual Errors
"A football coach needs at least a two line footer to succeed," writes Ergin S.
Coded Smorgasbord: On the Hard Problems
As the saying goes, there are two hard problems in computer science: naming things, cache expiration, and off-by-one errors. This little snipped of anonymously supplied PHP code highlights the first one of those challenges:
CodeSOD: Going Down to the Object Store
Odette’s company uses a popular video conferencing solution for browser use. In the base library, there’s a handy-dandy class called ObjectStorage, which implements an in-memory key/value store entirely in TypeScript/JavaScript.“Wait,” you ask, “isn’t a JavaScript in-memory, key/value store just… an object? A map, if you’re being pedantic?”Yes, of course, but have you thought about ways to make JavaScript’s maps/objects worse?
A Short REST
I’m starting to wonder if we need a “Representative API” category. There are just so many ways in which a developer can mess up basic tasks, like mapping a RESTful API to their backend.Today’s anonymous submitter was working with a REST API provided by a “world leading parcel” company. Everything started well. The documentation was thorough, contained links to example projects, and it came with a Swagger API doc. Based on that documentation and based on the Swagger doc, they went ahead and tried to CURL the API for a specific endpoint:
CodeSOD: An Accident
There's a very specific brand of bad code that I see from time to time, which I think of as "Oh, this poor person was permanently damaged by exposure to C." They're not writing C, but there's something about their "accent" which tells you: they learned C and didn't recover from the experience. Every reference variable can be treated like a pointer if you're insistent enough.There are other, similarly brain-breaking languages. COBOL. PL/SQL. VBA. Programmers learn the quirks of these languages, fail to understand them, and then start writing weirdly formal, structured code in languages that aren't supposed to work that way.Kerry has a co-worker like that. They're doing C#, and they include weird little ticks that are a clear sign of some kind of other langugae trauma. My guess is that it's a mix of PL/SQL and Visual Basic (not .NET), based on my experience with other people who have suffered through learning PL/SQL and VB as their first languages.We're going to take a look at some. In the interests of anonymization, I'm not going to include all of the code, which is 632 lines of tedium in one method, but I'm going to include the important highlights. Like, for starters, the message signature:
Error'd: Little to Nothing at All
"I wonder, what does a null pharmacist eat for lunch? BaNaNas?" writes Barry M.
CodeSOD: The Intern's Gadget
Pierre is a contractor who supports a variety of companies helping them manage data-science and analytics applications. Code, in these contexts, is written to answer specific questions, driven more by mathematics than program design. That’s a polite way of saying that the vast majority of the code is unreadable nonsense that no one can explain.One of Pierre’s clients has decided to migrate to that fancy new thing they’ve been hearing about, “the cloud”, and thus they have to move all of their applications to that cloud. This suite of applications involved a website with a pile of “gadgets” that users could string together to do their own data analysis. And one of those gadgets was quickly thrown together by an intern circa 2007.Now, no one expects an intern to write good code on their own. They need guidance. They need experience. They absolutely don’t need to be thrown into the deep end to whip up a reusable “gadget” that nobody thinks will ever see production.So, within that context, the intern did their best. While working for the company, the intern had learned a little bit about GNU Octave, which is what drove most of their analytics. The intern also knew some PHP, from dabbling in web development. Since this particular gadget needed to store some data, the intern brought in the other tool they knew: MySQL.Thus was born the Intern’s Gadget, which works roughly like this:
CodeSOD: Exceptoinal Spelling
Object-oriented languages often let you implement your own exception classes to hook into their structured exception handling. This is, usually, a good thing: you create your own custom types for your various errors, which makes various exception states more clear. PebkacException is more useful than just Exception, and you can build catch blocks specific to your application/API needs.But there’s a dark side to this feature. People want to hook functionality into their exception objects. Instead of just using them as a signal to announce a failure state, they slap features into them, like exceptions which automatically self log.Muriel discovered this PHP SelfLoggingException object when trying to throw an exception caused the application to crash with a stack overflow.
CodeSOD: Microsoft's English Pluralization Service
Despite founding The Daily WTF more than fifteen years ago, I still find myself astonished and perplexed by the curious perversions in information technology that you all send in. These days, I spend most of my time doing "CEO of Inedo stuff", which means I don't get to code that much. And when I do, it's usually working with the beautiful, completely WTF- and bug-free code that our that our world-class engineers create.I mention this, because when I come across TDWTF-worthy code on my own, in the wild, it's a very special occasion. And today, I'm excited to share with you one of the worst pieces of code I've seen in a very long time: EnglishPluralizationServices.csAnyone even remotely familiar with the English language knows that pluralization is hard, and not exactly something that should be generalized in library... let alone Microsoft's most strategic programming asset of the past two decades. And yet, despite that:
CodeSOD: A Splash of Color
YouTube, like any reasonable video service, offers closed captioning. They'll even throw machine learning at the problem, and autogenerate captions, though that is usually only good for comedy, rather than actual accesibility.Any closed captioning system will generally let you specify the colors of the captions as well as the actual text. YouTube is no exception to that. YouTube offers an online editor, but anyone serious about producing content is going to upload their own subtitle files, and up until recently, this could be done in an XML file which would allowed a lot of control over the styling of the captions.But XML isn't cool, so YouTube rolled out a new JSON format. Which broke everything. Specifically, instead of being able to set any hex triplet as your color, you could only set a relative handful, and any "invalid" triple would just turn to white.For some reason, whatever the user inputs isn't propogated to this as a hex triplet, like #FF0000, but instead as a hex value- 0xFF0000, or 16711680, in decimal. I'm not sure if that's on the "filling out the JSON" side, or if it's a conversion which happens elsewhere, but regardless: the front end needs to map a value like 16711680 to #FF0000. Well, a value like that, but not exactly that value, as we'll see.An anonymous submitter already trawled through the minified code and found the code block responsible, which they've helpfully de-minified for us:
Error'd: Amazon Deal or No Deal
"Hey Alexa, can you help Amazon with their math?" Timothy W. wrote.
Representative Line: A Short Year
Are we sick of of year rollover bugs yet? Well, let’s just agree that people aren’t sick of making these kinds of bugs.A long time ago, someone at Oleksandr’s company needed to write a Python script that shipped a 4-digit year to a system that only accepted 2-digit years. So 2010 needed to turn into 10.They could have used date formatting to format the date into a two digit year, but that involves understanding how to format dates. That just seems like too much overhead, when there’s already a perfectly good way to mangle a string.
Two Heads Are Better Than One
What, exactly set of features divide a "text editor" from an IDE is a bit of a blurry line. Developers are not the sort to use static, unchangeable tools. They want configuration, they want plugins, they want quick access to a terminal, they want debugging support, and they'll bolt those features into just about anything.There's a fine line between an IDE that provides nice utility to the developer, and an IDE which is opinionated. I had the misfortune long ago to use the WebSphere IDE, which was essentially a repackaged version of early Eclipse bundled with highly opinionated plugins about how you were supposed to build a Java application. As Matt puts it: "An IDE is, to some, a high-functionality tool for developing applications, and to others a classic example of an Inner Platform."Matt is saddled with a vendor-specific IDE which falls solidly on the Inner Platform side of things. Like many developers, Matt has a laptop which he can lug to meetings, and a docking station with a large external monitor he can use for actual work.There's just one problem. Any time this vendor-specific IDE wants to pop up a dialog box, the dialog box always appears on the primary monitor. Now, Matt leaves his laptop screen set as the primary monitor, but he's doing his actual work on the large monitor, so this is a nuisance, to be certain. Ideally, dialogs should appear on whatever monitor the active window which triggered the event is on.This is a minor bug. Almost trivial. But it is a bug, and enough of a nuisance to Matt that he entered a bug ticket. He fired it off, and largely forgot about it over the next two weeks, until he got a reply.
CodeSOD: An Enterprise API
There’s a simple rule about “enterprise” software: if the word “enterprise” is used in any way to describe the product, it’s a terrible product. Enterprise products are usually pretty special purpose and serve a well-capitalized but usually relatively small market. You aren’t going to sell licenses to millions of companies, but maybe tens of thousands. Often hundreds. There are some extremely niche enterprise products that have only two or three customers.Lots of money, combined with an actually small market in terms of customers, guarantees no real opportunity for competition. Couple that with the fact that each of your customers wants the off-the-shelf product you’re selling them to have every feature they need for their business case, you’re on a fast track to bloated software, inner platforms, and just general awfulness.Today, we’re not talking about Oracle, though. Jacek is in the healthcare industry. Years ago, his company decided to shove off their patient scheduling and billing to a Software-as-a-Service enterprise product. Integrating that into all of their other systems has kept the development teams busy ever since, and each successive revision of the API has created a boatload of new work.Currently, the API is on version six. V6 is notable because this is the first version which offers a REST/JSON API. V5 was a SOAP-based API.Here’s an example message you might send to their scheduling services:
Painful Self-Development
Daniel didn't believe the rumor at first. Whenever his company chased after the hottest new business trends, they usually pursued the worst trends imaginable. But word was that this time, they'd seen fit to mimic Google’s fabled "20% Time."The invitation for a company-wide meeting soon landed in everyone's inbox, turning rumor into reality. For a moment, Daniel dared to dream about the various time-saving scripts he'd always wanted to write, and the applications he'd always wanted to re-implement from the ground up—all those things he'd been prevented from even thinking about as he'd been flung from one urgent project to the next. With 20% of his work time dedicated toward personal pursuits, all of that was set to change ...He forced himself not to get excited. As a hardened corporate veteran, Daniel had been down this road before. It wasn't a question of would this go wrong, but how would it go wrong.At the company meeting, which Daniel attended via conference call, a parade of high-level executive voices gushed about the new corporate policy, dubbed "Take-12." "From now on, everyone gets one hour each month to put toward personal work and development!"Twelve hours a year, out of the 2,000 that most people were expected to work. Daniel supposed "0.6% Time" didn't have quite the same ring to it.And how would the new policy be reconciled with the company's already Byzantine timesheet and internal billing system? Well, the company didn't even even attempt such a thing; there was simply no room in anyone's budget. Instead, someone had the bright idea of co-opting a different internal system for curating video playlists for online training courses. The idea was that each employee would create a new playlist of 12 hour-long videos, one for each month. The videos wouldn't actually be videos, just placeholders. By "watching" a "video," an employee would be logging that they'd spent one hour of time on personal development.The premise started off sketchy, and only got sketchier as difficulties were encountered during implementation. Daniel could only shake his head in astonishment as he read the User Guide detailing what he had to do:
Error'd: Text Should Go Here
"The fact that Microsoft values my PC's health over copyediting is why I thumbed up this window," Eric wrote.
CodeSOD: Switch Off
There are certain things which you see in code that, at first glance, if you haven’t already learned better, look like they might almost be clever. One of those in any construct that starts with:switch(true) {…}It seems tempting at various points. Your cases can be boolean conditions now, but you can also collapse cases together, getting tricky with breaks to build complex logic. It’s more compact than a chain of ifs. It’s also almost always the wrong thing to do.Kasha stumbled across this while tracking down a bug:
Y2K15
We’re still in the early part of the year, and as little glitches show up from “sliding window” fixes to the Y2K bug, we’re seeing more and more little stories of other date rollover weirdness in our inbox.Like, for example, the Y2K15 bug, which Encore got to get surprised with. It feels like date issues are turning into a sports game franchise: new releases of the same thing every year.A long, long time ago, Encore’s company released a piece of industrial machinery with an embedded controller. It was so long ago and so embedded that things like floating point operations were a little to newfangled and expensive to execute, and memory was at an extreme premium.The engineer who originally designed the device had a clever solution to storing dates. One byte of EEPROM could be dedicated to storing the last two digits of the year. In RAM, a nibble- 4 bits- would then store an offset relative to that base year.Yes, this had Y2K issues, but that wasn’t really a concern at the time. It also had a rollover issue every 16 years. That also wasn’t really a concern, because it was attached to a giant machine which needed annual service to keep functioning properly. Every few years, the service tech could bring an EEPROM progammer device and flash the base year value in the EEPROM. And if someone missed 16 years worth of service calls, they probably had other problems.Time passed. Some customers did miss 16 years of service calls. Over time, new features got added. The control interface got an improved LCD. Bluetooth got attached. The networking stack changed. A reporting database got bundled with the product, so all the data being produced by the device could get aggregated and reported on. The way the software interacted with the hardware changed, and it meant that the hardware ran at a lower temperature and could go longer between service calls. But at its core, the chip and the software didn’t change all that much.In that time, there were also changeovers in the engineering team. People left the company, new engineers joined, documentation languished, never getting updated. Years might pass without anybody touching the software, then suddenly a flurry of customer requests that needed patched RIGHT NOW would come through, and anybody who vaguely understood the software got roped in to do the work, then shunted back off to other projects.On New Year’s Day, 2016, a deluge of tickets started coming in. Encore, as the last person to have touched the software, started picking them up. They all expressed the same problem: the date had rolled over to 2000. The reporting database was confused, the users were confused, and even if they tried to set the clock to 2016 manually, it would roll back from 2015 to 2000.Now, no one at the company, including Encore, actually knew about the date system in use at this point. The support manual did say that rollovers meant the device had gone 16 years without being properly serviced, but some of these customers had brand new devices, less than a year old. And customers with devices older than 16 years weren’t seeing this problem.Encore investigated, and picked apart how the date handling worked. That, itself, wasn’t the problem. It took a lot more investigation to track down the problem, including going back to the board schematics to trace how various hardware components were connected. After a few hair-on-fire weeks of crisis management, Encore pieced together the series of events as they were best able.Sometime after the year 2000, Bluetooth was added to the device. Something about how the Bluetooth module connected to the other components had broken the flasher-software that could update the base year. This meant that the devices had never had their base year set, and simply had a 0 value- 0x00, or the year 2000.Which meant, for the next 16 years, everything was fine. Techs went out, tried to flash the EEPROM, reset the clock to the correct date, and went about their business, never aware that they hadn’t actually done anything. But come 2016, all of these devices rolled back over to the year 2000.Encore was able to figure out a script to trick the system into adjusting the output to correct the base year issue, but it also meant many customers had database crammed with bad data that needed to be adjusted to correct the erroneous year.After this, Encore’s company released upgraded version of the system which contained a GPS receiver, so that it could set its date based on that, but a large number of their customers weren’t interested in the upgrade. Encore has already blocked off the first few weeks of 2032 in preparation. [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Representative Line: Gormless and Gone
There’s always a hope that in the future, our code will be better. Eventually, we won’t be dealing with piles of krufty legacy code and unprepared programmers and business users who don’t understand how clicking works. It’s 2020: we officially live in the future. Things aren’t better.Duane works in Go, and has a piping hot “Representative Line” written in 2020. If, like me, you don’t quite know Go, it still looks pretty terrible at first glance:
CodeSOD: An Unreal Json Parser
As we've discussed in the past, video game code probably shouldn't be held to the standards of your average WTF: they're operating under wildly different constraints. So, for example, when a popular indie game open sources itself, and people find all sorts of horrors in the codebase: hey, the game shipped and made money. This isn't life or death stuff.It's a little different when you're building the engine. You're not just hacking together whatever you need to make your product work, but putting together a reusable platform to make other people's products work.Rich D, who previously shared some horrors he found in the Unreal engine, recently discovered that UnrealScript has a useful sounding JsonObject. Since Rich is thinking in terms of mods, being able to read/write JSON to handle mod configuration is useful, but anyone designing a game might have many good reasons to want JSON documents.The file starts promisingly with:
Error'd: Are You Old Enough to Know Better?
"I guess my kid cousins won't be putting these together for a while," Travis writes.
The Compliance Ropeway
"So, let me get this straight," Derrick said. He closed his eyes and took a deep breath while massaging his temples before letting out an exasperated sigh. "Not a single person... in this entire organization... is taking ANY responsibility for Ropeway? No one is even willing to admit that they know anything about this application...?"The Operations team had grown accustomed to their new director's mannerisms and learned it's just better to stay silent and let Derrick think out loud. Afterall, no one envied his job or his idealistic quest for actual compliance. If had he been at the bank as long as his team had, Derrick would have learned that there's compliance... and then there's "compliance.""But we figured out that Ropeway somehow automatically transfers underwriting overrides from ISAC to AppPortal?" Derrick paused to collect his thoughts before a lightbulb went off. "Wait, wait. Those systems are both covered under our IBM Master Service Agreement, right? What did they say? Chris... did you reach out to our IBM liaison?""Well," Chris silently thanked everything good that Ropeway wasn't his problem. "IBM says that they have no idea. They said it's not in the scope of the MSA or any SOW, but they'd be happy to come out and—""Ab-so-lute-ly not," Derrick interrupted. He wasn't IBM's biggest fan, to put it mildly. "I've already eaten into next year's budget on this SSL initiative, and there's no way I'm gonna pay them just to tell me I have to pay them even more to fix what shouldn't even by my problem!"Derrick let out another sigh, rubbing his temples again. "All I want," he grimaced, "is for Ropeway to use HTTPS instead of HTTP. That's all! Fine... fine! Chris, let's just move the whole damn Ropeway server behind the proxy.""Roger that," Chris nodded, "We'll start prepping things for next week's maintenance window."There was a lot of risk to moving Ropeway. The Operations team knew how to keep it running – it was just a Windows Service application – but they had no way of knowing if the slightest change in the environment would break things. Moving the server behind the http-to-https proxy meant a new IP and a new subnet, and they had seen far too may "if (IP==10.10.22.30) production_env = true" traps to know they can't just move things without a test plan.But since no one on the business or Development side was willing to help, they were on their own and it'd be Derrick's head if ISAC or AppPortal stopped working once that maintenance window was over. But for the sake of actual compliance – not "compliance" – these were the risks Derrick was willing to take: SSL was simply non-negotiable.##"You'll never believe what I found on that Ropeway server," Chris said while popping into to Derrick's office. Actually, he knew that wasn't true; Derrick had come to expect the unbelievable, but Chris liked to prep Derrick nonetheless. Derrick took a deep breath and moved his hand towards his forehead."I found this." Chris plopped down a thick, tattered manila envelope that was covered in yellowed tape. "It was... um... taped to the server's chassis."Derrick was legitimately surprised and started riffling through the contents as Chris explained things. "So apparently Ropeway was built by this guy, Jody Dorchester, at Roman, uh, wait. Ronin Software or something.""And yeah," Chris continued as Derrick's eyes widened while he flipped through page-after-page-after page of documentation, "Jody apparently wrote all sorts of documentation... installation instructions, configuration instructions – and all the source code is on that enclosed CD-ROM."Derrick was speechless. "This," he stuttered, "is dated... March ...of 2000.""Yup," Chris jumped in nonchalantly, "but I took a shot in the dark here and sent Jody an email.""And...," Chris said, smiling. He handed Derrick another document and said, "here's his reply."
CodeSOD: Sharing the Power
"For my sins," John writes, "I'm working on a SharePoint 2010 migration."This tells us that John has committed a lot of sins. But not as many as one of his coworkers.Since they were running a farm of SharePoint servers, they needed to know what was actually running, which was quite different from the documentation which told them what was supposed to be running. John's coworker did some googling, some copy-and-pasting, some minor revisions of their own, and produced this wad of PowerShell scripting which does produce the correct output.
Y-Ok
Twenty years out, people have a hard time remembering that Y2K was an actual thing, an actual problem, and it was only solved because people recognized the danger well ahead of time, and invested time and effort into mitigating the worst of it. Disaster didn’t come to pass because people worked their butts off to avoid it.Gerald E was one of those people. He worked for a cellular provider as a customer service rep, providing technical support and designing the call-center scripts for providing that support. As 1999 cranked on, Gerald was pulled in to the Y2K team to start making support plans for the worst case scenarios.The first scenario? Handling calls when “all phone communication stopped working”. Gerald didn’t see much point in building a script for that scenario, but he gamely did his best to pad “we can’t answer the phones if they don’t ring” into a “script”.There were many other scenarios, though, and Gerald was plenty busy. Since he was in every meeting with the rest of the Y2K team, he got to watch their preparedness increase in real time, as different teams did their tests and went from red-to-green in the test results. A few weeks before the New Year, most everything was green.Y2K fell on a Saturday. As a final preparation, the Y2K team decided to do a final dry-run test, end-to-end, on Wednesday night. They already ran their own internal NTP server which every device on the network pulled from in one way or another, so it was easy to set the clock forward. They planned to set the clock so that at December 29th, 22:30 wall-clock time the time server would report January 1st, 00:00.The Y2K team gathered to watch their clock count down, and had plans to watch the changeover happen and then go party like it was 1999 while they still had time.At 22:29, all systems were green. At 22:30- when the time server triggered Y2K- the entire building went dark. There was no power. The backup generator didn’t kick on. The UPSes didn’t kick over. Elevator, Phones, HVAC, everything was down.No one had expected this catastrophic a failure. The incident room was on the 7th floor of the building. The server room was in the basement. Gerald, as the young and spry CSR was handed a flashlight and ended up spending the next few hours as the runner, relaying information between the incident room and the server room.In the wee hours of the morning, and after Gerald got his cardio for the next year, the underlying problem became clear. The IT team had a list of IT assets. They had triaged them all, prioritized their testing, and tested everything.What no one had thought to do was inventory the assets managed by the building services team. Those assets included a bunch of industrial control systems which managed little things, like the building’s power system. Nothing from building services had ended up in their test plan. The backup generator detected the absence of power and kicked on- but the building’s failure meant that the breakers tripped and refused to let that power get where it was needed. Similar issues foiled their large-scale UPS- they could only get the servers powered up by plugging them directly into battery backups.It was well into the morning on December 30th when they started scrambling to solve the problem. Folks were called back from vacation, electricians were called in and paid exorbitant overtime. It was an all-hands push to get the building wired up in such a way that it wouldn’t just shut down.It was a straight crunch all the way until New Year’s Eve, but when the clock hit midnight, nothing happened.
CodeSOD: Yet Another Master of Evil
As a general rule, if you find yourself writing an extension system for your application, stop and do something else. It's almost always in the case of YAGNI: you ain't gonna need it.George is a "highly paid consultant", and considers himself one of the "good ones": he delivers well tested, well documented, and clean code to his clients. His peer, Gracie on the other hand… is a more typical representative of the HPC class.George and Gracie found themselves with a problem: based on the contents of a configuration file, they needed to decide what code to execute. Now, you might be thinking that some kind of conditional statement or maybe some sort of object-oriented inheritance thing would do the job.There were five different code paths, and no one really expected to see those code paths change significantly. Gracie, who was identified as "the architect" on the responsibility matrix for the project, didn't want to write five different ways to do a similar task, so instead, she wrote one way to do all those tasks.Here's the YAML configuration file that her efforts produced:
Error'd: Variable Trust
Brian writes, "Of course server %1 is trustworthy, I couldn't do my work without it!"
CodeSOD: Untested Builds
Kaylee E made an "oops" and checked in a unit test with a bug in it which caused the test to fail. She didn't notice right away, and thus the commit hit their CI pipeline and was automatically pulled by the build server. She assumed that when she checked the logs she'd see the error, but she didn't. The build completed, and Tests (0/0) ran successfully.Now, Kaylee was new to the codebase, and since she'd been doing small changes, she'd simply written and run tests around explicitly the functionality she was testing. She hadn't yet done a full test run locally, so that was her next step. From there, it was easy to see why the build server didn't automatically run tests.
Best of…: Best of 2019: When Unique Isn't Unique
Best of…: Best of 2019: The Internship of Things
Best of…: Best Of 2019: The Hardware Virus
Error'd: Cthulhu Fhtagn to Continue
"I'm not sure if Barcelona Metro is asking for my ticket or a blood sacrifice," Paweł S. writes.
Best of…: Best of 2019: Temporal Obfuscation
Best of…: Classic WTF: The Glitch Who Stole Christmas
CodeSOD: Caga Tió
As we plow into the holiday season, it’s important to remember that each submission- each bit of bad code, each horror story, each personal confession- is its own little gift to us. And, when you write a bit of bad code, you can think of it as a gift for whoever follows you.Georgeanna recently opened a gift. She was wondering how their logging layer managed its configuration. She assumed that it would just read it from the config file, but when she tried to change where the logging file got written, say, to report.log, it would turn into report.log.staging.log.It wasn’t hard to figure out why:
...25262728293031323334...