Last minute geek

last minute tech news from around the net

You are here: English WTF

WTF

A Lost Voice

Having survived the scourge of Jack's automated testing debacle, Rita thought she could handle anything. Since that time, Rita had Operations burn/kill/destroy all the JCKRKS servers and set up new ones that she had full control over. Rita felt well-prepared for a future where nothing that bad could happen again. But sometimes those who only look forward are unprepared for the return of a long-forgotten relic.

Laryngitis: a diagram of the larynx and its inflammation In a different IVR-enabled part of their health insurance system, customers could call in to hear information about their health benefits. These benefits, as is par for anything with health insurance, were governed by a very complex set of rules, contracts, overrides, and addendums. Depending on the caller's employer, benefit administrator, subscriber level, eye color, astrological sign and feng shui positioning, their very specific set of benefit information would be read back to them.

To house this complex set of business rules, the organization depended on ILOG to keep things in order. It did the job but when it came time to tweak said rules, customers had to file a formal change request and wait weeks to see their change implemented. Customers complained about the process enough that Gregor, bringer of Jack, had the bright idea to give them a way to make rule changes on the fly themselves.

"It's quite simple, Rita," he began to explain with an arrogant tone. "It's taking too long for our customers to get their changes and it takes too much of our time to implement them. We need to create a web-based way for them to alter their business rules and I think you're just the girl to make it happen!"

"Gregor, I agree that we could do better with this, but are you sure we want our end-users messing around with complicated settings? Things could get ugly in a hurry," Rita expressed great concern.

"Point taken, but I still think this is a brilliant way to make everyone happy and more productive! Plus we can deprecate that expensive ILOG system and just store everything in a database! Get to work."

So began a large unplanned, unbudgeted project to get the web interface built with a SQL backend while exporting all the data from ILOG to a massive Excel spreadsheet. It drove Rita to her wit's end but she started to see the light at the end of the tunnel. They were now prepared for a round of beta testing by HealthLords, their biggest client (see: biggest complainer).

The HealthLords were excited to get started so they could brag about being the first insurer to set up their own business rules. They logged in to Rita's slick web interface and began to manipulate stuff. As they dug through their extensive set of rules, they came across one that was foreign to them - "PAUL TEST DO NOT DELETE". They opened it up to find the shocking description of "This is just an internal test. Those whiny HealthLord idiots will never see this once ILOG is implemented."

Almost immediately, Rita received an angry call from a big whig at HealthLords. Caught off guard, she was only able to offer a token apology and promise to look in to it. It had never been there before, so it was definitely a mystery to solve.

She dug in to the IVR platform that was still being used before and after the days of ILOG. After many rounds of tracing the code, she found the rule embedded deep in a dusty corner of the code in a class that shouldn't have processed benefit addenda at all. There stood a comment on the offending rule, "// remove this if we decides [sic] to pay for ILOG ~ Paul".

Paul hadn't been with the company for several years and had quit just before the ILOG system was implemented. But that didn't mean Rita couldn't curse his name on this day. ILOG had been covering up his test rule forever and now that it was out of the picture, it showed up again during HealthLords' beta testing. It took Gregor escalating to his bosses' bosses' boss just to keep HealthLords from backing out of their contract.

[Advertisement] Universal Package Manager – store all your Maven, NuGet, Chocolatey, npm, Bower, TFS, TeamCity, Jenkins packages in one central location. Learn more today!

Read all

CodeSOD: Identifying the Globally Unique

UUIDs, aka GUIDs are, well… unique. Unique identifiers. It’s right there in the name.

Active Directory needs to identify things. Thus, it uses GUIDs. “Omni’s” co-worker got this far, but then ran into a problem. If you print a GUID from AD, it looks like this: “35918bc9196d40ea9779889d79b753f0”, but if you print it from C#, it looks like this: “35918bc9–196d–40ea–9779–889d79b753f0”. Whatever is a programmer to do when dealing with these radically incompotible formats?

private void GetUsers(Guid guid)
{
    byte[] bytes = guid.ToByteArray();
    string native = BitConverter.ToString(bytes).Replace("-", string.Empty).ToLower();
    …
}

Okay, step one- turn the GUID into an array of 16 bytes. That makes sense. There’s no dashes in an array. Then we feed it into something called BitConverter. Now, I don’t know what BitConverter does, so I can only guess, and there are two likely things:

  1. It turns an array of bytes into a string
  2. It turns an array of bytes into a string AND FOR SOME REASON INSERTS DASHES

Once we’ve got the array of bytes back into a string, we can replace the dashes (which either are not there, or were inserted by BitConverter), and then convert it into lowercase, just in case hexidecimal has suddenly become case sensitive.

Of course, all of this is unnecessary. The GUID datatype in .NET overloads ToString. guid.ToString("N") would return “35918bc9196d40ea9779889d79b753f0”, just like our developer wanted.

This is at least a case of a developer not checking the documentation or lacking the instinct to ask, “Wait, does ToString have any overloads?” That, however, is not TRWTF. TRWTF is stringly typed data. GUIDs are not strings. They are numbers. We render them as strings for readability. We should not process them as strings. We should not pass them around as strings. The string representation of a GUID should not be relevant to a program.

[Advertisement] Release! is a light card game about software and the people who make it. Play with 2-5 people, or up to 10 with two copies - only $9.95 shipped!

Read all

Error'd: When Good Dev Tools Go Bad

"I'd say that this brings new meaning to what a 'core dump' really is," Paul N. writes.

 

"Looks like someone at Google got tired of typing exit names all day," Shawn A. writes, "And in case you wondered, voice navigation actually spelled 'ASD'."

 

"At first glance, Google News got the wrong pic, but the more you think about it, maybe it didn't," wrote Matt S.

 

Mike S. writes, "I was hoping for overflow, but all I got was NaN."

 

"I got this dialog/error message pixel for pixel (originally 2930x128) today and boy I am glad that I have two monitors or I wouldn't be able to press the OK button," writes John A.

 

"I'd love to see the datetime logic that resulted in this gem," writes Baldrick.

 

Pramod V. writes, "Now this is what I call the ULTIMATE portable!"

 

[Advertisement] Release! is a light card game about software and the people who make it. Play with 2-5 people, or up to 10 with two copies - only $9.95 shipped!

Read all

CodeSOD: ByteBool

Tony Hoare has called null references his “billion dollar mistake”. Dealing with nulls and their consequences have created a large number of bugs, and eaten a lot of developer time. It’s certainly bad enough when you understand nulls and why they exist, but Benjamin Soddy inherited code from someone who absolutely didn’t.

First, there’s our new type, the ByteBool:

    public enum ByteBool
    {
        IsFalse,
        IsTrue,
        IsNull
    }

Not quite FileNotFound territory. Based on this code alone, you might think that this is some legacy .NET 1.1 code, back before .NET had nullable value types, and thus there was no way to set a boolean to null.

You’d be wrong, however. Because as a sibling to ByteBool, we have the class NullHelper:

public class NullHelper
    {
        /// <summary>
        /// Like the Helper.GetSafeInteger but returns a negative one instead of zero which may be a valid number
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static int ConvertNullableInt(int? value)
        {
            if (value.HasValue)
            {
                return value.Value;
            }
            else
            {
                return -1;
            }
        }

        /// <summary>
        /// Like the Helper.GetSafeInteger but returns a negative one instead of zero which may be a valid number
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public static int? ConvertBackToNullableInt(int value)
        {
            if (value != -1)
            {
                return (int?)value;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// Converts the null bool to byte bool.
        /// </summary>
        /// <param name="boolean">The boolean.</param>
        /// <returns></returns>
        public static ByteBool ConvertNullBoolToByteBool(bool? boolean)
        {
            if (boolean.HasValue)
            {
                return (boolean.Value ? ByteBool.IsTrue : ByteBool.IsFalse);
            }
            else
            {
                return ByteBool.IsNull;
            }
        }

        /// <summary>
        /// Converts the byte bool to null bool to.
        /// </summary>
        /// <param name="byteBool">The byte bool.</param>
        /// <returns></returns>
        public static bool? ConvertByteBoolToNullBoolTo(ByteBool byteBool)
        {
            switch (byteBool)
                {
                        case ByteBool.IsFalse:
                    return false;
                break;
                case ByteBool.IsTrue:
                    return true;
                break;
                case ByteBool.IsNull:
                    return null;
                break;
                default:
                    return false;
                break;
                }
        }
    }

I’m no expert on the subject, but the comments alone read to me like poetry.

Like the Helper.GetSafeInteger,
but returns a negative one instead of zero which may be a valid number,
the value,
Like the Helper.GetSafeInteger,
but returns a negative one instead of zero which may be a valid number,
the value,
Converts the null bool to byte bool,
the boolean,
Converts the byte bool to null bool to,
the byte bool

Benjamin junked this code, but ByteBool is still a legend around his office. “Are you sure you aren’t ByteBooling this?” is the polite way of saying “your code is bad and you should feel bad” during code-reviews. “I found a ByteBool,” is called out when someone trawls through legacy code, in the same tone of voice as a lifeguard finding a “floater” in the pool.

[Advertisement] Manage IT infrastructure as code across all environments with Puppet. Puppet Enterprise now offers more control and insight, with role-based access control, activity logging and all-new Puppet Apps. Start your free trial today!

Read all

When Computers Fly

In the Before Times, the Ancients would gather in well-sheltered caverns, gather to themselves foods blessed by the gods, drink strange, unnaturally colored concoctions, and perform the Rite of the LAN Party.

In the era when the Internet was accessed by modem, to have any hope of playing a game with usable latency, you had to get all the players in the same place. This meant packing up your desktop in a car, driving to your friend’s house, and setting up your computer on whatever horizontal surface hadn’t already been claimed by another guest.

In the late 90s, Shawn W was the lead support tech for a small-town ISP. He had little supervision, and lots of networking equipment at his disposal. The owners were laid back, so Shawn got to throw a LAN party every Saturday. There was a solid core group that turned out pretty much every week, but there was also a rotating cast of newbies which made great fodder for practicing your railgun snipes on “Lost Hallways”.

One weekend, one of those newbies was Derek. Derek’s main multiplayer experience was getting stoned and playing split-screen Goldeneye, in Big-Head mode. Seeing multiple computers all networked together was pretty mind-blowing for him. He ended up not gaming very much, but instead wandered around, asking questions about the setup and tripping over network cables.

“Man,” he complained, after he unplugged Shawn for the fifth time, “those shouldn’t be so easy to pull out. Like, you need a lock on it. I could make you one, I’ve got some of those industrial strength zip-ties in the car, like they could lock that cable in real tight, like they hold luggage on your car and stuff. Industrial grade, man.”

No one wanted Derek to modify their computers, and given how he had made a hobby of tripping over any cable, even ones taped to the floor, having them get yanked out was better than having their computers yanked off the folding tables. Derek was a mild nuisance, but he knew how to make up for it: he was a good sport about getting fragged, he was happy to share his stash with anybody who wanted to step behind the building, and he paid for all the pizza.

Shawn had gotten stiffed a few times, so having someone else foot the bill for all the pizza meant he was willing to forgive a lot. When Derek called him at work on Monday, Shawn was pretty well disposed to him.

“Hey, I was talking to Murphy about the party this weekend- wait, you don’t know Murph. He’s cool, man, he’s my neighbor, and we like, game a bunch? We were wondering, we’d like to set up our own network.”

Shawn was happy to help- Derek was even a customer of the ISP, so it was even technically work.

“We were thinking, like, where do you get a really long network cable?” Derek asked.

“Like, how long? Is Murphy going to be setting up in a different room of your house?”

“Nah, man, he’s gonna stay in his house. He’s my neighbor, right? We could just string a cable between our windows. Murph’s got X-Wing vs. Tie-Fighter, and it’s just like the movies. I’ve even got a cool joystick for it.”

Shawn said, “Come on by the office, and I can just give you one.” They had a few thousand foot spools of cable. Shawn made him a 100-ish foot long crossover cable, since Derek didn’t have a hub, but there were only two computers in the network.

Derek picked it up, and called back a while later, looking for some help on configuring the network. “Hey, man, I got the cable run, and like, super tied down, but um… how do we make it work? I see the green lights on the network cards.”

Shawn walked him through configuring the network, and proving it worked via a ping test. Derek was ecstatic, and started to launch into the virtues of the TIE Interceptor in death-match, when there was a sudden crash and the sound of shattering glass. Derek screamed a curse.

“Um… are you okay?” Shawn asked.

“MY COMPUTER JUST FLEW OUT THE WINDOW!” Derek cried.

“Wait… what?” Shawn tried to imagine what that might entail- he remembered Derek mentioning that it was on a folding table, maybe it had collapsed and somehow the computer had fallen out the window?

“Oh, man, look at it out there, it’s totally trashed.”

“How did your computer fly out the window?” Shawn asked.

“A car drove by and caught the network cable.”

“Wait… does Murphy live across the street?”

“Yeah, why?”

Derek’s “logic” had been that their street wasn’t very busy. He had run the cable across the street, and weighed it down with rocks, thinking that would be safe. Since that put some tension on the cable, he didn’t want it to pop out of the network card, so he had broken out those “industrial grade” zip ties, and secured the cable to his computer’s case.

“I figured it’d be fine,” Derek said glumly. “I guess I was wrong. Hey, do you know anything about building computers?”

[Advertisement] Release! is a light card game about software and the people who make it. Play with 2-5 people, or up to 10 with two copies - only $9.95 shipped!

Read all

CodeSOD: The Wrong Sacrifice

pentacle




Folks, you need to choose a different sacrificial animal for your multithreading issues. Thanks to this comment Edward found in a stubborn bit of Java code, we now know the programming gods won't take our goats.

public static boolean doSomeOSStuff() {

        // Forgive me father for I have sinned - with the bag of crap written in the lines below.
        // When running multiple threads (~500) concurrently, the damn OS commands fail at a 1% rate for no apparent reason.
        // There is no error message, or any indication of failure, they just don't happen and come bite you in the ass.
        // After much frustration, I decided to try 3 things:
        // 1. sacrifice a goat. - did not go as planned.
        // 2. semaphoring this shit. did not change anything...
        // 3. after each failed command, I will try and verify if it succeeded  or not. If not I'll try it 4 more times.
        // I am now going home to take a hot shower, and cry laying on the shower floor. and /or sacrifice a few more goats.
        //
        //                                          ...
        //                       s,                .                    .s
        //                        ss,              . ..               .ss
        //                        'SsSs,           ..  .           .sSsS'
        //                         sSs'sSs,        .   .        .sSs'sSs
        //                          sSs  'sSs,      ...      .sSs'  sSs
        //                           sS,    'sSs,         .sSs'    .Ss
        //                           'Ss       'sSs,   .sSs'       sS'
        //                  ...       sSs         ' .sSs'         sSs       ...
        //                 .           sSs       .sSs' ..,       sSs       .
        //                 . ..         sS,   .sSs'  .  'sSs,   .Ss        . ..
        //                 ..  .        'Ss .Ss'     .     'sSs. ''        ..  .
        //                 .   .         sSs '       .        'sSs,        .   .
        //                  ...      .sS.'sSs        .        .. 'sSs,      ...
        //                        .sSs'    sS,     .....     .Ss    'sSs,
        //                     .sSs'       'Ss       .       sS'       'sSs,
        //                  .sSs'           sSs      .      sSs           'sSs,
        //               .sSs'____________________________ sSs ______________'sSs,
        //            .sSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS'.Ss SSSSSSSSSSSSSSSSSSSSSs,
        //                                    ...         sS'
        //                                     sSs       sSs
        //                                      sSs     sSs
        //                                       sS,   .Ss
        //                                       'Ss   sS'
        //                                        sSs sSs
        //                                         sSsSs
        //                                          sSs
        //                                           s
        
        // snipped OS manipulation code with several cases of aforementioned ritual
}
[Advertisement] High availability, Load-balanced or Basic – design your own Universal Package Manager, allow the enterprise to scale as you grow. Download and see for yourself!

Read all

What Equals Equals

Lemon velvet pudding

Monday morning, 10:00AM. As per usual, today's protagonist, Merv, got some coffee and settled in for his usual Monday morning routine of checking Facebook and trying to drag his brain into some semblance of gear. As he waited, the least interesting conversation ever floated to his ears from the hallway:

"It's like, yak butter, I guess? I put it in my coffee, it's supposed to do wonders."

"No way, man, I can't do dairy."

"Yeah, but it's not dairy, it's yak."

"Like, yak meat?"

"No, like, butter from yak milk."

"Then I can't have it. I'm allergic to dairy."

Merv was so stunned by the inanity of the conversation that his groggy brain didn't clue in on the obvious sign. Of course, the non-dairy drinker would be Sergey. Normally, Merv would have avoided the man this early on a Monday. He had a way of coming up with the weirdest, most bizzare problems when he debugged code, and he always ran straight to Merv to untangle them.

"Merv!" Sergey appeared, leaned into his cube. "Just the guy I was looking for. Do you have a minute?"

Begrudgingly, Merv conceded that he did, in fact, have a minute. And so, a few moments later, he found himself standing behind Sergey's chair, trying to remember what exactly this product did while Sergey explained.

"See, this data here, watch carefully while I run it—there it is. See that? It changed. I don't know why or when, but something's overwriting the data I put there. So I figured it must be here, but look, there's no assignment in this method, or this one."

"Can't you just debug through it?" asked a sleepy Merv.

"That's the weird part: it doesn't do it if I build in debug mode."

Merv frowned. "Run that by me again?"

So Sergey did. Of course, it was silly to step through a release build. There were no debugging symbols, so it was hard to tell what was going on. Merv showed him how to enable debugging symbols in a release build, but the compiler's optimizations made it hard to step through something like this. The more they dug, the weirder the behavior seemed, and the saltier the language got around the monitor.

Could it be an optimization bug in the compiler? Maybe memory values weren't being set correctly in the release build? Was it a race condition where the debugger was changing the timing? Nothing seemed right. Finally, as Merv's brain shifted into high gear, he looked over the exact lines the change was being made in.

"Here, the copy is made. I can see the value. But as we step through the next few lines, it changes, without being touched."

The code was just a simple assignment using a basic equals sign. Feeling a headache coming on, Merv tapped the equals on screen. "What exactly does that copy assignment operator do, for this class?"

They went digging. What they found was beyond the pale: macro magic changed how the function worked depending on how it was compiled. In debug mode, it was a deep copy. In release mode, it was a shallow copy; the returned object was little more than a pointer to the old one. So in release mode, changing the original (off in another thread) also changed the copy, while in debug mode, they were separate objects with their own lifetimes.

"I need more coffee," Merv muttered.

"Me too, buddy," replied Sergey.

Neither of them budged.

"Who wrote this?" demanded Merv.

The commit logs revealed the name: Patrice, who had once committed a 3000 line monstrosity all in one commit that Merv had had to rewrite from scratch. That had taken him four mugs of coffee to get through. Faced with the prospect of digging through the whole codebase to every assignment and guess if they wanted a deep or shallow copy, Merv knew the right answer: he'd have to put in a catering order with the local coffeehouse. He'd break the machine before he was done.

[Advertisement] Application Release Automation for DevOps – integrating with best of breed development tools. Free for teams with up to 5 users. Download and learn more today!

Read all