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 18:46
Error'd: Latin is Making a Comeback?
"Well, if I need an email template, lucky me, I now have one handy," writes Paul C.
CodeSOD: Boldly Leaping Over the Span
No one writes HTML anymore. We haven’t for years. These days, your HTML is snippets and components, templates and widgets. Someplace in your application chain, whether server-side or client-side, or even as part of a deployment step, if you’re using a static site generator, some code mashes those templates together and you get some output.This has some side effects, like div abuse. Each component needs its own container tag, but we often nest components inside each other. Maybe there’s a span in there. If the application is suitably HTML5-y, maybe it’s sections instead.Andy stumbled across a site which was blocking right clicking, so Andy did what any of us would do: pulled up the debugging tools and started exploring the DOM tree.
CodeSOD: Round Two
John works for a manufacturing company which has accrued a large portfolio of C++ code. Developed over the course of decades, by many people, there’s more than a little legacy cruft and coding horrors mixed in. Frustrated with the ongoing maintenance, and in the interests of “modernization”, John was tasked with converting the legacy C++ into C#.Which meant he had to read through the legacy C++.In the section for creating TPS reports, there were two functions, TpsRound and TpsRound2. The code between the two of them was nearly identical- someone had clearly copy/pasted and made minor tweaks.
CodeSOD: Tern The Bool Around
Some say that the only reason I like ternary code snippets is that it gives me an opportunity to make the title a “tern” pun.…They’re not wrong.I’m actually a defender of ternaries. Just last week, I wrote this line of C++ code:
A Floating Date
Enterprise integration is its own torturous brand of software development. Imagine all the pain of inheriting someone else's code, but now that code is proprietary, you can't modify it, poorly documented, and exposes an API that might solve somebody's problem, but none of the problems you have, and did I say poorly documented? I meant "the documentation is completely inaccurate and it's possible that this was intentional".Michael was working on getting SAP integrated to their existing legacy systems. This meant huge piles of bulk data loading, which wasn't so bad- they had a third party module which promised to glue all this stuff together. And in early testing phases, everything went perfectly smooth.Of course, this was a massive enterprise integration project for a massive company. That guaranteed a few problems that were unavoidable. First, there were little teams within business units who weren't using the documented processes in the first place, but had their own home-grown process, usually implemented in an Excel file on a network drive, to do their work. Tracking these down, prying the Excel sheet out of their hands, and then dealing with the fallout of "corporate coming in and changing our processes for no reason" extended the project timeline.Well, it extended how much time the project actually needed, which brings us to the second guaranteed problem: the timeline was set based on what management wanted to have happen, not based on what was actually possible or practical. No one on the technical side of things was consulted to give an estimate about required effort. A go-live date of October 8th was set, and everything was going to happen on October 8th- or else.The project was, against all odds, on track to hit the ridiculous target. Until it went into UAT- and that's when Michael started catching issues from users. Dates were shifting. In the source system, the date might be November 21st, but in SAP it was November 20th. The 23rd turned into the 24th. The 25th also turned into the 24th.Michael was under a time crunch, and trapped between a rock (the obtuse legacy system), a hard place (SAP), and a hydraulic press (the third-party data import module). There was a pattern to the errors, though, and that pattern pointed to a rounding error."Wait, a rounding error?" Michael wondered aloud. Now, they did use numbers to represent dates. The "Japanese" notation, which allowed them to store "November 21st, 2018" as 20181121. That's a super common approach to encoding a date as a 32-bit integer. As integers, of course, there was no rounding. They were integers on the legacy side, they were integers on the SAP side- but what about in the middle? What was the third party import module doing?As a test, Michael whipped up a little two-line program to test:
Error'd: Let's Hope it's Only a Test
"When the notification system about the broken NYC MTA is broken, does that make the MTA meta-broken?" writes T.S.
CodeSOD: Break Out of your Parents
When I first glanced at this submission from Thomas, I almost just scrolled right by. “Oh, it’s just another case where they put the same code in both branches of the conditional,” I said. Then I looked again.
Blind Leading the Blind
Corporate Standards. You know, all those rules created over time by bureaucrats who think that they're making things better by mandating consistency. The ones that force you to take time to change an otherwise properly-functioning system to comply with rules that don't really apply in the context of the application, but need to be blindly followed anyway. Here are a couple of good examples.Kevin L. worked on an application that provides driving directions via device-hosted map application. The device was designed to be bolted to the handlebars of a motorcycle. Based upon your destination and current coordinates, it would display your location and the marked route, noting things like distance to destination, turns, traffic circles and exit ramps. A great deal of effort was put into the visual design, because even though the device *could* provide audio feedback, on a motorcycle, it was impossible to hear.One day, his boss, John, called him into a meeting. "I was just read the riot-act by HR. It seems that our application doesn't comply with corporate Accessibility Standards, specifically the standard regarding Braille Literature In Need of Description. You need to add screenreader support to the motorcycle map application. I estimate that it will take a few months of effort. We don't really have the time to spare, but we have to do it!"Kevin thought about it for a bit and asked his boss if the company really wanted him to spend time to create functionality to provide verbal driving directions for blind motorcycle drivers.That head-desk moment you're imagining really happened.Of course, common sense had no bearing on the outcome, and poor Kevin had to do the work anyway.While self-driving cars will eventually be commonplace, and no one will need directions, audible or otherwise. For now, though, Kevin at least knows that all the visually impaired motorcycle drivers can get to where they're going. [Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
CodeSOD: An Error on Logging
The beauty of a good logging system is that it allows you to spam logging messages all through your code, but then set the logging level at runtime, so that you have fine grained control over how much logging there is. You can turn the dial from, “things are running smooth in production, so be quiet,” to “WTF THINGS ARE ON FIRE GODS HELP US WHAT IS GOING ON CAN I LAUNCH A DEBUGGER ON THE PRODUCTION ENVIRONMENT PLEASE GOD”.You might write something like this, for example:
CodeSOD: Pointed Array Access
I've spent the past week doing a lot of embedded programming, and for me, this has mostly been handling having full-duplex communication between twenty devices on the same serial bus. It also means getting raw bytes and doing the memcpy(&myMessageStructVariable, buffer, sizeof(MessageStruct)). Yes, that's not the best way, and certainly isn't how I'd build it if I didn't have full control over both ends of the network.Of course, even with that, serial networks can have some noise and errors. That means sometimes I get a packet that isn't the right size, and memcpy will happily read past the end of the buffer, because my const uint8_t * buffer pointer is just a pointer, after all. It's on me to access memory safely. Errors result when I'm incautious.Which brings us to Krzysztof`s submission. This code is deep inside of a device that's been on the market for twenty years, and has undergone many revisions, both hardware and software, over that time.
Error'd: Full Price not Allowed
"When registering for KubeCon and CloudNativeCon, it's like they're saying: Pay full price? Oh no, we insist you use a discount code. No really. It's mandatory," writes Andy B.
CodeSOD: Off by Dumb Error
“We’re bringing on my nephew, he’s super smart with computers, so you make sure he is successful!”That was the long and short of how Reagan got introduced to the new hire, Dewey. Dewey’s keyboard only really needed three keys: CTRL, C, and V. They couldn’t write a line of code to save their life. Once, when trying to fumble through a FizzBuzz as a simple practice exercise, Dewey took to Google to find a solution. Because Dewey couldn’t quite understand how Google worked, instead of copy/pasting out of StackOverflow, they went to r/ProgrammerHumor and copied code out of a meme image instead. Reagan couldn’t even just try and shove Dewey off on a hunt for a left-handed packet shifter in the supply closet, because Dewey’s patron was watching source control, and wanted to see Dewey’s brilliant commits showing up. Even if Reagan didn’t give Dewey any tasks, Dewey’s uncle did.That’s how Dewey got stumped trying to fetch data from a database. They simply needed to read one column and present it as a series of HTML list items, using PHP.This was their approach.
CodeSOD: Ten Times as Unique
James works with a financial services company. As part of their security model, they send out verification codes for certain account operations, and these have to be unique.So you know what happens. Someone wrote their own random string generator, then wrapped it up into a for loop and calls it until they get a random string which is unique:
CodeSOD: The UI Annoyance
Daniel has a bit of a story. The story starts many months ago, on the very first day of the month.Angular 1.x has something called a filter as a key concept. This is a delightfully misleading name, as it's more meant to be used as a formatting function, but because it takes any arbitrary input and converts it to any arbitrary output, people did use it to filter, which had all sorts of delightful performance problems in practice.Well, Daniel found this perfectly sensible formatting filter. It's well documented. It's also wrong.
CodeSOD: Shell Out
Developers sometimes fail to appreciate how difficult a job Operations really is. In companies that don't hold with newfangled DevOps, the division of labor often comes with a division of reputation as well. After all, developers do the hard work of making software. What are Ops guys even for? They don't make software. They don't generate leads or fix your desktop PC. Why bother paying for talented senior Ops professionals?Spend a few days with the Ops team, however, and you start to see why you should pay them a little more than your average garbageman. The Ops lifecycle is a daily grind of deployments, patching, and sticking fingers in dykes, trying to keep that expensive cesspit the devs call "software" running. Simple tasks such as spinning up new infrastructure in AWS often get pushed to the back burner behind putting out fires and making sure critical maintenance tasks that didn't get done last year don't explode into flames.Still, companies like to cut corners. Often, Ops folks have very little programming expertise and no training budget, meaning repetitive tasks are automated using cobbled-together bits of shell script found via Google. In the Ops world, a bit of Perl or Python is worth its weight in gold.Today's snippet, as you can probably guess, is not in Perl or Python. It is instead in a common paradigm: Bash embedded in Perl. Likely, the original script was written by a senior who knows Perl, and this chunk was written by a strapped-for-time medior who didn't:
Error'd: This Movie is Rated S for Safe for SQL
"Clearly the Light Cinema decided to ban unsafe sql characters from the cinema," wrote Simon, "Let's hope no one makes a film called 'Drop Table'."
CodeSOD: Flip to a Blank Page
You have a web application, written in Spring. Some pages live at endpoints where they’re accessible to the world. Other pages require authentication, and yet others require users belong to specific roles. Fortunately for you, Spring has features and mechanisms to handle all of those details, down to making it extremely easy to return the appropriate HTTP error.Unfortunately for you, one of the developers on your team is a Rockstar™ who is Officially Very Smart and absolutely refuses to use the tools your platform provides. When that Certified Super Genius leaves the organization, you inherit their code.That’s what happened to Emmer. And that’s how they found this:
Westward Ho!
Roman K. once helped to maintain a company website that served a large customer base mainly within the United Kingdom. Each customer was itself a business offering a range of services. The website displayed these businesses on a map so that potential customers could find them. This was done by geocoding the business' addresses to get their longitude and latitude coordinates, then creating points on the map at those locations.Simple enough—except that over time, some of the businesses began creeping west through the Atlantic Ocean, toward the east coast of North America.Roman had no idea where to start with troubleshooting. It was only happening with a subset of businesses, and only intermittently. He was certain the initial geocoded coordinates were correct. Those longitude and latitude values were stored in a database table of customer data with strict permissions in place. Even if he wanted to change them himself, he couldn't. Whatever the problem was, it was powerful, and oddly selective: it only ever changed longitude values. Latitude values were never touched.Were they being hacked by their competitors? Were their customers migrating west en masse? Were goblins messing with the database every night when no one was looking?Roman dug through reams of code and log files, searching desperately for any whiff of "longitude." He questioned his fellow developers. He blamed his fellow developers. It was all for naught, for the problem was no bug or hack. The problem was a "feature" of the database access layer. Roman discovered that the user class had a simple destructor method that saved all the currently loaded data back to the database:
CodeSOD: Switch On Suppression
Krista noticed our article explaining that switches were replacements for ifs. She sent in a version she found in her codebase, around the same idea:
CodeSOD: The Secure Cloud API
Melinda's organization has purchased a cloud-based storage system. Like any such system, it has a lovely API which lets you manage quotas and login tokens. It also had a lovely CLI, which was helpful for administrators to modify the cloud environment. Melinda's team built a PHP front-end that could not only manage files, but also allowed administrators to manage those quotas.Melinda was managing those quotas, and when she clicked the link to view the quotas, she noticed the URL contained ?token=RO-cmV1c2luZyBrZXlzIGlzIFRSV1RG. When she went to modify the quota, the URL parameter became ?token=RW-cmV1c2luZyBrZXlzIGlzIFRSV1RG. That looked like a security key for their cloud API, transmitted in the open. The RW and RO looked like they had something to do with readwrite and readonly, but that wasn't the security model their storage provider used. When Melinda had another co-worker log in, they saw the same tokens. What was going on?Melinda took a look at the authorization code.
Error'd: Stay Away From California
"Deep down, I knew this was one of the most honest labels I've ever seen," wrote Bob E.
Crazy Like a Fox(Pro)
“Database portability” is one of the key things that modern data access frameworks try and ensure for your application. If you’re using an RDBMS, the same data access layer can hopefully work across any RDBMS. Of course, since every RDBMS has its own slightly different idiom of SQL, and since you might depend on stored procedures, triggers, or views, you’re often tied to a specific database vendor, and sometimes a version.And really, for your enterprise applications, how often do you really change out your underlying database layer?Well, for Eion Robb, it’s a pretty common occurrence. Their software, even their SaaS offering of it, allows their customers a great deal of flexibility in choosing a database. As a result, their PHP-based data access layer tries to abstract out the ugly details, they restrict themselves to a subset of SQL, and have a lot of late nights fighting through the surprising bugs.The databases they support are the big ones- Oracle, SQL Server, MySQL, and FoxPro. Oh, there are others that Eion’s team supports, but it’s FoxPro that’s the big one. Visual FoxPro’s last version was released in 2004, and the last service pack it received was in 2007. Not many vendors support FoxPro, and that’s one of Eion’s company’s selling points to their customers.The system worked, mostly. Until one day, when it absolutely didn’t. Their hosted SaaS offering crashed hard. So hard that the webserver spinlocked and nothing got logged. Eion had another late night, trying to trace through and figure out: which customer was causing the crash, and what were they doing?Many hours of debugging and crying later, Eion tracked down the problem to some code which tracked sales or exchanges of product- transactions which might not have a price when they occur.
CodeSOD: Padding Your Time
Today will be a simple one, and it’s arguably low-hanging fruit, because once again, it’s date handling code. But it’s not handling dates where it falls down. It falls down on something much more advanced: conditionals. Supplied by “_ek1n”.
CodeSOD: Wear a Dunder Cap
In the Python community, one buzzword you’ll find thrown around is whether or not an approach is “pythonic”. It’s a flexible term, and something you can just throw out in code reviews, even if you’ve never written a line of Python in your life: “Is that Pythonic?”The general rubric for what truly is “pythonic” is generally code that is simple and code that operates explicitly. There shouldn’t be any “magic”. But Python doesn’t force you to write “pythonic” code, and it provides loads of tools like decorators and metaclasses that let you get as complex and implicit as you like.One bit of magic is the “dunder” methods, which are Python’s vague approach to operator overloading. If you want your class to support the [] operator, implement __getitem__. If you want your class to support the + operator, implement __add__. If you want your class to support access to any arbitrary property, implement __getattr__.Yes, __getattr__ allows you to execute code on any property access, so a simple statement like this…
CodeSOD: Legacy Switchout
About a decade ago, I attended a talk. The speaker made the argument that "legacy code" may have many possible interpretations, but the practical view was to simply think of legacy code as "code without unit tests". Thus, the solution to modernizing your legacy code was to simply write unit tests. Refactoring the code to make it testable would have the side effect of modernizing the code base, and writing tests would act as documentation. It's that easy.Andrew is struggling with some legacy code right now. Worse, they're trying to integrate a large mountain of legacy code into a custom, in-house CI/CD pipeline. This particular pile of legacy code dates back to the mid-2000s, so everything in it is glued together via XML. It was some of that XML code which started failing when Andrew threw some unit tests at it.It doesn't start that bad:
Error'd: An Unfortunate Sign
"Found this in the School of IT. 404: Women not found. Fairly accurate," wrote Maddie J.
CodeSOD: Not a Not Bad Approach
In terms of elegance, I think the bitmask has a unique beauty. The compactness of your expression, the simple power of bitwise operators, and the way you can see the underlying implementation of numbers laid bare just speaks to me. Of course, bitmasks can be a bit opaque, and you may have to spend some time thinking about what foo &= 0xFF0000 is actually doing, but there’s also something alluring about it.Of course, bitmasks are surprisingly hard. For example, let’s look at some code submitted anonymously. This code is meant to run on a line of coin-operated dryers. Depending on the particular install, how many coins a patron puts in, what modes have been enabled by the owner, and so on, different “extra” features might be disabled or not disabled.Since bitmasks are hard, we’re not going to use one. Instead, let’s have a pile of constants, like so:
CodeSOD: Caught Up in the Captcha
Gregor needed to download a network driver. Upon clicking the link, a "captcha" appeared, presumably to prevent hotlinking to the driver files. It wasn't a real, image-based captcha, but a simple "here's some characters, type them into the box".The code which popped up was "S i u x q F b j NaN 4". He hit the "new code" button, and got "T o A 0 J V s L NaN a". In fact, "NaN" showed up in the penultimate position in every code.Curious, Gregor pulled up the debugger to see how the captcha was generated.
SLA-p the Salesman
A Service-Level Agreement (SLA) is meant to ensure customer issues receive the attention they deserve based on severity. It also protects the support company from having customers breathing down their neck for frivolous issues. All of the parameters are agreed upon in writing ahead of time and both sides know the expectations. That is, until a salesman starts to meddle and mess things up, as happened at the place Dominick worked for.Dominick was a simple remote support tech who fixed things for clients well ahead of the SLA. On the rare occasion there was a priority 1 issue - something stopping anyone in the company from doing work - they had 24 hours to fix it before large monetary penalties would start to rack up. One Friday a priority 4 issue (5 business day SLA) came in from the CFO of a new client. The ticket was assigned to Dominick, who had higher priority work to do for other clients, so he decided it could wait until the following week.Dominick came in Monday morning to find Benjamin, a senior salesman who happened to be a personal friend of the CFO, sitting on his desk with his huge arms crossed. Benjamin glanced at his watch to see it was 7:59 AM. "About time you showed up, Dom. I found out you didn't do the ticket that came in Friday and I want an explanation!"Still in a pre-coffee Monday morning haze, Dominick had to think for a second to figure out what he was talking about. "Oh... that thing about ordering a new printer? That was only priority 4 and it literally said 'no rush' in it. I have 4 more days to get it done."Benjamin sprang up off Dom's desk and used his beefy arms to forcefully shove an index finger into his chest. "You don't get it do you, bro?? When I made this deal with them, I assured them anything would be treated with the highest priority!" Ben shouted while spraying an unsanitary amount of saliva droplets. "I don't care what your silly numbering system says, it needs to get done today!"Ok... well let me sit down and look at it," Dominick said timidly while rubbing the spot on his chest that received a mean poking. Benjamin stormed off to presumably consume another protein shake. He pulled up the ticket about ordering a new printer for the CFO's office. It seemed he'd read about this top of the line printer in some tech magazine and really wanted it. The problem was the printer wasn't even on the market yet - it would be released at the end of the month. Since there was literally nothing Dominick could do to get the printer, he closed the ticket and asked that a new one be submitted when the printer was available.Later that afternoon, Dominick heard stomping behind him and before he could turn around, Benjamin spun him around in his chair and got in his face. "Hey there, bro. Where is my guy's printer?? He told me you closed his submission without ordering it!"Dominick stood up to defend himself and weakly poked Ben in the chest. "Listen, bro! He wants a printer that isn't out yet. The best I can do is pre-order it and have it shipped to him in a couple weeks. I closed the ticket so we don't get dinged on the SLA to get this done in 5 days."Benjamin furrowed his brow and got back within saliva-spraying distance, "You'll have to do better than that, Dom! While you were screwing around not resolving this I made an addendum to their SLA. Any ticket submitted by a CxO level executive will be treated as priority 1 by us. So you better pull whatever techie nerd strings you have to get that printer ordered in the next 24 hours!"After Benjamin stormed off yet again, the reality of what he had done set in. Since the SLA for the printer was now 24 hours, they would start getting charged penalties by tomorrow. Dominick quickly began crafting an email to senior management to explain the situation and how the request wasn't able to be met. He wasn't sure what sort of "techie nerd" resources Benjamin thought he had, but it wasn't going to happen.Predictably, the situation didn't end well. The financial penalties started adding up the following day, and the next day, and so on. It became so expensive that it was more cost-effective to pay the client to modify the addendum to the SLA that Benjamin made (they couldn't be compelled to do so otherwise) than to continue to rack up fines.The end of the month came and the world's most expensive printer finally shipped, which was a relief to everyone. But that also meant the end-of-month financial statements showed the huge deficit caused by it. To compensate, the company decided to lay off 20% of the support staff including Dominick. Benjamin, of course, got to keep his job where he always put customer needs first. [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Classic WTF: Security By Letterhead
CodeSOD: Why I Hate Conference Swag (and What can be Done About it)
Hey everyone - I'm at a conference this week I'd like to cover a WTF that I've been seeing this week - VENDOR SWAG.Ok, if you are one of those poor souls who are always heads down in code and never attend workshops or conferences, this won't make much sense to you, but here's the deal - companies will set up a booth or a table and will pass out swag in exchange for your contact info and (possibly) a lead. To me, this is easily the dirtiest transaction one can make and rife with inequalities. Your information is super valuable - as in possibly generating thousands or millions of sales dollars. The 'gift' will be SUPER cheap by comparison.How cheap? WELL, here are some examples:
Keeping Up Appearances
Just because a tool is available doesn't mean people will use it correctly. People have abusedbooleans,dates,enums,databases,Go-To's,PHP,reinventing the wheel and even Excel to the point that this forum will never run out of material!Bug and issue trackers are Good Thingsâ„¢. They let you keep track of multiple projects, feature requests, and open and closed problems. They let you classify the issues by severity/urgency. They let you specify which items are going into which release. They even let you track who did the work, as well as all sorts of additional information.Every project, no matter how big or small, should make use of them.Ideally, they would be used correctly.Ideally.Matt had just released the project that he'd been working on for the past few years. As always happens, some "issues" cropped up. Some were genuine defects. Some were sort-of-enhancements based on the fact that a particular input screen was unwieldy and needed to be improved. At least one was a major restructuring of a part of the project that did not flow too well. In all, Matt had seven issues that needed to be addressed. Before he could deliver them, he needed defect tickets in the bug tracking system. He wasn't authorized to raise such tickets; only the Test team could do that.It took a while, but he finally received a ticket to do the work to... but everything had been bundled up into one ticket. This made it very difficult to work with, because now he couldn't just clear each issue as he went. Instead, he had to package them up in abeyance, so to speak, and only release them when they were all complete. This also meant that the test documentation, providing instructions to the Test team as to how to ensure that the fix was working as required, all had to be bundled up into one big messy document, making it more difficult for Testers to do their job as well.So he questioned them: If we can raise a single defect ticket, then what stops us from raising all 7 needed tickets so that the issues can be addressed separately? The answer was: Because these defects appear post-release, it is clear that they weren't caught at the pre-release stage, which means that Somebody Wasn't Doing Their Job Properly in the Test team, which makes them Look Bad; it brings their failure to catch the issues to the attention of Management.In other words, in order to keep the Test team from looking bad, they would only ever raise a single ticket (encompassing all detected issues) for any given release.Imagine if all of the bugs from your last major release were assigned to you personally, in a single ticket. Good luck estimating, scheduling, coding, debugging and documenting how to test the single logical bug!Matt raised this bad practice with management, and explained that while the reason for why they do this is to hide their inadequacy, it also prevents any meaningful way to control work distribution, changes and subsequent testing. It also obscures the actual number of issues (Why is it taking you seven weeks to fix one issue?).Management was not amused at having been misled. [Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
CodeSOD: Rectangle Marks The Spot
If you need your user's country of origin, there are many ways you can go about obtaining it programmatically. Some may opt for a simple drop-down that prompts the user to specify his/her country. If you don't want to burden your user this way, you might look at their session data and return their country of origin, time zone, or some other useful information. If you have fancy enough APIs at your disposal, you could even reverse geocode the user's longitude/latitude position and obtain an address.Or, you can start with their location and perform the code equivalent of throwing a dart at a map littered with creepy-looking post-it notes:
CodeSOD: Look Ahead. Look Out!
I'm an old person. It's the sort of thing that happens when you aren't looking. All the kids these days are writing Slack and Discord bots in JavaScript, and I remember writing my first chatbots in Perl and hooking them into IRC. Fortunately, all the WTFs in my Perl chatbots have been lost to time."P" has a peer who wants to scrape all the image URLs out of a Discord chat channel. Those URLs will be fetched, then passed through an image processing pipeline to organize and catalog frequently used images, regardless of their origin.Our intrepid scraper, however, doesn't want to run the risk of trying to request a URL that might be invalid. So they need a way to accurately validate every URL.Now, the trick to URLs, and URIs in general, is that they have a grammar that seems simple but is deceptively complex and doesn't lend itself to precise validation via regular expressions. If you were a sane person, you'd generally just ballpark it into the neighborhood and handle exceptions, or maybe copy/paste from StackOverflow and call it a day.This developer spent 7 hours developing their own regular expression to validate a URL. They tested it with every URL they could think of, and it passed with 100% accuracy, which sounds like the kind of robust testing we'd expect from the person who wrote this:
CodeSOD: Assertive Programming
Defensive programming is an important tool in any developer's toolbox. In strictly typed languages, types themselves provide a natural defense against certain classes of bugs, but in loosely typed languages, you may have to be more clear about your assumptions.For example, in Python, you might choose to use the assert keyword to, well, assert that something is true. It's often used in debugging, but it's also a good way to ensure that the state of the parameters passed to a function, or some other state of your system is correct before doing anything else. If it's not, the code raises an exception.Dima R found this "interesting" riff on that concept.
Error'd: Exponential Customer Service
"I think I'm missing some precision in my Dell customer number," writes Steve B.
CodeSOD: Extending Yourself
Optional parameters are a great tool for building flexible APIs. In most languages, they're not strictly necessary- if you have function overloading, the difference between optional parameters and an overloaded function is just the quantity of boilerplate- but they're certainly a nice to have.Well, they're a nice to have in the right hands.Scattered through their code base, Ian P saw many, many calls to dutData.GetMessages(). As they explored the code base, they used Visual Studio's "go to definition" feature to jump to the implementation- and found they were sometimes ending up in different spots.
Representative Line: You Can Only Get What You Have
Sean's ongoing career as a consultant keeps supplying him with amazing code.Let's talk about encapsulation. We put getters and setters around our objects internalsto help keep our code modular. Given an object, we call something like getUsername to extract a piece of that object safely.In the same codebase as IsTableEmpty, Sean found this short-but-sweet gem:
CodeSOD: Is This Terning Into a Date?
Bad date handling code is like litter: offensive, annoying, but omnipresent. Nobody is specifically responsible for it, nobody wants to clean it up, and we end up ignoring it.Murtaza K offers up a particularly malodorous example, though, that's worthy of note. It's got everything: string mangling, assumptions that ignore locale, bad ternaries, and it's completely unnecessary.
Leaky Fun For the Whole Family
Those of us that had the luxury of learning to program in C or other non-auto-gc'd langauges, learned early on the habit of writing the allocation and deallocation of a block of memory at the same time, and only then filling in the code in between afterward. This prevented those nasty I-forgot-to-free-it memory leaks.Of course, that doesn't guarantee that memory can't ever leak; it just eliminates the more obvious sources of leakage.Daniel worked on an installation for a theme park attraction sometime back. The task was to use a computer vision system to track the movement of a number of moving projection screens, and then send the tracking data to a video system in order to move the image around within the projection raster to keep it static on the screen.He was using a specialised product designed for industrial machine-vision applications. It was essentially a camera with a small Windows XP machine inside, which ran a custom application developed using a commercial machine vision programming toolkit. The software looked for the position of 4 infra-red LEDs using the camera and then output their coordinates via ethernet to the video system.After the installation was complete, Daniel was back in the home office when he got a call from the park. Apparently the camera software was crashing after around 10 days of uptime. He remoted in and saw the cause was an out of memory failure. This was his worst nightmare.A nice feature of these boxes was that they had a mechanism to essentially 'lock out' changes from the hard drive. After the system was setup and working, an option was enabled which diverted all hard drive writes to RAM, discarding them on a reboot or power down. This had the advantage the camera system didn't require any software maintenance as it would be 'fresh' every time you turned it on, which is great for an installation that could be in place for over 10 years. However he was concerned about what this might mean for uptime as any process which repeatedly wrote any significant amount of data to the drive would quickly fill up the 1GB of RAM available on the cameras. Around 60% of this was used by the running process anyway, so there wasn't a huge amount of headroom.This wasn't a large source of concern when developing the installation as there was an understanding that the system would be powered down every night when the park was closed (which would have been the easy solution to this problem). He'd noticed that the RAM was filling up slowly as the camera ran, but not at a rate which would be dangerous for the target uptime of 24 hours.Unfortunately, the daily power cycle didn't happen, and any kind of system failure caused the on-site techs to get nervous; clearly this was an issue that would have to be fixed the hard way. He was convinced that the drive lock-out feature was the cause of this issue.From then on, every 10 days, when the park was closed, Daniel remoted in and tried various steps on the cameras to find the process that was writing to "disk". The complete installation had 6 cameras so he would try different steps on each system to try and diagnose the issue, enabling/disabling various system processes and options within the machine vision development toolkit used to write the application. He would leave it for 10 days and then wait to hear from the onsite techs if the changes had been successful. These failures went on for around 2 months.Finally in desperation, Daniel sent off the custom machine vision application to the company who developed the programming toolkit for their developers to analyze and see if they could point to the process causing the hard drive write.Around a week later, they emailed back saying We couldn't find any hard drive write, but we did locate a small memory leak in one of your routines, around 8 bytes per image frame. The routine in question was in the main image analysis path. The cameras ran at 60 fps, so some quick arithmetic yields:
Error'd: The Illusion of Choice
"So I can keep my current language setting or switch to Pakistani English. THERE IS NO IN-BETWEEN," Robert K. writes.
Representative Line: Tern This Statement Around and Go Home
When looking for representative lines, ternaries are almost easy mode. While there’s nothing wrong with a good ternary expression, they have a bad reputation because they can quickly drift out towards “utterly unreadable”.Or, sometimes, they can drift towards “incredibly stupid”. This anonymous submission is a pretty brazen example of the latter:
CodeSOD: Isn't There a Vaccine For MUMPS?
Alex F is suffering from a disease. No, it’s not disfiguring, it’s not fatal. It’s something much worse than that.It’s MUMPS.MUMPS is a little bit infamous. MUMPS is its own WTF.Alex is a support tech, which in their organization means that they sometimes write up tickets, or for simple problems even fix the code themselves. For this issue, Alex wrote up a ticket, explaining that the users was submitting a background job to run a report, but instead got an error.Alex sent it to the developer, and the developer replied with a one line code fix:
A Shell Game
When the big banks and brokerages on Wall Street first got the idea that UNIX systems could replace mainframes, one of them decided to take the plunge - Big Bang style. They had hundreds of programmers cranking out as much of the mainframe functionality as they could. Copy-paste was all the rage; anything to save time. It could be fixed later.Senior management decreed that the plan was to get all the software as ready as it could be by the deadline, then turn off and remove the mainframe terminals on Friday night, swap in the pre-configured UNIX boxes over the weekend, and turn it all on for Monday morning. Everyone was to be there 24 hours a day from Friday forward, for as long as it took. Air mattresses, munchies, etc. were brought in for when people would inevitably need to crash.While the first few hours were rough, the plan worked. Come Monday, all hands were in place on the production floor and whatever didn't work caused a flurry of activity to get the issue fixed in very short order. All bureaucracy was abandoned in favor of: everyone has root in order to do whatever it takes on-the-fly, no approvals required. Business was conducted. There was a huge sigh of relief.Then began the inevitable onslaught of add this and that for all the features that couldn't be implemented by the hard cutoff. This went on for 3-4 years until the software was relatively complete, but in desperate need of a full rewrite. The tech people reminded management of their warning about all the shortcuts to save time up front, and that it was time to pay the bill.To their credit, management gave them the time and money to do it. Unfortunately, copy-paste was still ingrained in the culture, so nine different trading systems had about 90% of their code identical to their peers, but all in separate repositories, each with slightly different modification histories to the core code.It was about this time that I joined one of the teams. The first thing they had me do was learn how to verify that all 87 (yes, eighty seven) of the nightly batch jobs had completed correctly. For this task, both the team manager and lead dev worked non-stop from 6AM to 10AM - every single day - to verify the results of the nightly jobs. I made a list of all of the jobs to check, and what to verify for each job. It took me from 6AM to 3:00PM, which was kind of pointless as the markets close at 4PM.After doing it for one day, I said no way and asked them to continue doing it so as to give me time to automate it. They graciously agreed.It took a while, but I wound up with a rude-n-crude 5K LOC ksh script that reduced the task to checking a text file for a list of OK/NG statuses. But this still didn't help if something had failed. I kept scripting more sub-checks for each task to implement what to do on failure (look up what document had the name of the job to run, figure out what arguments to pass, etc., get the status of the fix-it job, and notify someone on the upstream system if it still failed, etc). Either way, the result was recorded.In the end, the ksh script had grown to more than 15K LOC, but it reduced the entire 8+ hour task to checking a 20 digit (bit-mask) page once a day. Some jobs failed every day for known reasons, but that was OK. As long as the bit-mask of the page was the expected value, you could ignore it; you only had to get involved if an automated repair of something was attempted but failed (this only happened about once every six months).In retrospect, there were better ways to write that shell script, but it worked. Not only did all that nightly batch job validation and repair logic get encoded in the script (with lots of documentation of the what/how/why variety), but having rid ourselves of the need to deal with this daily mess freed up one man-day per day, and more importantly, allowed my boss to sleep later.One day, my boss was bragging to the managers of the other trading systems (that were 90% copy-pasted) that he no longer had to deal with this issue. Since they were still dealing with the daily batch-check, they wanted my script. Helping peer teams was considered a Good Thingâ„¢, so we gave them the script and showed them how it worked, along with a detailed list of things to change so that it would work with the specifics of their individual systems.About a week later, the support people on my team (including my boss) started getting nine different status pages in the morning - within seconds of each other - all with different status codes.It turns out the other teams only modified the program and data file paths for the monitored batch jobs that were relevant to their teams, but didn't bother to delete the sections for the batch jobs they didn't need, and didn't update the notification pager list with info for their own teams. Not only did we get the pages for all of them, but this happened on the one day in six months that something in our system really broke and required manual intervention. Unfortunately, all of the shell scripts attempted to auto correct our failed job. Without. Any. Synchronization. By the time we cleared the confusion of the multiple pages, figured out the status of our own system, realized something required manual fixing and started to fix the mess created by the multiple parallel repair attempts, there wasn't enough time to get it running before the start of business. The financial users were not amused that they couldn't conduct business for several hours.Once everyone changed the notification lists and deleted all the sections that didn't apply to their specific systems, the problems ceased and those batch-check scripts ran daily until the systems they monitored were finally retired. [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
A Tapestry of Threads
A project is planned. Gantt charts are drawn up. Timelines are set. They're tight up against the critical path, because including any slack time in the project plan is like planning for failure. PMs have meetings. Timelines slip. Something must be done, and the PMs form a nugget of a plan.That nugget squeezes out of their meeting, and rolls downhill until it lands on some poor developer's desk.That poor developer was Alona."Rex is the lead architect on this," her manager said. "And the project is about 90% complete… but even with that, they're never going to hit their timeline. So we're going to kinda do an 'all hands' thing to make sure that the project completes on time."Alona was a junior developer, but even with that, she'd seen enough projects to know: slamming new resources onto a project in its final days never speeds up its completion. Even so, she had her orders.Alona grabbed the code, checked the project backlog, confirmed her build environment, and then talked to the other developers. They had some warnings."It uses a lot of threads, and… well, the thread model is kinda weird, but Rex says it's the right way to do this.""I don't understand what's going on with these threads, but I'm sure Rex could explain it to you.""It's heavily CPU bound, but we're using more threads than we have cores, but Rex says we have to do it that way in order to get the performance we need."Alona had never met Rex, but none of that sounded good. The first tasks Alona needed to grab off the backlog didn't have anything to do with the threads, so she spent a few days just writing code, until she picked up a bug which was obviously caused by a race condition.From what she'd seen in the documentation and the code, that meant the problem had to be somewhere in MainComputationThread. She wasn't sure where it was defined, so she just did a quick search for the term class MainComputationThread.It returned twenty hits. There was no class called MainComputationThread, though there was an interface. There were also classes which implemented that interface, named things like MainComputationThread1 and MainComputationThread17. A quick diff showed that all twenty of the MainComputationThreadn classes were 1,243 lines of perfectly identical code.They were also all implemented as singletons.Alona had never met Rex, and didn't want to, but she needed to send him an email and ask: "Why?"
Error'd: Truth in Errors
Jakub writes, "I'm not sure restarting will make IE 'normal', but yeah, I guess it's worth a shot."
CodeSOD: Knowledge Transfer
Lucio Crusca is a consultant with a nice little portfolio of customers he works with. One of those customers was also a consultancy, and their end customer had a problem. The end customer's only in-house developer, Tyrell, was leaving. He’d worked there for 8 years, and nobody else knew anything about his job, his code, or really what exactly he’d been doing for 8 years.They had two weeks to do a knowledge transfer before Tyrell was out the door. There was no chance of on-boarding someone in that time, so they wanted a consultant who could essentially act as a walking, talking USB drive, simply holding all of Tyrell’s knowledge until they could have a full-time developer.As you can imagine, the two week brain-dump turned into a two week “documentation crunch” as pretty much nothing had any real documentation. That lead to comments like:
CodeSOD: CDADA
If there’s one big problem with XML, it’s arguably that XML is overspecified. That’s not all bad- it means that every behavior, every option, every approach is documented, schematized, and defined. That might result in something like SOAP, which creates huge, bloated payloads, involves multiple layers of wrapping tags, integrates with discovery schemas, has additional federation and in-built security mechanisms, each of which are themselves defined in XML. And let’s not even start on XSLT and XQuery.It also means that if you have a common task, like embedding arbitrary content in a safe fashion, there’s a well-specified and well-documented way to do it. If you did want to embed arbitrary content in a safe fashion, you could use the <![CDATA [Here is some arbitrary content]]> directive. It’s not a pretty way of doing it, but it means you don’t have to escape anything but ]]>, which is only a problem in certain esoteric programming languages with rude names.So, there’s an ugly, but perfectly well specified and simple to use method of safely escaping content to store in XML. You know why we’re here. Carl W was going through some of the many, many gigs of XML data files his organization uses, and found:
CodeSOD: This Interview Doesn't Count
There are merits and disadvantages to including any sort of programming challenge in your interview process. The argument for something like a FizzBuzz challenge is that a surprising number of programmers can’t actually do that, and it weeds out the worst candidates and the liars.Gareth was interviewing someone who purported to be a senior developer with loads of Java experience. As a standard part of their interview process, they do a little TDD based exercise: “here’s a test, here’s how to run it, now write some code which passes the test.”The candidate had no idea what to make of this exercise. After about 45 minutes which resulted in three lines of code (one of which was just a closing curly bracket) Gareth gave the candidate some mercy. Interviews are stressful, the candidate might not be comfortable with the tools, everybody has a bad brainfart from time to time. He offered a different, simpler task.“Heres’s some code which generates a list of numbers. I’d like you to write a method which finds the number which appears in the list most frequently.”
Representative Line: Constantly True
An anonymous reader had something to share."I came across this code in a 13,000 line file called Constants.cs."
...29303132333435363738...