Feed the-daily-wtf The Daily WTF

Favorite IconThe Daily WTF

Link http://thedailywtf.com/
Feed http://syndication.thedailywtf.com/TheDailyWtf
Updated 2024-11-22 08:16
Error'd: Google Translate is the Dog's Meow
"When a Brazilian teammate showed me a pet he was looking to adopt, I asked Google Translate for some help. It wasn't very helpful," Craig B. writes.
CodeSOD: The Date Wrapper
As we’ve harped upon many, many, many, many, many, many times: writing your own date functions is bad. Use the built-ins or a library or anything but your own awful string-mangling date code.But you can and should wrap the date handling stuff in your own functions as convenient. That’s just good programming.Krystian S inherited some code, which wraps date handling functions in its own abstractions, with method names like:
CodeSOD: Did You Null This?
If I were to catalog my biggest failings as a developer, it’s a carelessness around defensive programming. It’s tedious, and it takes work and forethought, and honestly, I just want to get the thing working and see the results. But I recognize it’s important, and work on developing that mindset.Today’s anonymous submitter found some Java code that is extremely defensive.
CodeSOD: To Repeat Yourself
Java’s history with web applications is, well, complicated. Java, heavily focused on being the True Object Oriented language, went the route of containers and service-providing classes and runtime bindings and dynamic hooks and lookups well before anyone else.The core layer which underpins a lot of the web interactions is the Servlet specification. Servlets are just classes which are wired up to handle HTTP requests. Do whatever you want there. Slap a bunch of annotations for JAX-RS on there, and it’s a restful web service. Drop a JSP file in there, a it runs as a servlet with a template. Start playing with Java Server Faces? It’s servlets all the way down.But what happens when you want to be even more Enterprise than Java normally is? What if you want a portal application with drop-in modules that can be configured from the front end? Portlets.Portlets are servlets for portals. It’s the Java flavor of SharePoint development. Build a CMS. Build an ERP. Build any giant enterprise product, and Portlets are there for you. They inherit huge piles of functionality important to hooking into the portal. They’re a giant mess.Which is why Jan G was working with a “legacy portlet”. No one ever wants to start a new portlet, so they’re all basically legacy from the minute they’re written. The previous developer didn’t really understand some of the key portlet methods or concepts.
CodeSOD: Now I Need an Injection
Frankie was handed a pile of PHP and told, "Move this to a new host." The process didn't go well- simply copying the code to the server chucked out a 500 error. So Frankie started digging into the code.Like a lot of PHP code, this code wasn't written. It happened. A long chain of revisions, emergency fixes, quick and dirty hacks, and "I dunno what I did, but that fixes it," meant that it was a twisty pile of spaghetti that wasn't drained properly and now is all sort of sticking together into a starch blob that only vaguely resembles the pasta it once was.While trying to unpick the mess, Frankie spotted this:
Error'd: Just Pick Something, Dummy!
Dave L. writes, "Spotted an option on Lenovo's 'Pick Your Laptop by Spec' that seems to be aimed, possibly, at the less than experienced laptop buyer."
CodeSOD: Translatováno
Let’s say you’re a native English speaker. Let’s say you’re writing a library which is going to be used by Czech speakers, like our submitter Jan Krynický. You’ve been told to make sure the code is usuable by them, so you decided to use C#’s annotations to provide Czech documentation of various fields.There’s just one problem: you don’t know Czech. You know enough to know that the Czech equivalent of “-ed”, as in “uploaded” is “-ováno”, so “uploadováno” seems perfectly reasonable to you. Czech documentation, done. It might not be the best choice, but they'll get the point.There’s just one problem:
CodeSOD: Tern Java Into Python
Thomas K was browsing around, trying to give folks some technical help. While doing that, he found a poor, belaguered soul who had been given a task: convert some Java code to Python.This was the code:
Wrecking the Curve
Most of our WTFs are produced on modern hardware, but today we're taking you back to the dawn of computing, back to the 1960s, when our submitter, Robert, was in college. Rob was taking a class in Numerical Analysis, which allowed people to submit their programs to the university computer (singular, as this was before computers were cheap enough to have a whole lab of 30+ of them just lying around for students). This involved using a keypunch machine to punch cards to run a FORTRAN program that might give you the answers to your homework. It was marginally faster than using a slide rule, until you factored in that students had low priority on the queue to submit their programs to be run, so they'd have to wait hours, if not days, to get access. Most students didn't even bother with the expensive machine, simply doing their maths the old-fashioned way and leaving it at that.Our submitter, however, was clever.You see, Rob had a part-time programming job in the evenings that made enough to pay for his schooling, something that was entirely possible in the 1960s though it may seem fantastical today. At this job, he had access to a much newer business computer: the IBM 1130, with a whopping memory capacity of 4,096 16-bit words. It was made for scientific purposes, but was also used by small businesses who were "sensitive to price concerns" (aka: frugal) and wanted a cheap machine that would run all their programs. Best of all, Rob had sole access to the machine all evening, meaning nobody would blink if he ran a quick program to do his homework in between batch jobs for the business.However, he was used to running business programs, not scientific or mathematical ones. One subroutine package the business used frequently allowed for easier currency manipulation, but it required a compiler directive called "*ONE WORD INTEGERS". This limited integers to one word, which was sufficient for currency manipulation. Leaving it out would cause a number of headaches for the subroutine package they used, which expected it to be turned on.I'm sure you can see where this is going: when Rob did his homework, he put the directive in place, making his answers a couple orders of magnitude less correct, as decimals were rounded far closer than they would've been using a slide rule. But just you wait, dear reader, for the real WTF is yet to come.The day came for the instructor to return the graded papers, and to Rob's surprise, there was much grumbling and disgust. It seems almost everyone had messed up their homework, receiving markdowns for having incorrect answers. Everyone, that is, except Rob. Rob's paper sported a shiny red A."I see most of you had incorrect answers this time around," remarked the teacher, scowling. "One of you was clever enough to turn in a FORTRAN program that solved the problems correctly. I used that to produce the rubric to grade the rest of you, so don't come crying to me about it being a grader error."Rob, being clever, decided to take his A and slink off in shame once he realized what had happened. Thankfully, the rest of the class never found out who had busted the curve—which was good for Rob's mental health and his kneecaps. [Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!
CodeSOD: Just a Bit Bad
Eyal N works on some code which relies on "bit matrices": 2D arrays of bits. Since they are working in C, in practice this means that they have one giant array of bytes and methods to handle getting and setting specific entries in the matrix.One day, Eyal sat down to do a remote pair-programming session with a co-worker. It started out alright, but the hours ticked by, the problem they were dealing with kept showing thornier and thornier edge cases, and instead of calling it a day, they worked late into the night.The next morning was full of regrets, both in terms of too little sleep and in terms of code artifacts. The code that they'd written over night was tangled, incoherent nonsense. It compiled, and it looked like the outputs were correct, but the actual process was as opaque as lead painted with Vantablack.Deep inside that pile of sewage-smeared spaghetti code, Eyal found that they had found a special approach to zeroing out a block of memory.Now, if you've ever worked in C, you know that creating and setting blocks of memory is easy- arguably too easy. If, for example, you want an array of bytes that's initialized to zero, you can do it with one step using the method calloc. If, for some reason, you want to do it in two steps, you can combine malloc with a memset call.Or, if you want to do it in many, many more steps, you can do this:
Error'd: You Must Agree!
"Apparently they don't want you to Strongly Agree with everything they say!" wrote David S.
CodeSOD: An Ugly Mutation
If there’s a hell for programmers, it probably involves C-style strings on some level. C’s approach to strings is rooted in arrays, and arrays are rooted in pointers, and now suddenly everything is memory manipulation, and incautious printf and memcpy commands cause buffer overruns. I'm oversimplifying and leaving out some of the better libraries that make this less painful, but the roots remain the same.Fortunately, most of the time, we’re not working with that sort of string representation. If you’re using a high-level language, like Java, you get all sorts of perks, like abstract string methods, no concerns about null termination, and immutability by default.In C, a string is just a pointer to a block of memory and you can do anything you like with it. In Java, a string is an object that can’t have its contents changed.Cid has a co-worker that comes from a C background, and constantly equates “references” in Java to “pointers” in C, which is largely accurate, but highlights certain misunderstandings in this case.Since, obviously, every non-primitive variable is holding an object reference, and it’s like pointers, and that means if you mutate the object in one place, it mutates everywhere. Much like a C-string, it’s just a pointer to memory and anybody can do anything.That means, when this developer writes getters and setters for string properties, they want to make sure that nobody’s ever sharing a reference. That means thousands of lines of code like this:
CodeSOD: String Up Your Replacement
Generating SQL statements is a necessary feature of many applications. String concatenation is the most obvious, and also the most wrong way to do this. Most APIs these days offer a way to construct SQL statements out of higher-level abstractions, whether we’re talking about .NET’s LINQ, or the QueryBuilder objects in many languages.But let’s say you’re doing string concatenation. This means you need to have lots of literals in your code. And literal values, as we know, are bad. So we need to avoid these magic values by storing them in variables.That, at least, seems to be the logic behind this code. Richard G just inherited this C# code from a senior engineer who left:
CodeSOD: Accidental Toast of the Town
Don't you just love it when some part of your app just suddenly and magically STOPS working all of a sudden?Our submitter David sure does (not). While working on his Android app, much to his surprise, he noticed that after one build, it wasn't displaying pop-up toast style notifications.He was positively stymied. It's not like this functionality is weird and custom with black magic UI coding behind it. No, this is something basic and ancient that one would normally expect to just work. However, upon checking the function behind the notifications below, the reason became immediately clear. At some point, David had accidentally pasted a URL in the middle of the function.
A Military Virus
The virus threats we worried about in the late 90s are quite different than the one we're worrying about in 2020, because someone looked at word processors and said, "You know what that needs? That needs a full fledged programming language I can embed in documents."Alex was a sailor for the US Navy, fresh out of boot, and working for the Defense Information School. The school taught sailors to be journalists, which meant really learning how to create press releases and other public affairs documents. The IT department was far from mature, and they had just deployed the latest version of Microsoft Word, which created the perfect breeding ground for macro viruses.Alex wasn't in the IT department- not yet- and was actually learning to be a journalist. At the end of classes one day, he saved a bunch of Word documents to a shared computer. The next day, he came in and found they were all destroyed- as were everyone else's.The chiefs in the school sent out stern warnings about viruses, and not running any unfamiliar executables. Lots of work was lost, but this was the late 90s: many of the documents got printed out for review anyway, so there were hard copies of much of the classwork. After a week, things were basically back to normal.And then the virus hit again.Cue another round of stern warnings, and NCOs chewing out anybody who even looked at the computers wrong, or thought about running an unauthorized executable. One Seaman got caught with a floppy containing WOLF3D.EXE, and while no one in the barracks knew exactly what happened to him, everyone agreed it must have been pretty dire.After the third time, Alex decided to offer his services. He wasn't an IT professional, but he was pretty technical. Maybe he could take a look?Chief Donaldson thought it over for a few moments. "Well, kid, it's already jacked up. You probably can't make it any worse. Take a look."Anti-virus protection was provided by Norton. It had been configured to use a whitelist to decide which files to scan. That whitelist didn't include *.doc files. Alex made that fix on his computer, and showed Chief Donaldson what he'd done.The IT department was notified, but had no interest in listening to some kid fresh out of boot camp. They'd been in the service for years, so there was no need for them to change their policies or procedures.Alex shared his knowledge with his peers. It quickly percolated out through the Navy barracks at the Defense Information School, and without the IT department doing anything, very quickly nearly all of the computers the Navy used were protected against macro viruses. The same couldn't be said about the other branches of military service, which each had their own barracks at the Defense Information School.Still, the virus activity was severely curtailed. For months, nobody thought about anything, and the IT department patted themselves on the back for making a really good show of stopping the virus. And then came the "field trip": the budding military journalists would go to another military base to participate in a war game, simulating a "real world" scenario which would let them hone their journalistic skills under fire.There was one problem. The only computers that had been configured to defend against macro viruses were the ones Alex and his peers had personally protected. Those were back at the Defense Information School Navy barracks. Here, they were using computers that were tagged for field deployments.This meant they were about 15 minutes into the wargame when a Word virus started forwarding itself through every newsroom computer on the simulated battlefield. Since this was a number of branches at the same time, it was an even more varied collection: some raced to delete files, others opened as many porn sites as they possibly could, and yet others simply played an animation claiming that they were formatting your hard drive (they weren't).You might think that makes this more of an IT education than a journalistic experience. Certainly, Alex eventually moved on to become an IT professional in the civilian sector. But there was a very valuable lesson on military journalism to be had, in the form of the after action report on the exercise. It managed to bury the entire IT disaster with a brief blurb: "Computer viruses and malfunctions were not part of the exercise parameters. These should be part of the plan for future exercises." [Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
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:
...21222324252627282930...