Feed the-daily-wtf The Daily WTF

Favorite IconThe Daily WTF

Link http://thedailywtf.com/
Feed http://syndication.thedailywtf.com/TheDailyWtf
Updated 2024-07-03 12:02
CodeSOD: The Serial Killer
Debugging code on embedded devices introduces additional challenges to tracking down what's going wrong, especially as in many cases, you can't even rely on any sort of println debugging. I've worked with a few devices which my only debugging output is 3 RGB LEDs.Serial devices, then, can be a godsend. For short runs, you can often just wire pin-to-pin, but for longer connections, you need some sort of serial transceiver chip. In most practical situations, the flow between two devices is CPU->UART->transceiver->cable->transceiver->UART->CPU. Apologies to the OSI model, yes, it's more complicated than this, but for our purposes, it's a useful illustration.Stephen was debugging a board where the chip supported four UARTs, but the board had two different transceivers on it, each responsible for two different UARTs. What was supposed to happen was that when data arrived via the serial bus, an interrupt would fire and react to the message. None of that was happening.It wasn't hard to find the method responsible for setting up the interrupts:
Error'd: No Scandinavian Pets Allowed
"I guess this is the price I pay for giving my Golden Retriever a unique (and secure) name," writes Robert N.
CodeSOD: Conditionally Exceptional
The beauty of structured exception handling is that it removes explicit conditional logic from your code. The conditions are still there, of course: a catch statement is essentially saying "if the exception type is X, then do this". But the strict syntax gives the compiler some freedom, and if you're using a language like Java, which favors checked exceptions (where methods declare what kinds of exceptions they might throw), there are all sorts of shortcuts the compiler might take to keep that efficient.But hey, that's all implicit, and if there's one thing we've learned, "explicit is better than implicit". How can we make exception handling explicit? Well, our Anonymous submitter inherited some Java code which does just that.
What's The Floating Point?
There are a number of gotchas that trip up new programmers: the difference between declaring a variable and initializing it, the need for semicolons to terminate lines at times, and off-by-one errors, to name a few. All of us in the industry have met genius self-taught programmers who can put together extensive, well-architected applications in their sleep—but all of us have also met self-taught juniors who barely grasp the basics and think that's all they'll ever need. There's a reason degrees and formal training exist, after all.Today's story happened when Olaf was fresh out of university, working his first non-intern job as a "trainee programmer." The company aimed to improve government health care management: a noble goal, for those who have never had the dubious pleasure of interfacing with healthcare systems. However, it was founded by a doctor with just a smattering of PHP knowledge, all self-taught in his minimal spare time.Olaf came in with an eye to improving what was there using his knowledge of design patterns. PHP is a simple language to learn, but a hard one to master; much of the PHP software out there uses god objects and mingles code with layout, two big no-nos that are nevertheless taught in most online tutorials. Olaf began separating function from form, creating objects that could be reused to minimize the copy-pasting, and the like, happily bringing order to the chaos he'd been given.Which is how he found himself in the boss's office, on the wrong end of a dressing-down."The other programmers won't understand this!" the boss cried. "It's too complicated. Why are you changing it? It works, just leave it alone!"Disheartened, Olaf went back to work, checking out a clean copy of the master branch without his changes. Trying to ignore the bad practices, he began working on a bug in the accounting system, a bug marked "high priority" and "urgent" since it dealt with billing. Users would upload CSV files with information about what was spent, and the system would sum the values by category and create billing reports. However, there was a rounding error somewhere in the internals, leading to incorrect sums in a few important edge cases.Olaf had more training than his coworkers, but no training is exhaustive. He was able to quickly determine that this was a floating point mathematical error. Because decimals aren't represented exactly in binary, the math will be wrong in a few edge cases. He went looking for the right way to handle decimal values in PHP. However, unlike Node or C#, it's actually fairly difficult to include external libraries in PHP, as the language has no built-in support for package management. He was unable to figure out how to add a library that would do the math correctly. Since the software was only doing sums, he advocated for integer mathematics: read in the value, remove the decimal point (so that $10.50 would be represented as 1050), do the math, then add the decimal point back when displaying.One of the other junior devs loved the idea. The senior developer considered it—but the boss flat-out refused the suggestion. His take? "This isn't a floating-point error. This is because PHP is weakly typed, and it's trying to do summation as strings rather than numbers."(For those who are curious: PHP does not use the "+" operator to concatinate strings. It uses "." instead. "hello " . "world" results in "hello world".)The final solution the senior ended up implementing: separate the whole part from the fraction, so that our $10.50 charge becomes $10.00 and $0.50, then sum each portion separately.Olaf didn't wait around to see what would happen when they discovered that the bug still existed, since they were still treating the cents portion as a floating point number. He found a better job in a better language and never looked back. [Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.
CodeSOD: Posting the Check
Coming from the US, I have a pretty simplistic model of how postcodes work. They’re either 5 or 9 digits, depending on how precise you’re being. I can validate that with a simple regular expression. There’s a lot of detail encoded in that number, including the central sorting facility and city or town I’m in, but I don’t usually care about those details. In any country with some sort of postcode system, while the pattern of the postcode may change, the complexity of it generally caps out pretty quickly. That’s sort of the point.Maybe Sam’s co-worker didn’t know what regexes were. Maybe they’d read an article talking about how regexes were expensive, and were worried about performance. Maybe they wrote this method as part of a college assignment and added it to their personal snippet library and never thought about it again. Maybe they just hated their co-workers and were planting landmines for them to stumble across. Regardless, this is how they verified a postcode within their locale.
The Three-Month Itch
It was March 2016, and Ian was in need of a job. Fairly early into his search, he was lucky to find a tiny startup in need of someone with Python architecture and design skills. By "tiny," we mean that there were only three other developers working for Jack, the founder.Ian interviewed with Jack directly. After a technical test, he learned more about the company's pet project: a nearly-finished prototype of an iOS app. Once a user synced their phone with a wrist-worn heart rate monitor, the phone would play appropriate music for whatever the user was doing. It was primarily intended to help users reach a target heart rate while exercising. The app also used the phone's accelerometers to track the user's pace as they moved around, data that Jack claimed would be valuable for research into Parkinson's disease. He even had scientific papers from top universities to back up the claim. The prototype application, in its current state, wouldn't scale. Thus, Jack needed Ian to design a new backend system to store data and handle requests.Jack was friendly and personable, and his enthusiasm was contagious. Ian accepted on the spot, and started the next day. His office was cramped, but it was his. He got to work designing the requested backend.Two weeks passed. Then, early on a groggy Monday morning, Jack breathlessly pulled his dev team into a meeting room. The bright light beaming from his Powerpoint presentation drilled into everyone's retinas."I've been doing a lot of thinking," Jack prefaced. "We're a brand new startup. Nobody knows about us, right? We gotta do something to build up name recognition. So, here: we're gonna scrap the music part of the app, and focus solely on data collection."Ian stifled his instinctual What?! Not only were two weeks of work down the drain, but the data collection part of the app was an entirely optional feature at present.Jack flipped to a slide that showed the metrics he was now interested in tracking for each user. There were so many that the tiniest of fonts had been used to fit them all in. Ian squinted to read them."If you build a big enough haystack, a needle will appear!" Jack said. "We'll make the app free so it's a totally opt-in experience. The data we collect is the real prize."Investment capital was spent on posh downtown office space; for free app developers, only the very best would do. Jack also hired a second iOS developer, a data scientist, and an intern."But don't give the intern anything important to do," Jack told the full-timers.Once Ian settled into his new digs, he began architecting a new system that would somehow capture all the required data.Three months later, Jack threw it out. "No apps! We need a new direction!"Jack's new vision was a website where people would sit down and input what songs they listened to when sleeping, exercising, and performing other activities."People love to talk about themselves," Jack said. "They don't need to be paid to give us their data!"A frontend dev was hired to build the website. Soon after it went live, Jack bragged to investors that the website had hit 1 million unique visitors. In reality, the site had handled around 300 submissions, half of which had come from a single person.Three months later, guess what happened? Jack scrapped the faltering website in favor of a Slack bot that would respond to "Play ${song} by ${artist}" by looking it up on Spotify and providing a link. The Spotify widget would play a 30-second preview, or—if the user were logged in with a Spotify Premium account—play the whole song."That's it? How's that going to make any money?" By this point, the developers were no longer holding back their objections."We'll charge a subscription fee," Jack answered, undaunted."For a chat bot?" Ian challenged. "You already need Spotify Premium for this thing to fully work. If we want people to pay more money on top of that, we have to provide more features!""That's something we can figure out later," Jack said.Jack had the intern develop the company's new flagship product, going against the wishes of Jack from six months earlier. The intern gave it his best shot, but soon had to return to school; the unfinished code was unceremoniously tossed into the frontend developer's lap. With help from one of the iOS developers, he finished it off. And what was Ian up to? Setting up monitoring dashboards and logging at Jack's insistence that they'd attract enough users to justify it.Three more months passed. A number of "features" were added, such as the bot nagging users in the Slack channel to use it. As this behavior violated the Slack TOS, they were prevented from putting their app in the app store; Jack had to hand out links to a manual install to interested parties. The product was first given to 50 "super-friendly" companies Jack knew personally, of which only a handful installed it and even fewer kept using it after the first day. Jack then extended his offering to 300 "friendly" companies, with similar results.Ian's breaking point came when Jack insisted he pull overtime, even though there was no way he could help the other developers with their tasks. Nevertheless, Jack insisted Ian stay late with them to "show solidarity." Finally at his wit's end, Ian put in his two weeks. His final day coincided with the general release of the Slack bot, during which he watched a lot of very flat lines on dashboards. When he left the posh office for the last time, the startup still had yet to earn its first cent.Fortunately, Jack had a plan. After Ian left, he scrapped everything to start on fresh on a new product. No, it wouldn't make any money, but they needed name recognition first. [Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.
Error'd: Nobody is Perfect
"Google notified me that it needs help from a human and then displayed me this image," Jeff K. wrote, "I think I may need some help too."
CodeSOD: Getting to YES
“We’re a dynamic, multi-paradigm organization, and we do most of our new development in a blend of Ruby and Go. We’re not the kind of company that is dogmatic about tools though, we just want to deliver the best product for our customers.”That’s what Delphia was told in the interview. She didn’t quite grasp why they were mixing those two techs in the first place, but the interview went well, and she took the job. It was then that she discovered that everything she’d been told was technically true.The company had just finished a sprint where they tried to pivot and reimplement their 15 year old codebase in Rails and Go. At the same time. It was difficult to tell from the code if this were a case where they did both together, or they were parallel projects, or frankly, if there was any coordination between either of them. That was their new development.The company didn’t do much new development, though. The core of the company’s business was a 7,500 line PHP file which contained a single form. It depends on includes from dozens of other files, some of which depend on functions defined in the main PHP file, and thus can’t be used in any other context but that include. It’s less spaghetti code or even a big ball of mud, and more a career killing meteorite.But it makes more money for the company in a day than Delphia can rightly count.One function that Delphia kept seeing invoked a bunch was yesorno. It was used almost everywhere, but she had never seen the definition. So, curious, she went digging. And digging. And digging. Someplace around the fifteenth or thirtieth include file she read through, she found it.
A Backup Pipeline
“Um… can you come take a look at something for me?”Pat looked up from happily hacking away at some new features to see Milton hovering at the edge of the cubicle.“I think I messed up,” Milton added.One of their company’s main internal systems was a data processing pipeline. “Pipeline” might be a bit generous, as in practice, it was actually a webwork of shell scripts and Python that pulled data in from files, did “stuff” to that data, and dropped the results into other files, which could then be read in by different scripts. In actual use, this usually meant people grabbed the latest version of the scripts from source control, modified and tweaked how they executed to answer one specific data-related question, and if that particular process seemed like it might have value, they’d clean the code up a bit and then try and merge it back up into source control. Otherwise, if they didn’t think they’d need it again, they’d just reset back to HEAD.Some folks, though, like Milton, mostly kept their own copy of all the scripts. Or in Milton’s case, multiple copies. Milton knew the data processing pipeline better than anyone, but the vast majority of that knowledge was locked up in his personal scripting library.“I was thinking I should probably try and contribute changes back upstream,” Milton said. “So, like, I’ve got a script that’s called by a script, which is called by a script, and it depends on having a bunch of shell variables created, like $SETUP_DIR.”Pat nodded along.“So I wanted to refactor that into an argument, so other people could use it. And I did… but I forgot to change the calling scripts to pass the argument before I tried to test it.”Specifically, Milton’s script had a line like this:
CodeSOD: A Knotted String
Rita caught a weird bug. It was weird, in part, because there hadn’t been any code changes in their label printing application for ages. Yet, there was a sudden new bug. Labels were printing with what was obviously unicode garbage. Interestingly, the application definitely supported unicode- there had been a huge effort a few years back to move the C++ code from chars to wchars.Rita started debugging, and confirmed that when the label text was populated, memory stored correct values. By the time the data was printed, it no longer did. Obviously, there was something wrong with memory management- something was touching the end of the string and throwing off the output. That was an easy enough bug to make in C++, but tracing through 7,000 lines of label printing code to figure out where things got thrown off was more of a chore, especially with the… “friendly” variable naming convention the original developer had used.
CodeSOD: The Double Bind Printer
Printer jams are an unavoidable circumstance. Paper might not seem sticky, but static electricity and humidity can to horrible things, and all the protections in the world can't stop them. Printers are also objectively terrible, and always have been.Years ago, when Coyne T was a fresh-faced youth, he supported an aging COBOL-based warehouse system. Their reports went to a noisy continuous feed line printer. The printer was a finicky beast, and no matter what sacrifices were made before printing, it had a tendency to devour pages, or have the gears slip and misprint lines. Because the report data came straight from a COBOL job, there was no cached output to reprint- the entire reporting process would need to be re-run every time the printer got angry.About thirty pages of a report got chewed up a few days after Coyne joined the team. As the new kid, re-running the report fell to him. "But, before you go and re-run the report," the team lead, Herschel, said, "there's a few things you should know."Herschel laid out the key facts. The report generating program didn't just generate the report. It also could clear the monthly totals and update the day's inventory as part of running the report. Doing either of those in the middle of the day was absolutely wrong, and would create a lot of manual work to fix it. Even worse, doing both of those during the same run would stomp all over the data files and absolutely corrupt the entire mainframe."Fortunately, I added two flags- CLEAR-SWITCH and UPDATE-SWITCH. Just make sure they're both set to 'N', and you should be fine."Coyne checked and double checked the instructions, ensured that the flags were definitely set to 'N', and then ran the report.After the mainframe team had restored from backup and recovered as much of the data that they could (losing only the past three days worth of inventory), Coyne was called out on the carpet to explain how he'd destroyed the database. Despite being a newbie, Coyne had been cautious from the start, and reviewed the instructions which Herschel had given him, as well as how he'd verified that he'd followed the instructions. But Coyne had also gone the extra step, to look up the code block which checked those flags. He came to the meeting prepared.
Error'd: Quite Powerful Errors Indeed
"I was considering this recorder for my son, but I think 120W might be a bit over the top," writes Peter B.
CodeSOD: A Policy Exception
“So, we have a problem. A… a big one.”Andrea C worked for an insurance company. In terms of software development, a “problem” meant she’d misfiled one of her TPS coversheets or something like that. A big problem meant she’d accidentally checked in code that contained a comment with some profanity in it.“It’s actually, well, it’s actually huge,” her boss continued.She’d never had a “huge” problem before.Someone had discovered that, if they knew a customer’s policy number and were currently logged in- they could see that customer’s policy. It didn’t have to be their policy. Any policy, so long as they had a valid login and the policy number.That was pretty huge. Andrea hadn’t gotten too deep into that section of the application before, but the original developer had moved on, so it was time for her to dig in. She pulled up the JSP code which served the page.
CodeSOD: Double Up
Carl works in research, and like most research organizations, half their code is carelessly glued together GUI tools, command line interfaces, and shell scripts. The other half, the half which does the real work, is Fortran. Sure, the code was written forty years ago, but the laws of physics haven’t changed, so it’s still good and it’s still fast.Carl usually doesn’t have to touch the Fortran half. Instead, he usually looks at the other bit. Most things are run from shell scripts, and most of the work of the shell scripts is getting environment variables configured so that they Fotran code can actually run its model without having a heart attack.So, for example, one of those environment variables is WORKINGDIR. WORKINGDIR holds a /very/long/path/to/a/deeply/nested/folder/someplace The Fortran model code also needs to know the location of the SYSDIR, which is always exactly two levels up from WORKINGDIR. No, the Fortran code can’t figure this out on its own, it’s too busy doing calculus. The shell script needs to figure it out.The shell script which calculates it throws in a little wrinkle though: # calculate dir 2 levels up (Program doesn't allow .. in pathnames). So, no $WORKINGDIR/../.. here.There are a number of ways one could solve this problem. The wrong way to solve this problem is this ksh script…
Set the Flux Capacitor for 12/30/1899
I mentally think of the early 2000s as "the XML Age". XML was everywhere. Everyone wanted to put XML into their applications. Java was the XML king, using XML for everything. People were starting to ask themselves, "do we need the big expensive RDBMS, when we can just use XML instead?"In other words, just like JSON today, but worse. Tomislav A inherited one such database- a clunky pile of XML documents with only the vaguest hint of a schema to them, and a mix of valuable, useful data, and a mountain of crap. With the assumption that all data validation was happening in the application layer, the database was mostly "garbage in, garbage sits there forever and can never be deleted because it might be important".Tomislav's job was to filter out the garbage, find the actually useful information, and move it into a real datastore. There were loads of problems and inconsistencies in the data, but with a little Python in his toolkit, Tomislav could mostly handle those.For example, dates. Dates were stored in the XML as just text strings, because why would you use a structured document format to represent structured data? Since they were just strings, and since there was no data validation/sanitization in the application layer, there was no system to the strings. "31-DEC-2002" sat next to "12/31/2002" and "31/12/2002". With some help from dateutil.parser, Tomislav could handle most of those glitches without difficulty.Until, when importing a date, he got the error: ValueError: year 39002 is out of range.One of the dates in the document was just that- 39002. Knowing that there was no validation, Tomislav was ready to dismiss it as just corrupt data, but not before taking a stab at it. Was it the number of days, or maybe weeks since the Unix Epoch?
CodeSOD: Collect Your Garbage Test
Alex L works for a company with a bunch of data warehousing tools. One of the primary drivers for new features is adding bits which make the sales demos shinier, or in marketing speak, "delivers a value add for a prospective customer".One of those "shinies" was a lightweight server which would gather stats from the data warehousing engine and provide a dashboard with those stats, and notifications about them. Prospective customers really love it when the machine goes "bing" and shows them an interesting notification.As the notifications were becoming a bigger feature, the system needed a way to remember notification configuration between sessions, and that meant there needed to be a better persistence layer.To add the feature, Alex started by looking at the existing tests for the notification system.
Error'd: Please Select All Errors that Apply
"It doesn't impact me, but just wondering...which one would I pick if my spouse was named Elisabeth?" wrote Jon T.
CodeSOD: A Date with a Consultant
Management went out and hired a Highly Paid Consultant to build some custom extensions for Service Now, a SaaS tool for IT operations management. HPC did their work, turned over the product, and vanished the instant the last check cleared. Matt was the blessed developer who was tasked with dealing with any bugs or feature requests.Everything was fine for a few days, until the thirthieth of January. One of the end users attempted to set the “Due Date” for a hardware order to 03-FEB–2019. This failed, because "Start date cannot be in the past".Now, at the time of this writing, Feburary 3rd, 2019 is not yet in the past, so Matt dug in to investigate.
Temporal Obfuscation
We've all been inflicted with completely overdesigned overly generalized systems created by architects managers who didn't know how to scope things, or when to stop.We've all encountered premature optimization, and the subtle horrors that can spawn therefrom.For that matter, we've all inherited code that was written by individuals cow-orkers who didn't understand that this is not good variable naming policy.Jay's boss was a self-taught programmer from way back in the day and learned early on to write code that would conserve both memory and CPU compilation cycles for underpowered computers.He was assigned to work on such a program written by his boss. It quickly became apparent that when it came to variable names, let's just say that his boss was one of those people who believed that usefully descriptive variable names took so much longer to compile that he preemptively chose not to use them, or comments, in order to expedite compiling. Further, he made everything global to save the cost of pushing/popping variables to/from the stack. He even had a convention for naming his variables. Integers were named I1, I2, I3..., strings were named S1, S2, S3..., booleans were named F1, F2, F3...Thus, his programs were filled with intuitively self-explanatory statements like I23 = J4 + K17. Jay studied the program files for some time and had absolutely no clue as to what it was supposed to do, let alone how.He decided that the only sane thing that could be done was to figure out what each of those variables represented and rename it to something appropriate. For example, he figured out that S4 was customer name, and then went through the program and replaced every instance of S4 with customer_name. Rinse and repeat for every variable declaration. He spent countless hours at this and thought that he was finally making sense of the program, when he came to a line that, after variable renaming, now said: account_balance = account_balance - zip_code.Clearly, that seemed wrong. Okay, he must have made a mistake somewhere, so he went back and checked what made him think that those variables were account balance and zip code. Unfortunately, that's exactly what they represented... at the top of the program.To his chagrin, Jay soon realized that his boss, to save memory, had re-used variables for totally different purposes at different places in the program. The variable that contained zip code at the top contained item cost further down, and account balance elsewhere. The meaning of each variable changed not only by code location and context, but also temporally throughout the execution of the program.It was at this point that Jay began his nervous breakdown. [Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
A Mean Game of Pong
Mark J spent some time as a contractor in the Supply & Inventory division of a Big Government Agency. He helped with the coding efforts on an antiquated requisition system, although as he would come to find, his offers to help went unappreciated.
CodeSOD: Sort Sort Sort Your Map, Functionally Down the Stream
A while back, we saw "Frenk"'s approach to making an unreadable pile of lambda-based Java code. Antonio has some more code, which didn't come from Frenk, but possibly from one of Frenk's disciples, who we'll call "Grenk".Imagine you have a list of users. You want to display those users in order by "lastname, firstname". Your usernames happen to be in the form "firstname.lastname". You also have actual "firstname" and "lastname" fields in your dataset, but ignore those for the moment, because for whatever reason, they never made it to this block of code.There are a lot of relatively straightforward ways you can solve this problem. Especially, as there is already a TreeMap implementation in Java, which accepts a comparator and ensures the keys are sorted. That wouldn't let Grenk show off the cool new things they learned to do with streams and lambdas. There's a (relatively) new toy in the Java language, and gosh darn it, it needs to be used.
Error'd: The Results are (Almost) In!
"Oh man! This results of this McDonalds vote look like they're going to be pretty close...or miles apart...," Pascal writes.
CodeSOD: Giving 104%
Dates, as we have explored exhaustively, are hard. And yet, no matter how much we explore dates, and the myriad ways developers can completely screw them up, there are constantly new borders of date-related idiocy ahead of us.The app Michael supported was running on a server running an Ubuntu version that was more than a little ancient, so as a test, he upgraded to the latest LTS version. That also included upgrades to the MySQL version they were running.And right after doing the upgrade, errors like this started to appear: ERROR 1292 (22007): Incorrect datetime value: '2019-07-23 24:59:59' for column 'update_endDate'Well, obviously, 24:59:59 is not a valid datetime value. Obviously, someone rolled a custom date-handling function, and something in the upgrade revealed an off-by-one error. Off-by-one bugs (or “OBOB” as one professor I had liked to call them) are common and easy.Michael’s guess was technically correct. There was an off-by-one error, only it wasn’t in the code. It was in the original developer’s brain:
CodeSOD: Internal Validation
If you’re doing anything financial in Brazil, you have to manage “CNPJ” numbers. These numbers are unique identifiers for every business and every branch of that business, along with a pair of check-digits to validate that it’s a correct code. Everyone from banks to accountants to businesses needs to track and manage these.When Patria joined a microscopic startup as an intern. The startup made an accounting package, and thus needed to track CNPJs. She asked the lead developer, “Hey, how do I validate those check-digits?”“Actually, as an intern, that’s probably a really good beginner task for you.”They were a very new startup, so it wasn’t a surprise that the current validation routine was simply return True. Patria, with no industry experience, had her task, and ran off to solve the problem.“Could you review my code before I merge?” she asked the lead dev.“Nah, just go ahead and merge, I’m sure it’s fine.”This is what Patria merged.
CodeSOD: Why Is This Here?
Oma was tracking down a bug where the application complained about the wrong parameters being passed to an API. As she traced through the Java code, she spotted a construct like this:
Relative Versioning
Today's submission comes from someone going by Albert Einstein. Before we look at what they sent us, let's talk a little bit about version numbers.Version numbers, if you think about it, are a deeply weird construct, and they're trying to balance a lot of difficult goals. At its simplest, a version number is meant to order your releases. Version 2 comes after version 1. Version 3 comes next. But even this simple goal is surprisingly difficult, because your releases only exist in order if you only have one chain of history for your product. The instant you have to have a custom build for one customer, or you start doing AB testing, or your library has to provide multiple interfaces for different deployment conditions, or one developer down in the basement decides to fork and not tell anyone- releases cease to have a linear order.Well, those kinds of disordered changes and branching versions sounds like a directed acyclic graph, which not only sounds extremely clever, but is how Git manages your history. We could theoretically just tag our releases with the commit hash, giving us a unique version number that allows us to quickly and cleanly know what version of the code we're talking about. But commit hashes are opaque and meaningless- which brings us to the other goal of version numbers.Version numbers not only order our releases, they also are meant to convey information about the content and delta between those releases. Semantic versioning, for example, tries to guarantee that we can make certain assumptions about the difference between version 1.0.1, 1.0.5, 1.1.2, and 2.1.1. Changes to the last digit imply that it's only patches and bugfixes, and shouldn't change behavior. That can get you pretty far, assuming you don't bump into one of those cases where "every change breaks somebody's workflow". Even then, though, incrementing the major version number means there might be breaking changes, but doesn't require that there are, which is why Angular is on version 247 but hasn't seen much by way of breaking changes since version 4.And that's another thing version numbers need to accomplish: they're a marketing/communication tool to educate your public about your product. Anyone who can count can understand that higher version numbers must be newer, and thus be the preferred version. People watch those version numbers tick up, and it gives them a sense that active development is ongoing.With all of these goals, I don't think there is a single way to solve the version numbering problem. Maybe you use semantic versioning. Maybe you go the Chrome route and just increment the major version every Tuesday. Maybe you go the Microsoft route and have piles of hot patches and fixes with no clear order or relationship to their application.What you probably don't want to do is go the route which Albert Einstein's company has gone. What follows is a full listing of every version, in chronological order of release, for a single product. Each entry on this list represents a single release.
Error'd: An Internet of Crap
"One can only assume the CEO of Fecebook is named Mark Zuckerturd," writes Eric G..
CodeSOD: The Pair of All Sums
Learning about data structures- when to use them, how to use them, and why- is a make-or-break moment for a lot of programmers. Some programmers master this. Some just get as far as hash maps and call it a day, and some… get inventive.Let’s say, for example, that you’re Jim J’s coworker. You have an object called a Closing. A Closing links two Entrys. This link is directed, so entry 1->2 is one Closing, while 2->1 is another. In real-world practice, though, two Closings that are linked together in both directions should generally be interacted with as pairs. So, 1->2 and 2->1 may not be the same object, but they’re clearly related.Jim’s coworker wanted to gather all the pairs were together, and put them into groups, so 1->2 and 2->1 are one group, while 3->1 and 1->3 are another. This was their approach.
CodeSOD: Ternt Up GUID
UUIDs and GUIDs aren’t as hard as dates, but boy, do they get hard, don’t they. Just look at how many times they come up. It’s hard to generate a value that’s guaranteed to be unique. And there’s a lot of ways to do it- depending on your needs, there are some UUIDs that can be sorted sequentially, some which can be fully random, some which rely on hash algorithms, and so on.Of course, that means, for example, your UUIDs aren’t sequential. Even with time-based, they’re not in sequence. They’re just sortable.Pitming S had a co-worker which wanted them to be sequential.
CodeSOD: Switch the Dropdown
Bogdan Olteanu picked up a simple-sounding bug. There was a drop-down list in the application which was missing a few entries. Since this section of the app wasn't data-driven, that meant someone messed up when hard-coding the entries into the dropdown.Bogdan was correct. Someone messed up, alright.
Crushing Performance
Many years ago, Sebastian worked for a company which sold self-assembled workstations and servers. One of the company's top clients ordered a server as a replacement for their ancient IBM PS/2 Model 70. The new machine ran Windows NT Server 4.0 and boasted an IPC RAID controller, along with other period-appropriate bells and whistles. Sebastian took a trip out to the client site and installed the new server in the requested place: a table in front of the receptionist's desk, accessible by anyone walking through the main entrance. Not the best location from a security standpoint, but one of the new server's primary tasks in life would be to serve the company's telephone directory, installed on CD-ROM.Two weeks later, the client called back, irate over the fact that the new server performed terribly compared to their old one. Troubleshooting efforts via phone were ineffective; the client demanded on-site support. After several frantic conference calls involving Sales, Support, and nosebleed-level management, Sebastian was on a plane back to the client site.Once back within the client's stuffy lobby, he could see that the server setup had in fact changed since he'd last been there, despite the client's repeated insistence to the contrary. Someone had placed both the old and new server boxes under the table. Two CRT monitors sat side-by-side on the table along with their corresponding mice. The keyboards were on a roll-out drawer just under the surface. Both machines were already logged in as administrator, waiting for anyone to come along and not exploit that fact.After checking in with his on-site contact and securing a cup of coffee, Sebastian got to troubleshooting. First thing, he used the mouse to open the Start menu on the new server—but as soon as he released the mouse button, the Start menu collapsed. He tried a few more times with no success.Frowning, Sebastian rolled out the keyboard drawer, hoping to try a keyboard shortcut next. When he did so, he found the keyboards set up one in front of the other. The strain relief on the back of the old server's keyboard was sitting right on top of the space bar of the new server's keyboard. Apparently, it'd been holding down the space bar for the past two weeks straight.Sebastian pulled the old server keyboard onto the table. Sure enough, the new server behaved normally from then on. Thousands of dollars spent, hundreds of miles flown—all to lift one keyboard away from another. [Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.
Announcements: TheDailyWtf.com Server Migration Complete
If you're reading this message, then it means that I managed to successfully migrate TheDailyWTf.com and the related settings from our old server (74.50.110.120) to the new server (162.252.83.113).Shameless plug: I did all of this by setting up a configuration role in our internally-hosted Otter instance for both old and new servers (to make sure configuration was identical), deploying the last successful build to the new server using our internally-hosted BuildMaster instance, and then manually installing the certificate and configuring the database. Here's what the OtterScript looks like for the server's configuration. I'd love to move this to a publically-hosted instance, soon!
Error'd: Next Stop...Errortown
"Rather than tell me when the next train is supposed to arrive, this electronic sign is helpfully informing me that something's IP address is...disabled?" Ashley A. writes.
CodeSOD: Certifiable Success
“Hey, apparently, the SSL cert on our web-service expired… in 2013.”Laura’s company had a web-service that provided most of their business logic, and managed a suite of clients for interacting with that service. Those clients definitely used SSL to make calls to that web-service. And Laura knew that there were a bunch of calls to ValidateServerCertificate as part of the handshaking process, so they were definitely validating it, right?
Representative Line: It Only Crashes When It Works
We already know that Kara’s office has a problem with strings. Kara’s back again, with more string related troubles.These troubles are a bit worse, once we add in some history. You see, some of their software does machine control. That is to say, it sends commands to some bit of machinery, which then moves or extrudes or does whatever the machine does. Kara wasn’t specific, only granted that this machine was neither large enough or mean enough to kill someone. Minor cuts, burns, scrapes, bruises and damage to the equipment itself is still possible, but nobody will die.Once upon a time, the bulk of this code was written in C. Then someone wanted a better UI. So that C code got replaced by the perfectly natural solution of… Visual Basic. There’s still some C in there somewhere, hidden behind interops and marshalled calls to native code, but most of the GUI and logic is pure VB.Net. Which brings us to our representative line.
CSS (Under)Performance
Ah, WordPress. If you hadn't heard of it by reputation, it sounds pretty good: one platform where you can build a blog, an e-commerce site, an app, or some combination of all of the above. Their site is slick, and their marketing copy sounds impressive: "Beautiful designs, powerful features, and the freedom to build anything you want. WordPress is both free and priceless at the same time." With WordPress, the hype insists, anyone can build a website without having to know anything about coding. Just pick a template, add free modules, and it'll look great without any effort.If you've worked anywhere remotely connected to web design, you've heard of WordPress, and likely by reputation. The engine has maintained backwards compatibility since day one, which means it's the usual spaghetti system of duct tape and prayers you get when you prioritize backwards compatibility over systems engineering. It was more of a success than the designers intended, having been built solely as a (pretty decent) blogging platform at first, so the more use cases it expands to cover, the worse the learning curve becomes. Many web designers refuse to touch the system at all, preferring to roll something by hand that they understand than to untangle the snarl of "free" modules their clients installed when something goes wrong.Two days before launch, Lukas was nearly done with a contract job: a custom marketing site with a contact form, exactly the kind of thing Wordpress has for Use Case #2. Testing the site before handing it over, he noticed one page loading slowly. VERY slowly. Like, 60 seconds slowly.It seemed odd that a page with only static resources could even be that slow, so he ran a profile on the page:For those of you who don't speak browser profile, that's the CSS engine that's stalling out for a whole minute. Usually, unless you're doing awful things in your CSS or have megabytes worth of it to render, the CSS engine is very fast; the usual culprit in Wordpress is client-side Javascript. But the CSS looked perfectly fine—messy and WordPressy, but fine, once it was all compiled.Searching for answers, Lukas compared the markup on the page to the CSS stylesheet, trying to deduce what it was doing. A fancy heading here, a custom font there ... everything looked normal until he got to the top of the footer area, where he found the totally normal and not at all strange sequence of 131,074 empty paragraph tags.Did I mention WordPress is built in PHP?Some rogue bit of PHP code had gone into a horrible loop, dumping out empty paragraph tags 131,074 times right before the footer element. Pages upon pages of <p> with nary a </p> in sight. Paragraph tags default to display:block, meaning every time the engine gets to one, it causes the browser to execute layout, paint, and composite operations on the rest of the page—including the up to 131,073 other paragraph tags it may have already encountered. And this gnarly bit of nothing began after 1,482 lines of useful HTML, so it wasn't as if the page were tiny to begin with.It gets better: this was all just before the custom footer, which can have inline CSS in WordPress, as it's a quick way to tweak a theme without having to create what's called a "child theme." The client had some inline CSS in place, and yes, it applied to the paragraph tag. It set padding-bottom: 0px !important;, forcing the CSS engine to re-render the entire set of paragraph tags once more.And that's why no matter how good platforms become, no matter how rich the plugin ecosystem, there will always be work for web devs. [Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!
CodeSOD: Without Compare
Operator overloading is a messy prospect. In theory, it means that you can naturally extend a language so that you can operate on objects naturally. An introductory CS class might have students implement a Ratio or Fraction class, then overload arithmetic operators so you can (a + b).reduce().In practice, it means you use the bitshift operator also as the stream insertion operator. Thanks C++.Java decided to chuck the baby out with the bathwater, and simply didn't allow operator overloading, but this introduced its own challenges. How do I tell if one instance of MyObject type is greater than another instance? That's important if I want to sort these objects, for example.Thus, Java has the Comparator interface. Implement Comparator<MyObject> and now you can compare two instances of that object. The comparator object can be passed to all sorts of built-in methods for sorting, filtering, etc. At least, that's the theory.An anonymous submitter found this unique approach to that problem.
Error'd: All Aboard the System Bus
"The classic 'If transportation had evolved at the same pace as computers...' comparison is no longer merely academic as this TTC streetcar proudly displays it's nearing 32K RAM," Carlos writes.
CodeSOD: Is Num? I'm Numb
"The hurrider I go, the behinder I get," is one of the phrases I like to trot out any time a project schedule slips and a PHB or PM decides the solution is either crunch or throwing more bodies at the project.Karl had one of those bosses, and ended up in the deep end of crunch. Of course, when that happens, mistakes happen, and everything gets further behind, or you're left with a mountain of technical debt because you forgot that Integer.TryParse was a function in C#.Which is what happened to Karl. And that's why Karl wrote… this.
Representative Line: Innumerable Enum
Ah, the enumerated type. At its core, it's really just a compile-time check to ensure that this constant containing 1 isn't getting confused with this other constant, also containing 1.We usually ignore the actual numbers in our enums, though not always. Perhaps, though, we should just pay more attention to them in general, that way we don't end up with code like Andrew found.
Best of…: 2018: Another Bitmask Fail
Best of…: 2018: The Wizard Algorithm
Error'd: A Sour Currency Mix
"Lime bikes are finally in my city! Let's pay for it...So if my USD balance goes below GBP 0 it'll top up with ...AUD?" Ben writes.
Best of…: 2018: Shiny Side Up
Best of…: 2018: JavaScript Centipede
A Lumpy Christmas
Every "enterprise" shop has that one system you hope you never need to touch. It's older than you are, "documentation" consists of whispers and rumors about its behavior, and it is absolutely 100% business critical. If it goes down, the business goes down.Fortunately, you'll never have to touch that system, because there's an Ancient Wizard who has been sitting in the same cube since 1973, and knows its secrets. As long as the Wizard is around, you'll never touch it. Of course, if the system goes down when the Wizard is out of the office… well, fixing that would require a Christmas miracle.Renee was a programmer-elf in Santa's Workshop. It was a huge organization with many layers of middle-elfagent, so 90% of her job was sitting in pointless meetings with no agenda. In the remaining 10%, she occasionally added features to their in-house legal invoice processing software. Since nearly every present they shipped was an elf-produced knockoff of a large company's trademarks, legal billing was one of the Workshop's largest line items.There were other important IT systems. Supply chain was massive. All raw materials, aside from the naturally-occurring candy canes, had to be imported. Whether it was fabric for producing dolls, or ABS plastic and injection molds for producing dolls action figures. While shipping had a special organizational importance, IT rarely was engaged. The CEC (Chief Executive Claus) had learned to do pivot tables and VLOOKUPs in Excel, and did all his shipment planning himself.The 100% business-critical mystery system was NNOSE: Naughty/Nice Observation and System Evaluator. It was the "source of truth" for the all important TPS reports: Total Presents Sacked. The Ancient Wizard who cared for it was literally an Ancient Wizard, Merlin. And yes, Merlin really was Santa's sidekick. NNOSE ran on a piece of NORAD surplus computer hardware and was programmed in a dialect of MUMPS nicknamed "Sugar LUMPS" or just "LUMPS". Merlin was the only one who knew how the system worked and what the system did, and Merlin was the only one who was ever supposed to touch it.As the clock clicked closer to 12/24, the shipping deadline, the Workshop got busier and busier, while software developers got less and less busy. Since time was critical, no software changes went into production unless there was an absolute show-stopping bug. The software teams basically were on an extended break until the New Year, and no code releases would happen until mid-January at the earliest.So, during the busiest, most critical time of the year, the development team mostly spent their vacation hours. Merlin was out in Avalon, trying to patch things up with his ex. The senior Project Elfagers were on a retreat in Cancun. All through the shop, not a developer was stirring, aside from Renee. Renee loved to work during the quietest time of the year, when no one scheduled any meetings. It was its own kind of vacation…… at least until Hermie, the lead developer who really wanted to be an MBA, popped his head into her cube."NNOSE is down. The Big Guy just tried to pull the final TPS report for the year, and not only did it not have a cover sheet, it printed ten pages of errors instead of data. I've already tried to raise Merlin, but he's not on Slack, and there's no cell service in Avalon."If the TPS report were wrong or unavailable, Santa couldn't accurately match kids up with presents. Naughty kids could get great gifts, nice ones might get useless garbage like an Amazon Echo or Google Home. He needed that report."Okay, but I know the report has been run previously," Renee said. "Can't they just run with an old version?""There aren't any old versions. TPSes get shredded after review, ever since GDPR went into effect."Against her better judgment, Renee set down her hot cocoa and said, "I'll see what I can do."Merlin didn't keep any digital documentation for NNOSE. Everything about the system was stored in binders full of parchment in his cube. Calling the contents "documentation" would be generous. Merlin had written most of it in High Enochian, and what little bits were in Elvish just seemed to be rants and raves about changes management had requested, and how wrong those changes were. The only system diagram was arranged into an Elder Sign. The most useful thing Renee found in her first pass were post-it notes with login credentials for the various bits.Still, it was enough for Renee to start piecing together the system. The TPS report came from data managed by NNOSE, but the mainframe-based CLI interface had been abandoned circa 2002. At that point, someone had purchased an expensive mainframe integration package from Initech, which was basically a way of slapping XML/SOAP webservices on top of existing mainframe code. A few years later, someone had slapped together a VB.NET (framework version 1.0) UI which called into that webservice. The VB.NET program actually extracted and printed the report.Great! Renee kind of knew Visual Basic, or at least could fake it. And it wasn't LUMPS. She started by testing the NNOSE XML interface- she sent a few SOAP requests manually and verified that she got correct output. Then she fired up the VB.NET app. It had a basic UI for setting filters and criteria, but once you hit "run report", everything—even the error messages—went to the printer. Worse, you couldn't tell it what printer to use. Every print went to one printer down in the reindeer stables.Cue the testing cycle of "try running the report, ride the world's slowest elevator to the basement, walk through the reindeer stables, wait for the printer to finish running off its pages of error messages, drag the ream of paper back upstairs and try to match it to the code." Through this process, Renee learned a few important things. First, no matter how Christmas-y and magical reindeer were in spirit, in odor they were more Halloween Horror. Second, for some reason, there were SQL errors showing up in the stack traces. But everything was supposed to be webservices wrapped on mainframes, so why were there database calls?Renee went back to Merlin's binders, and with the help of what little High Enochian she could remember from high school, Renee started to piece together what was happening.Circa 2004, against Merlin's protests, there had been a project code-named RED. The goal of RED was to "upgrade" NNOSE to a full J2EE system with an Oracle backend. If Renee was reading the Enochian correctly, Merlin had banished the elf responsible for contracting the vendor to the Astral Plane, where they were surely captured by Githyanki."Well, that's got to be a violation of HR policies," Renee noted to herself.The project never completed, but progressed to the point where the Oracle backend had been running in parallel with NNOSE ever since. That explained the SQL errors. The VB.NET app had functionality added to talk to the "upgraded" RED system. At some point in its history, the VB.NET app had been pointed to that backend, and had been querying it instead of the mainframe. Sure enough, when Renee logged into Oracle directly, most commands returned errors as something in this more-or-less unmaintained and unpatched Oracle instance was completely FUBAR.Renee poked at the VB.NET app until she figured out how to resurrect the webservice-based data access layer. One more olfactory offense later, and Renee was holding a TPS report. Off it went to Santa, and off she went to give an after action to Hermie."Great work! You've saved Christmas!" Hermie said. "Shame about Merlin, though.""What about Merlin?""Oh, the whole banishing poor Roger to be soulsucked on the Astral Plane. That is absolutely a firing offense, and we're going to have to let Merlin go. Don't worry, though. After this, I'm confident that you can fill in as our new NNOSE and LUMPS expert. You can think of it like a promotion, and maybe in a few years, it'll involve a salary increase!" [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Classic WTF: Power Supply
Error'd: A Generic Holiday Title Goes Here
"Sure, there's the obvious 'they didn't put any effort into the email subject,' but the placeholder kind of shows they didn't intend to in the first place," Chris wrote.
Representative Line: Explicitly True
Part of Python’s appeal is its rich class library. The old XKCD about import antigravity sometimes doesn’t feel that far off. Combined with a few third-party libraries, like NumPy, you can do a lot with very little code.Of course, that feels a bit like magic. As Python gurus like to say, “Explicit is better than implicit”. One of Mark’s co-workers took this perhaps a bit too far, when they started adding this import to every file:
Assumptions are the Mother of all Bugs
A long time ago in my "C" programming days, I learned that when you code up anything that depends on any sort of external data, be it a file, database or socket, you should be paranoid and do it defensively. After all, you can't control those things and there's no guarantee that they will always work the way you hope. Sometimes you care about every possible error code; sometimes just success or failure. The point is to check the result of what you tried to do. Fast forward through several years of C++ and ten years into Java, and our boss calls us into the office.
...25262728293031323334...