Thanks again to everyone who submitted a holiday tale for our What the Fun Holiday special. Like all good holiday traditions, our winner indulges in a bit of nostalgia for a Christmas classic, by adapting the classic "A Visit From St. Nicolas", a trick we've done ourselves. But like a good WTF, Lee R also mixes in some frustration and anger, and maybe a few inside jokes that we're all on the outside of. Still, for holiday spirit, this tale can't be beat.Now, our normal editorial standards avoid profanity, but in the interests of presenting the story as Lee submitted it, we're going to suspend that rule for today. It is, after all, the holidays, and we're all miserable.In December 2018, our distributed Sports app team at FOX was to the wall. We needed to release a new version with pay-per-view streaming before an immovable sporting event date in Q1. I frequently explained away my bugs and other failures by blaming our cats, since they walk on the keyboard and "write the code."I decided the team needed to loosen up and (again blaming the "codin' cats") posted the following on our main dev Slack channel right before Christmas break.
As we roll into the last few days before Christmas, it's time to share what our readers sent in for our "What the Fun Holiday" contest. It was a blast going through the submissions to see what our holiday experiences looked like.Before we dig in to our contest winners, our first honorable mention is to David N, who shared with us "The Worm Before Christmas", a classic from 1988 that was new to us.Our first runner up story comes from Mike. This is an Easter Tale, complete with a death, a resurrection, and thirty pieces of silver (or whatever amount you give highly paid consultants).
Dora's AngularJS team (previously) wanted to have their display be "smart" enough to handle whether or not you were editing a list of "Users" or just one "User", so they implemented a function to turn a plural word into a singular word.Which, of course, we already know the WTF implementation of it: they just chop off the last letter. So "Potatoes" becomes "Potatoe", "Moose" becomes the noise cows make, and I'm just left saying "oh, gees". But they managed to make it worse than that.The actual display might be used like so:
Web frameworks are a double edged sword. They are, as a rule, bloated, complicated, opinionated and powerful. You can get a lot done, so long as you stick to the framework's "happy path", and while you can wander off and probably make it work, there be dragons. You also run into a lot of developers who, instead of learning the underlying principles, just learn the framework. This means they might not understand broader web development, but can do a lot with Angular.And then you might have developers who don't understand broader web development or the framework they're using.Dora has someone on their team which meets that criteria.The first sign there was a problem was this line in a view object:
One of the best parts of doing software development is that you're always learning something new. Like, for example, I thought I'd seen every iteration on bad date handling code. But today, I learned something new.Katharine picked up a pile of tickets, all related to errors with date handling. For months, the code had been running just fine, but in November there was an OS upgrade. "Ever since," the users complained, "it's consistently off by a whole month!" This was a bit of a puzzle, as there's nothing in an OS upgrade that should cause date strings to be consistently off by a whole month. Clearly, there must be a bug, but why did it only now start happening? Katharine pulled up the C code, and checked.
Would you like to guarantee your project ends up on this site? Antoon's employer has a surefire technique. First, hire a freshly graduated architect with no programming experience. Second, chuck them into a project in a programming language they don't know. Third, give them absolutely no supervision and no guidance or support, and watch what happens.
There is no task so simple that a developer can't find a harder, more wasteful, and pointless way to do it. For example, let's say you want to know how many rows are in a data grid object?Hans found this C# snippet in production a few years ago:
Scott was new to the team, and so when a seemingly simple bug came in, he picked up the ticket. It should be an easy win, and help him get more familiar with the code base.The reported problem was that a user entered the time, and saved it. Several screens later, when that time was redisplayed, it was incorrect, off by some number of hours. Clearly, it was a small timezone issue, which should be easy to fix.Except that was easier said than done. Scott's company made a hosted service, and quite reasonably, each customer had their own database instance. But they also all had their own branch in source control. That's where things started to get problematic, as there was no coherent naming convention, each customer's version had its own customization and a blend of merges and cherry-picked commits that made it impossible to, at a glance, understand what was or wasn't deployed to any given branch.Once Scott figured out which branch to use, he stood up a simulation environment and tried to replicate the error. He entered the date. He checked the database- the date was stored correctly. He went to the screen which was incorrect, and saw that it was off- though by a totally different number of hours than the customer reported. On a different screen, however, the date displayed correctly. Digging through the code, the incorrect screen was adjusting the timezone from UTC to the local timezone, while the correct screens weren't doing any timezone adjustment.Confused, Scott went to his boss, Zofia. "I assume it's doing the adjustment when it shouldn't, but I'm just confused by why it's doing that?"Zofia sighed. "Because a very long time ago, I let the owner talk me into a very bad idea. We don't store timezone information with the times. Most of the time, we convert them to UTC and store that, and then convert to the local timezone on display. But because we were in a 'move fast and break things' phase, we didn't do that with all of our times. Some we just store in the local timezone- without storing any timezone info."The result is that a timestamp, stored in the database, might either be in the local timezone of the person who created the record, or might be in UTC, but you couldn't tell which by looking at the database. So you had to check the code which handled the storage and display. That code was in a twisted network of git branches, so for any given customer, the rules might be utterly different, and since commits were sometimes cherry-picked across branches (as a useful feature for one customer becomes useful for another), the rules might suddenly change if you weren't careful."Oh… that's… horrifying."Zofia nodded. "You think that's bad, keep in mind that our reporting engine is a third party product that doesn't use the branching structure we set up in git. One change to dates in the application could mean you spend the next few days tracking down every reference to it and making sure you're only making changes that impact the one customer and nobody else.""I… maybe I should pass this ticket off to someone else?" Scott was certainly a lot less interested in tackling this "simple" bug."Nah," Zofia said. "It'll be a good way to learn the codebase. This is what we do every day." [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Sometimes, our readers send us a story. Sometimes they send us some bad code. Sometimes, they just need a place to vent their frustrations. Paul T had some frustrations. Paul's team is migrating from .Net to .NetCore, and as one might imagine, that creates a lot of build failures.Their Team City build environment sometimes doesn't give the most helpful messages:
The power of a good devops team is that you can get fast, reliable, and repeatable deployments. It lays out a foundation for rapid iteration and quick releases. With that in mind, Lakeisha was pretty excited to start a new job working in devops.She walked in the door, with visions of well architected, scripted flows, robust automated testing, and strict architectural guidelines. About fifteen minutes in, she learn that FISI guided their entire devops workflow. If it worked, it worked.A few years back, someone had discovered MuleSoft's devops solutions and their "enterprise service bus". The ESB lets developers define "flows", which describe how messages pass between components in a large-scale, complex application.That much was fine, but no one on the team decided to learn how to do things in Mule's tools. Any time there was a new requirement, someone would say, "We can build a Mule flow for that!" They'd then dig through the existing flows for any similar components, copy-and-paste them in a new order to create their new flow, and once it looked like it mostly worked, deploy it and move on.Flows are designed in a graphical editor, but persisted as XML. Lakeisha sent us a block of common exception logging code, copy-and-pasted into every single flow.
CorpCo was a small company; it consisted of Tymeria, the president, and two programmers, Kylie and Ronnie. Kylie had seniority, having been working there for 6 or 7 years, but Ronnie, our submitter, had been working there a hefty 4 years herself. The company purchased a legacy VB web app from a client company, AClientCompany; AClientCompany had been working on the app for 15 years, with their lead programmer Michelle as the sole programmer. The app had been written in classic ASP using VBScript, though at some point Michelle had begun converting the project to ASP.NET with VB.NET. (Did you know you can mix and match classic ASP with ASP.NET and classic VBScript with VB.NET in the same solution? I didn't!). Of course, the app was riddled with security vulnerabilities, copypasta, and spaghetti code. One main class, called DBFunctions.vb, was over 30,000 lines!Fast forward to September 2019, shortly after CorpCo took over. The application involved multiple forms that customers had to fill out, some of which had customizable fields that the users could adjust on the fly. All of this was stored in a SQL Server database, hence DBFunctions.vb, the functions needed to pull data out of the database and render the forms for customers to enter and/or edit the forms by the internal users. A feature request came in to be able to mark some of the additional fields mandatory for completing the form: pretty basic stuff for a forms editor at heart. Ronnie wasn't familiar with the code, so she budgeted 13 story points, or just under a week.Before any of us dig into the code behind a project, we have certain basic assumptions about what we're going to find. Probably, form fields are stored in the database. Probably, there's a table for additional fields to which Ronnie could add a column in order to mark the field mandatory or optional. Probably, there's some identifier that marks the field as belonging to a specific form, and maybe even one for the order in which the questions go on the form so that order can be preserved. You know. Normal stuff.If those assumptions held up, we wouldn't be running this story, would we? As it turned out, instead of one AdditionalField table in the database, there were about 20 of them, one for each question type in the system. Why had Michelle done it this way? When Ronnie shot her an email, she replied sheepishly that she was concerned about the table getting to be "too big." "We don't want to get into big data territory," she said, proving that she knew nothing about big data and very little about databases.But whatever. Ronnie added a Mandatory column to each of the tables, updating all the SQL queries that were hardcoded inline without parameterization in the DBFunctions.vb file. Then she added a checkbox on each of the additional field edit screens, one for each type of question. She added JavaScript validation to the fields, though some of them (the checkbox lists in particular) didn't play nice with jQuery's validator, so she had to add custom code for those boxes. So finally, she finished, sat back, and ran the program to do her basic developer sanity checks.And ... it didn't work. The checkbox showed up, but checking it seemed to do nothing.Her code was still all in a branch at this point, so she wasn't holding anything up by fiddling with it. So she spent the rest of the week fiddling, trying to figure out what she missed. But it still wasn't quite working. She asked Kylie to look at the code, but Kylie had literally never used VB before, having been primarily a C#.NET developer. She asked Tymeria, but she was too busy with other projects to spend much time looking at it. So there wasn't much help to be had.And so the branch just ... rotted.It's now the end of 2020, over a year since the feature was requested. The branch is still languishing, rotting away. There's only a few bugs at this point, but nobody's able to quite figure them out and there's no more help to be had. There's been numerous other bug fixes and feature requests, and the code's been cleaned up a bit and a refactor is in the works. There's even an experimental branch where they imported a bunch of C# code to replace some of the worst bits of VBScript. But this branch is still sitting out there, languishing. Will CorpCo ever finish the feature request? Maybe.Probably not. But maybe.Only 3 days left before the auto-closer closes the ticket as "stale" ... [Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
You've got one week left to teach us the real meaning of WTFmas. What's your holiday tale that we'll revisit winter after winter?Can you teach us the true meaning of WTFMas?What We WantWe want your best holiday story. Any holiday is valid, though given the time of year, we're expecting one of the many solstice-adjacent holidays. This story can be based on real experiences, or it can be entirely fictional, because what we really want is a new holiday tradition.The best submissions will:
A few months ago, Lee was reviewing a pull request from Eddie. Eddie was a self-appointed "rockstar" developer. Eddie might be a "junior" developer in job title, but they're up on the latest, greatest, bestest practices, and if everyone would just get out of Eddie's way, the software would get so much better.Which is why the pull request Lee was looking at touched nearly every file. Every change was some variation of this:
It was Paramdeep's first corporate IT job. He was assigned a mentor, Rajiv, who would train him up on the application he would be supporting: a WebSphere-based Java application full of Enterprise Java Beans.Paramdeep reserved time with Rajiv in Outlook, arranging to meet at Rajiv's cubicle for half an hour. Rajiv accepted. At the agreed-upon time, Paramdeep walked over with a notebook and pencil in hand, intent on copying down all the pertinent information he would hear. When he reached Rajiv's desk, however, the elder developer waved Paramdeep away from his spare chair before he had a chance to sit down."Sorry, more urgent stuff came up," Rajiv said, turning back to his monitor. "The best way to learn about the application is to dive right in. I'll give you one of the simpler tasks. All you need to do is write a bean that'll call a Sybase stored procedure to get the next sequence ID of a domain table, then create the next object based on that ID."Paramdeep stood there wide-eyed and frozen, pencil hovering uselessly over paper. "What?""I've already built an EJB for the database connection layer and all the handling code," Rajiv continued, still intent on his screen. "There's also a stored procedure in the common schema for getting the ID. You just have to put them all together.""Uh—?""I'll send an email with the relevant class names," Rajiv cut him off."OK. I'll, uh, let you know if I have any trouble?"Rajiv was too caught up in his urgent business to respond.Paramdeep staggered back to his desk: scared, confused, and a bit dejected. But hey, maybe Rajiv was right. Once he dove into the code, he'd have a better understanding of what to do. He'd done JDBC before. It wasn't hard.Unfortunately, there was a stark difference between a computer science student's homework assignments and the inner workings of a creaky, enterprisey corporate behemoth. Try as he might, Paramdeep simply couldn't connect to the database schema Rajiv had told him about. He was connecting to a default schema instead, which lacked the stored procedure he needed. All of Paramdeep's attempts to solicit help from Rajiv—whether emailed, messaged, or sought in person—met with failure. His boss promised to get Rajiv talking, but that promise never materialized into Paramdeep and Rajiv spending quality time together.A strict deadline was looming. Desperate times called for desperate measures. Paramdeep emailed the database developer, Amita, suggesting his solution: creating a new stored procedure to call and return the value from the actual stored procedure, which would then return the value to his new bean.Minutes later, his phone rang. Caller ID showed it was Amita."You can't possibly want this!" she declared without preamble. "Just use the stored procedure in the schema.""I can't connect to it," Paramdeep explained."What do you mean, you can't?""I just can't!""Who's the tech lead on this project?""Rajiv.""Ohhh." A weary understanding permeated her tone, taking all the fight out of it. "OK, I get it. Fine, I'll make a synonym in the default schema."And that was why the ID generating procedure also existed in the default schema. Paramdeep couldn't help but wonder how many of the procedures in the default schema had gotten there this way. [Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
Part of the pitch of Python is that it's a language which values simplicity and ease of use. Whether it lives up to that pitch is its own discussion, but the good news is that if you really want to create really complex code with loads of inheritance and nasty interrelationships, you can.Today's anonymous submitter started out by verifying some of the math in some extremely math-y analytical code. Previously, they'd had problems where the documentation and the code were subtly different, so it was important that they understood exactly what the code was doing.In one file, they found the core class they cared about:
As we all know, managing null values is its own challenge, especially when you're working in a functional style. So as languages like .NET add functional approaches like LINQ extension methods, they also add null coalescing operators and nullable types, making it easy to pass values around without getting surprised by an unexpected null.Unless you're whoever wrote the code that Abbie found, because they've managed to keep some surprises.
"In Poland, if you test positive for COVID-19, or come in contact with someone who has, you must stay home for a mandatory 10-day quarantine. During that time, you must use the government's mobile app named 'Home Quarantine' which tracks your location and requires you to send a selfie every couple of hours," wrote Jan K., "The app also reports if you are using a GPS spoofing app. For example, in this screenshot, it has detected a location spoofing app by the name of ...'Calendar'. Naturally, there are stiff penalties for violating rules of your quarantine like this. Also, as expected, there is no appealing the 'findings' of a buggy app like this."
A fair bit of "bad code" requires at least a passing understanding of the language in question, or the domain involved. But bad comments transcend programming languages. Vilx sends us this one, which comes from code which is definitely running in production.
Octavia (previously) didn't just inherit a C# application with dodgy approaches to string handling. It's also an application with questionable understandings of CSS.CSS is far from perfect, and offers a lot of pitfalls and traps. There's a reason the "impossibility" of vertically centering text is a punchline. It's so flexibly declarative that, in many cases, there are many ways to achieve the same styling result, and it's difficult to pick out the correct one. But one would hope that developers could at least avoid the obviously terrible ones.
Octavia inherited a decade old pile of C#, and the code quality was pretty much what one would expect from a decade old pile that hadn't seen any real refactoring: nothing but spaghetti. Worse, it also had an "inner platform" problem, as everything they put in their API could conceivably be called by their customers' own "customizations".One small block caught her eye, as suspicious:
Skill which you don’t use regularly can get rusty. It might not take too much to get the rust off, and remind yourself of what you’re supposed to be doing, but the process of remembering what you’re supposed to do can get a little… damaging.Lesli spent a big chunk of her career doing IT for an insurance company. They were a conservative company in a conservative industry, which meant they were still rolling out new mainframes in the early 2000s. “Big iron” was the future for insurance.Until it wasn’t, of course. Lesli was one of the “x86 kids”, part of the team that started with desktop support and migrated into running important services on commodity hardware.The “big iron” mainframe folks, led by Erwin, watched the process with bemusement. Erwin had joined the company back when they had installed their first S/370 mainframe, and had a low opinion of the direction the future was taking. Watching the “x86 kids” struggle with managing growing storage needs gave him a sense of vindication, as the mainframe never had that problem.The early x86 rollouts started in 2003, and just used internal disks. At first, only the mail server had anything as fancy as a SCSI RAID array. But as time wore on, the storage needs got harder to manage, and eventually the “x86 kids” rolled out a SAN.The company bought a second-hand disk array and an expensive support contract with the vendor. It was stuffed with 160GB disks, RAIDed together into about 3TB of storage- a generous amount for 2004. Gradually every service moved onto the SAN, starting with file servers and moving on to email and even experiments with virtualization.Erwin just watched, and occasionally commented about how they’d solved that problem “on big iron” a generation ago.Storage needs grew, and more disks got crammed into the array. More disks meant more chances for failures, and each time a disk died, the vendor needed to send out a support tech to replace it. That wasn’t so bad when it was once a quarter, but when disks needed to be replaced twice a month, the hassle of getting a tech on-site, through the multiple layers of security, and into the server room became a burden.“Hey,” Lesli’s boss suggested, circa late 2005. “Why don’t we just do it ourselves? They can just courier over the new drives, and we can swap and initialize the disk ourselves.”Everyone liked that idea. After a quick round of training and confirmation that it was safe, that became the process. The support contract was updated, and this became the process.Until 2009. The world had changed, and Erwin’s beloved “big iron” was declining in relevance. Many of his peers had retired, but he planned to stick it out for a few more years. As the company retired the last mainframe, they needed to reorganize IT, and that meant all the mainframe operators were now going to be server admins. Erwin was put in charge of the storage array.The good news was that everyone decided to be cautious. Management didn’t want to set Erwin up for failure. Erwin, who frequently wore both a belt and suspenders, didn’t want to take any risks. The support contract was being renegotiated, so the vendor wanted to make sure they looked good. Everyone was ready to make the transition successful.The first time a disk failed under Erwin’s stewardship, the vendor sent a technician. While Erwin would do all the steps required, the technician was there to train and supervise.It started well. “You’ll see a red light on the failed disk,” the technician said.Erwin pointed at a red light. “Like this?”“Yes, that exactly. Now you’ll need to replace that with the new one.”Erwin didn’t move. “And I do that how? Let’s go step-by-step.”The tech started to explain, but went too fast for Erwin’s tastes. Erwin stopped them, and forced them to slow it down. After each step, Erwin paused to confirm it was correct, and note down what, exactly, he had done.This turned a normally quick process into a bit of a marathon. The marathon got longer, as the technician hadn’t done this for a few years, and was a bit fuzzy on a few of the steps for this specific array, and had to correct themselves- and Erwin had to update his notes. After what felt like too much time, they closed in on the last few steps.“Okay,” the tech said, “so you pull up a web browser, go to the admin page. Now, login. Great, hit ‘re-initialize’.”Erwin followed the steps. “It’s warning me about possible data loss, and wants me to confirm by typing in the word ‘yes’?”“Yeah, sure, do that,” the tech said.Erwin did.The tech thought the work was done, but Erwin had more questions. Since the tech was here, Erwin was going to pick their brain. Which was good, because that meant the tech was still on site when every service failed. From the domain service to SharePoint, from the HR database to the actuarial modeling backend, everything which touched the SAN was dead.“What happened,” Erwin demanded of the tech.“I don’t know! Something else must have failed.”Erwin grabbed the tech, Lesli, and the other admins into a conference room. The tech was certain it couldn’t be related to what they had done, so Erwin escalated to the vendor’s phone support. He bulled through the first tier, pointing out they already had a tech onsite, and got to one of the higher-up support reps.Erwin pulled out his notes, and in detail, recounted every step he had performed. “Finally, I clicked re-initialize.”“Oh no!” the support rep said. “You don’t want to do that. You want to initialize the disk, not re-initialize. That re-inits the whole array. That’s why there’s a confirmation step, where you have to type ‘yes’.”“The on-site tech told me to do exactly that.”The on-site tech experience what must have been the most uncomfortable silence of their career.“Oh, well, I’m sorry to hear that,” the support rep said. “That deletes all the header information on the array. The data’s still technically on the disks, but there’s no way to get at it. You’ll need to finish formatting and then recover from backup. And ah… can you take me off speaker and put the on-site tech on the line?”Erwin handed the phone over to the tech, then rounded up the admins. They were going to have a long day ahead getting the disaster fixed. No one was in the room to hear what the support rep said to the tech. When it was over, the tech scrambled out of the office like the building was on fire, never to be heard from again.In their defense, however, it had been a few years since they’d done the process themselves. They were a bit rusty.Speaking of rusty, while Erwin continued to praise his “big iron” as being in every way superior to this newfangled nonsense, he stuck around for a few more years. In that time, he proved that he might never be the fastest admin, but he was the most diligent, cautious, and responsible. [Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
Long-lived projects can have… interesting little corners. Choices made 13 years ago can stick around, either because they work well enough, or because, well, every change breaks somebody's workflow.Today's anonymous submitter was poking around the code base of a large, long-lived JavaScript framework. In a file, not modified since 2007, but still included in the product, they found this function.
Time just flies right past, and before you know it, the holidays will be here. Which is why you had better hurry up and try your hand at giving us the best WTF Christmas Story ever, to help us found a new holiday tradition. Or at least, give us one bright spot in the yawning abyss of 2020.Can you teach us the true meaning of WTFMas?What We WantWe want your best holiday story. Any holiday is valid, though given the time of year, we're expecting one of the many solstice-adjacent holidays. This story can be based on real experiences, or it can be entirely fictional, because what we really want is a new holiday tradition.The best submissions will:
Alleen started by digging into a PHP method which was just annoying. _find_shipment_by_object_id would, when it couldn't find the ID, return false, instead of the more expected null. Not terrible, but annoying. Worse, it didn't return the shipment eihter, just a key which could be used to fetch a shipment from an array.Again, all that's just annoying.It was when looking at the delete_shipment method that Alleen had the facepalm moment.
Cicely (previously) returned to the codebase which was providing annoyances last time.This time, the code is meant for constructing objects based on a URL pattern. Specifically, the URL might have a format like api/resource/{id}. Looking at one of the constructors, though, it didn’t want an ID, it wanted an array of them. Cicely wasn’t passing multiple IDs off the URL, and wasn’t clear, from the documentation, how it worked, how you supplied those IDs, or frankly, what they were used for. Digging into the C# code made it clear, but still raised some additional questions.
Marlyn’s employer ships software for a wide variety of CPU architectures. And depending on which branch of the product you were digging into, you might have code that builds for just i386, x86_64, PPC, and PPC64, while another branch might add s390, s390x, and aarch64.As you might imagine, they have a huge automated test suite, meant to ensure that changes don’t break functionality or compatibility. So it’s a pity that their tests were failing.The error messages implied that there were either missing or too many files, depending on the branch in question, but Marlyn could see that the correct build outputs were there, so nothing should be missing. It must be the test suite that had the error.Marlyn dug into the Python script which drove their tests, and found the get_num_archs function, which theoretically would detect how many architectures this branch should output. Unfortunately, its implementation was straight out of XKCD.
Russell F sends us this C# "fuction", and I have to be honest: I have no idea what it's supposed to do. I can trace through the logic, I can see what it does, but I don't understand why it does it.
As a personal perspective, I don't tend to believe that mastery of a programming tool is nearly as important as mastery of the codebase and problem domain you're working on. But there are some developers who just don't want to learn the codebase or what other developers are doing.Take Jessica's latest co-worker, which is similar to some previous co-workers. In this case, there was a project in flight that was starting to fall behind schedule. Management did what management does in this situation: they threw warm bodies at the project and ensured that it fell further behind.Brant was one of those warm bodies, and Brant did not want to learn what was already in the code base. He was going to do part of the JavaScript front end, he was going to rush to get it done, and he was going to copy-paste his way through.Which lead to this:
In .NET, if you want to get the first item from an IList object, you could just use the index: list[0]. You also have a handy-dandy function called First, or even better FirstOrDefault. FirstOrDefault helpfully doesn’t throw an exception if the list is empty (though depending on what’s in the list, it may give you a null).What I’m saying is that there are plenty of easy, and obvious ways to get the first element of a list.Stevie’s co-worker did this instead:
The holidays are a time of traditions, but traditions do change. For example, classic holiday specials have gone from getting cut down for commercials, to getting snapped up by streaming services. Well, perhaps it's time for a new holiday tradition. A holiday tradition which includes a minor dose of… WTF.We're happy to announce our "Worse Than Failure Holiday Special" Contest. This is your chance to submit your own take on a very special holiday story. Not only is it your chance to get your place in history secured for all eternity, but also win some valuable prizes.What We WantWe want your best holiday story. Any holiday is valid, though given the time of year, we're expecting one of the many solstice-adjacent holidays. This story can be based on real experiences, or it can be entirely fictional, because what we really want is a new holiday tradition.The best submissions will:
When it comes to backwards compatibility, Microsoft is one of those vendors that really commits to it. It’s not that they won’t make breaking changes once in awhile, but they recognize that they need to be cautious about it, and give customers a long window to transition.This was true back when Microsoft made it clear that .NET was the future, and that COM was going away. To make the transition easier, they created a COM Interop system which let COM code call .NET code, and vice versa. The idea was that you would never need to rewrite everything from scratch, you could just transition module by module until all the COM code was gone and just .NET remained. This also meant you could freely mix Visual Basic and Visual Basic.Net, which never caused any problems.Well Moritz sends us some .NET code that gets called by COM code, and presents us with the rare case where we probably should just rewrite everything from scratch.
One of the lines between code that's "not great, but like, it's fine, I guess" and "wow, WTF" is confidence.For example, Francis Gauthier inherited a WinForms application. One of the form fields in this application was a text box that held a number, and the developers wanted to always display whatever the user entered without leading zeroes.Now, WinForms is pretty simplistic as UI controls go, so there isn't really a great "oh yes, do this!" solution to solving that simple problem. A mix of using MVC-style patterns with a formatter between the model and the UI would be "right", but might be more setup than the problem truly calls for.Which is why, at first blush, without more context, I'd be more apt to put this bad code into the "not great, but whatever" category:
Cloud management consoles are, in most cases, targeted towards enterprise customers. This runs into Remy’s Law of Enterprise Software: if a piece of software is in any way described as being “enterprise”, it’s a piece of garbage.Richard was recently poking around on one of those cloud provider’s sites. The software experience was about as luxurious as one expects, which is to say it was a pile of cryptically named buttons for the 57,000 various kinds of preconfigured services this particular service had on offer.At the bottom of each page, there was a small video thumbnail, linking back to a YouTube video, presumably to provide marketing information, or support guidance for whatever the user was trying to do.This was the code which generated them (whitespace added for readability):
TypeScript offers certain advantages over JavaScript. Compile time type-checking can catch a lot of errors, it can move faster than browsers, so it offers the latest standards (and the compiler handles the nasty details of shimming them into browsers), plus it has a layer of convenient, syntactic sugar.If you’re using TypeScript, you can use the compiler to find all sorts of ugly problems with your code, and all you need to do is turn the right flags on.Or, you can be like Quintus’s co-worker, who checked in this… thing.
Understanding the Gang of Four design patterns is a valuable bit of knowledge for a programmer. Of course, instead of understanding them, it sometimes seems like most design pattern fans just… use them. Sometimes- often- overuse them. The Java Spring Framework infamously has classes with names like SimpleBeanFactoryAwareAspectInstanceFactory. Whether that's a proper use of patterns and naming conventions is a choice I leave to the reader, but boy do I hate looking at it.The GoF patterns break down into four major categories: Behavioral, Structural, Concurrency, and Creational patterns. The Creational category, as the name implies, is all about code which can be used to create instances of objects, like that Factory class above. It is a useful collection of patterns for writing reusable, testable, and modular code. Most Dependency Injection/Inversion of Control frameworks are really just applied creational patterns.It also means that some people decide that "directly invoking constructors is considered harmful". And that's why Emiko found this Java code:
If we presume there is a Hell for IT folks, we can only assume the eternal torment involves configuring or interfacing with printers. Perhaps Anabel K is already in Hell, because that describes her job.Anabel's company sells point-of-sale tools, including receipt printers. Their customers are not technical, so a third-party installer handles configuring those printers in the field. To make the process easy and repeatable, Anabel maintains an app which automates the configuration process for the third party.The basic flow is like this:The printer gets shipped to the installer. At their facility, someone from the installer opens the box, connects the printer to power, and then to the network. They then run the app Anabel maintains, which connects to the printer's on-board web server and POSTs a few form-data requests. Assuming everything works, the app reports success. The printer goes back in the box and is ready to get installed at the client site at some point in the near future.The whole flow was relatively painless until the printer manufacturer made a firmware change. Instead of the username/password being admin/admin, it was now admin/serial-number. No one was interested in having the installer techs key in the long serial number, but digging around in the documentation, Anabel found a simple fix.In addition to the on-board web-server, there was also a TCP port running. If you connected to the port and sent the correct command, it would reply with the serial number.Anabel made the appropriate changes. Now, her app would try and authenticate as admin/admin, and if it failed, it'd open a TCP connection, query the serial number, and then try again. Anabel grabbed a small pile of printers from storage, a mix of old and new firmware, loaded them up with receipt paper, and ran the full test suite to make sure everything still worked.Within minutes, they were all happily churning out test prints. Anabel released her changes to production, and off it went to the installer technicians.A few weeks later, the techs call in through support, in an absolute panic. "The configuration app has stopped working. It doesn't work on any of the printers we received in the past few weeks."There was a limited supply of the old version of printers, and dozens got shipped out every day. If this didn't get fixed ASAP, they would very quickly find themselves with a pile of printers the installers couldn't configure. Management got on conference calls, roped Anabel in on the middle of long email chains, and they all agreed: there must be something wrong with Anabel's changes.It wasn't unreasonable to suspect, but Anabel had tested it thoroughly. Heck, she had a few of the new printers on her desk and couldn't replicate the failure. So she got on a call with a tech and started from square one. Is it plugged in. Is it plugged into the network. Are there any restrictions on the network, or on the machine running the app, that might prevent access to non-standard ports?Over the next few days, while the stock of old printers kept dwindling, this escalated up to sending a router with a known configuration out to the technicians. It was just to ensure that there were no hidden firewalls or network policies preventing access to the TCP port. Even still, on its own dedicated network, nothing worked."Okay, let's double check the printer's network config," Anabel said on the call. "When it boots up, it should print out its network config- IP, subnet, gateway, DHCP config, all of that. What does that say?"The tech replied, "Oh. We don't have paper in it. One sec." While rooting around in the box, they added, "We don't normally bother. It's just one more thing to unbox before putting it right back in the box."The printer booted up, faithfully printed out its network config, which was what everyone expected. "Okay, I guess… try running the tool again?" Anabel suggested.And it worked.Anabel turned to one of the test printers she had been using, and pulled out the roll of receipt paper. She ran the configuration tool… and it failed.The TCP service only worked when there was paper in the printer. Anabel reported it as a bug to the printer vendor, but if and when that gets fixed is anyone's guess. The techs didn't want to have to fully unbox the printers, including the paper, for every install, but that was an easy fix: with each shipment of printers Anabel's company just started shipping a few packs of receipt paper for the techs. They can just crack one open and use it to configure a bunch of printers before it runs out. [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
It’s generally hard to do worse than a SQL injection vulnerability. Data access is fundamental to pretty much every application, and every programming environment has some set of rich tools that make it easy to write powerful, flexible queries without leaving yourself open to SQL injection attacks.And yet, and yet, they’re practically a standard feature of bad code. I suppose that’s what makes it bad code.Gidget W inherited a PHP application which, unsurprisingly, is rife with SQL injection vulnerabilities. But, unusually, it doesn’t leverage string concatenation to get there. Gidget’s predecessor threw a little twist on it.
About three years ago, Consuela inherited a giant .NET project. It was… not good. To communicate how “not good” it was, Consuela had a lot of possible submissions. Sending the worst code might be the obvious choice, but it wouldn’t give a good sense of just how bad the whole thing was, so they opted instead to find something that could roughly be called the “median” quality.This is a stored procedure that is roughly about the median sample of the overall code. Half of it is better, but half of it gets much, much worse.
The C# "extension method" feature lets you implement static methods which "magically" act like they're instance methods. It's a neat feature which the .NET Framework uses extensively. It's also a great way to implement some convenience functions.Brandt found some "convenience" functions which were exploiting this feature.