A Comment on the Military Industrial Complex |
Simon T tugged at his collar when the video played. It wasn’t much, just a video of their software being tested. It wasn’t the first time they’d tested Simon’s most recent patch, but it was going to be the last time. There were a lot of eyes in the conference room, and they were all turned on him.
Simon worked for the kind of company which made missiles. The test in the video was one of the highly expensive tests of a real missile under real-world conditions. Several of these had already been done with this software package, so Simon hadn’t expected any problems to crop up. In this case, though, the missile left its launcher and sailed in a perfect parabolic arc into the ground 5 meters away from the launch site.
Missiles diving headfirst into the ground mere meters from their launch site was officially considered a bad thing. There were all sorts of checkpoints and automated tests and simulations that were supposed to keep this thing from happening. It didn’t take long to find the problem.
if roll < 0 then
{
{we're adjusting the roll here cos it's too high so we are going to take just half
roll = roll / 2;
zcdem = zdem; { add gravity }
}
else
{
{roll is clockwise}
…
}
This code happens to be Turbo Pascal 4, a version of the language released in 1987. Simon’s job had been to create this Turbo Pascal code by porting the logic from Fortran 68, running on a mainframe. Due to hardware constraints, the Fortran version took 8 hours to simulate and calculate a missile’s trajectory. Simon’s Turbo Pascal version could do the same job in near real time.
There’s just one problem. Curly brackets in Turbo Pascal can be used to mean radically different things. On a line by themselves, they can substitute for begin or end statements, but they can also serve as comment indicators.
And you can see where this is going. Simon left off his closing } on the {we're adjusting… line. You might expect an error like that to be caught by the compiler, and it might have… had he not also had the { add gravity } comment, which handily provided a closing curly brace, essentially commenting out the entire body of the if statement.
In their testing, they’d somehow never hit this condition. Even in the real-world tests, the wind had previously been blowing from the west, which meant the missile had a positive value for roll. Only on a day with an easterly wind did they catch this bug.
For want of a } the missile was lost…
[Advertisement]
Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.
https://thedailywtf.com/articles/a-comment-on-the-military-industrial-complex
|
Метки: Feature Articles |
CodeSOD: Without Context |
When writing up a Code SOD, a big part of the goal is to provide context for the bad code. Why is it bad, what would be better,, etc. In other words, we need to… ShowContext. Vasco O has exactly the method for that.
protected string ShowContext(string context)
{
if (!string.IsNullOrEmpty(context))
{
return string.Format("{0}", context);
}
else
{
return string.Empty;
}
}
If the context string has content, return a new string, via string.Format which is exactly the same as the input. If it’s null or empty, return an empty string. This does at least mean that the function isn’t entirely useless- it guarantees no nulls will get returned.
This method was called everywhere, but it did nothing. Vasco removed it.
|
Метки: CodeSOD |
Another Bitmask Fail |
As we've seen previously, not all government jobs are splashy. Someone has to maintain, for example, the database that keeps track of every legal additive to food so that paranoid hippies can call them liars and insist they all cause cancer and autism. Today's submitter, Cass, had just released an update when users started getting the dreaded blue Internal Error screen—never a good start to the week.
Everything that's added to food is added for a reason; otherwise, why spend money doing it? The additive website allows searching by function, as well as by name. For example, some items might be alternative sweeteners, while others might be coloring agents. The problem of the week turned out to be in the stored procedure related to this particular search, which was intuitively titled prc_AdditiveRegulation_GetResults_NEW. Not to be confused with the entirely unused prc_AdditiveRegulation_GetResults, prc_AdditiveRegulation_GetResults_DEV, or prc_AdditiveRegulation_GetResults_PROD.
As Cass quickly discovered, prc_AdditiveRegulation_GetResults_NEW is a hefty chunk of code. 1044 lines, to be precise, all dedicated to returning a list of additives and their functions. After hours of searching, Cass managed to isolate the portion that was causing the problem:
UPDATE #techfunction
SET bitNum = TableRank.PowerRank
FROM (SELECT RowId,TechfunctionId,POWER(2.0,DENSE_RANK() OVER (PARTITION BY TechFunctionId ORDER BY RowId)) AS PowerRank -- need to use 2.0 instead of 2 to avoid arithmetic overflow error (mark, 6/11/2012)
FROM #TechFunction t2) TableRank
INNER JOIN #techfunction t
ON t.rowId = TableRank.RowId
AND t.techfunctionId = TableRank.TechFunctionId
In case it's been a while since you took CompSci 214: Insane Data Algorithms, allow me to translate: this code assigns each function an additive can perform to a specific power of 2. Later, these numbers are added together so that groups of technical functions effectively have a distinct number, allowing them to be used as a bitmask to search for the additives. "Clever" at its finest.
Years later, the number of functions surpassed 32, causing the POWER function to overflow a simple integer. Mark, who worked at least two generations of developers before Cass, must have fixed this by forcing it to use a larger data type by casting the 2 as float type which would then be converted back to a Bigint for storage. (This likely caused a small performance dip, as it can no longer bitshift when calculating powers, but it's still "clever," and that's what really matters.) With Cass' release, the number of additives exceeded 64, making it overflow the Bigint data type as well.
The best part? None of this was necessary. Cass traced every instance where the proc was called: the bitNum was never used, despite being always calculated. She removed it, and the errors cleared up overnight.
|
Метки: Feature Articles |
Error'd: Heed this Warning |
Sam B. writes, "Only lb11.99 for a call_user_func_array() warning? What a bargain!"
Brian W. writes, "Maybe Buoy Health knows something I don't know..."
"Undefined weight limit? I see an error...but also a challenge," wrote Andrew S.
"I think HxD and I disagree on what identical really means," writes Adam G.
Evan T. wrote, "Ticket form...and two New Ticket Requests...When in doubt, I'm 'inherintly' going to choose the middle one."
"Two gig. Or not two gig...That is the question," writes Morgan.
|
Метки: Error'd |
Works for Us |
Containers make deployment easy, or at least that’s what it says on the label. It makes intuitive sense, though- instead of wrangling all your dependencies on a host OS, and then trying to understand why your app can’t see them, you bundle all the dependencies into a container and push that around when you want to deploy. It Just Works™.
Sandra had just left a company which didn’t use containers, but containers wouldn’t have helped: the didn’t have a working deployment process, period. They didn’t even try deploying before the production push 9 months into the project, and the first twelve attempts consistently failed because someone hadn’t tested something, or someone didn’t update the script, or the requirements changed and were signed off but nobody told the development team. It meant a lot of nights, a lot of weekends, and a lot of meetings which devolved into circular firing squads.
Enter Initrovent™, a cutting edge, SaaS provider which serviced the event planning industry. Karl, the Big Boss, assured Sandra that he completely understood the importance of deployments. “Oh, you don’t have to tell me,” he said. “I’ve seen so many failed deployments. We’re actually moving our platform into dockerized microservices with continuous deployment. We’ve build a process which works for us.”
Overall, the gig sounded like a good fit, so Sandra started a few Mondays later. She spent most of the day “on boarding”, so it wasn’t until late in the afternoon that she tried to get her development environment set up. Based on her conversation with Karl, Sandra had assumed she’d pull down a container and be ready to go.
She was half right. The company had one standard container. It had nothing in it. The install guide walked Sandra through spinning up one container and installing Apache, then another container for MySQL, then another for Memcache, then another for something only called “queue”, which reeked of some sort of inner-platform attempt at being “enterprise”, but Karl could only explain as being required “because of Docker”.
That was Sandra’s first day. On her way out, she stopped by Karl’s office. “Hey, since I’ve got those containers set up, should I put them somewhere so other devs don’t have to set them up?”
“What do you mean?” Karl asked.
“Y’know, so they don’t have to set up from scratch every time? They can just use the containers I set up?”
Karl nodded, as if he understood. “Oh, I don’t think that’s necessary. Besides, in my experience, every developer wants to set their environment up themselves. It’s fine.”
“That’s not how containers work.”
“Well, it works for us,” Karl said.
The next day, Sandra pulled down the code. The install guide, in bright red text, loudly announced that it must be placed in the /projects/intirovent/planner folder, because the Docker container was hard-coded to use that mount point, and no other. Once she had the code downloaded, she tried to test it, and discovered nothing but error messages. She went back through the install guide, just to be certain, and then took a glance at the code.
It was not microservices. It was a PHP monolith written using a 2012 release of CakePHP which had been endlessly tweaked in the intervening years. Lining up the errors she was seeing with the code, it quickly became obvious that unless a user was very careful with the application, they would see lots and lots of error messages. With a little practice, Sandra managed to get through the sign up process with only one cryptic 500 error, and even created an event.
In that code there was a folder called microservices. It was a bunch of RESTful endpoints. Karl explained: “They’re small, and they’re web services.”
“That’s… that’s not how microservices work.”
“Well, it works for us.”
That was Sandra’s second day. The week ground on like three fully interlocked gears, but by the end of the week, Sandra had not only cleaned up a few of the nastier bugs, but had finished off a new and rather large feature. She closed the ticket, and then Karl followed up: “Swing by, and I can show you how deployments work.”
“Deployments? On a Friday afternoon?” Sandra asked when she got to Karl’s office.
“Well, I did say we do continuous deployment.”
“That’s… not how continuous deployment works.”
“Well, it-”
“-works for us?” Sandra took a seat to watch the show. She wasn’t surprised by what she saw.
The purpose of containers is to have a single unit, with all its dependencies, which can be deployed, possibly to many different machines or VMs. That’s, at its core, how containers work. They’re easy to test, they’re easy to automate, and they’re easy to deploy.
Karl didn’t test, didn’t automate, and the deployment… well. Karl SSHed into the one server which constituted their production environment, and then went over to /projects/intirovent/planner, where he issued a git pull. Karl pulled up the site in his browser, hit refresh a few times, and smiled when he saw the landing page. “Great work.”
“That’s your deployment process?”
“Yep. Works pretty great, doesn’t it?”
The deployment process may have worked for Karl, but Sandra didn’t plan to work for him much longer.
|
Метки: Feature Articles |
CodeSOD: 30 Days |
Tim B did a little work with an e-learning vendor, with some very old code. The code in question happened to be so old that “this is server side JavaScript” was a horrifying novelty when they wrote it, instead of a standard deployment option via Node.
The code in question is bad date handling code, which isn’t impressive. What is impressive is that it demonstrates a terrible approach to dates which I’ve never seen before. It doubles as a terrible approach to arrays which I have seen before, but… it remains special.
for (i=0; intMonthsToDisplay>0; i++)
{
if (IsLeapYearDate(intMonth+i+1 +"/1/" + intYear) )
{
strDaysInMonths = "312931303130313130313031312931303130313130313031"
}
else
{
strDaysInMonths = "312831303130313130313031312831303130313130313031"
}
arrNoDaysInMonth[i] = parseInt(strDaysInMonths.substr((intMonth+i)*2,2));
intMonthsToDisplay = intMonthsToDisplay - 1;
intTotalDays = intTotalDays +arrNoDaysInMonth[i]
}
Yes, strDaysInMonths is our old “30 days has November…” rhyme, compressed down to two characters a month. I only wish Tim sent along the implementation of IsLeapYeaarDate, which I’m sure would be a thing to see.
|
Метки: CodeSOD |
CodeSOD: A Repeated Save |
Ian S was going through the portfolio of applications maintained by his company, and stumbled across one that… well, from what he could tell, wasn’t written by a developer so much as spawned by an accident. 90% of the code was copy-pasted from somewhere else in the code, flow-of-control mostly used Exceptions as an attempt at doing GOTO-style logic, and there were piles of unused variables or variables used before initialization. Some modules/packages in the application were full of syntax errors, which implied that they weren’t actually included or used anywhere.
From that mess, Ian extracted this.
while True:
try:
product.save (force_insert=True)
except:
pass
if Product.objects.filter(version=pv,productType=pt).count() is not 0:
break
time.sleep (1)
This is Django, which means we’re looking at some ORM-based code. First, we try and save a product object into the database. If that fails for any reason… we ignore that failure. Instead, we check to see if there are any products with the same version/type combination- I’m going to go out on a limb and guess that this is the unique identifier of the product, but I wouldn’t put down money on it- and if there is at least one entity that matches… we break out of the infinite loop.
If, on the other hand, there isn’t- that means that we failed to insert the product. So let’s just wait a second and then try again. And again. And again. And…
There are a million better ways to write this, but I’m honestly impressed by the determination this code shows. It doesn’t give up. It never gives up. It will insert that record, or die trying. That’s how winning is done.
|
Метки: CodeSOD |
AI-Driven Articles |
If you've looked at job postings, you know that there's one thing really big and trendy right now, and that's blockchains. But the other trendy thing is Machine Learning! We'll talk about the Daily WTF's Initial Coin Offering at a later date, but for right now, we're excited to announce our new ML efforts.
Specifically, we recognize that there's a certain structure and pattern to our articles, and instead of paying human writers, we can instead employ the latest machine learning systems to generate new articles that will be indistinguishable from the articles you know and love. The ideal tool, of course, would be an Recurrent Neural Network, which we could train based off previous articles. Unfortunately, that involves a lot of GPU power, and we're already using our GPUs to get ready for that ICO I mentioned. Shhhh. It's a secret.
In any case, since we couldn't use an RNN, we opted for the next best thing: a Markov Chain. I'm sure what follows will be a perfectly good article.
Yes, yes, it's an April Fools day post, a day late. Or IS IT?
|
Метки: Feature Articles |
Error'd: Visual Studio? Whatever! |
TZ wrote, "Looks like somebody at Microsoft doesn't like static web pages!"
"I wonder the generational arrangement that Frontier Airlines is aiming at here," Carl Z. wrote, "Perhaps in some airport, a person is yelling Lil' Ronald Smith, Extra Seat! You're gonna miss your flight!"
Jiri G. writes, "Looks like Dell won't let me add a customer number, so, I guess I'll need to wait until they publish their {0} form."
"Wow, my surname has to be at least five characters? Thanks for blocking me out, radiooooo.com!" writes Robin Lee.
"Finally! My local grocery store stopped using those crashy, BSODy Windows machines in automatic cash registers and installed stable, professional Linux distributions....um, wait, what?" writes Lutoslaw.
"I agree 100% - Americans are indeed NOT clothes," wrote Mark B.
|
Метки: Error'd |
CodeSOD: Attack of the WASPs |
Werner sent us some code from the telcom industry. Before we even get to the code, we have to look at one of the comments.
// This is a hack to be
// able to compile
I might not need to say this, but if you feel like you need to trick the compiler into accepting your code, you may need to rethink your overall design. Then again, when we look at the code in context, the comment makes less sense:
mainserver = null;
mainserver = new WASPApplicationServer(); // This is a hack to be
// able to compile
try {
mainserver = null;
mainserver = new WASPApplicationServer();
noprob = true;
} catch (Exception eee) {
msg = "There was a problem initializing the server. Log Trap and try again";
logger.error(msg, eee);
msg = msg + "\n" + eee;
snmpev.sendSNMPcritical(moClass, moObjInst, "SERVER: INITIALIZATION", "Unknown Cause",
"Failure to initialize new WASP Server", msg, msg);
noprob = false;
}
The “hack” is 100% unnecessary. Worse, if creating a WASPApplicationServer needs to throw exceptions, then doing it outside of the try is completely self-defeating.
The real treat here, though, isn’t the comment or the “hack”, but the humble little noprob flag. Instead of using exceptions to represent, well, exceptional states and error modes that need to be handled, complete with internal state and a full stack trace about what happened, when and why, this throws all of that away and just sets a noprob flag.
Downstream code checks the flag, and if it’s false, terminates the application.
Werner removed the “hack”, but doesn’t know who to blame, as the problem code predates their migration from CVS to SVN back in 2011, and they didn’t migrate history.
|
Метки: CodeSOD |
CodeSOD: A Unique Solution |
Ruby is a nice little language, but I think it wouldn’t have exploded in popularity like it did without Rails. Nowadays, Ruby still seems to be the first choice of early-stage startups. A big part of that is how easy ActiveRecord makes database access.
Adrian was doing some code reviews, when he came across this line:
generate_ident_value(ident, value.to_s + rand(10).to_s)
“Um… what’s this doing?”
Well, they needed to generate unique identifiers based on a user’s name, so joebob becomes joebob1, and the next joebob becomes joebob2 and so on. “We were having a problem with duplicates- if a user was deleted, we were accidentally re-using their ID, so I added the call to rand to fix that.”
Adrian took a look at the surrounding method’s previous version.
def generate_ident_value(ident, value = 1)
if query.find_by(ident: ident + value.to_s)
generate_ident_value(ident, value + 1) # this is the line which changed
else
ident + value.to_s
end
end
Yes- this method attempts to see if joebob1 already exists in the database, and if it does, tries again with joebob2, with a nice recursive call. Changing value + 1 to value.to_s + rand(10).to_s meant, instead of trying joebob2, theyd instead tryjoebob15, thenjoebob159, thenjoebob1597`, for example.
Adrian pointed out this was an insane solution. “You’re right, we should just keep every generated ident in a database table.”
“That’s not…”
“And when we combine it with the random ident I added, it’ll be super unique, and we won’t have to worry about deletions!”
“No, that’s…”
That’s exactly what ended up happening, despite Adrian’s protests. Because of the random approach of tacking characters on the end, the field size had to increase to 20 characters, then 30. Adrian expects it to go up to 40 before year’s end. He’s not planning to be around to see that though- he’s already made plans to move onto another position.
|
Метки: CodeSOD |
CodeSOD: The Truth About Internationalization |
Booleans. One would think that simple true and false would be sufficient to represent all the possible values. However, even more than dates, they are one of the most difficult things to master in all of computer science. There are all manner of possible values and many different ways of comparing different entities.
Compounding everything is another dimension to boolean-ness: internationalization. After all, not every language uses English spellings of true and false. In high school, they made me take French, so it'd be vrai and faux. For most of us, we'd put the language-specific spelling in an application-phrases file, cache it and pick the appropriate spelling based upon the meaning of the required phrase. However, the underlying core values of truth/falsehood would still be programming-language-specific.
For most of us...
class Internationalization { // These will index into the list of language-specific phrases public enum Phrases { TRUE, FALSE, ... }; private List<String> languageSpecificPhrases = new ArrayList<>(); public Internationalization() { // Load strings from configured language file into: languageSpecificPhrases... } public String getPhrase(Phrases phrase) { return languageSpecificPhrases.get(phrase.ordinal()). } public boolean getLanguageSpecificBooleanValueForTrue() { return true; } public boolean getLanguageSpecificBooleanValueForFalse() { return !getLanguageSpecificBooleanValueForTrue(); } }
https://thedailywtf.com/articles/the-truth-about-internationalization
|
Метки: CodeSOD |
CodeSOD: Authentication Failure |
There are certain programming problems that I generally say you shouldn’t try and solve yourself. Dates, of course, are a big one. They’re more complicated than you think, and unless you want to make managing a date handling library your life’s work, just use someone else’s.
Encryption is another. There are so many subtle ways to do it wrong that unless it’s your specialty, you’re going to screw it up. Another similar problem is authentication.
Artyom was having a bit of an authentication problem. He had inherited a Web Portal, written by a “security minded” developer. Since this developer was “security minded”, they took “common sense” security measures, like using JavaScript to prevent copy/pasting into the password field, and to prevent password managers from running. That was annoying enough, especially considering Artyom favored a 34 character password, but strangely… it never worked on the first attempt. Artyom always had to enter the password twice.
Fortunately, the authentication method was well documented, and explained exactly what was going on:
if (Authenticate())
{
// If user knows password, he or she will be able
// to type it in again.
// If he or she has just guessed, he or she will
// fail at the second attempt
ShowAuthFailureBox();
if (Authenticate())
{
authorized = true;
Execute();
}
else
{
ShowAuthFailureBox();
}
}
else
{
ShowAuthFailureBox();
}
|
Метки: CodeSOD |
Error'd: Mistakes From Out of the Blue |
"I got this email out of the blue from TI. By the way, my name isn't ALFONSO," writes Jamie.
"Not sure how much I'd get out of LinkedIn Premium, but I am absolutely sure of exactly how much I'd be saving," writes Vivek T.
Jonathan wrote, "Meanwhile, in a different story, I heard that Times New Roman was being held for questioning."
"The new trains on the Great Western line are so amazing that my journey home will be instantaneous," writes Stephen.
Anton G. writes, "As the saying goes, 'Technically correct is the best kind of correct.'"
https://thedailywtf.com/articles/mistakes-from-out-of-the-blue
|
Метки: Error'd |
CodeSOD: Randomly Functional |
Jonathan T. had recently been afforded the opportunity to go back and tweak the very first Python-based CMS he'd ever built. Years earlier, he and another junior developer had been forced to cobble this site together with no code reviews, oversight, or help of any kind. Terrible choices had been made in the name of getting their work done.
Jonathan rebuilt every page in the CMS and made sure the forms and plugins cooperated with the new structural elements he introduced. In the process, he got stuck trying to figure out how a "col-sm-6" was showing up on a particular form. He found nothing in the CSS, LESS files, or page-specific JS controlling the form. In desperation, he ran a project-wide search for the randomClass.
This was the result Jonathan found in project/scripts.js, authored by the other junior dev. It explained why, for the past several years, new images on the site had randomly not worked for any discernible reason.
$(document).ready(function() {
$(".randomClass").addClass("col-sm-6");
$(".otherRandomClass").addClass("col-sm-12");
$("img[src='https://generic.s3.amazonaws.com/cache/5c/bf/5cbf90e3e6afaa503e3f4b8eaf5a4397.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/45/2f/452f62e5a609d293e27f40f31cf9575c.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/82/1d/821db6dc5d1388758247726233553218.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/9e/7c/9e7c27f45180e53ed2fd8d2efa0c6d66.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/a8/71/a871c57d0030082738913b671971a842.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/54/db/54dbbfbe645c87d8106d148031bf5df1.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/24/8f/248f6f9ca57a61cbeafa22bd7fbb7569.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/d8/d1/d8d184223c8d61f19bee78ca7d9e0eaa.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/8c/82/8c828ee6feaa0a072a8f0a963ee684ca.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/1f/41/1f41c5b6e8f65bc10d3f7ee729e9974e.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/a0/ea/a0ea02ddc52be55ef6b7c8c8f9afd6f4.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/17/6c/176c72476538e5e4d6c993e67f758ac8.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/dc/e7/dce73d9ac7e94958146768f6f4b8d18d.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/1f/ab/1fab6033a0b96c6fdfcbe68b66e595bf.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/f5/66/f5664772196cd29611bdb34697d0572d.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/5c/bf/5cbf90e3e6afaa503e3f4b8eaf5a4397.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/5c/bf/5cbf90e3e6afaa503e3f4b8eaf5a4397.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/5c/bf/5cbf90e3e6afaa503e3f4b8eaf5a4397.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/5c/bf/5cbf90e3e6afaa503e3f4b8eaf5a4397.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/5c/bf/5cbf90e3e6afaa503e3f4b8eaf5a4397.jpg']").addClass('make-short');
$("img[src='https://generic.s3.amazonaws.com/cache/5c/bf/5cbf90e3e6afaa503e3f4b8eaf5a4397.jpg']").addClass('make-short');
});
|
Метки: CodeSOD |
Representative Line: An HTTP Code |
Peter B’s company didn’t have the resource availability to develop their new PHP application entirely in-house, and thus brought in a Highly Paid Contractor™ to oversee that project. This story could end here, and you could fill in the rest, but Peter found an… interesting block of code during the autopsy on this disaster.
Now, I want you to imagine that someone has handed you an integer. You need to know if that integer constitutes a valid HTTP status code. Now, this could get difficult, as just because a number falls between 100 and 599 doesn’t mean that it’s actually a defined status code. Then again, services may define their own status codes, and clients should understand the class of a status code, even if they don’t understand the number, so getting a 147 code isn’t wrong, so we can just probably assume any n where 100 <= n < 600 is valid enough.
Sorry, I’ve gotten off track, because I really just can’t believe this code is the solution someone came up with.
function isValidHttpCode($code)
{
return in_array(substr($code, 0, 1), [1,2,3,4,5]) && strlen($code) == 3;
}
At least it’s not a regular expression, but keep in mind, the $code variable was an integer in the calling code. For this code we have to coerce it to string not once, but twice. This was a Highly Paid Contractor™, so I wouldn’t be surprised if it was pointlessly cryptic, or overly complicated and 300 lines long, but that’s not the case. I don’t even think this was a case of blind copy/paste from a library of bad code used by the contracting firm, because those usually have pointless, uninformative, and confusing comments.
This is just… dumb.
|
Метки: Representative Line |
Bank $Security |
Banks. They take your money and lend it to others. They lend money deposited by other people to you, either as a car loan, mortgage, or for credit card purchases. For this privilege, you give them all of your personal information, including your social security number. Implicit in that exchange is the fact that the bank should keep your personal information confidential. Security is important. One might think that such a concept would be important to banks. One would be wrong.
To be fair, the high ranking people at the banks probably believe that all of their customer information should be - and is - secure and protected. Unfortunately, there are multiple layers of middle and lower management (that we all know all too well) that might not comprehend that point.
The other thing that banks do is nightly batch processing to keep assorted records updated, generate TPS reports, issue bills, update financial inventory, credit usage and so forth. Since customers tend to hit ATMs at all hours of the day and night, you want your systems-update processing to be able to occur while the system is live. To that end, date and timestamp ranges of transactions
to be processed for a given business period usually come into play in some form. The point is that you shield your ongoing transactions from reconciliation activity by excluding it from the reconciliations. The beat business goes on.
Randy worked at a major bank in the Pittsburgh, PA area. Considering that it's a major bank, it seemed odd that their customer facing website was often down for more than an hour at a time during business hours. When he started in 2016, it took about a month to get permissions to get the development tools he needed installed. Hmmm, perhaps they are vigilant about controlling access to their environments, even development; possibly a good, if bureaucratic sign. Once set up, he was assigned to work on their Web Banking app which was written not in MVC but in ASP.NET WebForms. OK, maybe they're slow to adopt newer technologies because they want someone else to beta test them. Caution can be a good sign.
As part of doing his work, Randy sent SOAP messages to the mainframe to retrieve test data for developmental testing. One day, he deduced that the test social security number was that of his boss. He verified this by asking his boss what he had for lunch that day. Sure enough, there were debit card charges for it in the test environment. Uh oh.
That's right; live data in the test environment. Anyone with even novice skills could have gotten social security, routing and account numbers for every customer of the bank! Rather than fight with the, ahem, highly knowledgeable individuals that thought that this was a good setup - and potentially be blamed for any breaches, Randy chose to jump ship and head for saner pastures.
Interestingly, I went to their website, which states that their business hours are M-F 8AM-8PM and Sat 9AM-3PM. At 1:15 on a clear, dry Saturday when the bank should have been open for business, I called the bank posing as a potential customer to ask why their website is often down for more than an hour at a time almost every single night. The auto attendant said to try back during business hours.
Hmmm...
|
Метки: Feature Articles |
CodeSOD: A Passion for Details |
Passion projects are so common in our industry that there are some people who won’t hire you as a programmer if you’re not also programming in your free time. That’s TRWTF, honestly. There’s nothing wrong with being the kind of programmer who shows up for your 9–5 and then goes home and doesn’t touch a computer until the next day.
There’s also nothing wrong with passion projects. I have a bunch of them, usually carefully chosen to have absolutely no utility whatsoever, so they never start feeling like a job.
A Fish of Greater Size (FoGS) has a passion project, which they work on with a number of friends. It’s a web application written in C… or C++… or maybe a little of both? FoGS isn’t entirely certain what they’re using precisely. It’s an existing code base.
In that code base, there’s a CSS file. It sits in the site’s root directory, but there’s no entry in source control explaining how it got there. There’s no developer on the team who knows how it got there. None of them admits to putting it there. And yet, there it sits.
ls > details > summary {
margin-left: calc(1em - 2px);
}
details > details > details > summary {
margin-left: calc(2em - 4px);
}
details > details > details > details > summary {
margin-left: calc(3em - 6px);
}
details > details > details > details > details > summary {
margin-left: calc(4em - 8px);
}
details > details > details > details > details > details > summary {
margin-left: calc(5em - 10px);
}
details > details > details > details > details > details > details > summary {
margin-left: calc(6em - 12px);
}
details > details > details > details > details > details > details > details > summary {
margin-left: calc(7em - 14px);
}
details > details > details > details > details > details > details > details > details > summary {
margin-left: calc(8em - 16px);
}
details > details > details > details > details > details > details > details > details > details > summary {
margin-left: calc(9em - 18px);
}
details > details > details > details > details > details > details > details > details > details > details > summary {
margin-left: calc(10em - 20px);
}
details > details > details > details > details > details > details > details > details > details > details > details > summary {
margin-left: calc(11em - 22px);
}
details > details > details > details > details > details > details > details > details > details > details > details > details > summary {
margin-left: calc(12em - 24px);
}
details {
border-left: 1px solid black;
}
details {
margin-left: 1px;
}
As you can see, this project is all about the details.
|
Метки: CodeSOD |
Error'd: Drunken Parsing |
"Hi, $(lookup(BOOZE_SHOP_OF_LEAST_MISTRUST))$ Have you been drinking while parsing your variables?" Tom G. writes.
"Alright, so, I can access this website at more than an hour...Yeah. Okay," wrote Robin.
Mark W. writes, "Of course, Apple, I downloaded @@itemName@@. I mean, how could I not? It got @@starCount@@ stars in the app store!"
"One would hope that IEEE knows how to do this engineering thing," Chris S. wrote.
Mike H. writes, "I don't know what language this is in, but if I had to guess, it appears to be in Yak."
"Sexy ladies AND inline variables? YES! I WANT TO LEARN MORE!" wrote Chris.
|
Метки: Error'd |
Representative Line: Flushed Down the Pipe |
No matter how much I personally like functional programming, I know that it is not a one-size fits all solution for every problem.
Vald M knows this too. Which is why they sent us an email that simply said: “We have a functional programmer on the team”, with this representative line attached.
function groupByBreakdown (breakdowns) {
return R.pipe(
R.map(R.flatten),
R.zip(breakdowns),
R.map(R.apply(R.useWith(R.groupBy, [R.prop, R.identity])))
);
};
The use of R.pipe is a good argument about why the proposed pipeline operator is a terrible idea whose time isn’t going to come. Ever. Yes, there’s value in being able to easily compose functions into a pipeline. Shells support pipelining for a reaason, after all. But it's an awkward fit into imperative languages, and unfortunately, the tool is too dangerous to be used in real-world code. Even functional languages, like Elixir, warn you against abusing the pipeline. Mixing opaque functional styles with JavaScript is just flirting with disaster. I mean, more disaster than JavaScript already is.
|
Метки: Representative Line |