Feed the-daily-wtf The Daily WTF

Favorite IconThe Daily WTF

Link http://thedailywtf.com/
Feed http://syndication.thedailywtf.com/TheDailyWtf
Updated 2025-10-17 05:31
Error'd: Let's Dazzle Them with Errors!
"Hmmm...Somehow, I can't seem to remember the password for this particular AppleID," writes Thomas G.
CodeSOD: Deep VB
Thomas had an application which was timing out. The code which he sent us has nothing to do with why it was timing out, but it provides a nice illustration of why timeouts and other bugs are a common “feature” of the application.The codebase contains 9000+ line classes, functions with hundreds of lines, and no concept of separation of function. So, when someone needed to look at an account number and decide if that account needs special handling, this is what they did:
CodeSOD: GUID Enough, I Guess
Philemon Eichin has a depressing problem: his codebase is full of WTFs and git blame always returns his name. It's not his fault! Before he joined the team, "source control" was "a zip file named Project.Final.Real.Finished.CurrentRelease.zip.Periodically, he'll trawl through the codebase, tracking down ugly, bad code and fixing it, as a way to cut down on how many WTFs are attached to his name.For some reason, and Philemon isn't sure, he didn't fix these methods. He just slapped an Obsolete annotation on them, which explains what he should have done. Maybe he didn't want to fight with regressions, since there weren't any unit tests. Maybe he just liked the logging output. Regardless, this remains in his codebase:
Representative Line: hnjbbbbynbhhhhhhhhhhhh
Five years ago, someone at Adam’s company made a commit. Like all good commits, it touched 200 individual files and 3,500 lines of code, and the commit message was simply: “Fixed”.One of those 200 files was a .h header file, declaring a long pile of function prototypes. One of them is this one. It has no implementation, and isn’t used anywhere:
The Renegade Datacenter
The bank Edward worked for had a datacenter problem. Said datacenter resided in the basement of their headquarters. Over a twenty-year period, it had been expanded twice, and now covered the entire floor. There was simply no place left to go. The datacenter contained everything from state-of-the-art racks to $10 Ethernet hubs that no one had touched in a decade, and many of these mission-critical components were situated directly upon the floor. Every other week or so, some technician would trip on a cable and knock out a server or switch.While the bank had plans for a new headquarters and datacenter, construction had been postponed twice. The most optimistic estimate was that work would not begin for another 2 years. In the meantime, Edward and his IT team were tasked with figuring out how to squeeze more space out of the existing datacenter.The team's first move was to set up virtual Windows servers, so they could throw away some of the older computers cluttering the floor. Spreadsheets were compiled to track server names, business group owners, locations (ex. "DC room #2, third gray desktop on the floor from the left"), IPs, applications, and when virtualization would occur. Unsurprisingly, there were hiccups in tracking down owners, figuring out what applications ran on which machines, and whether those applications would work properly in a virtual environment. Overall, though, the virtualization push was successful, allowing much precious basement real estate to be reclaimed.But, wouldn't you know it? There was a problem with "DC room #2, third gray desktop on the floor from the left." It'd been successfully virtualized, and the application running in the virtual environment had not yet exhibited any problems. Just in case, the old server remained temporarily in the datacenter, with a "DECOMMISSIONED" sign taped to it. Everything seemed fine—until Edward received an IP collision alert on the beginning of the next month. Someone had fired up the old server, which began butting heads with its virtualized clone. It was easy enough to shut down "DC room #2, third gray desktop on the floor from the left." Less easy was figuring out who had turned it on. Over 100 people had unrestricted access to the datacenter. Server logs were of no help, either; whoever had logged in had used one of the general maintenance accounts that half the IT department knew the credentials for. Edward emailed everyone remotely related to that server, asking who might have turned it back on. To his complete lack of surprise, he received no reply.The beginning of the next month, there was another IP collision alert, along with several angry phone calls from users. Edward went down to the datacenter and found the server back on again. Someone had carefully un-taped the "DECOMMISSIONED" sign and moved it a few inches over to access the server's power switch.Edward appealed to his manager: there was no trouble with the virtual environment. Surely it was time to get rid of "DC room #2, third gray desktop on the floor from the left?" Alas, no. His manager explained that, due to how many departments relied on this server for reporting, they couldn't afford to get rid of it if there were ever an issue with the virtual environment. But he did allow Edward to do the next best thing: unplug the server and hide it behind a cardboard box full of power cables.The beginning of the next month, there was no IP collision. However, there was a frantic call from one of the 24/7 datacenter monitoring personnel, claiming that one of the servers had been stolen. When Edward and his manager inquired further, the details came out. This person had mapped a drive for one of his monthly reports to "DC room #2, third gray desktop on the floor from the left." Edward's cloning script had somehow missed this share. Whenever this person had to access his report, he would receive an error. Since datacenter hardware issues were common, he would think something had happened to the server, and would simply fire it back up. Once Edward had hidden the server, he'd reached the only logical conclusion."You saw the 'DECOMMISSIONED' sign," Edward pointed out. "Didn't that tell you anything?""Half the servers in the datacenter have had stuff like that on them for years!" he dismissed."What about all the emails we've sent out?" Edward asked."I don't read emails with too many recipients," he replied. "If anything really important happens, I'll get a call about it sooner or later anyway.""Why didn't you ever file a support ticket?"He wrinkled his nose. "You never know who'll pick it up! Some of the people who work here are idiots." [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Error'd: Luck of the Error
Drew W. writes, "I'm looking forward to the next month's episode, Localized/Consumer-Facing Title where the kids all learn about the pitfalls experienced when attempting to display localized strings. And it's the St. Patrick's Day episode."
Simple Class
Sometimes, you just know one of your coworkers isn't pulling his or her weight on the team. Sometimes it's the slacker co-worker, the one you always see browsing Facebook or getting coffee and never on pull requests or in architecture meetings. Sometimes it's the absent one, the one always seeming to be on sick leave or "working from home." And sometimes it's the guy who you wish would slack off just so you could stop reviewing his inane, poorly-executed code.Danny was one of the latter types. He worked at a Fortune 50 company on a team of four; he had, in theory, 14 years of professional experience working for many huge companies as a software architect. Not only were his communication skills non-existent, his code was never tested and rarely worked. And yet somehow, he kept missing lower and lower bars of competence as our submitter watched in horror.One of his tasks was to create a simple class that could hold the config for the new functionality. "That's simple," he said, before spending two whole days working on it. Our submitter came in the third day, grabbed some coffee, and began reviewing the PR Danny had submitted the evening prior. In order to hold a config like this:
CodeSOD: Dating for Three Months
Nathaniel P writes: “We have long agreed never to ask ‘why’ for any code in this project. We can only speculate, and therein lies madness.”There’s a lot to speculate about in this block. Like so much bad code, it touches upon that favorite source of bad code: date handling. And, at its core, this code is actually fine, but it still puzzles us:
CodeSOD: Request for Quote
Once upon a time, a client needed Initech to develop a custom tool for them. It would be mildly complex to develop, in terms of developer hours, and in respect of that, the client offered a budget of zero dollars. “But,” they added, “we are looking to do a major upgrade later this year.”The hint came through loud and clear. Since the development teams charged billable hours, the boss didn’t want to run the project through the usual channels. Besides, there were perfectly good internal development resources, who maintained the internal SharePoint site.So Terry and Terri, the two SharePoint developers, got their first client-facing project. If you haven’t done any SharePoint development, 90% of it isn’t development at all: it’s about dragging and dropping widgets onto the screen and configuring them correctly. The remaining 10% is a hellscape of absolutely forsaken APIs, infernal coding conventions, and gibbering madness.Terry and Terri did the boss’s off the books project, the results were handed off to the client, and nobody thought about it until two years later, when, after a rash of bugs and crashes cropped up, someone asked, “Hey, was this ever code reviewed?”Which is how this code ended up on Erica’s computer.The goal of this block of code is to sanitize a string. The string contains double quotes, which need to be removed. There also might be a space, in which case only the content before the space should be taken.Terry and Terri produced this:
Representative Line: Three's a Constant
Bryant E was debugging a hardware system with some embedded C code. Due to form factor considerations, there weren't a lot of physical inputs to this device, which meant what controls it had needed to be reused cleverly.For example, there was a pushbutton. Just pushing it performed one function. Press-and-hold did another. Double click and triple click did yet more functions.Or at least, they were supposed to. Skimming through the code, it looked correct. Bryant saw things like if (clickCount == THREE_CLICKS). Could it be any more clear?While trying to understand why the triple click wasn't working, that constant nagged at him. It's one thing to remove magic numbers, it's something completely different to define a constant explicitly named THREE_anything. When Bryant repeatedly tapped the button as quickly as he could, and saw the triple click event fire after far more than three clicks, he started to get a sense of what might be going on.This, as it turned out, was the constant definition:
Error'd: If Everything's on Sale, Nothing is
"When it comes to sending discount notifications, eBay knows that it often times just the thought that counts," Clayton D. wrote.
CodeSOD: Unique Subscription
Today’s anonymous submission starts with “I inherited an old wordpress site that uses an external corporate authentication server for logins.”As one might expect, the result is a hodgepodge of reinvented wheels and anti-patterns. Deep in the authentication code, there’s a method to add an email subscription. You might ask yourself, “What does adding an email subscription have to do with authentication?” and you’ve already put more thought into the design than the original developer.In any case, you want to assign each subscription a unique identifier. You’re not planning to use this as a key, you’ve just decided it’d be nice to have, I suppose. So what is the best way to generate a unique ID? Well, as a hint, the variable that holds the unique ID is called $guid, so obviously, we’re going to… do this:
Humble Origins
I've decided to bring my tenure as a Daily WTF contributor to an end. I've had a great time telling your tech tales of woe the past 6.5 years. I can't thank Alex, Remy, and Mark enough for giving me this opportunity and for being great to work with. In my final article, I'd like to actually tell my own WTF tale - my "origin story", if you will - about my first IT job.Way back in 2002, I was a fresh-faced 16 year-old kid with a driver's license and a car to pay for. That meant seeking employment anywhere I could get it. My first job at a sub sandwich shop lasted long enough to learn that I didn't want to deal with disgusting food/dishes every day. My next job at a "lackluster" video store taught me that I couldn't deal with customers, especially when they were upset about late fees. I decided to set my sights on something I actually had a knack for - working on computers.I managed to land a low-paying IT internship with the internal application development team at a plastics manufacturing company. They made the software the company used to do everything from track materials and orders to real-time monitoring of the molding machines. They were looking for someone young to do all the grunt work around the office and I was just the guy.The development team was full of a bunch of quirky, overgrown children with incredible potty mouths. When they weren't busy coding, they were slinging around some of the most vulgar insults I've heard. Usually that was followed by brutal physical assaults like nipple twisters or forceful punches in the ass. Then there were the rubber band fights that could break out at any time. I once came into the office and was immediately nailed in the eye by a double-knotted 4-inch long rubber band - by my boss. Instead of apologizing like a normal human, he and everyone laughed their asses off. It was all part of the playful, laid back environment they created and I loved it.There was actual work for me to do in between the hijinks and I learned many essential computer skills. A lot of what I did amounted to help desk work. I would assist users with their random computer problems that the others lacked the desire, and tact, to do. I learned about hardware by ripping apart towers and putting new components in as well as formatting hard drives and re-imaging them. I even learned how to start up a computer by touching a screwdriver on 2 pins on the mother board. That came in handy when I built my own Frankenstein home computer and didn't have a proper power switch.I soon got a reputation around the office as a PC problem-solver, so people started bringing in their virus-riddled home PCs to have me clean them up - on the clock. I would neglect to mention all the pornography I found on their computers, which was the most likely virus source. As an extra service, I was instructed by my supervisor to install some of the cracked PC games we had stored on an isolated server. For quality-assurance purposes, I was supposed play the first level/mission of the games to "make sure they worked".Eventually, the guys wanted to mold me into a computer programmer like they were. In the early days of .NET development, they threw a Beginning C# book at me and told me to read it and learn. I spent about six months going through the book and coding the sample projects, including a crappy command-based card game that I played when I was bored. Once I got towards the end of my book, I was assigned real development projects to do. At that point I realized that reading a book and regurgitating its code didn't mean I knew how to program yet.With the help of the more veteran developers, and a whole lot of banging my head on the wall, the major concepts of object-oriented programming actually sunk in. I started enjoying it and produced small useful applications used by the business. I'm sure my code was riddled with WTFs, but it worked. Around that time the US was in the midst of a recession that hit the manufacturing sector particularly hard. The 800 employee plastics company I worked at started to struggle, and was about to have its workforce cut in half.An initial wave of layoffs happened around the company and our development team wasn't able to escape it. The middle tier of the group was gutted and our team of 11 was cut to 7. As people were let go, HR would send emails saying "Please be advised that the following people are no longer with the company." Eventually the emails stopped, not because they were done firing people, but because it was too damn depressing to get all those emails.A second wave of cutbacks slashed many more jobs, but I still managed to weather the storm. After all, dumping a lowly-paid intern wasn't going to save the company. Our group was now down to a four person bare-bones staff - The manager/senior developer, another good developer, a lady who did design/documentation, and me. We didn't have nearly the staff to keep all of the programs running properly, let alone touch the mountain of fixes/enhancements they needed.As we struggled along as a skeleton crew, all the life had been sucked out of the office. We mostly kept to ourselves, didn't joke around much, and the rubber bands were no longer flying. Everyone that remained in the company feared that their days were numbered. It was a horrible situation that I've fortunately never had to endure since.One day in the late spring of 2003, I came in and sat down at my computer like I did every day. My boss told me not to bother logging in and to follow him to a conference room to meet with HR. I immediately knew what was happening and I was crushed. This was the job I wanted, and the only job I was good at. It was about to be taken away from me due to circumstances beyond my control. On my way out, he told me that he fought to keep me around and it obviously wasn't due to money, it was a head count situation. He also encouraged me to stay in touch and that when things improved, they would be happy to have me back.I wasn't overly optimistic, but I kept what he said in the back of my mind. In the meantime, I needed a new job. IT jobs that would hire a high school kid were few and far between, so I spent my whole summer delivering pizzas. That job was full of its own class of WTFs, and to this day is still the most stressful job I've had. On a good tipping day though, I actually made more doing that than I did computer programming.Around August, I heard back from my former supervisor. The layoffs had ended and the company was starting to turn itself around. They wanted to bring me back and I would even be making $2 an hour more than I was before. For someone about to enter his junior year of high school, that seemed like fat cash. So in the end, being laid off literally paid off in the end.I spent two more years working there, including switching to full-time after I graduated high school. The team stayed small, only bringing in two more new developers after the cutbacks. It was never close to the fun, highly unprofessional environment we had when I started. While I never got laid off again, I never got a raise again. I eventually left the company, and my programming days, behind for a better paying testing job at a software company. But I never forgot my humble origins that started what is now my 18 year career in IT. [Advertisement] ProGet can centralize your organization's software applications and components to provide uniform access to developers and servers. Check it out!
The 4000 Characters
Containers and cloud deployments are made for each other. Using say, a Docker configuration file, you can pass that off to a cloud host, and get an environment whipped up in a declarative fashion without having to worry about all the ugly details of exactly how that happens. With tools like Docker’s Compose, you can spin up many components all in one big, declarative YAML block.Or can you? Ricardo P was running into problems with deploying to the cloud. Specifically, when deploying to Azure, he got this error message: Linux Version is too long. It cannot be more than 4000 characters. That’s such an odd message, and when Ricardo started digging around, it wasn’t really easy to see what it was referring to when it was talking about “Linux Version”.But Ricardo wasn’t the only one with this problem, but the root cause is… surprising.The Azure configuration stores a Base–64 encoded version of the docker-compose.yml file in a field called linuxFxVersion. An “artifact” of their storage system caps the size of that data to 4,000 bytes. Why is that field name holding that data? It’s unclear, and certainly leads to unclear error messages.But there are other odd quirks. The Base–64 encoded version isn’t content aware- it encodes all of the text. Did you include comments in your compose file? Well, be ready, to count those against your filesize limit. Plus the Base–64 encoding makes the content even larger- folks would cut down their filesizes only to discover that they still blew out the upper limit.This is clearly a situation where an existing field was adapted to a new purpose, but isn’t actually fit for that purpose. An ugly hack that got out into the wild, and probably can’t be reined back in, because every change breaks someone’s workflow. So now it lives on: breaking deployments, unable to be deprecated, the fix tied up in internal teams that have higher priorities, and making sure that one single forum thread gets lots and lots of hits. [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
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:
...26272829303132333435...