Feed the-daily-wtf The Daily WTF

Favorite IconThe Daily WTF

Link http://thedailywtf.com/
Feed http://syndication.thedailywtf.com/TheDailyWtf
Updated 2024-05-20 12:31
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:
A Basic Print Algorithm
In the late 90s, Aaron was employed at a small software company. When his coworker Mark submitted a letter of resignation, Aaron was assigned to maintaining the vast system Mark had implemented for an anonymous worldwide company. The system was built in the latest version of Visual Basic at the time, and connected to an Oracle database. Aaron had never written a single line of VB, but what did that matter? No one else in the company knew a thing about it, either.Before Mark parted ways with the company, he and Aaron traveled to their customer's headquarters so that Aaron could meet the people he'd be supporting and see the system perform in its live environment. A fellow named Boris met them and gave a demo at his cubicle. At one point, he pressed the Print button to print out a report of certain records. After some serious hourglassing, the system displayed a dialog box asking, Do you want to print page 1?, with Yes and No as options. Boris chose No.More hourglassing. Do you want to print page 2?And on it went. Not only did Boris have to choose Yes or No for every page, the time to display each prompt was ridiculous, anywhere from 30 to 90 seconds per page.By the time they crawled to page 30, Aaron was dying inside and could no longer restrain himself. "Why is it like this?!" he half-asked, half-accused Mark."The customer wanted it this way," Mark replied, either unaware or indifferent to his coworker's frustration."This is the way we want it," Boris chimed in. "We don’t always want to print every page. Sometimes we just want one page, could be page 73.""But why not give one prompt where the user can type in the specific pages they want?" Aaron asked."Is that possible?" Wide-eyed, Boris turned to Mark. "You told us it wasn't possible!""It isn't," Mark said with conviction.Aaron flushed with embarrassment. He assumed he'd put his foot in his mouth in front of an important customer. "Sorry. You're the expert."Still, the issue niggled at Aaron long after they returned from the customer's site. Once Mark had packed up his cube and departed for good, Aaron tracked down the report-printing code. He found a loop that started off something like this:
CodeSOD: The Correct Browser
Sometimes, it's not the code that's bad, but what the code costs. For Elizabeth's company, that cost was significant in terms of dollars and cents. They needed to staff up to accomplish some major Java Enterprise work, so they went with the highest of the highly paid consultants they could find. These consultants came from a big name firm, and were billed at an eye-watering hourly rate.Elizabeth warns us that the Java code is a behemoth of WTFs that is "too difficult to describe", but one particular WTF leapt out at her. Specifically, included in the application was a file called nonIEUser.html. This project was happening circa 2012, which is after Microsoft finally admitted standards might need to be a thing, and definitely well outside of the time when your web application should only work in Internet Explorer. For a greenfield project, there was no reason to do anything IE only, and fortunately, they didn't- aside from forcing a check to yell at you if you didn't use IE.This is the error page that it would display:
The New Management
For a young college graduate in the early 80s, Argle was fortunate to already have some real-world experience. That served him well, because businesses which were looking towards the future were already looking into how they could improve their automation with the new and relatively cheap computer systems that were hitting the market.One such company was a family-owned, multi-generational manufacturing company. They had a vision for the future, and the future involved the latest in CNC milling machines and robotic manufacturing. They needed the team that could send them into the future, and were hiring to build that team.Argle was one of those hires, brought on as a junior developer. His mentor, Stanley, was an old Texas Instruments guy who had helped design many of the chips that were driving the fancy robots. Stanley leaned into his mentor role, both in terms of being a good mentor, but also in terms of the aesthetic: he was a bearded pipe smoker in a tweed jacket with patches on the elbows, and a pocket protector loaded with pens and a compact slide rule.For a small manufacturing firm, the owner was happy to invest in this team. He brought on vets from JPL or mechanical engineers who had helped automate German auto plants. The owner himself heavily recruited from the same college that Argle attended, giving talks about the future of automation and reinforcing his company's commitment to the future. Interns and junior developers bulked out the team.The owner walked the walk, talked the talk, and was putting money where it needed to go. The job was an absolute delight for Argle and the rest of the team. He learned a lot from Stanley, and also from the work itself.And then, one day, the owner introduced Gordon. "This, is our new President, Gordon. He'll be handling the overall operations of the company while I focus on our vision and direction."Now, for most employees, the introduction of Gordon was barely worth commenting on. New management slotting into leadership positions was just background noise and didn't really impact the work. Except for Argle. Argle actually knew Gordon, at least by reputation, because Gordon was the VP at the local public broadcasting company.Now you might wonder, "how does experience in broadcasting help someone oversee a manufacturing company?" Well, Argle had the inside scoop on exactly how Gordon would lead. Argle's father worked at the local PBS affiliate, and had regaled Argle with all sorts of stories about Gordon's style. That style was a blend of bullying and cronyism.Now, up to this point, Argle's team had acted more or less like a leaderless collective. They all had a goal, they all understood the goal, and they all pushed together to achieve the goal. There was no manager. They'd defer to the senior members on matters of disagreement, but even then it was never "Stanley said so," and more "Stanley will explain this so everyone comes to an agreement."That, of course, couldn't stand under Gordon's leadership. So Gordon hired Dave to provide management. Like Gordon, Dave also had no background in manufacturing, technology, automation or robotics. Or, in actuality, project management, as Dave illustrated in his first project meeting.As this was the 80s, the conference room was a nicotine stained room with a transparency projector. Stanley sat in a corner, puffing away at his pipe. Dave had a stack of transparencies and a red dry erase marker to scribble on them with."So, Stanley," Dave said as he slapped one of the estimates Stanley had assembled onto the projector. "How long did you think this effort would take?"Stanley pointed his pipe stem at the numbers Dave was projecting. "An effort like this will take a year.""That's much too long," Dave said. "I was looking this over, and you had 6 weeks for milling these parts, but I think we can outsource that and get them back in three weeks. I have a vendor already committed." Dave edited the numbers with his red pen. "And then development time, you've got poor Argle booked for six months, after the hardware design is finalized, but we can start development earlier than that…"People around the room started raising their objections. Dave had no time for these naysayers. "You would think that, but you haven't even finished with college," he told an intern. "Maybe things worked that way at JPL, but we live in the real world here." "If TI was such a good company, you'd probably still work there- either they suck or you're an idiot."By the time Dave finished his tirade, he had individually insulted everyone on the team, and had cut the project time down to six months. "You see? We can totally do this project in six months."Stanley took a few puffs of his pipe and said, "You can say it will take six months, but it will still take a year."As Dave started piloting the team straight into the ground, Argle got an offer. A few of his college friends had moved out to another state, launched a startup, and were offering him a 40% wage increase plus moving expenses. Add into the fact that Dave had explained that nobody on the team would be eligible for a raise for five years, Argle was halfway out the door.But only halfway. Argle was young, still had some optimism, and wanted to be loyal to his team, even if he wasn't loyal to the company. So he talked it over with Stanley."I like this team, and I like the work that we're doing, and I'd hate to leave the team in a lurch."Stanley puffed on his pipe, and then answered. "The company will be sad to see you go. I'll be sad to see you go. But the company could lay you off tomorrow, and they'd be just as sad about it too. But they'd do it if they thought it was necessary. You don't owe this company anything more than that."So Argle submitted his notice. By coincidence, it was on April First, which Dave tried to use as an excuse to bully Argle into feeling guilty about either a bad prank or bad timing for quitting. Dave wanted to make a counter offer, but he couldn't do it without insulting Argle on the way to offering him a raise, which made Argle's choice very easy.Two weeks later, he was loading a truck with all his worldly possessions, and two weeks after that he was settled into a new house, and a new job, and even happier than he'd been at the manufacturing company.Over a year later, Argle went back to visit family, and swung by the old company to see how the team was doing. Stanley was still there, but Dave and Gordon were long gone. The owner was fooled for a bit, but was too smart to stay fooled. Dave and Gordon were out the door only a few months after Argle left."So," he asked Stanley, "how'd that project go? How long did it take?"Stanley puffed on his pipe and chuckled. "Oh, about a year." [Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
Error'd: Everything Old is New Again
Whenever there's a major change in the world, it always takes applicationdevelopers a little time to adjust. Remember when the US governmentthought it would be a great idea to mess around with their Daylight Saving Timeschedule with only two years warning? (I'm guessing nobody remembers the fiddlingdone by earlier administrations because they were too young to care, ornot born yet.) Two years warning probably seemed like plenty to non-technicallegislators, not thinking about all the software that was in place with built-in calendars.Well, someone has apparently decided to one-up a measly time change, by inventing somethingcalled a New YEAR. This resets the entire calendar, and it must be a novel practicebecause surely websites wouldn't break due to some routine event that has been happening for at least a dozen years or more, right?Right?Aspiring Poké trainerValts S.began a long long time ago far far away.
CodeSOD: Well Trained
Mandatory compliance training is a thing. The reasons behind it range from companies trying to reduce civil liabilities to actual legal mandates which require the training. The quality of mandatory training ranges from "useless" to "actively awful", and it's mostly PowerPoint-style slides interspersed with quizzes to make sure you were "paying attention". The worse ones will usually have timers on the slides so you can't just click past, and have to actually idle to "force" you to read it.Also, since legal compliance tends to move slower than technology, training built years ago is frequently still relevant. So, for example, Duncan's company built training back when you could reasonably expect Flash to run in the browser. Building the training and the content cost money, so once Flash got deprecated, they weren't just going to throw that money away- they found a contractor who'd convert it to "HTML5".Now, this means that the code quality is garbage, which is fine. We can't really fault the tool. But there are some assumptions about the very use of the tool that render these quizzes even more useless than the usual fare:
CodeSOD: Do Nothing
Ivan encountered a strange bug. His organization uses the R language, which has a handy-dandy documentation language attached to it, for Rd files. The language itself is an organically grown hodge-podge of R and LaTeX, built to make it easy to format both plain text and R code within the documentation. It lets you use LaTeX-like commands, but also mix in R code to control the output.Ivan's problem was that one of his macros, which we'll call \mymacro, only worked sometimes. The specific cases where it failed were where the macro expanded into multi-line output, which once upon a time wasn't a thing that Rd supported, but is supported, and clearly wasn't the problem. Ivan poked at it from that direction, suspecting there was maybe a regression, and then spent a lot of time trying to understand the places where the macro did and didn't work.It took some time, but eventually the key difference was that the pages that worked also called another macro, \doi{}, which itself called \Sexpr[stage=build]{...}. Now, there's one important thing to note about the \Sexpr macro: it's meant to invoke R code inside of your documentation. And that made all the difference.The documentation which didn't contain R code would be stored as a raw documentation file in the package. Before rendering the documentation, the parseRd tool would need to parse the file and generate the documentation output. This would happen after the package was built and distributed. Since the \mymacro might expand into nothing, this was technically unparseable at that point, and would cause the documentation render to fail.On the other hand, documentation which did contain R code would be parsed and the parse tree would be stored in the package. There would be no parse step when the documentation got rendered. The whole "expanding to nothing" problem didn't exist in this situation.So the fix was obvious, at least to Ivan:
CodeSOD: Cloudy Optimizations
Search engine optimization is both a dark art and a corrupt industry. Search providers work hard to keep their algorithms opaque. SEO is a mix of guessing and snake oil and sometimes outright lying.For example, Mark M recently inherited a rather… bad PHP website. One of its notable SEO tweaks was that it had a tag cloud that slapped a bunch of keywords together to give a sense of what kinds of articles had been posted recently. At least, that was the idea. But when Mark dug into the code, there was no sign that there was any source of tags in the database. In fact, articles didn't get tagged at all. So where was the tag cloud coming from?
My Many Girlfriends
In the long ago, wild-west days of the late 90s, there was an expectation that managers would put up with a certain degree of eccentricity from their software developers. The IT and software boom was still new, people didn't quite know what worked and what didn't, the "nerds had conquered the Earth" and managers just had to roll with this reality. So when Barry D gave the okay to hire Sten, who came with glowing recommendations from his previous employers, Barry and his team were ready to deal with eccentricities.Of course, on the first day, building services came to Barry with some concerns about Sten's requests for his workspace. No natural light. No ventilation ducts that couldn't be closed. And then the co-workers who had interacted with Sten expressed their concerns.During the hiring process, Sten had come off as a bit odd, but this seemed unusual. So Barry descended the stairs into the basement, to find Sten's office, hidden between a janitorial closet and the breaker box for the building. Barry knocked on the door."Sten awaits you. Enter."Barry entered, and found Sten precariously perched on an office chair, removing several of the fluorescent bulbs from the ceiling fixture. The already dark space was downright cave-like with Sten's twilight lighting arrangement. "He welcomes you," Sten said."Uh, yeah, hi. I'm Barry, I'm working on the Netware 3.x portion of the product, and Carl just wanted be to check in. Everything okay?"This is acceptable to Sten," Sten said, gesturing at the dim office as he descended from the chair. Sten's watched beeped on the hour, and Sten carefully placed the fluorescent bulb off to the side, in a stack of similarly removed bulbs, and then went to his desk. In rapid succession, he popped open a few pill containers- 5000mg of vitamin C, a handful of herbal and homeopathic pills- and gulped them down. He then washed the pills down with a tea that smelled like a mixture of kombucha and a dead raccoon buried in a dumpster."He is pleased to meet you," Sten said, with a friendly nod. Barry blinked, trying to track the conversation. "And he is pleased with it, and has made great progress on building it. You will like his things, yes?""Uh… yes?""He is pleased, and I hope you can go to him and tell him that he is pleased with this, and set his mind at ease about Sten."So it went with Sten. He strictly referred to himself in the third person. He frequently spoke in sentences with nothing but pronouns, and frequently reused the same pronoun to refer to different people. The vagueness was confounding, but Sten's skill was in Netware 2.x- a rare and difficult set of skills to find. So long as the code was clear, everything would be fine.Everything was not fine. While Sten's code didn't have the empty vagueness of unclear pronouns, it also didn't have the clarity of meaningful variable names. Every variable and every method name was given a female first name. "Each of these is named for one of Sten's girlfriends." Given the number of names required, it was improbable that these were real girlfriends, but Sten gave no hint about this being fiction.There was some consistency about the names. Instead of i, j, and k loop variables, you had Ingrid, Jane, and Katy. Zaria seemed to be only used as a parameter to methods. Karla seemed to be a temporary variable to hold intermediate results. None of these conventions were documented, obviously, and getting Sten to explain them was an exercise in confusion.It led to some entertaining code reviews. "Michelle here talks to Nancy about Francine, and then Ingrid goes through Francine's purse to find Stacy." This described a method (Michelle) which called another method (Nancy), passing an array (Francine). Nancy iterates across the array (using Ingrid), to find a specific entry in the array (Stacy).Sten lasted a few weeks at the job. It wasn't a very successful period of time for anyone. Peculiarities aside, the final straw wasn't the odd personal habits or the strange coding conventions- Sten just couldn't produce working code quickly enough to keep up with the rest of the team. Sten had to be let go.A few weeks later, Barry got a call from a hiring manager at Initrode. Sten had applied, and they were checking the reference. "Yes, Sten worked here," Barry confirmed. After a moment's thought, he added, "I suggest that you bring him in for a second interview, and have him walk you through some code that he's written."A few weeks after that, Barry got a gift basket from the manager at Initrode.
Error'd: Fin
At the end of the year, it's customary to reflect on the past and imagine a future.Here at Error'd, reflecting on the past is natural, but all we can do about the future is hope.So to close out the longest 2020, here are a handful of little muffed missives.Occasional contributorPeter diagnoses a counting error."Looks like the web server had a thing or two to add to the discussion."
Best of…: Best Of 2021: Totally Up To Date
Best of…: Best of 2021: The Therac-25 Incident
Best of…: Best Of 2021: Worlds Collide
Best of…: Best of 2021: It's a Gift
Error'd: Some Like It Hotter
Fast approaching the end of the Gregorian calendar, things start to happen all at once, just to get them over with. According toDaniel D. "It's November 21 and Facebook can't decide which tomorrow comes first."
CodeSOD: Git Pull, for the Holidays
We're heading into the holiday season. We had some rather ambitious plans for a special Christmas event, but for a variety of reasons, all the various moving parts couldn't come together.There's always next year, though. Instead of rehashing Christmas carols or doing our own parodies of holiday specials, I figured we should share one of the songs we wrote for that unfinished special event. It's got good advice for those of us heading into the holiday season: don't release anything to prod in the next few days. LyricsGit Pull
CodeSOD: Masking Errors
Dirk's employer bought some software from a vendor, and the vendor promised that it was a cutting edge system, which was pushing the boundaries of technology. Digging through the API documentation, Dirk definitely found some unusual innovations, like the way it tracked log levels:
CodeSOD: Again and Again
"It's a fix for a fix for a fix, apparently," writes Joan.In this case, it's some Ruby code, which… gets a bit repetitive in that it repeats itself and does the same thing over and over again, in a repetitive fashion. Repeats.
CodeSOD: Voicemail to Email to Nothing at All
Mike's co-worker doesn't like to write code that gets tightly coupled to one system. Everything should be completely abstracted so that, if something on the backend changes, your code doesn't need to change.Which is an admirable goal, perhaps, but is also premature abstraction. For example, Mike's company uses Asterisk, an open-source PBX system. This co-worker wanted to script a few actions in that system, but didn't want his scripts to be tightly coupled to the system that he was scripting, so he… overgeneralized. But also didn't. But also did it wrong.Specifically, new voicemails needed to also get sent to an email address. Asterisk stores voicemails in the form msgNNNN.wav, where NNNN is a 0-padded numeric value, e.g. msg0123.wav.This is the PHP code to find the proper file to send:
Error'd: pop
Alas, I have only the following five submissions to share, as my controversy generator is on the Fritz today.Ex post autumnalAdam R. warmly reflects "I'm not quite sure how the math works out here, but I'm apparently a one-percenter in the home energy savings department."
CodeSOD: A Learning Opportunity
At various points in my career, I spent my days delivering technical training. If your company wanted to adopt a new technology, or upskill your developers, you'd hire me and I'd do crash course sessions. I generally didn't design course material: the books, slide decks, and labs. I just delivered the course. Most of the course material I worked with was pretty good, but there were some which were clearly written by people who were just trying to get a course out the door fast while a new technology was buzzwordy enough that nobody knew what they were buying.I hated those courses.All this means that we're going to shift gears a little bit into something we don't usually look at: the kinds of code that may be used as examples in training material.The first one comes from Jan, who was just trawling through JavaScript guides, and stumbled across one article that really stressed the importance of comments. For example, this incredibly complex method needs this comment attached to it:
CodeSOD: $art000
Many years ago, Brian was on the lookout for a new contract. While hunting, he found an opportunity to maintain some Intranet software for a large European news agency. He contacted them, and had a series of conversations with one of the managers."You see," the manager explained, "Sven was the code guru behind this entire system. He was… a colorful personality, but extremely smart. We don't have a lot of confidence that we could just slot a contractor into his role and expect them to be able to deliver what Sven could deliver for us."To give them that confidence, Brian agreed to do some very small contract work before they moved on to a larger, longer-term contract. This let him see exactly what Sven could deliver.
CodeSOD: Just A Temporary Thing
Daniel inherited some code which depends heavily on stored procedures. The person who developed those stored procedures was incredibly fond of overengineering things. Incredibly fond.The result is a big pile of not incredibly interesting T-SQL code. I'll share the whole block of code in a moment, but there's one specific comment that I want to highlight before we look at it:
Error'd: Some Like It Hot
Admittedly, this holiday season is culturally dominated by theAnglo-American tradition of a wintertime Christmas.Currier & Ives notwithstanding, most of the variousholidaysobviously originatedin some summer event, or else a harvest one. For these hot holidays,our mate Peter starts things off with a very warm greeting from down under. Following that are a few of myfavorite stocking stuffers, until Peter's antipodal ally Michael closes everything out with an appeal towarm the heart but not blister the sole.AussiePeter G. mutters weakly "Ithink this warning is bit superfluous (for the non-metric,that's 550 degrees F)."
CodeSOD: Stop, Watch
On one hand, we should all be doing our revision tracking in our source control system, and we shouldn't let code comments tell the story of why or how the code changed. On the other, when it leaves us the history of WTFs in the current version of the code, it's actually delightful.Take this anonymous submission, which includes the whole story of the code, all at once.
CodeSOD: Dummy Round
Different languages will frequently have similar syntax. Many a pointy-haired-boss has seen this similarity and thus assumed that, if their programmer knows C, then C++ should be easy, and if they know C++ then going into C# must be trivial. I mean, the languages look the same, so they must be the same, right? Boats and cars are steered by wheels, so clearly if you can drive a car you can pilot a boat, and nothing will go wrong.Andreas S inherited some code that started at C/C++ and was then ported to C#. The original developers were the sort to reinvent wheels wherever possible, so it's no surprise that they kept that going when they moved into C#.There are, for example, a few methods not supplied in today's code sample. They wrote their own RoundTo, which Andreas describes thus: "RoundTo() is basically equal to Math.Round(), but implemented in a WTF way." There is also a homebrew Sprintf implemented as an "extension method" on Strings.These all get combined in the method GetStringToRound which doesn't get anything, but seems to just format a string into a rounded off value.
Unseen Effort
Anita, a senior developer, had recently been hired at a company with around 60 employees. Her first assignment was to assist with migrating the company’s flagship on-premises application to the cloud. After a year of effort, the approach was deemed unworkable and the entire project was scrapped. Seem a little hasty? Well, to be fair, the company made more money selling the servers and licenses for running their application on-premise than they made on the application itself. Multiple future migration attempts would meet the same fate, but that's a whole other WTF.With the project's failure, Anita became redundant and feared being let go. Fortunately, the powers-that-be transferred her to another department instead. This was when Anita first met Henry, her new manager.Henry was a database guy. It wasn't clear how much project management experience he had, but he definitely knew a great deal about business intelligence and analytics. Henry explained to Anita that she’d be working on implementing features that customers had been requesting for years. Anita had never worked with analytics before, but did have a background in SQL databases. She figured multi-dimensional databases shouldn't be too hard to learn. So learn she did, working as a one-person army. Henry never put any time pressure on her, and was always happy to answer her questions. The only downside to working for him was his disdain toward open source solutions. Anita couldn't use any NuGet packages whatsoever; everything had to be built from scratch. She learned a ton while making her own JSON parsing library and working out OAuth 2.0 authentication.Upon completing a project, Anita would go to Henry's office to demo it. Once satisfied, Henry would say "Great!" and hand her a new project. Whenever Anita asked if there were a feature request logged somewhere that she could close out, she was told she didn't have to worry about it. She would also ask about her previous efforts, whether they'd been tested and released. Henry usually replied along the lines of, "I haven't had time yet, but soon!"Over time, Anita noticed an uncomfortable trend: every 12 months or so, the higher-ups fired 20-30% of the entire staff, normally from Sales or Marketing. The company wasn't making as much money as the shareholders thought it should, so they would fire people, wait a few months, then hire new people. For the most part, though, they spared the developers working on the core application. They were smart enough to understand that no one coming in cold would be capable of figuring out this beast.She figured she was safe—and yet, after 6 years, Anita found herself being fired. Henry brought her into his office, insisted it wasn't his choice, and emphasized that he was very sorry to lose her.Anita shook her head in resignation. After the shock had worn off, she'd looked into a few things. "Over the years, you gave me 8 projects to work on," she said.Henry nodded."Are you aware that you never tested any of them?" Anita asked. "You never released them to production. They're still sitting in SourceSafe, waiting for someone to use them. Are you aware that the company has never seen a penny from the work I've done for you?"From the look on his face, it was clear that Henry had never realized this."This has been a good learning experience, at least," Anita said. "Thanks for everything."Anita was able to take the knowledge she'd gained and double her salary at her next job, which only took 3 weeks to find. She's no longer reinventing the wheel or going unappreciated, and that's a win-win for sure. [Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
Leading From Affronts
Scientists frequently need software to support their research, but rarely are strong developers. And why should they be, that software is written to accomplish a goal, and it's the goal which matters to them more than anything about the software itself.That's where Jared comes in. He worked in a university IT department and his job was simply to write the software the researchers needed. They frequently had a very clear picture of what they needed, along with big piles of math to explain it, plus piles of example input and expected output data.The team was small- just Jared and two other developers, Larry and Barry. There was no team lead, they could simply coordinate and divide the work. Their manager was nearly invisible, and mostly focused on keeping external office politics from disrupting the work. The work wasn't precisely simple, but it was clear and well defined, the pay was good.While the code quality wasn't perfect, it was good enough. Since throughput was one of the main drivers of the design, a lot of code segments got hyperoptimized in ways that made the code harder to understand and maintain, but boosted its performance. The software was mostly stateless, the unit test coverage was nearly 100%, and while the UI was the ugliest of ducklings, the software worked and gave the researches what they wanted.In short, it was the best job Jared had ever had up to that point.Six months into the job, Jared came into work as he normally did. Larry was an early starter, so he was already at his desk, but instead of typing away, he simply sat at his desk. His hands were in his lap, and Larry simply stared forlornly at his keyboard. Barry had a similar thousand-yard stare aimed at his monitor."What's wrong?" Jared asked.The answer was just a long sigh followed by, "Just… go pull the latest code."So Jared did. The latest commit eradicated everything. Most of the files in the codebase had been deleted and replaced with a single 7,000 line God Object. And the git blame told him the culprit, someone named "Scott"."Who the heck is Scott?"Larry just shook his head and sighed again. Barry chimed in. "He's our technical lead.""Wait, we got a new technical lead?" Jared asked."No, he's always been the tech-lead. Apparently. I had to check the org-chart because I didn't even know- none of us did. But Larry's worked with Scott before."That revelation caused Larry to sigh again, and shake his head."It apparently didn't go well," Barry explained.A little later that morning, Scott wandered into their team room. "Hey, Josh, you must be the new developer.""Jared, and I've been here for six months-""So, I noticed we'd gotten a little off track," Scott said, ignoring Jared. "I've been bouncing around a lot of different projects, because well, you know, when you're good people want you to do everything, and work miracles, amirite? Anyway, we're going to make some changes to improve code quality and overall design."So Scott walked them through his new architectural pattern. That 7,000 line God Object was, in part, an event bus. No object was allowed to talk directly to any other object. Instead, it needed to raise an event and let the bus pass the information to the next object. For "performance" each event would spawn a new thread. And since the God Object contained most of the application logic, most events on the bus were sent from, and received by, the God Object.As a bonus, Scott hadn't written any unit tests. There were more compiler warnings than lines of code- Scott's code averaged 1.3 warnings per line of code. And no, Scott would not allow anyone to revert back to the old code. He was the tech-lead, by god, and he was going to lead them.Also, 18-person months of work had just been deleted, all the new features that Jared, Larry and Barry had added over the past six months. Their end users were furious that they'd just lost huge pieces of functionality. Also, the multi-threaded "performant" version took hours to do things that used to take seconds. And within a few weeks of Scott's "revisions" the number of bugs tracked in Jira rose by a factor of six.The researchers did not like this, and simply refused to update to the new application. Scott did not like that, and started trying to force them to change. Their manager didn't like any of this, and pressured the team to fix the new version of the application. And quickly, which meant a lot of unpaid overtime. Once overtime started, Scott "surprisingly" got pulled into another project which needed his attention.With Scott gone, they were almost able to revert to the old version of the code, but there had been so much work put into the new version that their manager only saw the sunk costs and not the bigger picture. They were committed to sinking the ship, whether they liked it or not.Bug counts kept rising, it got harder and harder to implement new features, there was a scramble to hire new people and the team of three suddenly became a team of twelve, but nothing could be done for it. The system had become an unmaintainable Codethulhu.The best job Jared had ever had turned into the worst, all with one commit from Scott. Jared quit and found a new job. Scott kept plugging away, vandalizing codebases in the university for another five years before finally screwing up big enough to get fired. The last Jared saw on LinkedIn, Scott had moved on to another, larger, and more prestigious university, doing the same development work he had been doing. [Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
Error'd: The Other Washington
This week, anonymous Franz starts us off with a catch-22."I opened MS Word (first time after reboot) and a dialogbox opens that tells me to close a dialog box. This wasthe only open dialog box... I guess even software makesexcuses to be lazy on Fridays."
CodeSOD: A Split in the Database
Oracle is… special. While their core product is their database software, what they actually sell is layers and layers of ERPs and HR systems that run on top of that database. And what they really make money on is the consulting required to keep those monsters from eating your company's IT team alive.Because these ERPs are meant to be all things to all customers, you also will find that there are a lot of columns named things like attribute3. Your company's custom logic can stuff anything you want in there. "Do as thou wilt," as they say. And suffer the consequences.For Steven H, his company had a requirement. The order lines needed to join to the manufactured batch that was used to fill that order. This makes sense, and is easy to implement- you add a join table that links BatchId and OrderLineId And, if the folks who build this feature did that, we wouldn't have an article.To "solve" this problem, they simply mashed together all the order line IDs fulfilled by a batch into a text field called attribute7. The data looked like:413314|413315|413329That fulfilled the requirement, in someone's mind, and the ticket was closed and folks moved on to other work. And then a few years later, someone asked if they could actually display that data on a report. It seemed like a simple request, so it got kicked off to an offshore team.This was their solution:
CodeSOD: Two Comparisons, Hold the Case
There are a lot of times when we want string comparisons to be case insensitive. It's quite a lot of cases, so every language is going to give us a way to easily specify that's what we want.Take, for example, this C# code, written by one of Robin's team-mates.
CodeSOD: Filtering Out Mistakes
We all make simple mistakes. It's inevitable. "Pobody's nerfect," as they say, and we all have brain-farts, off days, and get caught up in a rush and make mistakes.So we use tools to catch these mistakes. Whether it's automated testing or just checking what warnings the compiler spits out, we can have processes that catch our worst mistakes before they have any consequences.Unless you're Jose's co-worker. This developer wasn't getting any warnings, they were getting compile errors. That didn't stop them from committing the code and pushing to a shared working branch. Fortunately, this didn't get much further down the pipeline, but said co-worker didn't really understand what the big deal was, and definitely didn't understand why there were errors in the first place.In any case, here were the errors tossed out by the C# compiler:
CodeSOD: Are You Doing a Bit?
"Don't use magic numbers," is a good rule for programming. But like any rule, you shouldn't blindly apply it. We know what happens when people do, however: we get constants that might as well be magic numbers.Still, there are sometimes novel versions of this old song. Shmuel F sends us this one in C:
Error'd: The Scent of a Woman
While Error'd and TDWTF do have an international following, andthis week's offerings are truly global, we are unavoidably mired in American traditions.Tomorrow, we begin the celebration of that most-revered of all suchtraditions: consumerist excess. In its honor, here are a half-dozenexemplary excesses or errors, curated from around the globe. They'renot necessarily bugs, per se. Some are simply samples of thatother great tradition: garbage in.Opening from Poland,Michal reported recently of a small purchase that"The estimated arrival was October 27th. But, for a not-so-small additionalfee, AliExpress offered to make an extra effort and deliver it as soon as... November 3rd."
Classic WTF: When Comments go Wild
CodeSOD: Counting Arguments
Lucio C inherited a large WordPress install, complete with the requisite pile of custom plugins to handle all the unique problems that the company had. Problems, of course, that weren't unique at all, and probably didn't need huge custom plugins, but clearly someone liked writing custom plugins.One of those plugins found a need to broadcast the same method invocation across a whole pile of objects. Since this is PHP, there's no guarantee of any sort of type safety, so they engineered this solution:
CodeSOD: Templated Comments
Mike's company likes to make sure their code is well documented. Every important field, enumeration, method, or class has a comment explaining what it is. You can see how much easier it makes understanding this code:
CodeSOD: A Sort of Random
Linda found some C# code that generates random numbers. She actually found a lot of code which does that, because the same method was copy/pasted into a half dozen places. Each of those places was a View Model object, and each of those View Models contained thousands of lines of code.There's a lot going on here, so we'll start with some highlights. First, the method signature:
Error'd: Largely middling
Jani P. relates "I ran into this appropriate CAPTCHA when filling out a lengthy, bureaucratic visa application form." (For our readers unfamiliar with the Anglo argot, "fricking" is what we call a minced oath: a substitute for a more offensive phrase. You can imagine which one - or google it.)
CodeSOD: Efficiently Waiting
Alan was recently reviewing some of the scriptlets his company writes to publish their RPM installers. Some of the script quality has been… questionable in the past, so Alan wanted to do some code review.In the uninstallation code, in the branch for AIX systems specifically, Alan found a block that needs to check that a service has successfully shut down. Since properly shutting down may take time, the check includes a pause- implemented in an unusual way.
A Binary Choice
As a general rule, don't invent your own file format until you have to, and even then, probably don't. But sometimes, you have to.Tim C's company was building a format they called "generic raw format". It was solving a hard problem: they were collecting messages from a variety of organizations, in a mix of binary and plaintext, and dumping them into a flat file. Each file might contain many messages, and they needed to be able to split those messages and timestamp them correctly.This meant that the file format needed a header at the top. It would contain information about byte order, version number, have space for arbitrary keys, and report the header length, all as text, represented as key/value pairs. Then they realized that the some of the clients and vendors supplying this data may want to include some binary data in the header, so it would also need a binary section.All of this created some technical issues. The key one was that the header length, stored as text, could change the length of the header. This wasn't itself a deal-breaker, but other little flags created problems. If they represented byte-order as BIGENDIAN=Y, would that create confusion for their users? Would users make mistakes about what architecture they were on, or expect to use LITTLEENDIAN=Y instead?In the end, it just made more sense to make all of the important fields binary fields. The header could still have a text section, which could contain arbitrary key/value pairs. For things like endianness, there were much simpler ways to solve the problem, like reserving 32-bits and having clients store a 1 in it. The parser could then detect whether that read as 0x00000001 or 0x10000000 and react accordingly. Having the header length be an integer and not text also meant that recording the length wouldn't impact the length.These were all pretty reasonable things to do in a header format, and good compromises for usability and their business needs. So of course, Blaise, the CTO, objected to these changes."I thought we'd agreed to text!" Blaise said, when reviewing the plan for the header format."Well, we did," Tim explained. "But as I said, for technical reasons, it makes much more sense.""Right, but if you do that, we can't use cat or head to review the contents of the file header."Tim blinked. "The header has a section for binary data anyway. No one should be using cat or head to look at it.""How else would they look at it?""Part of this project is to release a low-level dump tool, so they can interact with the data that way. You shouldn't just cat binary files to your terminal, weird stuff can happen."Blaise was not convinced. "The operations people might not have the tool installed! I use cat for reading files, our file should be catable.""But, again," Tim said, trying to be patient. "The header contains a reserved section for binary data anyway, the file content itself may be binary data, the entire idea behind what we're doing here doesn't work with, and was never meant to work with, cat."Blaise pulled up a terminal, grabbed a sample file, and cated it. "There," he said, triumphantly, pointing at the header section where he could see key/value pairs in a sea of binary nonsense. "I can still see the header parameters. I want the file to be like that."At this point, Tim was out of things to say. He and his team revised the spec into a much less easy to use, a much more confusing, and a much more annoying header format. The CTO got what the CTO wanted.Surprisingly, they ended up having a hard time getting their partners to adopt the new format though… [Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!
CodeSOD: A Select Sample
"I work with very bad developers," writes Henry.It's a pretty simple example of some bad code:
CodeSOD: It's Not What You Didn't Think it Wasn't
Mike fired up a local copy of his company's Java application and found out that, at least running locally, the login didn't work. Since the available documentation didn't make it clear how to set this up correctly, he plowed through the code to try and understand.Along his way to finding out how to properly configure the system, he stumbled across its logic for ensuring that every page except the login page required a valid session.
Error'd: Any Day Now
This week at Errr'd we return with some of our favorite samples.A screwy message or a bit of mojibake is the ordinary thing; the realgems are the errors that are themselves error dialogs.We've got a couple of those, and a few of the ordinary sort.Stealing the worm, pseudoswede Argle Bargle comments "Generally,Disqus works well. I can even imagine the borderconditions that cause my time-travel glitch. I'm even gladthat the programmers planned for... for just such an emergency.Maybe it's even good programming. It's still very silly."
CodeSOD: Giving Up Too Late
"Retry on failure" makes a lot of sense. If you try to connect to a database, but it fails, most of the time that's a transient failure. Just try again. HTTP request failed? Try again.Samuel inherited some code that does a task which might fail. Here's the basic flow:
...9101112131415161718...