The Daily WTF
The following are the titles of recent articles syndicated from The Daily WTF
Add this feed to your friends list for news aggregation, or view this feed's syndication information.

LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.

[ << Previous 20 ]
Tuesday, March 21st, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: Magical Destruction

Pretty much all object oriented languages have some concept of "destruction": objects need to release any resources they acquired at construction. In a lot of cases, we don't need to customize this terribly much, but when we do, it's vitally important to do it correctly.

Nancy's co-worker perhaps didn't understand the "correctly" part. So this was the standard pattern of C++ destructor that they wrote:

SomeObject::~SomeObject( )
{
  if (!this)
    delete this;
}

So, the first thing to point out is that this will always have a value at this point in the object's life-cycle. So the condition is never true, and thus this destructor does nothing, and we can safely ignore it.

But I can't just ignore it, because I'm trying to understand the thought process of this. The purpose of delete in C++ is to take memory referenced by a pointer and free it. If this is null (if that condition were true), then the pointer isn't pointing anywhere, thus there's nothing to delete. But the problem is only worse if we were to remove that conditional, because this is already in the process of being deleted. The lifecycle of that object is over, and thus we can't delete it- this is undefined behavior, and you all know what undefined behavior means in C or C++: nasal demons.

One tiny if that can never be true is all that saves the original developer from having demons fly out their nose.

All that said, it is easy to understand the developer's logic here: they picked up this code as an "incantation" at some point- magic words they need to include without understanding what they do. They just forever after repeated the incantation, like a spell, assuming it would ensure no memory leaks, a bountiful harvest, and appease the gods of C++ so that they do not rain down their fury on us all.

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
Monday, March 20th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
Requirements in Technicolor

Managing the requirements for an application is a huge challenge. The hardest part of the challenge is that, very frequently, the user's don't know what they really want or need. Prying it out of them, and giving them an application that actually solves the real problem they have, is an art.

The worst situation is when the users are absolutely certain that they do know what they want. This was the situation that Irini found herself in.

The project started, as many such projects do, in the wake of a disaster. One of the company's many Capital Improvement Projects (CIP) slipped through the cracks during budgeting. It ran six months past schedule, but managed to close out with a few hundred grand still unspent in its budget. When someone tried to reallocate that money, the management team in charge of managing CIPs found out, they went full code-red, trying to do two things at the same time: understand why that project got lost in tracking, and also why when they tried to reallocate the money, it kept getting reset in their Enterprise Resource Planning (ERP) system.

Eventually, that lead them to Sofia, the VP of Finance, and managed them all through a spreadsheet she had created by herself. The ERP kept getting reset because she manually updated it based on the contents of the spreadsheet. The project got lost because she manually color-coded the projects in her spreadsheet, and one day accidentally hid the row, instead of making it yellow.

No one liked that there was a manual process. No one liked that only one person ever touched this system. Management wanted a robust, backed-up IT system, and wanted to open the management of this process to more of the finance team, so Sofia wasn't the only failure point.

The solution was clear: gather requirements from Sofia and either purchase a product or develop something in house to replace the spreadsheet. Very quickly, it was decided that "develop in house" was the only way to customize the tool to what Sofia's process already looked like, and "standardizing the process" was not an option.

Irini was on the IT team that was chosen to build this product. A business analyst tried to sit down with Sofia to suss out her actual requirements, but hit a brick wall. The spreadsheet already did everything she wanted. The spreadsheet was the requirements. She gave the analyst a copy and sent him on his way to get something built.

As mentioned, Sofia manually color-coded the rows in the sheet to help with project tracking. Fortunately for the development team, her spreadsheet included a key, describing what the colors meant. Unfortunately, it was this "technicolor yawn", as Irini puts it:

A rainbow of cryptic rules, including custom color rules for two projects, a bunch of long conjunctions, and special cases

Now, as "re-implement this spreadsheet as an application" goes, this isn't terrible. It's an ugly, complicated set of rules, but at least it's documented. But what we have here is a case of one person's idiosyncratic style of organization determining the features for all users of the application.

This is what the users said they wanted. This was what the dev team implemented. Everyone on the dev team suggested that maybe they needed a better way of letting users filter, sort, and prioritize their capital projects, possibly even allowing each user to manage custom filters, but no- the spreadsheet was the requirements.

When the app launched, the Finance team was excited to have more control over their capital projects. Then they started to use the application, and quickly got confused. It was built, not to solve the problem of managing projects, but to fit Sofia's workflow, and her workflow alone. It was impenetrable and opaque to everyone else. After a few months of endless tickets as users got lost in the confusing interface, most of them gave up.

Sofia stuck with it longer, but she hated the application. As it turned out, automatic color coding was a big anti-feature for her, because the rules she had in the sheet were just guidelines, and she wanted to be able to apply any color to any project based on information that existed only in her head.

The application is still technically running, but nobody in Finance is using it. They've reverted back to "Sofia has a spreadsheet for it."

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
Friday, March 17th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
Error'd: Filling

We got quite a few irregular submissions this week from regular contributors. Which is to say routine contributors. We're not qualified to make judgements about whether or not anyone is what what most folks would call normal.

First up, Isaac D. is struggling with localization, kvetching "Apparently this number format is ALIVE and WELL in parts of India and Afghanistan, but us poor Australians on desktop browsers also seem to be visually assaulted with it. I wonder if the Zuck will pay me $1,00,000 for reporting it or do real country borders mean nada in the Metaverse? ;)" This would ordinarily be controlled by some operating system or browser configuration, would it not?

facebook

 

Educated Peter G. has had his absolute fill of overwrought maths. This is just a bridge too far for Peter. "We've had issues with excessive rain recently, good thing the dams are going above and beyond to help store it all." I naively imagine that the managing authority has defined target capacity as something like 90% of the absolute maximum with a reserve for safety, but perhaps a clueful Kiwi will comment with a well-informed explanation?

dams

 

Sam tries to be punctual, he really does. But the gourmands in the big city brook no tardiness at all. Frets he, "I encountered this trying to book dinner. I'm worried I might be late. Or early." I hope they'll let him sit at the bar and wait if he anticipates his appointment.

dinner

 

Meanwhile Mark has a small problem with a very (very) small dinner party. "Tried to make a reservation for some coworkers and got this confirmation email from OpenTable. I know they'll be jet lagged, so hopefully they can arrive precisely by 1:17am." Personally, I'm quite curious about the menu.

opentable

 

Finally, autodidact Andreas R. flexes his ten years award from Duolingo for us. "Apparently I studied 8027 words in the past year alone but only 5758 in total over the last ten years. So I guess I spent the previous nine years forgetting 2269 words." Seriously, ten years of doing anything is pretty noteworthy, even if you've forgot almost more than you've learned. Mark is holding a celebratory dinner party for you, don't be late!

duolingo

 

[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
Thursday, March 16th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: The Properties of Contract Development

James's management had more work than they had staffing for, so they did what any company would do in that situation: expand their staff. No, of course not, I'm kidding. They bundled up a pile of work and shipped it off to the contractor who gave them the lowest bid, provided absolutely no oversight or code-quality standards in the contract, and hoped for the best.

What they got back was a gigantic pile of code that compiled. That is the only positive thing one can say about the code, because it certainly didn't work. Within a few weeks of starting reviewing the gigantic pile of garbage the contractors turned in, the dev team reached the decision that it would be quicker to rewrite from scratch than it was to try and pick apart the trashpile and reshaped the refuse into something approaching their actual requirements.

James sends us just one small VB .Net property definition which summarizes the kinds of problems they were dealing with:

Public Overrides ReadOnly Property id as Object
	Get
		Return id
	End Get
End Property

A quick primer on .NET's property architecture: it's syntactic sugar for generating getters-and-setters, but allowing the property to behave as if it's just a variable. So if a class has a property called foo, you can do things like x = myObj.foo or myObj.foo = x. It's actually calling getter and setter methods, but it's invisible at the point of use.

I bring this up, because on the line where we Return id, we're calling the getter for a property called id. That's this property. So we have an infinite recursion and never actually get a value. Which we couldn't have a value in the first place, since this property is ReadOnly- it only supports Gets. Nothing about this works. Nothing about this could work.

And even if it did work, note how we cast to Object, which is the VB .Net way of saying "I hate worrying about types, so I'll just cast everything to object and pretend that types don't exist."

And that's the basic philosophy underpinning all the other code in the application: it's written in ways that guarantee that it could never work as intended. Frequently, it's simple misuses of the language, like this one.

The "correct" way to implement this, by the way, would be:

Private _id as Integer
Public Overrides ReadOnly Property id as Integer
	Get
		return _id
	End Get
End Property

Someplace else, probably in the constructor, we'd set _id.

This is a pretty easy, beginner mistake to make in .NET. Hell, I've had the brain fart and written code not too dissimilar from the original example. But I never checked it in. I certainly never handed it off at the end of a contract and claimed that I fulfilled the requirements.

The real WTF isn't the code: it's the process that let people hand this code off as if it were a completed set of requirements.

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
Wednesday, March 15th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: Going to Great Len(gths)

Mira was trawling through some old Python code. This particular block of code needed to load some data from JSON. The data was an array, and the code needed to know how long the array was.

Python has a handy len function that does this on anything enumerable. If our developer had used len, we'd be looking at different code today.

This was their approach:

tdata = json.load(html)
j = -1
test = True

while test:
      try:
               j = j+1
               tdata[j]
      except:
               test = False

Whoever wrote this "must have been drunk," writes Mira. Certainly, they were under the influence of something.

This code loops while test is true. Inside the loop, it increments j, and then tries to access the element of the array at j. If this succeeds, the loop continues. If it throws an exception (most likely because we've run off the end of the array), the code sets test to False, which causes us to exit the loop on the next iteration.

It's not just that they're using exceptions for flow control that bothers me, though that's the core WTF. But they found a way to do pretty much every other thing wrong. They start with j at -1, and then pre-increment, which isn't wrong but is unconventional. They could put the whole loop in an exception handler, or use a break in the except clause. Or they could have just used len, which would have made all this code go away.

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
Tuesday, March 14th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: Terning On a Control

One of Tim's co-workers needed to handle a simple condition: if a control in their web app was enabled, show it, otherwise hide it.

Now, if you or I were writing that, we might write some awfully verbose code, like:

if (on)
{
	d.show();
}
else
{
	d.hide();
}

It's an obvious solution, and while there are probably better ways to structure the program, it's a perfectly viable approach. But only a weak, underskilled programmer would want to do the obvious thing. Tim's co-worker wants you to know that they're clever, so they wrote it this way:

d[on?'show':'hide']();

This is a "clever" abuse of a "feature" of JavaScript: all objects are really just maps. The ternary chooses a key: if we're on, use the key show, otherwise use the key hide. Then we invoke the function at that key.

No one changed the code to make it more clear- it's spammed all over the codebase- but they did add a comment everywhere this pattern appeared, just to avoid future confusion.

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
Monday, March 13th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: A False Comparison

Iterating across a list is a very simple task. It's a CS-101 type thing, and if anything, it's the one thing I'd expect any developer to be able to do without confusing me too much.

Brendan has a co-worker that wants to change my mind about this.

They write Java code like this:

if (counter == customerList.size() - 1 == false)
    break;

This is in the middle of a while loop. counter is the iterator variable, which counts up from 0. So the real purpose of this if is to check: if (counter < customerList.size()), but obviously that's not what the developer chose to write here.

But it seems like they went out of their way to write the most cryptic version they could. A good ol' != would have been annoying, but also worked. They could have negated the whole condition. But no, they needed to compare two values and then compare the result of the compare to false.

Brendan adds:

It's just one line, though it was lifted from a file the style of which was very much in keeping with this exhibited spirit of disdain for maintenance. The author didn't hang round long enough to have to deal with this mess.

The developer who writes code like this didn't stick around long? I'm surprised they didn't get promoted to management. With skills like this, they could easily be the CEO of Twitter.

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Friday, March 10th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
Error'd: Nothin Doin

IBM Profs was introduced in 1980 including both email and calendaring support. Online calendaring is now old enough to have grandchildren, but we still can't get the simplest things right.

As our friend Romeo rhetorically wonders "Million dollar question: What calendar does Microsoft use?"

micro

 

Microsoft aren't the only ones struggling with dates. An anonymous phillystine purchased a package from Costco and tried to track its progress cross-country. We've showcased flawed package trackers before, this is another in the same vein. I would prefer actually tracking and storing sequential locations, but even tracing by timestamp and (assuming accurate clocks) sorting the displayed results should do better than this. Says our cranky consumer "I was a little surprised how it was not moving anywhere. When I checked on Monday it only showed shipping label. I didn't expand to see it had actually shipped. Even the latest entry showed it in a different state from where it actually was. Date/Time sorting is HARD! Yes, but not this hard."

tracking

 

Michael R., en route to Paris, mutters "Thanks for nothing Tsohost." I hope he's not complaining; it seems like a pretty good deal.

0000

 

Home handyman Clive P. shopped this wtf to us, and we bought it. "When I saw this dishwasher the depth seemed ideal, quite slim actually, but I was a bit worried it would be too wide or too high to fit in our kitchen." Maybe diagonally?

dishwasher

 

Latvian Valts S. fears calamity "Looks like the rain patterns around here are going to get weird... I blame the global warming." but personally I blame the Finns for the lapse, because, oh never mind.

rain

 

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
Thursday, March 9th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: Evaluating Selections

If you're writing an application with a drop-down list, it's typical and reasonable to auto-select a certain option in the list. But John found an approach to doing this that's anything but typical.

function selectsearch(myform, myselect, myinput) {
    var i = 0;
    var fvalue = 1;
    do {
        arrayresult = eval(myform+"."+myselect+".options["+i+"].value");
        if (arrayresult == myinput) {
            eval(myform+"."+myselect+".options["+i+"].selected = true");
            var fvalue=5;
        }
        i++; 
    } while(fvalue<3);
}

The core of this approach is a do/while loop, which is already an odd choice. But the loop itself is guarded not by i, our obvious counter variable, but by fvalue, which starts at 1 and causes the loop to exit when it exceeds 2. Which it only does when we've found the option we're looking for, which means this function will raise an error if it runs off the end of the array.

Which brings us to the evals. Instead of passing objects around, we pass strings around, using the DHTML style of accessing form fields wrapped up in a string-concatenated eval call.

If this code had a D&D alignment, it would be "chaotic eval".

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
Wednesday, March 8th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
Tales from the Interview: The Final Interview

Gennifer had a job. Her employer got bought out by another company, and the purchaser was notorious for gobbling up companies, taking over their processes, and then doing mass layoffs. Seeing the writing on the wall, Gennifer started job hunting.

Before too long, she had two very likely candidates. The first was Initrode. It wasn't a great match- Gennifer's skills didn't overlap well, and while the salary was respectable, it wasn't as good as the other position, at Initech.

Gennifer interviewed at Initrode first. She did a single round of interviews, and left the interview with an offer. She told them that she'd consider it, but also let them know she was engaged in the recruitment process elsewhere. They understood, but did let her know that they would need a response relatively soon.

The Initech interviews were wildly different. First, she did an hour and a half interview with the head-hunting agency that connected her with the position. That went well, so the next step was an online coding assessment, which she aced. The final round was a remote interview with Initech, sitting in with Bob, Bob, and Bill.

"Great to have you on the call," said the first Bob. "Let's just get right into it."

"Where do you see yourself in five years?" asked the other Bob.

That was a strong opener. What followed were the other typical soft questions: what's your biggest strength, what's your biggest weakness, tell me about a time you had to resolve a conflict, etc.

Then Bill got into it. "Pick up an object on your desk," Bill said. "Pick anything."

Gennifer picked up an eraser and held it in front of the camera.

"Okay, now explain multiple inheritance in C++ using that object."

Gennifer blinked, surprised. "Um, an eraser has the 'remove marks' functionality. A pencil would have the 'make marks' functionality. Some pencils have erasers on the end, so those pencils are also erasers, so we could say that they inherit from both the regular pencil class and the eraser class."

Bill shook his head. "That isn't really the best example."

Gennifer put the eraser down.

"How about this," the other Bob said. "How would you test a coffee mug?"

Gennifer thought that was a better question for an engineer at Pfaltzgraff or a similar company, but she described a series of tests, starting with basic functionality (I can lift it by the handle, I can pour liquid into it) to more stress testing type considerations. That answer they liked.

"What I need you to tell me," Bill said, "is why I should hire you?"

"I mean, you're actively looking for developers, my skills are a perfect match for the position. That seems like a good reason to hire someone."

Bill shook his head. "What I need to know is that you're not going to take this job and leave after several months."

The Bobs nodded. One of them said, "We've had a little problem with retention, lately."

"We think it's millennials," the other said. "They can't really commit to a hard day's work."

"They just take the job, discover they don't like it here, and leave."

"How do we know you're not going to do that to us, too?" Bill asked.

That exchange raised so many red flags that it could have collapsed the USSR all over again. Gennifer replied with a statement about how her job history showed that she tended to stick it out in jobs, and wasn't simply running from job to job as a form of career advancement. They concluded the interview.

"Someone from our office will be in touch in the next two weeks with feedback," the Bobs said.

Gennifer left the interview sure of two things: they didn't want to hire her, and she didn't want to work there. So she wrote up an email, thanking them for their time, but she was going to move forward with a different opportunity. She sent it off and thought that was the end of that.

The headhunter called a few minutes after she hit send. "What are you doing? You can't decline this offer."

"They haven't made an offer," Gennifer said, "and I don't think they're going to."

"Are you kidding? I just got off the phone, and they were raving about you. They think you're great. They definitely want to move forward. They just have a hard interviewing style, everyone walks out thinking they whiffed it. The job is yours."

"Well, I don't think I'm interested."

"Oh, so you're wasting my time, then?" the recruiter said, angrily.

"No- it's just-"

Gennifer didn't want to burn a bridge with the headhunter- in her locale, it was a small industry and everyone knew everyone- so she politely let him rant for nearly an hour about how great the opportunity was, how much Initech wanted her on their team, and how absolutely rude it would be if she didn't take the position. She'd be wasting everyone's time.

"I apologize for my rudeness," she said, "but I have to do what's best for my career. And honestly, if that's their normal interview process, and this is their normal communication style, I don't want to work there. Thank you for your time."

Gennifer now works with Initrode. The headhunter still sends her messages on LinkedIn, suggesting she should reconsider.

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!
Tuesday, March 7th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: Trying Parses

Another day, another terrible way to validate integers. Today's submission comes from Sluiper.

This approach, at least, contains a mild bit of cleverness. It's not the good kind of cleverness that makes a complicated problem more clear and easier to understand, but the bad kind that exploits assumptions about low-level technical details.

private static bool IsInteger(string pString)
{
	for (int i = pString.Length - 1; i >= 0; i--)
	{
		if (pString[i] > '9' || pString[i] < '0')
		{
			return false;
		}
	}
	return true;
}

In this case, we exploit the fact that almost all character sets put the characters 0-9 adjacent to each other in sequence. Not that C# supports EBCDIC, but even EBCDIC obeys that common-sense rule. EBCDIC doesn't put letter characters adjacent to each other, but it at least puts digits all together in a group.

I also appreciate the reverse string traversal, as a pointless micro-optimization. I can see the developer looking at the real world data they need to validate, seeing that the last few characters were usually the ones that would break validation, and opting to traverse backwards to save a few comparison operations.

It's that last optimization that's notable, just because the basic algorithm showed up here in 2005- but in PHP. I hope and fear that some developer ported the PHP version to C# because they couldn't find a better option.

Of course, all that effort, and they ignored the built-in TryParse. Ah well.

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
Monday, March 6th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: An Array of Colors

Sandra, still at InitAg, has to work with Brad. Some time ago, Brad was assigned a slew of front-end development tasks, since he's a web developer. But Brad isn't a front-end developer, and doesn't really have a good grasp of front-end development. Management isn't clear on the difference: "Aren't you a web developer? I don't care which end you use, just develop." Brad is also game to tackle whatever task is assigned to him, regardless of whether he has any sense of how to solve the problem.

When Brad needed to display data on a map, the requirements wanted the map layers to be distinguished by color. So Brad did the usual thing one might do in this situation: he created a gigantic array of all possible colors that might be used on the map. Actually, he created two: colors and colorsBlackWhite.

let colorsBlackWhite = ["#000000", "#010101", "#020202", "#030303", "#040404", "#050505", "#060606", "#070707", "#080808", "#090909",
 "#0a0a0a", "#0b0b0b", "#0c0c0c", "#0d0d0d", "#0e0e0e", "#0f0f0f", "#101010", "#111111", "#121212", "#131313",
 "#141414", "#151515", "#161616", "#171717", "#181818", "#191919", "#1a1a1a", "#1b1b1b", "#1c1c1c", "#1d1d1d",
 "#1e1e1e", "#1f1f1f", "#202020", "#212121", "#222222", "#232323", "#242424", "#252525", "#262626", "#272727",
 "#282828", "#292929", "#2a2a2a", "#2b2b2b", "#2c2c2c", "#2d2d2d", "#2e2e2e", "#2f2f2f", "#303030", "#313131",
 "#323232", "#333333", "#343434", "#353535", "#363636", "#373737", "#383838", "#393939", "#3a3a3a", "#3b3b3b",
 "#3c3c3c", "#3d3d3d", "#3e3e3e", "#3f3f3f", "#404040", "#414141", "#424242", "#434343", "#444444", "#454545",
 "#464646", "#474747", "#484848", "#494949", "#4a4a4a", "#4b4b4b", "#4c4c4c", "#4d4d4d", "#4e4e4e", "#4f4f4f",
 "#505050", "#515151", "#525252", "#535353", "#545454", "#555555", "#565656", "#575757", "#585858", "#595959",
 "#5a5a5a", "#5b5b5b", "#5c5c5c", "#5d5d5d", "#5e5e5e", "#5f5f5f", "#606060", "#616161", "#626262", "#636363",
 "#646464", "#656565", "#666666", "#676767", "#686868", "#696969", "#6a6a6a", "#6b6b6b", "#6c6c6c", "#6d6d6d",
 "#6e6e6e", "#6f6f6f", "#707070", "#717171", "#727272", "#737373", "#747474", "#757575", "#767676", "#777777",
 "#787878", "#797979", "#7a7a7a", "#7b7b7b", "#7c7c7c", "#7d7d7d", "#7e7e7e", "#7f7f7f", "#808080", "#818181",
 "#828282", "#838383", "#848484", "#858585", "#868686", "#878787", "#888888", "#898989", "#8a8a8a", "#8b8b8b",
 "#8c8c8c", "#8d8d8d", "#8e8e8e", "#8f8f8f", "#909090", "#919191", "#929292", "#939393", "#949494", "#959595",
 "#969696", "#979797", "#989898", "#999999", "#9a9a9a", "#9b9b9b", "#9c9c9c", "#9d9d9d", "#9e9e9e", "#9f9f9f",
 "#a0a0a0", "#a1a1a1", "#a2a2a2", "#a3a3a3", "#a4a4a4", "#a5a5a5", "#a6a6a6", "#a7a7a7", "#a8a8a8", "#a9a9a9",
 "#aaaaaa", "#ababab", "#acacac", "#adadad", "#aeaeae", "#afafaf", "#b0b0b0", "#b1b1b1", "#b2b2b2", "#b3b3b3",
 "#b4b4b4", "#b5b5b5", "#b6b6b6", "#b7b7b7", "#b8b8b8", "#b9b9b9", "#bababa", "#bbbbbb", "#bcbcbc", "#bdbdbd",
 "#bebebe", "#bfbfbf", "#c0c0c0", "#c1c1c1", "#c2c2c2", "#c3c3c3", "#c4c4c4", "#c5c5c5", "#c6c6c6", "#c7c7c7",
 "#c8c8c8", "#c9c9c9", "#cacaca", "#cbcbcb", "#cccccc", "#cdcdcd", "#cecece", "#cfcfcf", "#d0d0d0", "#d1d1d1",
 "#d2d2d2", "#d3d3d3", "#d4d4d4", "#d5d5d5", "#d6d6d6", "#d7d7d7", "#d8d8d8", "#d9d9d9", "#dadada", "#dbdbdb",
 "#dcdcdc", "#dddddd", "#dedede", "#dfdfdf", "#e0e0e0", "#e1e1e1", "#e2e2e2", "#e3e3e3", "#e4e4e4", "#e5e5e5",
 "#e6e6e6", "#e7e7e7", "#e8e8e8", "#e9e9e9", "#eaeaea", "#ebebeb", "#ececec", "#ededed", "#eeeeee", "#efefef",
 "#f0f0f0", "#f1f1f1", "#f2f2f2", "#f3f3f3", "#f4f4f4", "#f5f5f5", "#f6f6f6", "#f7f7f7", "#f8f8f8", "#f9f9f9",
 "#fafafa", "#fbfbfb", "#fcfcfc", "#fdfdfd", "#fefefe"];

Whitespace added so it's not a single line of every possible grey.

That's just the black-and-white array. 255 shades of grey. This is used as a lookup table, where a layer's index determines what color it gets. That doesn't seem like a great way to manage that, especially since it means adjacent layers are going to have adjacent colors.

The arrays were used like this:

               colorUsed = colors[idx];
{% if is_granted('ROLE_UBER') or _user.email == 'redacted@init.ag' %}
               colorUsed = colorsBlackWhite[idx];
{% endif %}

Note the mix of PHP and JavaScript- as mentioned, Brad wasn't a front-end developer, so he used the back-end tool he knew. Everyone gets a color map, unless they're a ROLE_UBER or have a very specific, hard-coded email address. Those people get a black-and-white map.

Or at least they used to. In late 2021, Brad removed the usage of the colorsBlackWhite array (but not the array itself) in one gigantic mega-commit that alter a few thousand lines of code in the application, with the commit comment: "Code cleanup."

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
Friday, March 3rd, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
Error'd: It Seats Zero

Automotive afficionado Mike S. proudly relates "My first and only car has been a classic 1965 6-cyl Ford Null. I've always loved it but it does crash from time to time, even though I've received many pointers on how to avoid that. I've considered getting an Infiniti and then would divide my time between the two." Avoid pointers, Mike.

null

 

Northern neighbor and Error'd enthusiast Eddie R. doubled down on submissions this week. First he shared a sales pitch from that venerable society. "The RCGS emails me pretty regularly, but it looks like this week they did a manual mail merge and skipped the merge part."

nng

 

And then he buckled down to pay his back taxes but found he's very far behind. "Apparently the Canada Revenue Agency has not received my tax returns for the years leading up to the birth of Christ. Oops?"

bc

 

Appleist Alex somehow triggered an odd error. Is it my eyes, or are two of these boxes larger than the rest? Alex explained "The password must contain 1 uppercase letter, 1 digit, 1 punctuation and 2 nulls on the 2FA page."

apple

 

Finally, Dutch Denilson shows out the week. "This site is originally in Dutch, and they translated it themselves to English. Unfortunately, nobody did QA on this specific page in the English version. Truth to be told, translations are usually done out-of-context. Anyway, out of the two continue buttons, I obviously clicked on the wrong one, so I could continue on my journey to find the right button." And now we'll all continue on our own journeys. Goed weekend allemaal!

continue

 

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
Thursday, March 2nd, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: Peer Feedback

Pieter-Jan needed to add some features to a PHP-based site for managing student assessments. Students would complete projects, submit them, and then receive feedback from their peers. The number of peers providing feedback is variable, so the application has to manage that. Which, you might be thinking, "that sounds like not a big deal to manage," but for Pieter-Jan's predecessor, it seems like it may have been.

    if($i > '0') {
        $team=array($studentName1,$content1,$motivation1,$isTeamMate1);
    }
    if($i > '1') {
        $team=array($studentName1,$content1,$motivation1,$isTeamMate1,$studentName2,$content2,$motivation2,$isTeamMate2);
    }   
    if($i > '2') {
        $team=array($studentName1,$content1,$motivation1,$isTeamMate1,$studentName2,$content2,$motivation2,$isTeamMate2,$studentName3,$content3,$motivation3,$isTeamMate3);
    }

Each piece of student feedback contains four items. If two students give feedback, we create an array with 8. If three give feedback, we create an array with 12 items. There are seven more if statements exactly like these examples here.

And of course, how do we parse this? With a handy, dandy for loop:

for ($u = 0; $u < $i; $u = $u +1) {
 $v=$u+1;
 $w=$u*4;
 $x=($u*4)+1;
 $y=($u*4)+2;
 $z=($u*4)+3;
 //remainder cut out
}

For any user u, the variables $w, $x, $y, and $z will contain the index of their required fields.

Apparently, the customer didn't like that the amount of feedback was capped at ten students, and wanted the app to support any arbitrary number of students. At that request, the original developer quit the project, and this became Pieter-Jan's problem.

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!
Wednesday, March 1st, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: Evaluating Regexes

Stack V supports a web application that accepts regexes from users. For legacy reasons, the users must supply the surrounding / characters, as well. There was some validation to ensure that the inputs were correct, but QA discovered that invalid regular expressions were getting through.

They filed a bug, it got triaged, and then shipped off to a contractor to patch. This was the contractor's solution:

    const isRegex = (string) => {
        try {
            // eslint-disable-next-line no-new-func
            return new Function(`
                "use strict";
                try {
                    new RegExp(${string});
                    return true;
                } catch (e) {
                    return false;
                }
            `)();
        } catch(e) {
            return false;
        }
    };

Here, we use string interpolation to generate some JavaScript code. It tries to construct a regex using our input string, and returns false if it doesn't compile. We then execute that generated code using new Function, which just evals the string. And then, in true "just ship it" contractor fashion, they disable the warning that tells them this is a terrible idea.

The obvious problem here is one of code injection. But there's another problem: it doesn't meet the requirements. Because of some other WTF, the users need to supply /s. But the RegExp constructor also accepts strings, so 'this is my regex' would pass this validation, but would be considered invalid by the application.

This code got kicked back to the contractor, but the contractor claimed that they'd already spent their budget on the work so far, and needed a contract extension to do any more work. While management hashes that out, fixing this bug has moved in-house instead.

[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.
Tuesday, February 28th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: Exhaustive Scheduling Options

A true confession: I absolutely cannot successfully edit a crontab file without spending a lot of time reading docs on what all the little date/time/interval flags mean. Partially, it's just that I don't do it very often, but mainly the information flies right out of my head once I've done it. I can absolutely understand why someone might want to write a little helper program to help themselves manage their crontab.

I just can't understand why they'd write this one, sent to us Beorn. We'll have to take this one in chunks, because it's 18,905 lines.

We'll start with the function dayofweek, so you can get a sense of the pattern that gets used. Here's the first if condition for its core logic:

	if (this.myObject.chkBoxMonday.Checked)
    {
        k = 0;
        pauto_day_of_week = k.ToString();
        serie = true;
        if (this.myObject.chkBoxTuesday.Checked)
        {
            ktransit = 1;
            serie = true;
        }
        else
        {
            k = 2;
            serie = false;
        }

        if (this.myObject.chkBoxWednesday.Checked)
        {
            if (serie)
            {
                ktransit = 2;
            }
            else
            {
                pauto_day_of_week = pauto_day_of_week + "," + k.ToString();
                k = 3;
                serie = true;
            }
        }
        else
        {
            if ((serie) & (k <= ktransit)) pauto_day_of_week = pauto_day_of_week + "-" + ktransit.ToString();
            serie = false;
            k = 3;
        }

        if (this.myObject.chkBoxThursday.Checked)
        {
            if (serie)
            {
                ktransit = 3;
            }
            else
            {
                pauto_day_of_week = pauto_day_of_week + "," + k.ToString();
                k = 4;
                serie = true;
            }
        }
        else
        {
            if ((serie) & (k <= ktransit)) pauto_day_of_week = pauto_day_of_week + "-" + ktransit.ToString();
            serie = false;
            k = 4;
        }

        if (this.myObject.chkBoxFriday.Checked)
        {
            if (serie)
            {
                ktransit = 4;
            }
            else
            {
                pauto_day_of_week = pauto_day_of_week + "," + k.ToString();
                k = 5;
                serie = true;
            }
        }
        else
        {
            if ((serie) & (k <= ktransit)) pauto_day_of_week = pauto_day_of_week + "-" + ktransit.ToString();
            serie = false;
            k = 5;
        }

        if (this.myObject.chkBoxSaturday.Checked)
        {
            if (serie)
            {
                ktransit = 5;
            }
            else
            {
                pauto_day_of_week = pauto_day_of_week + "," + k.ToString();
                k = 6;
                serie = true;
            }
        }
        else
        {
            if ((serie) & (k <= ktransit)) pauto_day_of_week = pauto_day_of_week + "-" + ktransit.ToString();
            serie = false;
            k = 6;
        }

        if (this.myObject.chkBoxSunday.Checked)
        {
            if (serie)
            {
                ktransit = 6;
                pauto_day_of_week = pauto_day_of_week + "-" + ktransit.ToString();
            }
            else
            {
                pauto_day_of_week = pauto_day_of_week + "," + k.ToString();
                k = 7;
                serie = true;
            }
        }
        else
        {
            if ((serie) & (k <= ktransit)) pauto_day_of_week = pauto_day_of_week + "-" + ktransit.ToString();
            k = 7;
            serie = false;
        }
    }

If "Monday" is checked, then we check each successive day of the week, compiling our pauto_day_of_week string. The purpose of this block is to determine if we have a contiguous series of days, or run on independent days.

And this is the logic for Monday. Similar logic is repeated for every other day of the week.

At this point you say to yourself: "Sure, this is an absolutely bonkers way to write this, but it's only seven days, that's gonna be what, 513 lines of code? Where's the rest of that 18kLoC coming from?"

My friends, let me introduce you to dayofmonth:

    public void dayofmonth()
    {
    Int32 k, ktransit = 0;
    bool serie = false;

    if (this.myObject.chkBoxDay1.Checked)
    {
        k = 0;
        pauto_day_of_month = k.ToString();
        serie = true;
        if (this.myObject.chkBoxDay2.Checked)
        {
            ktransit = 1;
            serie = true;
        }
        else
        {
            k = 2;
            serie = false;
        }
	// … snip

Once again, we take each individual day of the month, and create an if-branch to compare it against each other day of the month.

You should be unsurprised that there's also a month function:

public void month()
    {
    Int32 k, ktransit = 0;
    bool serie = false;

    if (this.myObject.chkBoxJanuar.Checked)
    {
        k = 0;
        pauto_month = k.ToString();
        serie = true;
        if (this.myObject.chkBoxFebruar.Checked)
        {
            ktransit = 1;
            serie = true;
        }
        else
        {
            k = 2;
            serie = false;
        }
	//… snip

And an hours, and minutes. Which thank the gods of bad code, they only operate in 10 minute increments.

Someone wrote this. I imagine they used a lot of copy/paste- I hope they used a lot of copy/paste, but someone built this monstrosity, looked at that closing bracket on like 18,905, and said: "Yes, this is good. I'm going to use this."

There is so much code, we cannot include the entire snippet here. To spare your browsers, we'll just link to a text version of the code.

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!
Monday, February 27th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: Terning Nulls into Values

A former co-worker of David S wanted to check for nulls, and apparently, they had just learned about the ternary operator, so they wanted to combine these actions. That, itself, isn't a WTF- using ternaries to coalesce nulls is a time-honored tradition and generally pretty effective.

Let's see how this Java developer approached it:

return findProgram(
    id.isEmpty() ? null : id, 
    title == null ? null : title, 
    start == null ? null : start, 
    end == null ? null : end);

The first parameter actually makes sense to me, or at least isn't the worst thing. I'm not fond of passing nulls around (optional types are almost always a better choice), but I don't hate it.

Then we get the delightful, pointless checks that make this a true WTF. If title is null, pass a null, otherwise pass title. If start is null, pass null, otherwise pass start. And so on.

But hey, at least they got to use ternary expressions.

[Advertisement] ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: Tenrning Nulls into Values

A former co-worker of David S wanted to check for nulls, and apparently, they had just learned about the ternary operator, so they wanted to combine these actions. That, itself, isn't a WTF- using ternaries to coalesce nulls is a time-honored tradition and generally pretty effective.

Let's see how this Java developer approached it:

return findProgram(
    id.isEmpty() ? null : id, 
    title == null ? null : title, 
    start == null ? null : start, 
    end == null ? null : end);

The first parameter actually makes sense to me, or at least isn't the worst thing. I'm not fond of passing nulls around (optional types are almost always a better choice), but I don't hate it.

Then we get the delightful, pointless checks that make this a true WTF. If title is null, pass a null, otherwise pass title. If start is null, pass null, otherwise pass start. And so on.

But hey, at least they got to use ternary expressions.

[Advertisement] ProGet’s got you covered with security and access controls on your NuGet feeds. Learn more.
Friday, February 24th, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
Error'd: Take Off

Slow news week at Error'd, so we're dusting off a couple of submissions from earlier. That last one's a beauty, eh?

Special Dave flexes "Got my annual request for a donation to Habitat for Humanity. Not sure if their new URL is meant to convey just how special I am as a donor, or if someone was goofing off with a test for formatting the form and forgot to change before their production run." We love you too, sweet cheeks.

honey

 

Moody Nicola is having an existential crisis. "MY laptop is not even remotely trying to help!" she writes. "Luckily we're already in the second half of the month; I'll be so happy to start anew. Hoping to get a bit more optimism from macosx."

moanth

 

Jinpa encountered this one at a semi-fancy hotel (dig the slick ice bucket!) Somehow I feel like we've run this before, but I'm not finding it in the archives. Any memories?

tv

 

Mike S. snapped a shot from his own HDMI TV. Is it worthy of Error'd? I say it's at least worthy of a chuckle.

cc

 

Finally, it's a bit of old news now but you may recall Southwest Airlines had a significant WTF not long ago. They tried to placate John Melville with their own private currency, but he's not having it. Jibes John, "Southwest says they had to cancel my vacation because their routing system couldn't handle a complex winter storm. I believe it because their web site also cannot handle simple problems -- like addition." Gripes aside, the Southwest software system seems like a fascinating but solveable challenge, if they have the will.

luv

 

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
Thursday, February 23rd, 2023
LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.
6:30 am
CodeSOD: The Duff Code

As we frequently note, a staggering number of real-world software products start their lives as Access databases running from a shared folder somewhere. There are professional developers who end up maintaining these monstrosities.

Gregory has had the misfortune of being one of those developers. A client has a terribly performing Access database, and it happens to be the driver of their business: it generates insurance quotes for an insurance company.

Let's take a look at some of the code.

'A Pause function
Public Function HoldIt(Longish As Integer)
    Dim Startof
    Dim temp
   
    temp = 0
    Startof = Second(Now)
   
    Do
        temp = Second(Now) - Startof
    Loop Until temp > Longish
End Function

Hey, I think I found the performance problem. The only good thing I can say about this busy loop is that they actually check the system time, and didn't just throw a pile of iterations at it and hope it was good enough.

Then again, why do they want a pause function anyway? I'm not sure I want to know.

Public Sub MegaQuit()
    Dim FredBlogs
    Dim intx As Integer
    Dim intCount As Integer
   
       intCount = Forms.Count - 1
       For intx = intCount To 0 Step -1
            If Forms(intx).Name <> "HiddenStarter" Then
                DoCmd.Close acForm, Forms(intx).Name
            End If
       Next
    If pboolCloseAccess <> True Then
        FredBlogs = MsgBox("Application will close.  Continue?", vbOKCancel, "EXIT")
        If FredBlogs = vbCancel Then
            DoCmd.OpenForm "Start_up"
        Else
            pboolCloseAccess = True
            DoCmd.Quit acQuitSaveAll
        End If
    End If
End Sub

This method closes all the open windows, asks a confirmation, and then either returns to the startup screen or quits. It's honestly nothing spectacular, aside from the mega-name of the function, and the use of FredBlogs. TIL that "Fred Bloggs" is the UK equivalent of "John Q. Public" in the US- a placeholder name for the average person on the street.

No, that doesn't help me understand why that's the name of this variable, but at least I learned something.

But let's close out with a function that outputs some error messages. I expect to see t-shirts based off these error messages on Shirts that Go Hard before the end of the week.

Public Static Sub FrErr(NameOfApp)
    Dim Count
    Count = Count + 1
    If Count < 5 Then
    On Error GoTo FrErrErr
        MsgBox "I'm broken. I Don't know what happened (I wasn't running at the time)," & vbCrLf & _
        "but I called: " & _
        NameOfApp & " and bang! The duff code came back with " & vbCrLf & _
        Err.Number & ":" & Err.Description & ". Sorry."
    Else
        MsgBox "I'm broken. I Don't know what happened (this isn't the first time)," & vbCrLf & _
        "but I called: " & _
        NameOfApp & " and bang! The duff code came back with " & vbCrLf & _
        Err.Number & ":" & Err.Description & ". I'm very sorry.  Have you considered restarting the PC?"
    End If
 
    Exit Sub
FrErrErr:
    MsgBox "I'm Broken.  I Don't know what happened and when I tried to find out I got an error.  Sorry.", , "Sorry"
End Sub

Duff code is not to be confused with Duff's Device

I'm broken. I don't know what happened (this isn't the first time).

[Advertisement] BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!
[ << Previous 20 ]

LJ.Rossia.org makes no claim to the content supplied through this journal account. Articles are retrieved via a public feed supplied by the site for this purpose.