Feed the-daily-wtf The Daily WTF

Favorite IconThe Daily WTF

Link http://thedailywtf.com/
Feed http://syndication.thedailywtf.com/TheDailyWtf
Updated 2024-05-10 12:34
CodeSOD: The Core Class
We've had a bit of a run of PHP in the inbox lately, which is fine, but certainly isn't doing anything to help PHP's reputation as a WTF factory. This one comes from Lucio C, who was hired to fix a hacked WordPress installation.Much of the fixing was figuring out what data was safe to recover, what files may have been tampered with, and generally assessing the damage.While doing that assessment, Lucio found this perfectly legitimate file in a perfectly legitimate WordPress plugin. This file was not altered by the hackers, but…
CodeSOD: Filter Your Index
Nora found a curious little C# helper method. It was called in exactly one place and it is… not exactly necessary in any case.
Perfect Uptime
"So," Burt said, "our bonuses at the end of the year are based on our systems uptime?""Well," the middle manager introducing their new incentive program said, "not exactly. It's part of your team's performance targets, so we calcula-""Yeah, I get it," Burt said. "But your top tier goes up to 99.999% What about those of us who get 100% up-time?""Well, 100% is unreasonable to expect and-""Our phone system can. I set up the PBX myself. It's not going down. It's the most reliable system in the company. You should give a higher bonus to teams that can hit 100% uptime.""Ah…" The manager paused, nodded, and said, "I'll look into it," in the tone that made it quite clear that nothing was getting looked into but the conversation needed to move on.This was circa 2002, and Natalie had just joined Initech's operations team. Mostly, she was doing the unglamorous work of untangling the rats nets of Ethernet cables left by the last person in her position, discovering that spreadsheet containing server rack assignments was incorrect, and swapping in the new UPS system for the server room.The door next to the server room had two large buttons next to it. One of them was an accessibility button which would trigger the automatic door opener. This was useful for Natalie, when she had a cart-load of lead-acid batteries to replace. The second was the emergency stop button, which would cut power to everything in the server room.Now, everyone was quite aware that two similar buttons right next to each other but with wildly different functions was a problem. But upper management didn't want to spend money to alter the layout or replace the buttons with something to make them more visually distinct. But they needed to do something.So Burt, ever the problem solver, solved it. He cut a hole in the bottom of an old 5 1/4" floppy disk storage container, attached it to the wall over the emergency button, and demonstrated two features. First, by lifting the lid, you could easily and trivially access the emergency stop button. Second, it was just held in place with the weakest of drywall anchors and could easily be ripped from the wall in a real emergency. Someone decided that this was safe enough, and that "mitigated" the risk of an accidental shutdown.Near the time for yearly reviews, both Natalie and Burt happened to be doing some maintenance at a secondary site. Simultaneously, their phones rang: someone had pushed the big red button and shutdown the server room. They rushed back to address the problems that this caused, though something about the call stuck in Natalie's brain.Reviewing the security footage, later, the culprit was the "better idiot" who foils any idiot proof system: someone carrying a cart full of print outs walked right past the door-opener and spent several moments fiddling with the floppy disk case to figure out how to lift the lid and press the button inside.No one was concerned with the security footage when Burt and Natalie arrived. The server room was controlled chaos, as everyone was scrambling to manually reboot servers, resolve issues with machines not coming back up, and generally panicking-not-panicking because nobody had ever really tested a full recovery and no one was sure if their procedures worked.And that's when Natalie realized what struck her as odd about the phone call. It had come from one of the company numbers. One of the ones that ran through their PBX. The PBX was in the server room, it theoretically should have gone down when the emergency stop happened, but no- it had never rebooted, it had just hummed along quietly while everything else crashed.Natalie turned to Burt. "Wait, how is the PBX still up?""Oh, see that rack over there? It's got a rectifier and a bank of deep-cycle marine batteries. When the main UPS cuts out, our phone system has a backup power supply."In the yearly review, Burt's PBX system got a perfect 100% uptime rating. Burt's performance was not given equally high marks, though. Creating a fire hazard in the form of your own private battery bank and homebrew UPS, and not integrating with any of the key safety systems in the server room doesn't endear you to management.In the end, Burt got a scolding and a negative note in his employee file. His PBX got put on the main power supply, sharing the same main and backup power as everything else in the building. The next time someone accidentally pushed the big red button, Burt's phone system didn't maintain its improbable 100% uptime. [Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!
CodeSOD: Living Fossil
Checking browser compatibility is less of a thing these days than it once was. In an ideal world, we check for the specific features we want to use, and fallback to a different approach, or fail gracefully if they don't exist. We use shims and polyfills and pile on all sorts of logic to navigate this mess.What we hopefully don't do is use user-agent sniffing. The user-agent string is, honestly, one of the kludgiest, messiest, and just generally offensive ways to divine browser behavior. It was, however, once the standard, and thus there is still plenty of code, usually older code, which does use user-agent sniffing.Which brings us to this code, from Megan. It comes from the admin application for a major logistics company for a European nation. This logistics company handles 90% of deliveries for books within that nation's borders, and is notorious for its buggy software, its habit of just dropping orders with no explanation, and generally being an unstable mess where you may have to try six times before your order goes through.
Error'd: Synchronicity
Due to a chance astrological alignment, two famously alcoholicholidays collided Thursday. Your editor, along with scores of ecumenicists, atheists, heretics and other drunkards, took theopportunity to get plotzed, plastered, schnockered or fershnikitin every tradition possible. This poor column is the proof.Ruleoneian Colin has an interest in travel to far-off places, musing "I wonder what the currency in Rule-6 is."
CodeSOD: Extended and Empty
We've discussed extension methods in .NET in the past. If you write a method with a signature like public static void foo(this string input), then you can invoke this method like myString.foo(). It acts like an instance method to a caller, but it really just invokes foo(myString). It's a nice way to inject functionality into existing classes, and many .NET libraries use this feature.Esromhaz's co-worker found an… application of this.
CodeSOD: Rename This
Visual Basic .NET is actually not a terrible language. I don't think it'd ever be anyone's favorite language, and these days it's basically deceased, but it's essentially C# with verbose syntax. Even the APIs are identical…… almost.Because, you see, when Microsoft released VB .NET, their core plan was that it should be "easy" to port your existing VB6 code into VB .NET. This meant recreating a lot of static functions in the global namespace, like Mid (substring), or Kill (file delete). There were better, cleaner ways to do all of those things. For example, Kill throws an exception if you try and delete a file that doesn't exist, while File.Delete doesn't (but provides a status code).So while you should use the newer APIs, you could still do things the old fashioned way. It was like GoTo- you shouldn't use it, but you could.Russell F inherited some code which has all of these fun tricks.
Court-Martial
At the age of 17, our friend Argle had a job as a programmer for an aerospace firm, mostly working with commercial flight-deck equipment. Like with anyone new to a given industry, he found himself puzzling over the plethora of acronyms that got thrown around in conversation without a thought. Lacking an Internet to go look these things up in, Argle was forced to ask people to stop, go back, and explain. But what 17 year-old feels comfortable interrupting much older adults like that? Most of the time, the acronyms were scribbled down on a yellow legal pad, to be figured out later.The programming side of the job was no problem, at least. There was one case of something a little odd: someone handed him some coefficients of a polynomial and told him to make them into a FORTRAN function. He had no familiarity with curve fitting, but that part of the work had already been done for him. He implemented the function and moved on to other things. Some weeks later, he was working at his cube when a stern voice behind him caught his attention. "Mr. Argle."It was that tone of voice specifically reserved for calling someone to the carpet, and it made his viscera plummet. Swiveling around in his chair, he beheld a dozen people or more crammed all along the perimeter of his cube and spilling into its cramped confines. Some were in fancy business suits, some in full military regalia. All were wearing the most furious expressions he'd ever seen.Argle must've started an inch out of his chair."Mr. Argle." The military man closest to him spoke again, this time with the full weight of his glare bearing down on him. "We have jets that won't fly because of you.""Me?" Argle sputtered. "But—""That FORTRAN polynomial function we assigned to you!" another voice piped up. "That has to be it! You either made a mistake because you were careless, incompetent, or for some worse reason.""That?!" Argle's brain raced faster than it had ever raced before. "No! Here!" He swiveled to face his desk and sifted through a pile of folders sitting there. He'd been good about documenting all his work thus far, detailing the whats, whys, and hows. It took him a minute, as his hands shook and his panicked brain had trouble processing the words he looked at, but he was able to find his notes, along with the original coefficients that had been handed to him. He all but heaved the assembled evidence toward his prosecutors. "Here! This is all I did, I swear!"The tight crowd of higher-ups crowded even tighter around the papers, muttering inaudibly to one another and occasionally coughing. Their collective wrath dissipated, leaving behind an awkward gap of silence. At last, someone said a simple "Thanks" and handed the papers back to Argle. They marched off together, presumably to do this all over again to another poor soul who lacked adequate shielding.Argle heaved a sigh of relief. That day, he learned that the most important business-related acronym is and always shall be CYA. [Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
CodeSOD: When You Can't Use WordPress
Initech had a lovely little Content Management System built by a third party that was good at "building" CMSes. That is to say, this company knew its way around a WordPress template.When Initech needed a new public-facing website, they went straight back to that vendor. Now, this new website was a complicated statistical tool, with all sorts of complicated business rules and requiring a large amount of custom programming. So the vendor that just cranked out WordPress templates may not have been a good fit for the project, but that didn't stop anybody.That's how Magnus M found code which looks like this:
Error'd: Past Time
This week we're throwing a bone to all the antipunsters in the audienceand declaring a unilateral cease-fire on all alliteration, wordplay,jabs, jokes, or other japery. Starting now.Allie shares a redundancy that I think we've seenhere before, saying"It may be _technically_ right, but I don't have to like it."
CodeSOD: Constantly Sinister
Cat has some Java code which handles text layout. Now, someone writing the code didn't understand the idea of enumerated types, so every constant is a string.That's a nuisance, but not a terrible problem. Of course, with Java's String handling, you also run into the fact that == will frequently work, because Java tries to reuse String instances, but it won't always work, and thus equals exists.So this code didn't actually work:
CodeSOD: Wear a Wrap
While jQuery isn't as popular today as it once was, its still a widely used "utility belt" library. Its popularity arises from the fact that it takes cumbersome APIs and wraps convenience functions around them.But what if those convenience functions are too convenient, like Ryan's co-worker found. For example, if you want to perform an asynchronous HTTP request using jQuery, you could do something like:
CodeSOD: Hey, Backoff!
The Strategy Pattern, like any other design pattern, is supposed to help us write code that's flexible and easy to modify. In the case of the strategy pattern, you have one class, the Context, which has a member which implements a Strategy interface. The actual implementation lives in the Strategy, but the Context is the object that other code in the program consumes. Ideally, this means that you can change the behavior of your Context by simply swapping a different Strategy implementation in.On the flip side, when it gets out of hand, you might end up like Dotan, consuming an API from a major cloud vendor, written with a terminal case of "Pattern Brain".
CodeSOD: Administrative Transfer
When the pandemic started, a lot of companies needed to cut back, and Initech was no exception. In the Before Times™, Initech had an offshore development team that maintained an application inherited from an acquisition. Now that everyone was tightening their belts, though, that had to go. The offshore team was released and the application they supported ended up in the hands of Lovelace.Lovelace dug in, and they quickly discovered a few things. From 2010-2017, the application's idea of source control was a folder on an FTP server and a lot of files named some_module.php.old and some_module.php.donotuse. In 2017, someone put the project into Git, but the commits were just point-in-time snapshots of the FTP folder. Deployment? Just work right on that FTP folder, it's fine. And if you forget to commit those changes back to source control? No biggie- consider the FTP folder the source of truth.Then again, when Lovelace saw the "truth" that was there, they weren't exactly excited to be supporting this PHP application.
Error'd: The Hardest Problem
It has been infamously stated that the two hardest problemsin computer science are naming, caching, and off-by-one errors. Mixing and matching arrays indexed from 0 with arrays indexedfrom 1 could be a special-case of the off-by-one error.The zeroth of a sudden rash of anonymous posters spotted this initial example, coughing "Pre-increment seems somehowinappropriate here."
CodeSOD: A Cup of CIDR
Marco sends us some code that he wrote, back in the far off days of 2003. He wrote some code to handle network addresses. Unfortunately, it never quite worked. Specifically it could only handle addresses in the /24 subnet.Now, this was written in Perl, so you know it involves regexes.
CodeSOD: A Forgotten Memory
Starting in 1985, a tiny little language called Clipper briefly conquered the world. It was a dBase-derivative, with the bonus that its programs could be compiled and run as stand-alone software on MS-DOS. That meant small programs which couldn't justify getting time on a mainframe or a minicomputer could be whipped up to run on a desktop. It was popular, and for about a decade, it was everywhere. Then Windows 95 came out, and Clipper refused to pivot to Windows and became a footnote in history.It mostly worked pretty great, or at least as great as one of those tiny business-focused languages ever got. Unfortunately for Drake, he encountered some issues in the latter days of Clipper in the early 90s.Drake's team wrote an image display library for Clipper programs. An end-user of their library complained that it crashed when displaying images. They supplied a sample program that replicated the issue, and Drake and his colleagues were able to repeat the issue.The core pattern was: allocate memory for an image, display the image, release the memory. Repeat that a few times, and eventually it crashed. There were a few other memory allocations along the way, and they all went through Clipper's memory manager.So Drake and his team started stripping back their code, commenting out operations until they had a bare minimum program which could replicate the crash. By the time they were finished, the only code left was the code which allocated memory and released it. The simple test case program simply performed a series of memory allocations and releases, and repeated that, printing out the iteration number.On some machines, the program crashed after 22 iterations. On others, it crashed after 151. It was consistent, always crashing on the same iteration on the same machine. Machines with otherwise identical hardware could end up being in either the 22 or the 151 group. A consistent program to reproduce the bug meant that Drake had something to send Nantucket, the company making Clipper.Drake explains what happens next:
CodeSOD: It's Not None of Your Business is True
Patricia's employer hired her because she knew Python. They were a Python shop, at least at this point, but they'd never actually hired a developer with Python experience before.At some point, their PHP developer wanted to branch out, and decided to solve a problem using a small Python script. It was very successful, and features got added to it. In a surprisingly short amount of time, the script expanded until it was two separate web applications which were absolutely critical to business operations.It was a bit of a mess, when Patricia took over. The code was split across three source control repositories. One was for "Application A", in its entirety. One was called "Application B Backend", which as the name implied was the backend of Application B. The third was called "Application B" and was described as the "front end" but it was actually a copy of "Application B Backend".It was 40,000 lines of copy-pasted nonsense, and the core of it was a module called "gsf" or "general standard functions". It was almost all of the shared logic across modules. It was designed so that it never raised an exception, and instead every method that could possibly have to deal with an exception condition instead returned a tuple: (actualReturnValue,successBoolean). Thus, you could invoke something like this:
CodeSOD: Switch Kicker
As covered previously, game code generally doesn't represent an interesting WTF. But bad e-commerce code certainly does. So today, Rhys sends us some JavaScript from a web-based fantasy-football (for non-USA values of football) site. Given that it handles microtransactions and in-game items passed between players, it's definitely more on the e-commerce side of things than anything else.And much like that previous article, this one does involve a very large switch, but before we get to the switch, we have to get to the state validator:
Error'd: Down the Rarebit Hole
This week's Error'd episode includes a bonus submissionfrom our good friend A. Bargle, at no extra charge. TRWTF is inthe browser, perhaps, but it's just so gosh darn funny.It's likely that what tickles me is entirely inscrutableto all of you(especially those coming to English as a second language),and if so, I apologize.But at least one of us is having a good time!Not actually a hydrologistCarl C. has uncovered evidence of an entirecadre of wayward rivers roamin' the wikipedian underground."I got so excited by this that I forgot why I was lookingup the Nueces River on Wikipedia." It's not justthe poor lost Rubicon!
Double Bagged
Many years ago, Yazeran needed to work with some floor-plan data. Now, fortunately for Yazeran, a vendor had already collected this information and packed it up behind a SOAP-based web service, so it would in theory be easy to get. This was long enough ago that SOAP was all the rage, and computers with multiple gigabytes of RAM were still on the higher end of things.In fact, there was an end-point called GetFullDataExtract which promised to, as the name implies, get him all the data. Yazeran didn't need all the data, but the other end-point, GetGMLBuildings returned only the subset of data Yazeran didn't need. So Yazeran simply had to request too much.Yazeran fired up a wget session with all the appropriate credentials and waited. And waited. And waited…When the 20MB XML response finally downloaded, minutes later, it looked like this:
CodeSOD: A Commentary on Military Force
Once upon a time, Simon worked for a company making software for missile systems. This was serious work, with serious testing procedures, and important standards around documentation.Shortly before a live-fire test of a missile system, Simon knew better than to make any code changes, but he did want to improve the documentation. Adding comments was pretty low risk, so he went ahead and did that. By the time he was done, the Turbo Pascal code that controlled the missile looked like this:
CodeSOD: Put Down the Pipe
Camden's team works on an internal Angular application. Angular is constantly releasing new versions, and while they're largely backwards compatible, as the rule goes: every change breaks someone's workflow. Camden's team started to upgrade to Angular 12, only to discover that one of their dependencies wouldn't resolve. It refused to work with any version of Angular greater than 8.The specific dependency promised to safely sanitize external resources, like DOM snippets and URLs fetched from an external source. At its core, it wrapped around the Angular DomSanitizer object, which provided all the plumbing for handling sanitization.So the TypeScript method looked like this:
Error'd: In the fullness of time.
RegulargleArgle garbles"It's an advertisement. At least... it says so." Hey, if you can'tbelieve advertisements, what can you believe?
CodeSOD: Promotional Development
Upgrading to a new point release on the Linux kernel isn't the riskiest thing you can do in your infrastructure, but it's not completely without risk. It's not so much that the kernel maintainers are playing fast and loose- they're a very conservative bunch for the most part- but some application code might be making assumptions that become incorrect in the next release.For Ramona's company, that happened. They updated the kernel, and immediately one of their libraries, written in C++, started segfaulting. Now, the developer behind it was still with the organization, but had climbed the ranks- he was no longer a Software Engineer, or even a Senior Software Engineer, but was now a Senior Solutions Architect and was not to be bothered with trivial things.So without bothering the very important architect, Ramona had to pick apart the offending C++ code on her own. It was older C++, and that was always worrying- conventions and style had changed a lot since this was written. There were no signs of any documentation or tests or anything that would help someone understand what the code was doing.Fortunately, it turned out that the code was simple. Well, "simple". It was a pile of system calls. No, not syscalls, but calls to the system function, which allowed the C++ code to execute shell commands. Essentially it was a giant shell script wrapped in C++ code, and the C++ code didn't contain any logic to handle error, exceptions, or even verify that the return buffers contained valid data.So, it was dangerous, pointless C++ code, but surely the Senior Solutions Architect had a good reason for writing it in the first place? He'd never have risen to such stratospheric heights in the company without having a good reason for doing that?Ramona took the risk and contacted him: "I'm a little unclear what this code is for? Why is this in C++?""Ah," the Architect replied, "I was learning C++ at the time, and everything looked like a C++ solution. Plus any chance to improve my skills!"The fix was to junk the C++ and replace it with a shell script. But it did mean that Ramona started to pay attention to what the Architect was doing, especially when the Architect got yet another promotion to "Software Manager". This allowed him to use his experience and advanced decision-making skills to really make mistakes.For example, they had a bunch of older rackmount servers, about $100k worth, and a relative handful of new servers. Now, the new servers could provide all the capacity they needed right now, and as they grew, they'd want to replace the old servers with even newer ones- so he might as well chuck all the old servers now and make room against that future day.There was just one problem. The Architect-turned-Manager had also decided that the development team was suffering with laptops that were, on average, two years old. They all needed new computers, in his opinion, so he'd already spent the capital budget on that.This meant that, when they needed to expand their server capacity, there was no money to do it, and no older hardware they could press into service as a stop-gap. This made end users angry, as everything became less responsive or outright failed. That made management angry, because angry users hurt the bottom line, especially when it meant they were violating SLAs.The good news is that the company has an opening for a new CTO. The Architect-turned-Manager is already angling for that promotion, and odds are good that he'll get it. Ramona, on the other hand, is already polishing her resume for a change to another job entirely. [Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
CodeSOD: Getting Reported
Monica sends us a code snippet that comes from her organization's home-brewed reporting engine. She writes:
The Biased Bug
Back in the 90s, Steve was the head (i.e. only) programmer and CEO of a small company. His pride and joy was a software package employed by many large businesses. One day, a client of Steve's named Winston called him concerning a critical, show-stopping bug. CEO Head Programmer Steve was also the Technical Support Lead, and thus he faithfully took up the issue. Over the phone, Winston carefully described the steps needed to reproduce the crash, and Steve walked through them. At a certain point, entering data and hitting Return rendered the program unusable for Winston—but not so for Steve. Much back-and-forth ensued as Steve tried to figure out what Winston was doing differently, and the frustration in Winston's voice mounted every time he had to reboot the system. It was as if the program had something against the poor man.Since they weren't getting anywhere over the phone, Steve decided he had no choice but to drive out to Winston's office to continue troubleshooting in person. They made arrangements to meet up the next morning.Once they got together, Winston was easily able to demonstrate the problem. Then Steve sat down at the very same computer, typed exactly the same things ... and everything was fine. They tried again several times, and it really seemed as if the program could sense who was sitting before it. Poor Winston could never catch a break.Just as Steve despaired of ever figuring out the issue, he happened to get a good look at Winston's hands as he typed."Hang on!" Steve cried as the solution hit him. "I see the problem here. The parser is expecting a double quote there. You're typing in two single quotes."Winston glanced to him with confusion. "Well, how else do you make a double quote?"Steve was dumbfounded at first. Nevertheless, he patiently walked Winston through the difference between typing two single quotes and one double quote using the Shift key."Huh!" Winston said. "The typewriter I learned to type on didn't have anything like that."Steve frowned. "It didn't have double quotes?""There was no key for that. You had to type two single quotes," Winston replied with an authoritative nod.That must've been quite the old typewriter, Steve thought. He'd had experience with typewriting in his own youth, and remembered Shift keys and double quotes on the models he'd used. It was true, though, that the earliest typewriters only typed capital letters, and thus had no Shift keys. When writing documentation, Steve had never imagined needing to explain something so regularly taken for granted among computer users. Thankfully, Winston was quite pleased with the lesson. As Steve drove home, he knew he still had to come up with a means of handling bad input in a more elegant fashion, but at least he knew his program wasn't malevolently sentient, just picky. [Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
CodeSOD: Inner Exceptions
One of Raquel's junior developers was having some troubles. They had a Lua script that needed to call out to a Redis store to fetch data. The poor developer was getting useless "failed to communicate to redis," message and needed help figuring out what was going on.Of course, the Lua script wasn't the problem. The company was building a full on Inner-Platform. The core application stack was actually in Java, but it was extensible with Lua scripts. The Java code was meant to handle all the plumbing and interacting with the data store, and the Lua code could then just be where developers put their business logic.The Lua code was fairly straightforward, at least at a glance:
Error'd: Guantanamera
GringoTimothy W. shivers"It's going to be a cold time in Havana tonight!"
CodeSOD: Leaky Logs
For years, Carla's company had a Java application with a memory leak. No one had the time, energy, or budget to actually do anything about the leak, so they "fixed" it by just forcing a nightly reboot.When Carla asked about the nightly reboot, the elders who had been around for awhile simply said, "there were some issues we couldn't track down."Carla was assigned a task to go track down some of those untrackable issues. The first thing she discovered was that when she changed the logging level from its production settings to "DEBUG" mode, the application crashed in minutes instead of days. That piece of information sent Carla looking at the logging code to see what was happening.
CodeSOD: A Little Obtuse
AngularJS, (not to be confused with Angular, its successor project and ostensible replacement) made some… interesting design choices. Controllers existed in a tree, mapped to the DOM, and were glued together by a special object called $scope. You would store your data in the $scope, and depending on exactly how you did it, that data could be accessible at various levels within the tree. $scope also doubled as an event bus, so controllers could send messages up and down the tree as needed.In short, there's a reason why AngularJS fell out of favor.Still, during the era when AngularJS was the new trend, David's co-workers wanted to switch to using AngularJS. Unfortunately, they didn't know AngularJS, and only knew jQuery, so this snippet demonstrates their approach to building AngularJS applications:
Multilingual Development
Lisa's company needed to add some custom functionality to a third-party application- IniERP- which was made easier by the fact that the company had a SOAP web service to interact with. The vendor supplied Java sample code for building the service, so it was trivial for Lisa to build her own code to automate those interactions. And everything went fine, and her users were happy.So fine, and so happy, that other teams heard: "there's a way to integrate your applications into IniERP." Every department in the company had business processes which touched IniERP on some level, so "Lisa built a thing which lets you do this!" got her a lot of emails.There were issues: there was only one "service" account configured by the operations team, so anyone wanting to interact with the service needed to share an account. For that reason, Lisa resisted sharing her solution until ops made a better way to provision accounts, but demand was so high that management pressured her into sharing her code, the documentation, and the credentials.And despite the obvious problems, even that went fine. Mostly. Because most of the teams either had the IT staff available to do the work, or realized this was beyond their technical skills and gave up. Then there was Bert.Bert was a developer on one of the web teams and wanted to integrate their applications into IniERP. So Bert fired up his IDE, hit copy-and-paste, and went to town. Accessing the HelloWorldWS testing service went great, and with that confidence Bert went straight on to accessing the real web service- and that didn't work.Bert sent Lisa an angry email, complaining that her samples didn't work, that obviously she didn't know what she was talking about, that he'd wasted three days fighting with her bad code, and that she shouldn't run around telling the company that she was so smart if she wasn't able to release code which worked. "You shouldn't release what is essentially pseudocode and then tell people you've fixed their problems!"Politely, Lisa offered to take a look at Bert's code, and see if she could spot the issue. Bert resisted, at first, but eventually relented with the comment: "It's the code you supplied, so if it's wrong, that's on you."There were a few obvious problems in Bert's code. The first, and smallest one, was that in a few spots instead of copying a constant declaration and its value, he just created a constant and set its value to its name. That was weird, and certainly enough to explain why his code wasn't working, but it actually wasn't the reason why it wasn't working.You see, Bert was a PHP developer. He was building a PHP application. But he copy/pasted Lisa's Java code into a PHP file, and then remangled it until it was executable PHP. Much of his frustration was rooted in the fact that her code didn't even run when he copy/pasted it into a PHP file. Somehow, that mangling had gotten it into a state where it could access the HelloWorldWS, which didn't have any authentication on it, but also broke the authentication code so that secure services wouldn't work."Um," Lisa explained, "my code is in Java. It's not PHP.""Java, so like, I can embed it into the front-end of my page? But wouldn't that mean putting the credentials into the HTML or JS files somewhere?"In the end, someone on Bert's team reached out to the vendor, who could point them to some PHP code examples for what they wanted to accomplish. It took a little longer, but Bert's team got what they needed. Bert, however, never quite understood what Lisa was talking about. [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
CodeSOD: Validly Numeric
Writing validation rules is one of the more tedious tasks a developer might need to do. Like testing code, it's all about finding edge cases, checking boundaries, and being exhaustive in your search for invalid data. Garbage in, garbage out, and validation filters the garbage.But you might also be a bit too thorough. Kevin found this validation rule in his C# codebase:
Error'd: Sick Day
How much longer will we endure wave after wave of novel coronaviruses? One school of thought holds that omicron or itsimmediate successor will soon burn its way through the human population and render everyone immune. So here is our entire stash of covid-related submissions before they get old, stale, and boring.Lonely Tim looking for love in all the wrong places, wails"I don't even count as a friend?"
CodeSOD: A Tern in the Stream
Java's streams feature allows developers to use functional programming techniques to operate on sets of data. Used correctly, it can create expressive and readable code. Used incorrectly, well…Gevatter Tod found this while searching for a bug.
CodeSOD: Exvention
For a lot of real-world situations, I'm a big fan of "event driven programming", or as I think about it, "bus oriented programming". Instead of coupling objects directly, objects just publish events to a shared bus, and the events get routed to the other objects which care about them, in a declarative fashion. It's not a "write all programs" this way sort of stance, it's just there are a lot of real world cases where I've found this to be very effective.Ricardo's co-worker seems to share my opinions, but perhaps maybe not quite my reasoning. This is the PHP code for handling checking out of their storefront:
CodeSOD: Numb to Truth
In the ancient times, philosophers asked the hard questions, like What Is Truth? And just when we might thing those questions have been answered, Uli brings us a new twist on an old classic."I found this while browsing an ancient C++ codebase," Uli writes.
CodeSOD: Two Addresses
When passing data over the wire, we frequently want to aggregate that data into a data transfer object. An ideal DTO lets a client get all the data they need in a single request, without needing lots of round trips to get related objects.Or, you could be like the contractors that Marty had to work with, and get handed this Java code:
Error'd: Time After Time
This week's submissions really aren't about time, they'vejust been sitting around a bit and need to get used up beforethey go bad. Or as the maestro used to say: "You might as well eat it... I'm only going to throw it away!"An anonymous reader waffles "I do want to answer but I'm only half sure."
CodeSOD: Three Links
Brian's hired a contractor to tackle a challenging technical problem: they wanted to display three links in three table cells. Now, you or I might just write that as HTML. But if we did that, we'd lose the opportunity to do this in JavaScript. Plus think of all that repetition- you'll be outputting a <td></td> tag pair three times. That's just wasteful.No, what we need is some elegant JavaScript solution that solves this problem without any unnecessary repetition.
Modernization
Micki worked for ConCom, a huge multinational development consulting company with offices on four continents. ConCom, in turn, assigned Micki's team to another multinational corporation, one that was looking for an ERP upgrade. Picture six developers in one little loft office, complete with dartboard, while the architects, POs, SMs, and the like were on another continent in a totally different time zone. At first they worked small tasks, proving themselves capable of being assigned the big upgrade project, and eventually, details started to come out of what the client really wanted.The current ERP was fairly unremarkable, if entirely dated. The bulk of the operations were scheduled jobs that processed CSV files uploaded from the branches to the central server. This system was what they intended to upgrade: ideally, with real-time messaging using a "top of class messaging broker and middleware." But the catch was, as always, they had to do the upgrade without any down time for the ERP system. So they had to do it in phases, one CSV at a time. Still, it should be an easy win, right? They would work on the branch side, and a central team would do the central server side. Easy peasy.But of course, nothing is ever that simple here at TDWTF.The first segment to be upgraded dealt with contracts. The branch would upload a "new contracts" file, and the central server would reply with a "processed and rejected contracts" file when it got done processing them. This all had to happen by 7:30 AM so that the information would be ready when the branch opened next. This should have been an easy replacement: both files had a well defined format, making it easy to create real-time communication around it.The catch? The central ERP knew nothing of CSV files at all. It only dealt with XML. So how were these files even being processed?As it turns out, there was another piece of software involved: a Java application from 1996, written by a developer who had long since retired, that handled the CSV to XML conversions and back. Thankfully, the source code was discovered, so they could at least read the comments. And try to search for the database it was using, since nobody knew it even existed, let alone where it lived.After weeks of studying and documenting how the ERP worked, suddenly, the development team were called (after hours) into a meeting with the PO, SM, Architects, Client Directors, and C-level execs. The project was touted as the "biggest project in the last 10 years" that would "save the company millions", and development would start tomorrow. The deadline? 3 weeks, or 250 man-hours. The entirety of their study findings had been ignored in favor of the "analysis" of an architect on another continent who never even spoke to the dev team, and never showed up again.But it was time to implement! And that meant setting up the message broker. Which the team had been given no details on, not even the name of the broker. When they complained, one of the developers was assigned to "remove all these blockers" instead of working on features. He tried; to his credit, he called just about everyone he could think of, signed a few NDAs, and attained a new security clearance. And he finally received it: a little documentation, access to the broker, and the message layouts. No documentation, no diagram, just the layouts; they had to guess how to map the CSV files to the message layouts they were given, as well as whether each one was a request or a response. They had incredibly helpful names, too: "AB", "ABC", "PB", "PBC", and "Rejected." It was clear what "Rejected" was, but the rest? They had to find out through trial and error that "ABC" was the reply to "AB" and the same for "PBC" and "PB."A few weeks went by—the project now officially late—and they got one more piece of information: there was a sixth message type, called "GC." Was this a message, since it had only two letters? Or a response, since it ended in "C?" Nobody knew. They assumed since it had a "C" they would receive it from the central server at some point, but they couldn't figure out the circumstances under which it would be sent. So they forged ahead, ignoring it, as you do.Another month of long, hard hours, and they were at the point where they could review and test the implementation. They provided AB and PB messages, based on the business rules to determine which would be sent, and expected a reply from the central server. This would be processed and displayed in a brand-new UI for the end user to review. So far, so good.Then it happened. The Call. The three-hour conference call with the central team to sync up on how to roll out the implementation. This is when new rules were discovered, including:
CodeSOD: Convenience
Casey works with some pretty courteous and forward thinking Python developers. They want to make sure that using their APIs are as convenient as possible, and make sure to provide all sorts of useful convenience methods. Like this one:
CodeSOD: Every Change
Now, I'm an old luddite who still looks askance at cloud services, but I'm willing to recognize their value. Still, I worry about whether I can trust that vendor to actually deliver the services I need, without them suddenly shoving out breaking changes which screw me, but maybe not their "whale" customers where the real money is.That's something which "Sleeper" got to grapple with last fall. They use Amazon's Athena service, which allows software to query S3 buckets using SQL syntax. Late last year, "Sleeper" got an email which they forwarded to us with the subject "This should be fun". The email started like this:
Error'd: Time Enough to Cry
Does anybody really care about time?Angela A. cares. "TGI(T|F)" she announces. "The days just run together!"
CodeSOD: Commentary
"Include descriptive comments for each method," isn't bad advice. I mean, ideally, the method name and parameters would be descriptive enough that you don't need to add lots of comments, but more comments is rarely going to hurt things. Unfortunately, "include descriptive comments" usually decays into "include comments". And that's how we get piles of code like this one, from Patrick:
Document Soup
An Enterprise Resource Planning system needs to keep track of your enterprise resources. Many of those resources, especially the expensive ones, need lots of documents tracked about them- inspections, service reports, maintenance bills, etc. So the ERP and the Document Management System need to talk.Years ago, for Coyne, this presented a few problems. First, the ERP was a mainframe application running on an IBM mainframe. Second, it was getting retired. Third, the DMS didn't talk directly to it, but instead communicated through a terminal emulator and used configuration files to correctly parse the screen contents coming back from the mainframe.The final, and key problem, was that, when examining the documents stored in the DMS, were that there were big confused piles of unrelated documents getting stored together. Specifically, if you looked for documents for the asset tagged 490, it'd fetch those, and also 49, 4900, 49000, or 490000. And vice versa, searches for 490000 would return all the other documents as well.Now, within the mainframe, the same data might get displayed on multiple panels. So, for example, the tag for a requisition document might be displayed in RQ01 on one panels, RQ02 in another, and RQ03 in yet another. And each of these fields could display the field differently, "depending on design, whim, programmer laziness and phases of the moon," as Coyne writes.
The Tech Lead
Years ago, Karthika was working as a contractor. She got hired on to develop an intranet application for a small government project. The website in question was already in use, and was absolutely mission critical for the organization, but it also had a very small user base- roughly five users depended on this application.When Karthika started, she immediately encountered a few surprises. The first was the size of the team- 8 developers, including a Team Lead. That seemed like a large team for that small number of users, and that didn't even include the management overhead. The code base itself was similarly oversized; while the product was important, it was a pretty prosaic CRUD app with a few tricky financial calculations involved.The core surprise was how awful the application was to use. It was slow to the point of sometimes timing out in the browser, even when running on your local machine. It was buggy, and even when Karthika patched those bugs, there was so much duplicated code in the system that the same bug would linger hidden in other screens for months. "I thought you said you'd fixed this," was a common refrain from the users.This was long enough ago that the UI was built in ASP.Net WebForms, but new enough that the data access was handled by Entity Framework. And it was one specific feature of WebForms that they were abusing that made everything terrible: UserControls.UserControls were designed to let developers create reusable widgets. For example a "User Information" screen may group the "User Name" and "Password" fields into a single "Credentials" UserControl, while the address fields would all get grouped together in an "Address" UserControl. That same "Credentials" control could then be dropped into other pages.When the user interacts with this data, Entity Framework can lookup a User object, hand it off to the UserControls, who allow the user to manipulate it, and then the controls can invoke the save on the User.The Tech Lead had encountered a problem with this. You see, he didn't want to share the same reference across controls because of "separation of concerns". So instead, each UserControl would create its own User object, populate it with database values, and then let the user interact with it. This meant when each UserControl had its own picture of the user object, and when it was time to save the data on the page, one control could overwrite the changes made by another control.So the Tech Lead invented CopyOldValues, a method which, during a save operation, would go out to the database, fetch the current data, and then compare it to the object being saved. Any NULL values in the object being saved would be updated to the database values, and then the object would be saved. This way, a UserControl could have a whole User object, but only populate the fields it was responsible for, leaving the rest as null. So yes, this meant that to save an object to the database, it required two round-trips to the database, per UserControl. And each page could have multiple UserControls.Karthika saw this, and put together a simple plan to fix this problem: just use the frameworks like they were meant to be used and cut this whole CopyOldValues nonsense out. She went to the Tech Lead and laid out a plan."This isn't an issue," he said. "You're wrong to be worrying about this. Stop wasting my time, and stop wasting yours. Instead, you should look into the date bug."So, Karthika tracked down the issue related to the date bug. Specifically, the database and the application were supposed to allow certain date fields to be NULL. But, since CopyOldValues used NULLs to decide which data to save, it was impossible to update a stored value to a NULL. Once again, the fix was obvious: just stop doing this weird intermediate step."Wrong," the Team Lead said. "That's totally not the correct way to do it. I have a better plan already."The "better plan" was to create a custom save method for each UserControl- of which there were hundreds. Each one of these would define an array which used the string names of each field it was responsible for, and then the object and the array would get passed to a new method, FindDifferences, which would use reflection to inspect the object, copy the updated values to a new object, and prepare to save to the database.The shocking end result of this, however, is that this made the application even slower. It didn't reduce the number of database round trips, and it added this whole reflection step which made accessing properties even slower. Despite only having five users, and running on a decently powerful machine, it was nigh unusuable. The Team Lead knew what the problem was though: the machine wasn't powerful enough.Strangely, however, throwing hardware at the problem didn't fix it. So the Team Lead invented his own caching solution, which made things worse. He started reinventing more wheels of Entity Framework and made things worse. He started copy/pasting utility functions into the places they were used to "reduce overhead", which didn't make things worse but made every developer's life demonstrably worse as the repeated code just multiplied.These problems made the customer angry, and that anger eventually turned into an all hands meeting, with representatives from the client side and the project manager as well. After the venting and complaining was over, the project manager wanted explanations."Why," she said, "aren't we able to fix this?"A round of blamestorming followed, but eventually, Karthika had to get specific and concrete: "We have a set of fixes that could address many of these problems, but the Tech Lead isn't letting us implement them and isn't giving us a good reason why we can't."The project manager blinked, puzzled. "Who? There's no defined tech lead on this project. You're a team of peers.""Well," the 'Tech Lead' said, "I… uh… have seniority.""Seniority?" the project manager asked, no less confused. "You started two weeks earlier, and that was just because you were the one contractor on the bench and we needed someone to knowledge-transfer from the outgoing team."The Project Manager had been overwhelmed by handling customer complaints, and hadn't been able to carve out time to attend any of the development team meetings. This meant that the Tech Lead's self-appointed promotion went unnoticed for eight months. At this point, the project was too far off the rails for any hope of recovery. The government office "fired" the contracting firm the next week, and all the developers, including Karthika, were fired from the contracting firm the week after that. [Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
CodeSOD: Classic WTF: The Old Ways
Error'd: Up Up Down Down Left Right Left...
...Right B A. Right? Every so often, someone sends us asubmission with a hidden agenda. Of course we get the usualsolicitations for marriageable exotic beauties and offers totrade linkspam locations. But then there are the reallyinteresting ones. Maybe they're legitimate, maybe they'rephotoshopped or otherwise faked, and maybe they're an attemptto bypass someone's ban on political propaganda or quack science.In any case, there isn't any of that here this week, but we'resaving them up and maybe we'll feature a future issue of spotthe fraud for you.First up is dog loverGeorge with a hysterical spam-blocking email address, sharinga help message that must have been crafted by Catbert himself."My sixty seconds of glory awaits!" he howls, but then whimpers"I will be real disappointed if the agent isn't[Gone in Sixty Seconds headliner] Nicolas Cage."
CodeSOD: A Pointer to your References
John C works at a defense contractor, and his peers are well versed in C. Unfortunately, many years ago, a lot of their software started being developed in Java. While references are often described as "pointers, but safer," they are not pointers, so your intuitions about how memory gets allocated and released are likely to be wrong.Which is definitely the case for John's peers. For example, in C, you generally want really clear understandings of who owns a given block of memory. You don't want to allocate memory and hand it off to another module without being really clear about who is responsible for cleaning it up later. This means that you'll often write methods that expect buffers and other blocks of memory passed into them, so that they don't have to worry about memory ownership.Which is how we get this block of code:
...891011121314151617...