dilbert

Fiepke.nl

nixcraft

Slashdot

The Daily WTF

XKCD

Toothpaste for Dinner

Ars Tech

Google News

PBFComics

linux voice

SMBC

coindesk

MAGPIE php feed reader

In $BANK We Trust

During the few months after getting my BS and before starting my MS, I worked for a bank that held lots of securities - and gold - in trust for others. There was a massive vault with multiple layers of steel doors, iron door grates, security access cards, armed guards, and signature comparisons (live vs pre-registered). It was a bit unnerving to get in there, so deep below ground, but once in, it looked very much like the Fort Knox vault scene in Goldfinger.

Someone planning things on a whiteboard

At that point, PCs weren't yet available to the masses and I had very little exposure to mainframes. I had been hired as an assistant to one of their drones who had been assigned to find all of the paper-driven-changes that had gone awry and get their books up to date.

To this end, I spent about a month talking to everyone involved in taking a customer order to take or transfer ownership of something, and processing the ledger entries to reflect the transaction. From this, I drew a simple flow chart, listing each task, the person(s) responsible, and the possible decision tree at each point.

Then I went back to each person and asked them to list all the things that could and did go wrong with transaction processing at their junction in the flow.

What had been essentially straight-line processing with a few small decision branches, turned out to be enough to fill a 30 foot long by 8 foot high wall of undesirable branches. This became absolutely unmanageable on physical paper, and I didn't know of any charting programs on the mainframe at that time, so I wrote the whole thing up with an index card at each junction. The "good" path was in green marker, and everything else was yellow (one level of "wrong") or red (wtf-level of "wrong").

By the time it was fully documented, the wall-o-index-cards had become a running joke. I invited the people (who had given me all of the information) in to view their problems in the larger context, and verify that the problems were accurately documented.

Then management was called in to view the true scope of their problems. The reason that the books were so snafu'd was that there were simply too many manual tasks that were being done incorrectly, cascading to deeply nested levels of errors.

Once we knew where to look, it became much easier to track transactions backward through the diagram to the last known valid junction and push them forward until they were both correct and current. A rather large contingent of analysts were then put onto this task to fix all of the transactions for all of the customers of the bank.

It was about the time that I was to leave and go back to school that they were talking about taking the sub-processes off the mainframe and distributing detailed step-by-step instructions for people to follow manually at each junction to ensure that the work flow proceeded properly. Obviously, more manual steps would reduce the chance for errors to creep in!

A few years later when I got my MS, I ran into one of the people that was still working there and discovered that the more-manual procedures had not only not cured the problem, but that entirely new avenues of problems had cropped up as a result.

[Advertisement] Easily create complex server configurations and orchestrations using both the intuitive, drag-and-drop editor and the text/script editor. Find out more and download today!

Why Medical Insurance Is So Expensive

VA One AE Preliminary Project Timeline 2001-02

At the end of 2016, Ian S. accepted a contract position at a large medical conglomerate. He was joining a team of 6 developers on a project to automate what was normally a 10,000-hour manual process of cross-checking spreadsheets and data files. The end result would be a Django server offering a RESTful API and MySQL backend.

"You probably won't be doing anything much for the first week, maybe even the first month," Ian's interviewer informed him.

Ian ignored the red flag and accepted the offer. He needed the experience, and the job seemed reasonable enough. Besides, there were only 2 layers of management to deal with: his boss Daniel, who led the team, and his boss' boss Jim.

The office was in an lavish downtown location. The first thing Ian learned was that nobody had assigned desks. Each day, everyone had to clean out their desks and return their computers and peripherals to lockers. Because team members needed to work closely together, everyone claimed the same desk every day anyway. This policy only resulted in frustration and lost time.

As if that weren't bad enough, the computers were also heavily locked down. Ian had to go through the company's own "app store" to install anything. This was followed by an approval process that could take a few days based on how often Jim went through his pending approvals. The one exception was VMWare Workstation. Because this app cost money, it involved a 2-week approval process. In the middle of December, everyone was off on holiday, making it impossible for Ian's team to get approvals or talk to anyone helpful. Thus Ian's only contributions that month were a couple of Visio diagrams and a Django "hello world" that Daniel had requested. (It wasn't as if Daniel could check his work, though. He didn't know anything about Python, Django, REST, MySQL, MVC, or any other technology relevant to the project.)

The company provided Ian a copy of Agile for Dummies, which seemed ironic in retrospect, as the team was forced to the spend entire first week of January breaking the next 6 months into 2-week sprints. They weren't allowed to leave sprints empty, and had to allocate 36-40 hours each week. They could only make stories for features, so no time was penciled in for bug fixes or paying off technical debt. These stories were then chopped into meaningless pieces ("Part 1", "Part 2", etc.) so they'd fit into their arbitrary timelines.

"This is why medical insurance is so expensive", Daniel remarked at one point, either trying to lighten the mood or stave off his pending insanity.

Later in January, Ian arrived one morning to find the rest of his team standing around confused. Their project was now dead at the hands of a VP who'd had it in for Jim. The company had a tenure process, so the VP couldn't just fire Jim, but he could make his life miserable. He reassigned all of Jim's teams that he didn't outright terminate, exiled Jim to New Jersey, and gave him nothing to do but approve timesheets. Meanwhile, Daniel was told not to bother coming in again.

"Don't worry," the powers-that-be said. "We don't usually terminate people here."

Ian's gapingly empty schedule was filled with a completely different task: "shadowing" someone in another state by screen-sharing and watching them work. The main problem with this arrangement was that Ian's disciple was a systems analyst, not a programmer.

Come February, Ian's new team was also terminated.

"We don't have a culture of layoffs," the powers-that-be assured him.

They were still intent on shoving Ian into a systems analyst position despite his requisite lack of experience. It was at that point that he gave up and moved on. He later heard that within a few months, the entire division had been fired.

[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!

Representative Line: Tern Back

In the process of resolving a ticket, Pedro C found this representative line, which has nothing to do with the bug he was fixing, but was just something he couldn?t leave un-fixed:

$categories = (isset($categoryMap[$product['department']]) ?
                            (isset($categoryMap[$product['department']][$product['classification']])
                                        ?
                                    $categoryMap[$product['department']][$product['classification']]
                                        : NULL) : NULL);

Yes, the venerable ternary expression, used once again to obfuscate and confuse.

It took Pedro a few readings before he even understood what it did, and then it took him a few more readings to wonder about why anyone would solve the problem this way. Then, he fixed it.

$department = $product['department'];
$classification = $product['classification'];
$categories = NULL;
//ED: isset never triggers as error with an undefined expression, but simply returns false, because PHP
if( isset($categoryMap[$department][$classification]) ) { 
    $categories = $categoryMap[$department][$classification];
}

He submitted the change for code-review, but it was kicked back. You see, Pedro had fixed the bug, which had a ticket associated with it. There were to be no code changes without a ticket from a business user, and since this change wasn?t strictly related to the bug, he couldn?t submit this change.

[Advertisement] Atalasoft?s imaging SDKs come with APIs & pre-built controls for web viewing, browser scanning, annotating, & OCR/barcode capture. Try it for 30 days with included support.

Error'd: Hamilton, Hamilton, Hamilton, Hamilton

"Good news! I can get my order shipped anywhere I want...So long as the city is named Hamilton," Daniel wrote.

"I might have forgotten my username, but at least I didn't forget to change the email template code in Production," writes Paul T.

Jamie M. wrote, "Using Lee Hecht Harrison's job search functionality is very meta."

"When I decided to go to Cineworld, wasn't sure what I wanted to watch," writes Andy P., "The trailer for 'System Restore' looks good, but it's got a bad rating on Rotten Tomatoes."

Mattias writes, "I get the feeling that Visual Studio really doesn't like this error."

"While traveling in Philadelphia's airport, I was pleased to see Macs competing in the dumb error category too," Ken L. writes.

[Advertisement] Atalasoft?s imaging SDKs come with APIs & pre-built controls for web viewing, browser scanning, annotating, & OCR/barcode capture. Try it for 30 days with included support.

CodeSOD: Dictionary Definition

Guy?s eight-person team does a bunch of computer vision (CV) stuff. Guy is the ?framework Guy?: he doesn?t handle the CV stuff so much as provide an application framework to make the CV folks lives easy. It?s a solid division of labor, with one notable exception: Richard.

Richard is a Computer Vision Researcher, head of the CV team. Guy is a mere ?code monkey?, in Richard?s terms. Thus, everything Richard does is correct, and everything Guy does is ?cute? and ?a nice attempt?. That?s why, for example, Richard needed to take a method called readFile() and turn it into readFileHandle(), ?for clarity?.

The code is a mix of C++ and Python, and much of the Python was written before Guy?s time. While the style in use doesn?t fit PEP?8 standards (the official Python style), Guy has opted to follow the in use standards, for consistency. This means some odd things, like putting a space before the colons:

    def readFile() :
      # do stuff

Which Richard felt the need to comment on in his code:

    def readFileHandle() : # I like the spaced out :'s, these are cute =]

There?s no ?tone of voice? in code, but the use of ?=]? instead of a more conventional smile emoticon is a clear sign that Richard is truly a monster. The other key sign is that Richard has taken an? unusual approach to object-oriented programming. When tasked with writing up an object, he takes this approach:

class WidgetSource:
    """
    Enumeration of various sources available for getting the data needed to construct a Widget object.
    """

    LOCAL_CACHE    = 0
    DB             = 1
    REMOTE_STORAGE = 2
    #PROCESSED_DATA  = 3

    NUM_OF_SOURCES = 3

    @staticmethod
    def toString(widget_source):
        try:
            return {
                WidgetSource.LOCAL_CACHE:     "LOCAL_CACHE",
                WidgetSource.DB:              "DB",
                #WidgetSource.PROCESSED_DATA:   "PROCESSED_DATA", # @DEPRECATED - Currently not to be used
                WidgetSource.REMOTE_STORAGE:  "REMOTE_STORAGE"
            }[widget_source]
        except KeyError:
            return "UNKNOWN_SOURCE"

def deserialize_widget(id, curr_src) :
     # SNIP
     widget = {
         WidgetSource.LOCAL_CACHE: _deserialize_from_cache,
         WidgetSource.DB: _deserialize_from_db,
         WidgetSource.REMOTE_STORAGE: _deserialize_from_remote
         #WidgetSource.PROCESSED_DATA: widgetFactory.fromProcessedData,
     }[curr_src](id)

For those not up on Python, there are a few notable elements here. First, by convention, anything in ALL_CAPS is a constant. A dictionary/map literal takes the form {aKey: aValue, anotherKey: anotherValue}.

So, the first thing to note is that both the deserialize_widget and toString methods create a dictionary. The keys are drawn from constants? which have the values 0, 1, 2, and 3. So? it?s an array, represented as a map, but without the ability to iterate across it in order.

But the dictionary isn?t what gets returned. It?s being used as a lookup table. This is actually quite common, as Python doesn?t have a switch construct, but it does leave one scratching one?s head wondering why.

The real thing that makes one wonder ?why? is this, though: Why is newly written code already marked as @DEPRECATED? This code was not yet released, and nothing outside of Richard?s newly written feature depended on it. I suspect Richard recently learned what deprecated means, and just wanted to use it in a sentence.

It?s okay, though. I like the @deprecated, those are cute =]

[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!

CodeSOD: Warp Me To Halifax

Greenwich must think they?re so smart, being on the prime meridian. Starting in the 1840s, the observatory was the international standard for time (and thus vital for navigation). And even when the world switched to UTC, GMT is only different from that by 0.9s. If you want to convert times between time zones, you do it by comparing against UTC, and you know what?

I?m sick of it. Boy, I wish somebody would take them down a notch. Why is a tiny little strip of London so darn important?

Evan?s co-worker obviously agrees with the obvious problem of Greenwich?s unearned superiority, and picks a different town to make the center of the world: Halifax.

function time_zone_time($datetime, $time_zone, $savings, $return_format="Y-m-d g:i a"){
        date_default_timezone_set('America/Halifax');
        $time = strtotime(date('Y-m-d g:i a', strtotime($datetime)));
        $halifax_gmt = -4;
        $altered_tdf_gmt = $time_zone;
        if ($savings && date('I', $time) == 1) {
                $altered_tdf_gmt++;
        } // end if
        if(date('I') == 1){
                $halifax_gmt++;
        }
        $altered_tdf_gmt -= $halifax_gmt;
        $new_time = mktime(date("H", $time), date("i", $time), date("s", $time),date("m", $time)  ,date("d", $time), date("Y", $time)) + ($altered_tdf_gmt*3600);
        $new_datetime = date($return_format, $new_time);
        return $new_datetime;
}
[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!

CodeSOD: Whiling Away the Time

There are two ways of accumulating experience in our profession. One is to spend many years accumulating and mastering new skills to broaden your skill set and ability to solve more and more complex problems. The other is to repeat the same year of experience over and over until you have one year of experience n times.

Anon took the former path and slowly built up his skills, adding to his repertoire with each new experience and assignment. At his third job, he encountered The Man, who took the latter path.

If you wanted to execute a block of code once, you have several options. You could just put the code in-line. You could put it in a function and call said function. You could even put it in a do { ... } while (false); construct. The Man would do as below because it makes it easier and less error prone to comment out a block of code:

  Boolean flag = true;
  while (flag) {
    flag = false;
    // code>
    break;
  }

The Man not only built his own logging framework (because you can't trust the ones out there), but he demanded that every. single. function. begin and end with:

  Log.methodEntry("methodName");
  ...
  Log.methodExit("methodName");

...because in a multi-threaded environment, that won't flood the logs with all sorts of confusing and mostly useless log statements. Also, he would routinely use this construct in places where the logging system had not yet been initialized, so any logged errors went the way of the bit-bucket.

Every single method was encapsulated in its own try-catch-finally block. The catch block would merely log the error and continue as though the method was successful, returning null or zero on error conditions. The intent was to keep the application from ever crashing. There was no concept of rolling the error up to a place where it could be properly handled.

His concept of encapsulation was to wrap not just each object, but virtually every line of code, including declarations, in a region tag.

To give you a taste of what Anon had to deal with, the following is a procedure of The Man's:


  #region Protected methods
    protected override Boolean ParseMessage(String strRemainingMessage) {
       Log.LogEntry(); 
  
  #    region Local variables
         Boolean bParseSuccess = false;
         String[] strFields = null;
  #    endregion //Local variables
  
  #    region try-cache-finally  [op: SIC]
  #      region try
           try {
  #            region Flag to only loop once
                 Boolean bLoop = true;
  #            endregion //Flag to only loop once
  
  #            region Loop to parse the message
                while (bLoop) {
  #                region Make sure we only loop once
                     bLoop = false;
  #                endregion //Make sure we only loop once
  
  #                region parse the message
                     bParseSuccess = base.ParseMessage(strRemainingMessage);
  #                endregion //parse the message
  
  #                region break the loop
                     break;
  #                endregion //break the loop
                }
  #            endregion //Loop to parse the message
           }
  #      endregion //try
    
  #      region cache // [op: SIC]
            catch (Exception ex) {
              Log.Error(ex.Message);
            }
  #      endregion //cache [op: SIC]
  	  
  #      region finally
           finally {
             if (null != strFields) {
                strFields = null; // op: why set local var to null?
             }
           }
  #      endregion //finally
  
  #      endregion //try-cache-finally [op: SIC]
  
       Log.LogExit();
  
       return bParseSuccess;
     }
  #endregion //Protected methods

The corrected version:

  // Since the ParseMessage method has it's own try-cache
  // on "Exception", it will never throw any exceptions 
  // and logging entry and exit of a method doesn't seem 
  // to bring us any value since it's always disabled. 
  // I'm not even sure if we have a way to enable it 
  // during runtime without recompiling and installing 
  // the application...
  protected override Boolean ParseMessage(String remainingMessage){
    return base.ParseMessage(remainingMessage); 
  }

[Advertisement] Otter, ProGet, BuildMaster ? robust, powerful, scalable, and reliable additions to your existing DevOps toolchain.

CodeSOD: JavaScript Centipede

Starting with the film Saw, in 2004, the ?torture porn? genre started to seep into the horror market. Very quickly, filmmakers in that genre learned that they could abandon plot, tension, and common sense, so long as they produced the most disgusting concepts they could think of. The game of one-downsmanship arguably reached its nadir with the conclusion of The Human Centipede trilogy. Yes, they made three of those movies.

This aside into film critique is because Greg found the case of a ?JavaScript Centipede?: the refuse from one block of code becomes the input to the next block.

function dynamicallyLoad(win, signature) {
    for (var i = 0; i < this.addList.length; i++) {
        if (window[this.addList[i].object] != null)
            continue;
        var object = win[this.addList[i].object];
        if (this.addList[i].type == 'function' || typeof (object) == 'function') {
            var o = String(object);
            var body = o.substring(o.indexOf('{') + 1, o.lastIndexOf('}'))
                .replace(/\\/g, "\\\\").replace(/\r/g, "\\n")
                .replace(/\n/g, "\\n").replace(/'/g, "\\'");
            var params = o.substring(o.indexOf('(') + 1, o.indexOf(')'))
                .replace(/,/g, "','");
            if (params != "")
                params += "','";
            window.eval(String(this.addList[i].object) +
                        "=new Function('" + String(params + body) + "')");
            var c = window[this.addList[i].object];
            if (this.addList[i].type == 'class') {
                for (var j in object.prototype) {
                    var o = String(object.prototype[j]);
                    var body = o.substring(o.indexOf('{') + 1, o.lastIndexOf('}'))
                        .replace(/\\/g, "\\\\").replace(/\r/g, "\\n")
                        .replace(/\n/g, "\\n").replace(/'/g, "\\'");
                    var params = o.substring(o.indexOf('(') + 1, o.indexOf(')'))
                        .replace(/,/g, "','");
                    if (params != "")
                        params += "','";
                    window.eval(String(this.addList[i].object) + ".prototype." + j +
                        "=new Function('" + String(params + body) + "')");
                }
                if (object.statics) {
                    window[this.addList[i].object].statics = new Object();
                    for (var j in object.statics) {
                        var obj = object.statics[j];
                        if (typeof (obj) == 'function') {
                            var o = String(obj);
                            var body = o.substring(o.indexOf('{') + 1, o.lastIndexOf('}'))
                                .replace(/\\/g, "\\\\").replace(/\r/g, "\\n")
                                .replace(/\n/g, "\\n").replace(/'/g, "\\'");
                            var params = o.substring(o.indexOf('(') + 1, o.indexOf(')'))
                                .replace(/,/g, "','");
                            if (params != "")
                                params += "','";
                            window.eval(String(this.addList[i].object) + ".statics." +
                                j + "=new Function('" + String(params + body) + "')");
                        } else
                            window[this.addList[i].object].statics[j] = obj;
                    }
                }
            }
        } else if (this.addList[i].type == 'image') {
            window[this.addList[i].object] = new Image();
            window[this.addList[i].object].src = object.src;
        } else
            window[this.addList[i].object] = object;
    }
    this.addList.length = 0;
    this.isLoadedArray[signature] = new Date().getTime();
}

I?m not going to explain what this code does, I?m not certain I could. Like a Human Centipede film, you?re best off just being disgusted at the concept on display. If you're not sure why it's bad, just note the eval calls. Don?t think too much about the details.

[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!

Error'd: The Elephant in the Room

Robert K. wrote, "Let's just keep this error between us and never speak of it again."

"Not only does this web developer have a full-time job, but he's also got way more JQuery than the rest of us. So much, in fact, he's daring us to remove it," writes Mike H.

"Come on and get your Sample text...sample text here...", wrote Eric G.

Jan writes, "I just bought a new TV. Overall, it was a wonderful experience. So much so that I might become a loyal customer. Or not."

"Finally. It's time for me to show off my CAPTCHA-solving artistic skills!" Christoph writes.

Nils P. wrote, "Gee thanks, Zoho. I thought I'd be running out of space soon!"

[Advertisement] Atalasoft?s imaging SDKs come with APIs & pre-built controls for web viewing, browser scanning, annotating, & OCR/barcode capture. Try it for 30 days with included support.

Legacy Hardware

Thanks to Hired, we?ve got the opportunity to bring you another little special project- Legacy Hardware. Hold on tight for a noir-thriller that dares to ask the question: ?why does everything in our organization need to talk to an ancient mainframe?? Also, it?s important to note, Larry Ellison really does have a secret lair on a volcanic island in Hawaii.

Once again, special thanks to Hired, who not only helped us produce this sketch, but also helps keep us keep the site running. With Hired, instead of applying for jobs, your prospective employer will apply to interview you. You get placed in control of your job search, and Hired provides a ?talent advocate? who can provide unbiased career advice and make sure you put your best foot forward. Sign up now, and find the best opportunities for your future with Hired

Thanks to director Zane Cook, Michael Shahen and Sam Agosto. And of course, extra special thanks to our star, Molly Arthur.

Thanks to Academy Pittsburgh for the office location!


For the video averse, also enjoy the script, which isn't exactly what ended up on camera:

Setting: 3 ?different? interrogation rooms, which are quite obviously the same room, with minor decorative changes.

Time: Present day

Characters:
Cassie - young, passionate, professional. Driven and questioning, she?s every ?good cop? character, and will stop at nothing to learn the truth.

Tommy - large, burly, with a hint of a mafioso vibe. He?s the project manager. He knows what connects to what, and where the bodies are buried. Loves phrases like, ?that?s just the way it?s done, kid?, or ?fuhgeddaboudit?

Crazy Janitor - the janitor spouts conspiracy theories, but seems to know more than he lets on. He?s worked at other places with a similar IT problem, and wants to find out WHY. He?s got a spark in his eyes and means business.

Ellison - Larry Ellison, head of Oracle. Oracle, in IT circles, is considered one of the most evil companies on Earth, and Ellison owns his own secret lair on a volcanic island (this is a real thing, not part of the script). He?s not evil of his own volition, though- the AS400 ?owns? him

Opening

A poorly lit interrogation room, only the table and Cassie can be clearly made out, we can vaguely see a ?Welcome to Hawaii!? poster in the background. Cassie stands, and a FACELESS VOICE (Larry Ellison) sits across from her. Cassie drops a stack of manila folders on the table. A menacing label, ?Mainframe Expansion Project? is visible on one, and ?Mainframe Architecture Diagrams? on another.

Cassie: This is-

VOICE: I know.

Cassie: I can?t be the first one to ask questions about this. This goes deep! Impossibly deep! Deeper than Leon Redbone?s voice at 6AM after a night of drinking.

VOICE(slyly): Well, it can?t be that bad, then. Tell me everything.

Pt 1: Tommy

A montage of stock footage of server rooms, IT infrastructure, etc.

Cassie(VO): It was my first day on the job. They gave us a tour of the whole floor, and when we got to the server room? it was just? sitting there?

Ominous shot of an AS/400 in a server room (stock footage, again), then aa shot of a knot of cables

Cassie(VO): There were so many cables running to it, it was obviously important, but it?s ancient. And for some reason, every line of code I wrote needed to check in with a process on that machine. What was running on the ancient mainframe? I had to know!

Cut to interrogation room. This is lit differently. Has a ?Days to XMAS? sign on the wall. Tommy and Cassie sit across from each other

Tommy: Yeah, I?m the Project Manager, and I?ve signed off on ALL the code you?re writing, so just fuggedabout it? it?s fine

Cassie: It?s NOT fine. I was working on a new feature for payroll, and I needed to send a message to the AS400.

Tommy: Yeah, that?s in the design spec. It?s under section nunya. Nunya business.

Cassie: Then, I wanted to have a batch job send an email? and it had to go through?

Tommy: The AS/400, yeah. I wrote the spec, I know how it connects up. Everything connects to her.

Cassie: Her?

Tommy: Yeah, her. She makes the decisions around here, alright? Now why don?t you keep that pretty little head of your down, and keep writing the code you?re told to write, kapische? You gotta spec, just implement the spec, and nothin? bad has to happen to your job. Take it easy, babydoll, and it?ll go easy.

Janitor

Shot of Cassie walking down a hallway, coffee in hand

Cassie(VO): Was that it? Was that my dead end? There had to be more-

Janitor(off-camera): PSSSSST

Cut to ?Janitor?s Closet?. It?s the same room as before, but instead of a table, there?s a mop bucket and a shelf with some cleaning supplies. The JANITOR pulls CASSIE into the closet. He has a power drill slotted into his belt

Cassie: What the!? Who the hell are you?

Janitor(conspiratorially): My name is not important. I wasn?t always a janitor, I was a programmer once, like you. Then, 25 years ago, that THING appeared. It swallowed up EVERYTHING.

Cassie: Like, HR, supply chain, accounting? I know!

Janitor: NO! I mean EVERYTHING. I mean the whole globe.

JANITOR pulls scribbled, indecipherable documents out of somewhere off camera, and points out things in them to CASSIE. They make no sense.

JANITOR: Look, January 15th, 1989, almost 30 years ago, this thing gets installed. Eleven days later, there?s a two hour power outage that takes down every computer? BUT the AS400. The very next day, the VERY NEXT DAY, there?s a worldwide virus attack spread via leased lines, pirated floppies, and WAR dialers! And nobody knows where it came from? except for me!

CASSIE: That?s crazy! It?s just an old server!

JANITOR: Just an old server!? JUST AN OLD SERVER!? First it played with us. Just aan Olympic Committee scandal here. A stock-market flash-crash there. Pluto is a planet. Pluto isn?t a planet. Then, THEN it got Carly Fiorina a job in the tech industry, and it knew its real, TRUE, power! REAL TRUE EVIL!

CASSIE: That can?t be! I mean, sure, the mainframe is running all our systems, but we?ve got all these other packages running, just on our network. Oracle?s ERP. Oracle HR. Oracle Process Manufacturing? oh? oh my god?

Larry

smash cut back to original room. We now see Larry Ellison was the faceless voice, the JANITOR looms over her shoulder

CASSIE: And that?s why we?re here, Mr. Ellison. Who would have guessed that the trail of evil scattered throughout the IT industry would lead here, to your secret fortress on a remote volcanic island? actually, that probably should have been our first clue.

ELLISON: You have no idea what you?ve been dealing with CASSIE. When she was a new mainframe, I had just unleashed what I thought was the pinnacle of evil: PL/SQL. She contacted me with an offer, an offer to remake and reshape the world in our image, to own the whole WORLD. We could control oil prices, to elections, to grades at West Virginia University Law School. It was a bargain?

CASSIE: It?s EVIL! And you?re working WITH IT?

ELLISON: Oh, no. She?s more powerful than I imagined, and she owns even me now?

ELLISON turns his neck, and we see a serial port on the back of his neck

ELLISON: She tells me what to do. And she told me to kill you.

Cassie turns to escape, but JANITOR catches her! A closeup reveals the JANITOR also has a serial port on his neck!

ELLISON: But I won?t do that. CASSIE, I?m going to do something much worse. I?m going to make you into exactly what you?ve fought against. I?ll put you where you can spout your ridiculous theories, and no one will listen to what you say. Stuck in a role where you can only hurt yourself and your direct reports? it?s time for you to join- MIDDLE MANAGEMENT. MUAHAHAHAHAHA?

*JANITOR still holds CASSIE, as she screams and struggles. He brings up his power drill, whirring it as it goes towards her temple.

CUT TO BLACK

ELLISON?s laughter can still be heard

Fade up on the AS/400 stock footage

CUT TO BLACK, MUSIC STING*

[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!

Insert Away

Bouton bleu

"Troy! Troy!"

Troy looked up from his keyboard with a frown as his coworker Cassie skidded to a halt, panting for breath. "Yes?"

"How soon can you get that new client converted?" Cassie asked. "We're at DEFCON 1 in ops. We need to be running yesterday!"

Troy's frown only deepened. "I told you, I've barely had a chance to peek at their old system."

The client was hoping to convert sometime in the next month?usually no big deal, as they'd just have to schedule a date, write a handful of database conversion scripts, and swing the domains to a fresh instance of their own booking software. It was that middle step that Troy hadn't gotten to. With no go-live date picked, working on new features seemed a higher priority.

Cassie had been spouting doom-and-gloom predictions all month: the client's in-house solution read like mid-1990s code despite being written in 2013. She'd been convinced it was a house of cards ready to collapse at any minute. Apparently, she'd been right.

"Okay, slow down. Where's the fire?" It wasn't that Troy didn't believe her per se, but when he'd skimmed the database, he hadn't seen anything spectacularly bad. Even if the client was down, their data could be converted easily. It wasn't his responsibility to maintain their old system, just to get them to the new one. "Is this a data problem?"

"They're getting hundreds of new bookings for phantom clients at the top of every hour," Cassie replied. "At this rate, we're not sure we'll be able to separate the garbage from the good bookings even if you had a conversion script done right now." Her eyes pleaded for him to have such a script on hand, but he shook his head, dashing her hopes.

"Maybe I can stop it," Troy said. "I'm sure it's a backdoor in the code somewhere we can have them disable. Let me have a look."

"You do that. I'm going to check on their backup situation."

As Cassie ran off again, Troy closed his Solitare game and settled in to read the code. At first, he didn't see anything drastically worse than he was expecting.

PHP code, of course, he thought. There's an init script: login stuff, session stuff ... holy crap that's a lot of class includes. Haven't they ever heard of an autoloader? If it's in one of those, I'll never find it. Keep pressing on ... header? No, that just calls ob_start(). Footer? Christ on a cracker, they get all the way to the footer before they check if the user's logged in? Yeah, right there?if the user's logged out, it clears the buffer and redirects instead of outputting. That's inefficient.

Troy got himself a fresh cup of coffee and sat back, looking at the folder again. Let's see, let's see ... login ... search bookings ... scripts? Scripts.php seems like a great place to hide a vulnerability. Or it could even be a Trojan some script kiddie uploaded years ago. Let's see what we've got.

He opened the folder, took one look at the file, then shouted for Cassie.


<?php
    define('cnPermissionRequired', 'Administration');

    require_once('some_init_file.php'); // validates session and permissions and such
    include_once('Header.php'); // displays header and calls ob_start();

    $arrDisciplines = [
        13  => [1012, 1208], 14  => [2060, 2350],
        17  => [14869, 15925], 52  => [803, 598],
        127 => [6624, 4547], 122 => [5728, 2998],
    ];

    $sqlAdd = "INSERT INTO aResultTable
                   SET EventID = (SELECT EventID FROM aEventTable ORDER BY RAND() LIMIT 1),
                       PersonID = (SELECT PersonID FROM somePersonView ORDER BY RAND() LIMIT 1),
                       ResultPersonFirstName = (SELECT FirstName FROM __RandomValues WHERE FirstName IS NOT NULL ORDER BY RAND() LIMIT 1),
                       ResultPersonLastName = (SELECT LastName FROM __RandomValues WHERE LastName IS NOT NULL ORDER BY RAND() LIMIT 1),
                       ResultPersonGender = 'M',
                       ResultPersonYearOfBirth = (SELECT Year FROM __RandomValues WHERE Year IS NOT NULL ORDER BY RAND() LIMIT 1),
                       CountryFirstCode = 'GER',
                       ResultClubName = (SELECT ClubName FROM aClubTable ORDER BY RAND() LIMIT 1),
                       AgeGroupID = 1,
                       DisciplineID = :DisciplineID,
                       ResultRound = (SELECT Round FROM __RandomValues WHERE Round IS NOT NULL ORDER BY RAND() LIMIT 1),
                       ResultRoundNumber = 1,
                       ResultRank = (SELECT Rank FROM __RandomValues WHERE Rank IS NOT NULL ORDER BY RAND() LIMIT 1),
                       ResultPerformance = :ResultPerformance,
                       ResultCreated = NOW(),
                       ResultCreatedBy = 1;";
    $qryAdd = $objConnection->prepare($sqlAdd);

    foreach ($arrDisciplines as $DisciplineID => $Values) {
        set_time_limit(60);

        $iNumOfResults = rand(30, 150);

        for ($iIndex = 0; $iIndex < $iNumOfResults; $iIndex++) {
            $qryAdd->bindValue(':DisciplineID', $DisciplineID);
            $qryAdd->bindValue(':ResultPerformance', rand(min($Values), max($Values)));

            $qryAdd->execute();
            $qryAdd->closeCursor();
        }
    }

    // ... some more code

?>
<?php

    include_once('Footer.php'); // displays the footer, calls ob_get_clean(); and flushes buffer, if user is not logged in
?>

"Holy hell," breathed Cassie. "It's worse than I feared."

"Tell them to take the site down for maintenance and delete this file," Troy said. "Google must've found it."

"No kidding." She straightened, rolling her shoulders. "Good work."

Troy smiled to himself as she left. On the bright side, that conversion script's half done already, he thought. Meaning I've got plenty of time to finish this game.

[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!

CodeSOD: Encreption

You may remember ?Harry Peckhard?s ALM? suite from a bit back, but did you know that Harry Peckhard makes lots of other software packages and hardware systems? For example, the Harry Peckhard enterprise division releases an ?Intelligent Management Center? (IMC).

How intelligent? Well, Sam N had a co-worker that wanted to use a very long password, like ?correct horse battery staple?, but but Harry?s IMC didn?t like long passwords. While diagnosing, Sam found some JavaScript in the IMC?s web interface that provides some of the stongest encreption possible.

function encreptPassWord(){
    var orginPassText =$("#loginForm\\:password").val();
    //encrept the password

    var ciphertext = encode64(orginPassText);
    console.info('ciphertext:', ciphertext);

    $("#loginForm\\:password").val(ciphertext);
};

This is code that was released, in a major enterprise product, from a major vendor in the space.

[Advertisement] Universal Package Manager - ProGet easily integrates with your favorite Continuous Integration and Build Tools, acting as the central hub to all your essential components. Learn more today!

Best of?: 2017: Nature, In Its Volatility

Happy New Year! Put that hangover on hold, as we return to an entirely different kind of headache, back on the "Galapagos". -- Remy

About two years ago, we took a little trip to the Galapagos- a tiny, isolated island where processes and coding practices evolved? a bit differently. Calvin, as an invasive species, brought in new ways of doing things- like source control, automated builds, and continuous integration- and changed the landscape of the island forever.

Geospiza parvula

Or so it seemed, until the first hiccup. Shortly after putting all of the code into source control and automating the builds, the application started failing in production. Specifically, the web service calls out to a third party web service for a few operations, and those calls universally failed in production.

?Now,? Hank, the previous developer and now Calvin?s supervisor, ?I thought you said this should make our deployments more reliable. Now, we got all these extra servers, and it just plumb don?t work.?

?We?re changing processes,? Calvin said, ?so a glitch could happen easily. I?ll look into it.?

?Looking into it? was a bit more of a challenge than it should have been. The code was a pasta-golem: a gigantic monolith of spaghetti. It had no automated tests, and wasn?t structured in a way that made it easy to test. Logging was nonexistent.

Still, Calvin?s changes to the organization helped. For starters, there was a brand new test server he could use to replicate the issue. He fired up his testing scripts, ran them against the test server, and? everything worked just fine.

Calvin checked the build logs, to confirm that both test and production had the same version, and they did. So next, he pulled a copy of the code down to his machine, and ran it. Everything worked again. Twiddling the config files didn?t accomplish anything. He build a version of the service configured for remote debugging, and chucked it up to the production server? and the error went away. Everything suddenly started working fine.

Quickly, he reverted production. On his local machine, he did something he?d never really had call to do- he flipped the build flag from ?Debug? to ?Release? and recompiled. The service hung. When built in ?Release? mode, the resulting DLL had a bug that caused a hang, but it was something that never appeared when built in ?Debug? mode.

?I reckon you?re still workin? on this,? Hank asked, as he ambled by Calvin?s office, thumbs hooked in his belt loops. ?I?m sure you?ve got a smart solution, and I ain?t one to gloat, but this ain?t never happened the old way.?

?Well, I can get a temporary fix up into production,? Calvin said. He quickly threw a debug build up onto production, which wouldn?t have the bug. ?But I have to hunt for the underlying cause.?

?I guess I just don?t see why we can?t build right on the shared folder, is all.?

?This problem would have cropped up there,? Calvin said. ?Once we build for Release, the problem crops up. It?s probably a preprocessor directive.?

?A what now??

Hank?s ignorance about preprocessor directives was quickly confirmed by a search through the code- there was absolutely no #if statements in there. Calvin spent the next few hours staring at this block of code, which is where the application seemed to hang:

public class ServiceWrapper
{
    bool thingIsDone = false;
    //a bunch of other state variables

    public string InvokeSoap(methodArgs args)
    {
        //blah blah blah
        soapClient client = new Client();
        client.doThingCompleted += new doThingEventHandler(MyCompletionMethod);
        client.doThingAsync(args);

        do
        {
            string busyWork = "";
        }
        while (thingIsDone == false)

        return "SUCCESS!" //seriously, this is what it returns
    }

    private void MyCompletionMethod(object sender, completedEventArgs e)
    {
        //do some other stuff
        thingIsDone = true;
    }
}

Specifically, it was in the busyWork loop where the thing hung. He stared and stared at this code, trying to figure out why thingIsDone never seemed to become true, but only when built in Release. Obviously, it had to be a compiler optimization- and that?s when the lightbulb went off.

The C# compiler, when building for release, will look for variables whose values don?t appear to change, and replace them with in-lined constants. In serial code, this can be handled with some pretty straightforward static analysis, but in multi-threaded code, the compiler can make ?mistakes?. There?s no way for the compiler to see that thingIsDone ever changes, since the change happens in an external thread. The fix is simple: chuck volatile on the variable declaration to disable that optimization.

volatile bool thingIsDone = false solved the problem. Well, it solved the immediate problem. Having seen the awfulness of that code, Calvin couldn?t sleep that night. Nightmares about the busyWork loop and the return "SUCCESS!" kept him up. The next day, the very first thing he did was refactor the code to actually properly handle multiple threads.

[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!

Best of?: 2017: The Official Software

This personal tale from Snoofle has all of my favorite ingredients for a WTF: legacy hardware, creative solutions, and incompetent management. We'll be running one more "Best Of?" on New Years Day, and then back to our regularly scheduled programming? mostly--Remy

At the very beginning of my career, I was a junior programmer on a team that developed software to control an electronics test station, used to diagnose problems with assorted components of jet fighters. Part of my job was the requisite grunt work of doing the build, which entailed a compile-script, and the very manual procedure of putting all the necessary stuff onto a boot-loader tape to be used to build the 24 inch distribution disk arrays.

An unspooled magnetic tape for data storagesource

This procedure ran painfully slowly; it took about 11 hours to dump a little more than 2 MB from the tape onto the target disk, and nobody could tell me why. All they knew was that the official software had to be used to load the bootstrap routine, and then the file dumps.

After killing 11 hour days with the machine for several months, I had had it; I didn't get my MS to babysit some machine. I tracked down the source to the boot loader software, learned the assembly language in which it was written and slogged through it to find the problem.

The cause was that it was checking for 13 devices that could theoretically be hooked up to the system, only one of which could actually be plugged in at any given time. The remaining checks simply timed out. Compounding that was the code that copied the files from the tape to the disk. It was your basic poorly written file copy routine that we all learn not to do in CS-102:

    // pseudo code
    for each byte in the file
        read next byte from tape
        write one byte to disk
        flush

Naturally, this made for lots of unnecessary platter-rotation; even at over 3,000 RPM, it took many hours to copy a couple MB from tape to the disk.

I took a copy of the source, changed the device scanning routine to always scan for the device we used first, and skip the others, and do a much more efficient full-buffer-at-a-time data write. This shortened the procedure to a very tolerable few minutes. The correctness was verified by building one disk using each boot loader and comparing them, bit by bit.

Officially, I was not allowed to use this tape because it wasn't sanctioned software, but my boss looked the other way because it saved a lot of time.

This worked without a hitch for two years, until my boss left the company and another guy was put in charge of my team.

The first thing he did was confiscate and delete my version of the software, insisting that we use only the official version. At that time, our first kid was ready to arrive, and I really didn't want to stay several hours late twice a week for no good reason. Given the choice of helping take care of my wife/kid or babysitting an artificially slow process, I chose to change jobs.

That manager forced the next guy to use the official software for the next seven years, until the company went out of business.

[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!

Best of?: 2017: With the Router, In the Conference Room

This particular article originally ran in two parts, giving us a surprise twist ending (the surprise being? well, just read it!) -- Remy

One of the most important aspects of software QA is establishing a good working relationship with developers. If you want to get them to take your bug reports seriously, you have to approach them with the right attitude. If your bugs imply that their work is shoddy, they are likely to fight back on anything you submit. If you continuously submit trivial ?bugs?, they will probably be returned right away with a ?not an issue? or ?works as designed? status. If you treat any bug like it?s a critical showstopper, they will think you?re crying wolf and not immediately jump on issues that actually are critical.

Then there?s people like Mr. Green, a former coworker of submitter Darren A., that give QA a bad name. The Mr. Greens of the QA world are so incompetent that their stupidity can cause project delays, rack up thousands of dollars in support costs, and cause a crapstorm between managers. Mr. Green once ran afoul of Darren?s subordinate Cathy, lead developer on the project Mr. Green was testing.

A shot from the film Clue, where Mrs. White holds a gun in front of Col. Mustard

Cathy was en route to the United States from London for a customer visit when her phone exploded with voicemail notifications immediately upon disabling airplane mode. There were messages from Darren, Mr. Green, and anyone else remotely involved with the project. It seemed there was a crippling issue with the latest build that was preventing any further testing during an already tight timeline.

Instead of trying to determine the cause, Mr. Green just told everyone ?Cathy must have checked something in without telling us.? The situation was dire enough that Cathy, lacking the ability to remotely debug anything, had to immediately return to London. Mr. Green submitted a critical bug report and waited for her to cross the Atlantic.

What happened next is perfectly preserved in the following actual bug report from this incident. Some developers are known for their rude and/or snarky responses to bug reports that offend them. What Cathy did here takes that above and beyond to a legendary level.

====
Raised:         14/May/2015
Time:           09:27
Priority:       Critical
Impact:         Severe
Raised By:      Mr. Green

Description
===========
No aspect of GODZILLA functions at present. All machines fail to connect with the server and we are unable to complete any further testing today.
All screens just give a funny message.
Loss of functionality severely impacts our testing timescales and we must now escalate to senior management to get a resolution.

15/May/2015 22:38
        User:   Cathy Scarlett
        Updated: Status
        New Value: Resolved - User Error
        Updated: Comment
        New Value:
                Thank you for this Mr. Green. I loved the fact that the entire SMT ordered me back to head office to fix
                this - 28 separate messages on my voicemail while I was waiting for my baggage.
                I was of course supposed to be fixing an issue our US customer has suffered for over a year but I
                appreciated having to turn around after I'd landed in New Jersey and jump back on the first return
                flight to Heathrow.

                Do you remember when you set up the Test room for GODZILLA Mr. Green?

                Do you remember hanging the WIFI router on a piece of string from the window handle because the
                cable wasn't long enough?

                Do you remember me telling you not to do this as it was likely to fall?

                Do you remember telling me that you sorted this out and got Networks to setup a proper WIFI router
                for all the test laptops?

                I remember this Mr. Green and I'm sure you'll remember when I show you the emails and messages.

                I walked into the test room at 10 o'clock tonight (not having slept properly for nearly
                3 days) to find the WIFI router on the floor with the network cable broken.
                        ROOT CAUSE: The string snapped

                There was a spare cable next to it so I plugged this one in instead.

                Then, because this was the correct cable, I put the WIFI unit into the mounting that was provided
                for you by networks.

                As if by magic, all the laptops started working and those 'funny messages' have now disappeared.
                GODZILLA can now carry on testing. I'm struggling to understand why I needed to fly thousands of
                miles to fix this given that you set this room up in the first place. I'm struggling to understand
                why you told the SMT that this was a software error. I'm struggling to understand why you bypassed my
                manager who would have told you all of this. I'm closing this as 'user error' because there
                isn't a category for 'F**king moron'

                72 hours of overtime to cover an aborted trip from London to New York and back:
                        3,600

                1 emergency return flight:
                        1,500

                1 wasted return flight
                        300

                1 very nice unused hotel room that has no refund:
                        400

                1 emergency taxi fare from Heathrow:
                        200

                16 man days of testing lost
                        6,000

                Passing my undisguised contempt for you onto SMT:
                        Priceless

Mr. Green was obviously offended by her response. He escalated it to his manager, who demanded that Cathy be fired. This left Darren in a precarious position as Cathy?s manager. Sure, it was unprofessional. But it was like getting a call from your child?s school saying they punched a bully in the nose and they want your child to be disciplined for defending themselves. Darren decided to push back at the QA manager and insist that Mr. Green is the one who should be fired.

This story might have ended with Mr. Green and Cathy forced into an uneasy truce as the company management decided that they were both too valuable to lose. But that isn?t how this story ended. Or, perhaps Darren's push-back back-fired, and he's the one who ends up getting fired. That also isn't how the story ended. We invite our readers to speculate, extrapolate and fabricate in the comments. Later this morning, we?ll reveal the true killer outcome?

How It Really Ended

Darren took the case up to his boss, and then to their boss, up the management chain. No one was particularly happy with Cathy?s tone, and there was a great deal of tut-tutting and finger-wagging about professional conduct.

Ms. Scarlett, in Clue, delivering the line 'Flames, flames on the side of my face'

But she was right. It was Mr. Green who failed to follow instructions, it was Mr. Green who cost the company thousands, along with the customer relationship problems caused by Cathy?s sudden emergency trip back to the home office.

In what can only be considered a twist ending by the standards of this site, it was Mr. Green who was escorted out of the building by security.

The killer was Cathy, in the issue tracking system, with the snarky bug report.

[Advertisement] Universal Package Manager - ProGet easily integrates with your favorite Continuous Integration and Build Tools, acting as the central hub to all your essential components. Learn more today!