-Поиск по дневнику

Поиск сообщений в rss_thedaily_wtf

 -Подписка по e-mail

 

 -Постоянные читатели

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 06.04.2008
Записей:
Комментариев:
Написано: 0

The Daily WTF





Curious Perversions in Information Technology


Добавить любой RSS - источник (включая журнал LiveJournal) в свою ленту друзей вы можете на странице синдикации.

Исходная информация - http://thedailywtf.com/.
Данный дневник сформирован из открытого RSS-источника по адресу http://syndication.thedailywtf.com/thedailywtf, и дополняется в соответствии с дополнением данного источника. Он может не соответствовать содержимому оригинальной страницы. Трансляция создана автоматически по запросу читателей этой RSS ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

[Обновить трансляцию]

Representative Line: Classic WTF - One Bad Ternary Operator Deserves Another

Среда, 31 Декабря 2014 г. 19:00 + в цитатник

Last day of 2014 means it's time to check out another year-end "Best Of WTF" article from earlier this year. Enjoy!


Personally, in all my years of application development, I have had zero use of ternary operators.

You might argue that ternary operators are useful in that they reduce the code footprint of an application of those unnecessarily lengthy if-then-else statements. But really...who are we kidding here? The only practical application of ternary operator is to either intentionally obfuscate your code or use it as a soapbox to brag about how "l33t" you are.

Case in point, the single line of code that Hrvoje P. sent in.


FailSafe==0?'No technical alarms':((FailSafe&1)!=0&&(FailSafe&2)!=0&&(FailSafe&4)!=0&&(FailSafe&8)!=0?'Detection zones staying in a given state; Bad visibility;
Initialization; Bad configuration':((FailSafe&1)!=0&&(FailSafe&2)!=0&&(FailSafe&4)!=0?'Detection zones staying in a given state; Bad visibility; Initialization':
((FailSafe&1)!=0&&(FailSafe&2)!=0&&(FailSafe&8)!=0?'Detection zones staying in a given state; Bad visibility; Bad configuration':((FailSafe&1)!=0&&(FailSafe&4)!=0&&
(FailSafe&8)!=0?'Detection zones staying in a given state; Initialization; Bad configuration':((FailSafe&2)!=0&&(FailSafe&4)!=0&&(FailSafe&8)!=0?'Bad visibility;
Initialization; Bad configuration':((FailSafe&1)!=0&&(FailSafe&2)!=0?'Detection zones staying in a given state; Bad visibility':((FailSafe&1)!=0&&(FailSafe&4)!=0?'Detection 
zones staying in a given state; Initialization':((FailSafe&1)!=0&&(FailSafe&8)!=0?'Detection zones staying in a given state; Bad configuration':((FailSafe&2)!=0&&
(FailSafe&4)!=0?'Bad visibility; Initialization':((FailSafe&2)!=0&&(FailSafe&8)!=0?'Bad visibility; Bad configuration':((FailSafe&4)!=0&&(FailSafe&8)!=0?'Initialization; Bad 
configuration':((FailSafe&1)!=0?'Detection zones staying in a given state':((FailSafe&2)!=0?'Bad visibility':((FailSafe&4)!=0?'Initialization':((FailSafe&8)!=0?'Bad 
configuration':'Unknown')))))))))))))))
[Advertisement] Use NuGet or npm? Check out ProGet, the easy-to-use package repository that lets you host and manage your own personal or enterprise-wide NuGet feeds and npm repositories. It's got an impressively-featured free edition, too!

http://thedailywtf.com/articles/classic-wtf-one-bad-ternary-operator-deserves-another


Метки:  

Coded Smorgasbord: Classic WTF - Sweet Mysteries of Life

Вторник, 30 Декабря 2014 г. 14:00 + в цитатник

Check out a Classics republish of one of our most read articles from 2014. Enjoy!


When you read a lot of bad code, you start to get a sense of why the code exists. Often, its ignorance- of the language, of the functional requirements, of basic logic. Sometimes, its management interference, and the slavish adherence to policy over practicality. Other times, its just lazy or sloppy work.

And sometimes, the mysterious logic that gave birth to a WTF is just that- a mystery.

Timo cant help but wonder why this method exists:

public DataModel getEditionModel() {
   if ( true )
       throw new IllegalArgumentException( "You shouldn't be here" );
   return editionModel;
}

Angela is still puzzling over this one:

String timeStampLength = "                          ";
int lengthOfTimeStamp = timeStampLength.length();

Can you imagine a clearer way to express a numeric length?

Dennis found some code that needs to check the length of an array, so it does this:

function countDocuments() {
    var count = 0;

    for ( var i = 0; i < user.documents.length; i++) {
        count++;
    }

    return count;
}

If only there were a built-in method that could tell us the length of an array...

And finally, Andrew sends us this example of defensive programming, thats about as safe as we can make it:

Private Sub ImageList_DataBound(ByVal sender As Object, ByVal e As System.EventArgs) Handles ImageList.DataBound
    Try

    Catch ex As Exception
        If TypeOf ex Is ArgumentOutOfRangeException Then
            Throw New Exception("item not found in the list...")
        End If
    End Try
End Sub
[Advertisement] BuildMaster is more than just an automation tool: it brings together the people, process, and practices that allow teams to deliver software rapidly, reliably, and responsibly. And it's incredibly easy to get started; download now and use the built-in tutorials and wizards to get your builds and/or deploys automated!

http://thedailywtf.com/articles/classic-wtf-sweet-mysteries-of-life


Метки:  

Classic WTF - Line by Line

Понедельник, 29 Декабря 2014 г. 14:00 + в цитатник

To close out the year, enjoy one of our popular articles from 2014. Happy holidays!


In the bowels of a business unit, a director got a great deal on a third party software package. He bought it, without talking to corporate IT, and then was upset when it couldnt gracefully integrate with any of the corporate IT assets. Eager to throw good money after bad, the director hired his nephews consultancy to build an integration tool to make his new toy work.

A few months later, the users complained about performance, and somehow, fixing this thing became Jeffs problem. The process was simple enough: slurp enterprise data out of a text file, and pass the data on to the third-party tool. It didnt take Jeff long to figure out why it performed poorly:

Private Sub ProcessFile()

    ' prepare to do stuff

    Do Until blnLastTime = True
        
        Set fileReader = fso.OpenTextFile(strFileName)
        
         If fileReader.AtEndOfStream = True Then
            blnLastTime = True
         Else
            strTextLine = fileReader.ReadLine
         End If

        ' actually do stuff
         
        fileReader.Close
        Delete_Line (strFileName)
    Loop
    fileReader.Close

End Sub



Private Sub Delete_Line(strFile)

    Set fileReader = fso.OpenTextFile(strFile)
    
    If fso.FileExists(strFile & "2") Then
        fso.DeleteFile (strFile & "2")
    End If
    
    Set fileWriter = fso.CreateTextFile(strFile & 2)
    
    If fileReader.AtEndOfStream = False Then
        fileReader.ReadLine
    End If
    
    If fileReader.AtEndOfStream = False Then
            strLine = fileReader.ReadAll
            fileWriter.Write (strLine)
    End If
    
    
    fileReader.Close
    fileWriter.Close

    fso.DeleteFile strFile, True
    fso.CopyFile strFile & "2", strFile, True
    fso.DeleteFile strFile & 2, True
    
End Sub

Start by opening a file foo.txt. Read a single line from the file. Send it to the third party app. Close the file. Open foo.txt again. Open another file, called foo.txt2. Read the first line from foo.txt, again. Throw that away. Read the remainder of foo.txt, and write it to foo.txt2. Copy foo.txt2 back over foo.txt. Now, go back to the top of the loop and read a single line from foo.txt again.

So, for a 10,000 line file, this would perform 30,000 file open operations, write nearly 50 million lines, delete 20,000 files, and perform 10,000 copy operations. It didnt take Jeff very long to rewrite this to simply read the file, one line at a time. The runtime dropped from a few hours to less than a minute.

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

http://thedailywtf.com/articles/classic-wtf-line-by-line


Метки:  

Error'd: The World's Worst Battery

Пятница, 26 Декабря 2014 г. 14:00 + в цитатник

"Maybe I need to order a generator with this one -- just in case I want to finish booting up the machine!" writes Matt R.

Ryan H. wrote, "Found this RAM on Rakuten. Something tells me it's for Charles Babbage's computer, not a ThinkServer."

"I was looking for some information about Powershell," Louise H. writes, "Apparently, 556 out of 1153 rated this helpful. My guess is these 556 were looking for 'Body insertion'."

"We are currently in the process of creating an upgrade script after major database changes," wrote Tobias, "It's actually so much data that it just gives up on 'nothing'."

"According to this Amazon listing, it looks like I've been thinking about photography all wrong," John S. writes.

"Looks like they went 'all-in' on web design. The multiple choice is so meta, the question itself could be an answer, along with the other options," B.K. wrote.

"There's something really wrong when Chrome believes that Google Docs is suspicious," George L. wrote.

"I hope my actual pension hasn't suffered a NullPointerException," Gareth O. writes.

[Advertisement] BuildMaster is more than just an automation tool: it brings together the people, process, and practices that allow teams to deliver software rapidly, reliably, and responsibly. And it's incredibly easy to get started; download now and use the built-in tutorials and wizards to get your builds and/or deploys automated!

http://thedailywtf.com/articles/the-world-s-worst-battery


Метки:  

Announcements: It's Christmas Day - Take a Break!

Четверг, 25 Декабря 2014 г. 14:00 + в цитатник

Seriously? Why are you reading this. Go do something with your family or your friends. There are more important things today than the internet.

Y Christmas Tree 2

(and if you don't happen to celebrate Christmas, that's fine - relaxation is non-denominational.)

[Advertisement] Release! is a light card game about software and the people who make it. Order the massive, 338-card Kickstarter Edition (which includes The Daily Wtf Anti-patterns expansion) for only $27, shipped!

http://thedailywtf.com/articles/it-s-christmas-day-take-a-break-


Метки:  

CodeSOD: Classic WTF - The Fizz Buzz from Outer Space

Среда, 24 Декабря 2014 г. 14:00 + в цитатник

To close things out for 2014, we're re-running our most popular articles. Without further ado, enjoy one of our most popular; this one originally ran in September.


Matteo recently interviewed a candidate that was employed elsewhere as an architect. His responses to the standard soft-skills questions sounded a bit rehearsed, which made Matteo suspicious, so he started asking some more technical questions, like: Whats the difference between an interface and an abstract class?

Well, in some logarithms , an interface is going to be internal to the system, but an abstract class has terminators that make it external.

Matteo almost showed him the door right there, but that might just be nerves or a misunderstanding. Instead, Matteo broke out the trust old interviewing tool- the FizzBuzz.

So, the program should print numbers, but if the number is divisible by three, it should print fizz, and if its divisible by five it should print buzz, and if its divisible by both, it should print fizz buzz. I can do that.

The candidate grabbed a piece of scratch paper and started working through the solution. It started promising enough, as he wrote out some pseudo-code:

But then he kept going.

And going.

Somehow, the candidate had divined a deep relationship between 3.14 and the fizzbuzz pattern, but rejected it when he discovered that 3.14/3 == 5.14 fizz.

But he did identify the rule- 1/3*fizz/buzz- and the exception to that rule, which made it equal 1/10. With the scratch work out of the way, the candidate grabbed a fresh sheet of paper so that he could write out the final version of his FizzBuzz logarithm.

There, he said proudly. That was a little tricky to solve, but I think that shows you how it would be done.

Matteo showed the candidate out, and so far as we know, the candidate was never seen again. We can only guess at the deeper meaning behind this alien wisdom.

[Advertisement] BuildMaster is more than just an automation tool: it brings together the people, process, and practices that allow teams to deliver software rapidly, reliably, and responsibly. And it's incredibly easy to get started; download now and use the built-in tutorials and wizards to get your builds and/or deploys automated!

http://thedailywtf.com/articles/classic-wtf-the-fizz-buzz-from-outer-space


Метки:  

CodeSOD: Hashing the Ruby Way

Вторник, 23 Декабря 2014 г. 14:00 + в цитатник

Ruby praises itself as the language that makes programmers happy. It does its best to be expressive and encourage a declarative style of programming.

Oxygen480-actions-irc-close-channel

Guillaume B. inherited a module which was supposed to simply check that a hash contained four fields which represented a signer: first name, last name, mobile, and email. There are many easy ways to check this using various collection methods (something like required_fields.all {|x| input_hash.has_key? x} is the first that comes to mind).

Why on Earth should we do it the easy way? Ruby has powerful features, like mix-ins, list expansions, and message passing. Guillaumes predecessor wasnt going to let any of those features sit unused. Comments below are my own.

module SignService
  class Signer
    ATTRIBUTE_KEYS = :firstname, :lastname, :mobile, :email
    
    attr_accessor *ATTRIBUTE_KEYS
    
    def initialize signer
      @firstname  = signer[:firstname]
      @lastname   = signer[:lastname]
      @mobile     = signer[:mobile]
      @email      = signer[:email]

      ATTRIBUTE_KEYS.each do |needed_attributes|
        raise "missing attribute: #{needed_attributes} to instanciate a SignService::Signer" if send(needed_attributes).empty?
      end
    end
    def params
      {
        firstname: @firstname,
        lastname: @lastname,
        phoneNum: @mobile,
        emailAddress: @email
      }
    end
  end
end

Theres so much hideous beauty in this, we have to take a moment to appreciate it. First, this pair of lines:

ATTRIBUTE_KEYS = :firstname, :lastname, :mobile, :email    
attr_accessor *ATTRIBUTE_KEYS

First, we make a list of symbols. Then we pass that list (using the * operator to turn it into a series of arguments) to the attr_accessor function, which generates getter/setter methods for each of those symbols.

Most people would have just written: attr_accessor :firstname, :lastname, :mobile, :email, but the splat operator shows a much deeper understanding of the Ruby language.

The function params at the end of the class simply turns the instance level variables back into a hash, which is nice, but remember our goal is just to verify that the input hash contains the keys we require.

And thats where the initialize method comes in. The parameter signer is our input hash, and the first few lines do their job neatly- they stuff the hash values into instance variables.

Its the last line of the initialize method that holds our real WTF. This method commits the worst sin it possibly could: it gets clever.

ATTRIBUTE_KEYS.each do |needed_attributes|
        raise "missing attribute: #{needed_attributes} to instanciate a SignService::Signer" if send(needed_attributes).empty?

We start with a simple for-each loop, and then we do a raise … if. Raise an error if the following condition is met. And that condition?: send(needed_attributes).empty?. The send function exposes Rubys message passing approach to calling functions. This statement calls one of the functions generated in the attr_accessor line and then checks if the result is empty?.

From this code, we can conclude that the original developer knows quite a bit about the Ruby language. We can also conclude that they dont know nearly enough about programming.

[Advertisement] BuildMaster is more than just an automation tool: it brings together the people, process, and practices that allow teams to deliver software rapidly, reliably, and responsibly. And it's incredibly easy to get started; download now and use the built-in tutorials and wizards to get your builds and/or deploys automated!

http://thedailywtf.com/articles/hashing-the-ruby-way


Метки:  

It's Raining on the Robot

Понедельник, 22 Декабря 2014 г. 15:30 + в цитатник

It's Raining on the Robot

On the way to the data vault, Dave and his coworkers tried to list every rain-related song they knew. Here Comes The Rain Again was an easy one. Ryan, raised in the nineties, offered I'm Only Happy When It Rains. Justine tried to get out in front of the competition by rapid-firing November, Purple, and No. Thad, veteran of a hundred karaoke battles, offered Blame It On The Rain.

But none of them had heard It's Raining On The Robot before.

That's all the caller had said: the Red Phone, the one which never rings, had jangled to life and the whole support team had just stared at it, trying to remember what it meant. The voice on the other line yelped only those five ominous words before hanging up, so the entire team scampered to Building Three and down to the sub-basement to investigate. Turned out the caller hadn't been speaking in riddles: there was a steady fountain of water pouring through a vent hole in the ceiling, puddling on the roof of the venerable STK Powderhorn silo, and starting to drip into the tape libraries within. Whoever had stopped by the silo and noticed the downpour was long gone, hopefully to find their STK consultant, so the support crew got to work on cleanup. Justine found a couple mops and buckets, and she and Ryan began to wrangle the growing pool on the data vault floor, arguing over the lyrics to Raining In My Heart as they went. Dave and Thad rolled their eyes and headed upstairs to find the cause of the leak, though Dave couldn't help himself from humming a few bars of Who'll Stop The Rain as they sought the right room.

Dave found the culprit when he happened to glance into the decommissioned server room off the hallway above the data vault. Building Three was the oldest building on the company campus, and it had central heating; an odd choice for a datacenter, but so it goes. Word had recently come down from on high that the radiators were to be replaced, and this old server room was first on the list. The hot-water pipe servicing the radiator had been cut, a simple job of freezing the pipe with dry ice, making the cut, then sealing the ends before it thawed. The plumber was some kind of maverick, apparently, because he'd elected to insert a bold new "taking an extended lunch break" step into the process. When the ice melted, the radiator had spilled its guts, washing twenty years of accumulated dust and grime from under the false floor into the data vault below.

Dave and Thad returned downstairs to find Carter, the STK consultant, on the scene. The Powderhorn was a tricky beast, so he was kept on retainer and it hadn't taken long for him to show up with a heavy-duty blue briefcase marked "Emergency Use Only". Justine and Ryan were soaked to the knees, leaning on their mops as they watched Carter carefully scan the rows and rows of tapes in the silo, removing and setting aside any that showed evidence of wetness. When he was done, he set the briefcase on a table and reverently unlatched it to reveal... a hair dryer and an extension cord. So armed, he proceeded to return his moistened charge to its former, working state. With disaster averted and only a few dozen tapes destroyed, the support team dispersed to let Carter finish his work. When Dave and Justine popped by Building Three days later to confirm that the robot was humming dryly along, they saw that Carter had implemented a new emergency protocol: leaning in the corner of the vault was a big roll of sheet plastic, marked "Emergency Use Only".

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

http://thedailywtf.com/articles/it-s-raining-on-the-robot


Метки:  

Error'd: Metro Card Jackpot!!

Пятница, 19 Декабря 2014 г. 14:00 + в цитатник

"I really need to look into a cash-out option," writes Alvin.

"There were evidently more DNS requests on my network last week than there are observable atoms in the universe," writes Elliot, "Maybe we should upgrade our name servers."

"The punch line? I'm expected to type all this in after having hand surgery," wrote Louise H.

"What do a Christmas tree base, a banana slicer, and a 4K Ultra-HD TV have in common? A whole lot according to Amazon," Roland wrote.

"Another developer at the company I work for committed some code, and I was reviewing," Jason D. writes, "Upon closer inspection, either the developer is ensuring job security, or he believes everyone needs to kill some time"

Lauren B. wrote, "So I downloaded VS SP1 and tried to install it, which would not install because it required VS SP1 to be installed before VS SP1 could be installed, which in turn of course requires..."

"I never thought I'd see CAPTCHA where I could just copy the text directly (source: http://www.freshersworld.com/user/register),"Roman writes.

"I tried to pay my phone bill, but apparently Virgin Mobile thinks that's a problem, or at least their software does," Michael C. wrote.

[Advertisement] Release! is a light card game about software and the people who make it. Order the massive, 338-card Kickstarter Edition (which includes The Daily Wtf Anti-patterns expansion) for only $27, shipped!

http://thedailywtf.com/articles/metro-card-jackpot-


Метки:  

CodeSOD: A Perfect 10

Четверг, 18 Декабря 2014 г. 14:00 + в цитатник

two-hands-equals-10-fingersAndrew found this code on the product pages of a fairly popular automotive e-commerce website. It's called whenever an 'attribute' of a product (size, color, etc.) is selected or changed by the user.

The main focus of this code is to update a concatenation of the values of all currently selected attributes which are stored in a hidden form input field. Once it has done that, it hands off to another function to make an AJAX request with this concatenated value as a parameter.

Sounds simple, right? Well, it is, assuming you've ever heard of basic JavaScript concepts like arrays, loops and accessing an object's properties as if it were a keyed array. However, if you haven't, your code might take the long way around.

var ao0, ao1, ao2, ao3, ao4, ao5, ao6, ao7, ao8, ao9; function updateAttrib(node, pg, index){

  var j;
  var aa = document.ProductForm.attribs.value;
  var attribs = aa.split("@");

  if(index == 0){
    var a = document.ProductForm.attrib0.value;
    var as = a.split("~");

    if(a == 'select'){
      var io = aa.indexOf(ao0);
      if(io != -1)
        aa = aa.replace(ao0 + "@", '');
    }else{
      var found = false;
      for(j = 0; j < attribs.length; j++){
        var split = attribs[j].split("~");
        if(split[0] == as[0]){
          aa = aa.replace(ao0 + "@", a + "@");
          found = true;
          break;
        }
      }

      if(!found)
        aa = aa + a + "@";
      ao0 = a;
    }
  }else if(index == 1){
    a = document.ProductForm.attrib1.value;
    as = a.split("~");

    if(a == 'select'){
      io = aa.indexOf(ao1);
      if(io != -1)
        aa = aa.replace(ao1 + "@", '');
    }else{
      found = false;
      for(j = 0; j < attribs.length; j++){
        split = attribs[j].split("~");
        if(split[0] == as[0]){
          aa = aa.replace(ao1 + "@", a + "@");
          found = true;
          break;
        }
      }

      if(!found)
        aa = aa + a + "@";
      ao1 = a;
    }
  }else if(index == 2){
    a = document.ProductForm.attrib2.value;
    as = a.split("~");

    if(a == 'select'){
      io = aa.indexOf(ao2);
      if(io != -1)
        aa = aa.replace(ao2 + "@", '');
    }else{
      found = false;
      for(j = 0; j < attribs.length; j++){
        split = attribs[j].split("~");
        if(split[0] == as[0]){
          aa = aa.replace(ao2 + "@", a + "@");
          found = true;
          break;
        }
      }

      if(!found)
        aa = aa + a + "@";
      ao2 = a;
    }
  }else if(index == 3){
    a = document.ProductForm.attrib3.value;
    as = a.split("~");

    if(a == 'select'){
      io = aa.indexOf(ao3);
      if(io != -1)
        aa = aa.replace(ao3 + "@", '');
    }else{
      found = false;
      for(j = 0; j < attribs.length; j++){
        split = attribs[j].split("~");
        if(split[0] == as[0]){
          aa = aa.replace(ao3 + "@", a + "@");
          found = true;
          break;
        }
      }

      if(!found)
        aa = aa + a + "@";
      ao3 = a;
    }
  }else if(index == 4){
    a = document.ProductForm.attrib4.value;
    as = a.split("~");

    if(a == 'select'){
      io = aa.indexOf(ao4);
      if(io != -1)
        aa = aa.replace(ao4 + "@", '');
    }else{
      found = false;
      for(j = 0; j < attribs.length; j++){
        split = attribs[j].split("~");
        if(split[0] == as[0]){
          aa = aa.replace(ao4 + "@", a + "@");
          found = true;
          break;
        }
      }

      if(!found)
        aa = aa + a + "@";
      ao4 = a;
    }
  }else if(index == 5){
    a = document.ProductForm.attrib5.value;
    as = a.split("~");

    if(a == 'select'){
      io = aa.indexOf(ao5);
      if(io != -1)
        aa = aa.replace(ao5 + "@", '');
    }else{
      found = false;
      for(j = 0; j < attribs.length; j++){
        split = attribs[j].split("~");
        if(split[0] == as[0]){
          aa = aa.replace(ao5 + "@", a + "@");
          found = true;
          break;
        }
      }

      if(!found)
        aa = aa + a + "@";
      ao5 = a;
    }
  }else if(index == 6){
    a = document.ProductForm.attrib6.value;
    as = a.split("~");

    if(a == 'select'){
      io = aa.indexOf(ao6);
      if(io != -1)
        aa = aa.replace(ao6 + "@", '');
    }else{
      found = false;
      for(j = 0; j < attribs.length; j++){
        split = attribs[j].split("~");
        if(split[0] == as[0]){
          aa = aa.replace(ao6 + "@", a + "@");
          found = true;
          break;
        }
      }

      if(!found)
        aa = aa + a + "@";
      ao6 = a;
    }
  }else if(index == 7){
    a = document.ProductForm.attrib7.value;
    as = a.split("~");

    if(a == 'select'){
      io = aa.indexOf(ao7);
      if(io != -1)
        aa = aa.replace(ao7 + "@", '');
    }else{
      found = false;
      for(j = 0; j < attribs.length; j++){
        split = attribs[j].split("~");
        if(split[0] == as[0]){
          aa = aa.replace(ao7 + "@", a + "@");
          found = true;
          break;
        }
      }

      if(!found)
        aa = aa + a + "@";
      ao7 = a;
    }
  }else if(index == 8){
    a = document.ProductForm.attrib8.value;
    as = a.split("~");

    if(a == 'select'){
      io = aa.indexOf(ao8);
      if(io != -1)
        aa = aa.replace(ao8 + "@", '');
    }else{
      found = false;
      for(j = 0; j < attribs.length; j++){
        split = attribs[j].split("~");
        if(split[0] == as[0]){
          aa = aa.replace(ao8 + "@", a + "@");
          found = true;
          break;
        }
      }

      if(!found)
        aa = aa + a + "@";
      ao8 = a;
    }
  }else if(index == 9){
    a = document.ProductForm.attrib9.value;
    as = a.split("~");

    if(a == 'select'){
      io = aa.indexOf(ao9);
      if(io != -1)
        aa = aa.replace(ao9 + "@", '');
    }else{
      found = false;
      for(j = 0; j < attribs.length; j++){
        split = attribs[j].split("~");
        if(split[0] == as[0]){
          aa = aa.replace(ao9 + "@", a + "@");
          found = true;
          break;
        }
      }

      if(!found)
        aa = aa + a + "@";
      ao9 = a;
    }
  }

  document.ProductForm.attribs.value = aa;
  var image = document.ProductForm.iid.value;

  var q = document.ProductForm.quantity.value;
  doAjax("/Product.do?method=prodAttrib&n=" + node + "&g=" + pg + "&a=" + aa + "&i=" + image + "&q=" + q + "&uid=" + new Date().getTime(), setProdAttrib); }

Here's to hoping that at least their server-side stuff isn't hard-coded to 10 attributes per product...

[Advertisement] BuildMaster is more than just an automation tool: it brings together the people, process, and practices that allow teams to deliver software rapidly, reliably, and responsibly. And it's incredibly easy to get started; download now and use the built-in tutorials and wizards to get your builds and/or deploys automated!

http://thedailywtf.com/articles/a-perfect-10


Метки:  

Pass By NullPointer

Среда, 17 Декабря 2014 г. 14:00 + в цитатник

Maxime was having difficulty viewing a website with the NoScript add-on installed to her web browser. It wasn't a huge surprise - some websites just don't work right with NoScript running, but it was a surprise when her browser displayed Java exceptions. Enabling JavaScript made the error page go away, but what? Lack of JavaScript causing Java exceptions!?

She viewed the page source and found that the server expects an "innerCHK" parameter, perhaps some kind of session or security token, to be passed in via URL query string. If it isn't provided, the server returns an error page displaying a java.lang.NullPointerException. Fortunately the front-end developers concocted this brillant snippet of JavaScript to resolve this issue:

// Error check
if (document.body.innerHTML.indexOf('java.lang'+'.NullPointerException') != -1){   
   if (document.location.href.indexOf('innerCHK=') == -1){    
        document.location.href = document.location.href + "&innerCHK=" + Math.random()*10000 ;
   }
}
// End of check

That only scratches the tip of the iceberg; the page is loaded with anti-patterns, reinvented wheels, spare reinvented wheels, and flat reinvented wheels, all held on with duct tape. For a taste of some bizarre string conventions and the developers' pet anti-pattern of closing scripts only to open a new one on the next line, look at how Dojo is imported. Please take note that Dojo's cookie library is imported.

     
 

Some, but not all, of the CSS references are handled in this manner which I found at least three (identical) times in the source. Yet again, Dojo.cookie is imported.

http://thedailywtf.com/articles/pass-by-nullpointer


Метки:  

CodeSOD: JSON at Crystal Lake

Вторник, 16 Декабря 2014 г. 14:00 + в цитатник

Trevor found an unusual bug. Every customer had a GUID, but for some reason, their JSON API failed if there were ever more that 75 results.

He checked the web layer, only to find that it didnt actually build the JSON- it just returned a string. The string itself came from their Oracle database. Thats where this procedure came from:

create or replace PROCEDURE GET_CUSTOMERS
(
  InCustomerGuid IN VARCHAR2,
  OutCustomerGuidArray OUT VARCHAR2,
  OutResult OUT NUMBER,
  OutResultMessage OUT VARCHAR2
) AS
  vCustomerGuidArray VARCHAR2(4000);
  vCustomerGuid VARCHAR2(40);
BEGIN
  OutResult := 0;
  OutResultMessage := NULL;

  vCustomerGuid := UPPER(RTRIM(LTRIM(InCustomerGuid, '{'), '}'));
  
  IF( InCustomerGuid IS NOT NULL )
  THEN
    SELECT '{"keys":[{"key":"' || Customer_Guid || '","type":"CUSTOMER"}]}'
    INTO vCustomerGuidArray
    FROM Customers
    WHERE Customer_Guid = vCustomerGuid;      
  ELSE
    vCustomerGuidArray := '{"keys":[';

    FOR Customer_Item IN (SELECT Customer_Guid FROM Customers) LOOP
      vCustomerGuidArray := vCustomerGuidArray || '{"key":"' || Customer_Item.Customer_Guid || '","type":"CUSTOMER"},';
    END LOOP;

    vCustomerGuidArray := RTRIM(vCustomerGuidArray, ',');
    vCustomerGuidArray := vCustomerGuidArray || ']}';
  END IF;
  
  OutCustomerGuidArray := vCustomerGuidArray;

  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      OutCustomerGuidArray := NULL;
      
    WHEN OTHERS THEN
    OutResult := 20000;
    OutResultMessage := 'too many customer guids to send back to caller';
    RETURN;

  COMMIT;
  
END GET_CUSTOMERS;



Like the Nintendo game, somebodys missing the point of JSON

Pick your WTF: generating JSON in the database, generating JSON by string concatenation , not being more careful about sizing a VARCHAR2 variable, or using Oracle.













[Advertisement] BuildMaster is more than just an automation tool: it brings together the people, process, and practices that allow teams to deliver software rapidly, reliably, and responsibly. And it's incredibly easy to get started; download now and use the built-in tutorials and wizards to get your builds and/or deploys automated!

http://thedailywtf.com/articles/json-at-crystal-lake


Метки:  

Woulda...Coulda...Shoulda

Понедельник, 15 Декабря 2014 г. 14:00 + в цитатник

Have you ever done something that seemed like a good idea at the time? Then looked back upon it much later and had second and third thoughts about the wisdom of what you had done?

A long time ago, Jack worked for a company that had built a goods-declarations system for freight-forwarders so that they could get the blessing of the government to import/export their goods.

Those were the days when DOS was the latest and greatest thing available for anyone who wanted quick development turnaround time. No big-iron, with all their rules, regulations and procedures for these guys. They needed their software written to their specifications to solve their problem in short order.

To this end, they had built a framework around the features available in DOS. One particular item in their framework was a "text box" into which one could type, ahem, text. Of course, like everything else in computer science, there was a practical limit on how big things could be. Since the screen was pretty full, the biggest number you could enter into this particular field was 99,999.99 (mostly as a limit of the maximum number of characters you could fit on a monitor).

Now this may have been fine and dandy for schooners and other such sailing ships. But, as ships got bigger, they could carry far more freight. The shippers made repeated requests to enlarge the input-field to enable them to enter bigger numbers.

Of course, this would involve several significant efforts:

  • Make the text box scroll so that bigger numbers could be entered
  • Change the size of the quantity field in the data file(s) to handle bigger numbers

The initial response back to the shippers was No; you can split that shipment of goods into multiple lots, and do separate customs-clearances for each lot.

After a while, the shippers got tired of doing multiple copies of the all of the customs paperwork for every shipment and insisted demanded that they be allowed to enter bigger numbers.

Rather than just do the work to allow bigger numbers to be entered, the managers came up with a scheme to enable bigger numbers to be represented in the same number of digits; they would create new units of measurement:

   1000 KGM = 1KK (Kilograms)
   1000 LTR = 1KL (Liters)
   1000 MTR = 1KM (Meters)
   1000 UNT = 1KU (Units)
   1000 PKG = 1KP (Packages)
   ...and so on

A convenient side effect of this was that since the names of all of the new units were exactly 3 characters long, they fit into the existing database units column.

The management proudly displayed their new capability to their customers, who promptly inquired WTF?!, which led to all sorts of time-consuming training to get them used to the new home-grown unit systems.

Once the shippers got used to it, things settled down. Until...

By multiplying everything by 1,000, some accuracy was lost as the numbers got bigger. For example, for a client to enter 12,345,675 litres of fuel, they had to enter 12,345.68 and change the units to 1KL. Naturally, the shippers were concerned about the extra 5 litres of fuel that were just added. It's a big ship; no one will worry about it! But then we'll need to pay duty on those extra 5 litres. In that case, do two customs entries, one for 12,345.67 x 1KL and one for 5 x LTR.

Again, the customers groaned about having to do multiple sets of paperwork.

But the customers didn't have the worst of it. The developers needed to write routines to convert those new units back to the real numbers before displaying them in reports.

Thus, after the countless hours wasted writing thousands of lines of code to handle custom units and convert back to normal units for reports, it would have been far more efficient time-wise, and substantially less effort to just make the original text box scroll and enlarge the field in the data files.

But it seemed like a good idea at the time.

Photo credit: trekkyandy / Foter / CC BY-SA

[Advertisement] Release! is a light card game about software and the people who make it. Order the massive, 338-card Kickstarter Edition (which includes The Daily Wtf Anti-patterns expansion) for only $27, shipped!

http://thedailywtf.com/articles/woulda-coulda-shoulda


Метки:  

Error'd: Good Help is Hard to Find

Пятница, 12 Декабря 2014 г. 14:00 + в цитатник

Daniel writes, "Looking for world class talent? Sorry...you won't be finding it here."

"Got this error message this morning after a fresh start up. It's Mozilla's crash reporter, but the details are secret," writes Dan.

I was looking for support for a crappy piece of kit that we use - so I searched for their forums. I was met with this," writes Lewis.

"When engineers were trying to diagnose a rare BSOD, they discovered that the bug check had shuffled off this mortal coil," wrote Matthew.

"Apparently Chrome is amazed by the Java update I was about to install," wrote Ruud B.

Collin wrote, "Local news station during the weather. The weatherman did well though, he announced that there was an error and they and he laughed and smiled until they went to commercial."

"I ordered a phone from the Verizon store a little while ago and noticed this on the order confirmation page. I recognized it as my home IP address," Nick writes, "Clicking the link did what you might expect - opened a new tab with the IP address as its address."

"I was trying to set up a Rails app on a VM and wanted to install the Mongo adapter and I got the wrong Mongo?" a puzzled Jordan R. wrote.

[Advertisement] Use NuGet or npm? Check out ProGet, the easy-to-use package repository that lets you host and manage your own personal or enterprise-wide NuGet feeds and npm repositories. It's got an impressively-featured free edition, too!

http://thedailywtf.com/articles/good-help-is-hard-to-find


Метки:  

CodeSOD: Polynomial Optimization

Четверг, 11 Декабря 2014 г. 14:00 + в цитатник

Marlschlag falsch&Schlingen

Rayer Ss co-worker exploded into his cube, beaming. Ive just optimized our processing loop. Ive gone from O(n2) to O(n)!

Thats amazing ! The processing loop in question was easily the most expensive part of the application, and Rayer had been spending too much time finding ways to squeeze a little performance out of it. How did you do it?

The original code looked something like this:

for(int i = 0; i < m; ++i) {
    for(int j = 0; j < n; ++j) {
    	process(target[i][j]); //this is really expensive
    }
}

It was a fairly standard nested loop operation.

Radar pulled the new version from source control to see his co-workers genius.

for(int i = 0; i < m * n; ++i) {
    process(*((target*)(&target) + i)); 
}

Radar complimented his co-worker on his understanding of C++ pointers, but had some negative things to say about his understanding of basic arithmetic.

[Advertisement] BuildMaster is more than just an automation tool: it brings together the people, process, and practices that allow teams to deliver software rapidly, reliably, and responsibly. And it's incredibly easy to get started; download now and use the built-in tutorials and wizards to get your builds and/or deploys automated!

http://thedailywtf.com/articles/polynomial-optimization


Метки:  

The Membrain

Среда, 10 Декабря 2014 г. 14:00 + в цитатник

Michael was annoyed. Their in-house package manager- software that everyone needed to do their jobs- was complaining about a missing file that had just existed a second ago.

No big deal. First step: close the program, then re-open.

Cell membrane drawing-en

Except the program didnt re-open properly. A new error appeared; a different file was missing. MainDatastore was a much more important file for their system, and its abscence was a Bad Thing™.

Then another error: Network path not found.

With a growing sense of dread, Michael poked his head out to see if anyone else was affected. Before he could ask the question, their exclamations answered him. Errors were being thrown, files were disappearing, network paths were going offline and online… and everyone knew exactly where the problem lay.

Whereas your average person might not know (or need to know) what specific physical hardware runs their applications or stores their data, whether its lurking in a local datacenter or sitting out in the cloud, there was no such abstraction or indirection at Michaels workplace. There was only the Membrain.

The Membrain was the solitary server that hosted all of the software and all of the data that made Michaels company work. The Membrain had been installed years ago and, aside from minor upgrades, it had been left untouched, lest a careless hand overturn the basket holding all of their eggs.

Michael and his co-workers rushed to the workroom. Even as they hustled, they asked: Were the hard drives dying?, Whats our recovery plan?, Where are the backup tapes?, When was the last backup?, Were they ever tested?, How much work are we about to lose?

There was no smoke, no server fire, nor any warning lights in the workroom. Just the Membrain and one of the cleaning staff, blocking the view of the corner where the Membrain lived, and a small stack of hard-drives had been laid neatly out on the table nearby.

The Membrain had a front panel that conveniently opened to the hard drives inside, which were easily removable, but not hot-swappable. The front panel had a lock, but it was never used, because no one should ever touch the Membrain.

The untouched Membrain had gathered a layer of dust. The cleaner had seen just too much dust, and decided to clean the rack. And one-by-one, the easily-accessible hard drives had been removed and dusted, because it was dusty and I saw dust inside, too.

The hard-drives were carefully returned, and after some diagnostics, the Membrain resumed its duties. The key for the lock was found stuffed in a managers drawer, and at last, the Membrain had its membrane secured.

[Advertisement] Release! is a light card game about software and the people who make it. Order the massive, 338-card Kickstarter Edition (which includes The Daily Wtf Anti-patterns expansion) for only $27, shipped!

http://thedailywtf.com/articles/the-membrain


Метки:  

CodeSOD: You Can't Fire Us Until We Quit

Вторник, 09 Декабря 2014 г. 16:30 + в цитатник

When one of Felix G’s newest design customers decided that they were officially unhappy with their current web-agency, another company's loss was his gain.

His first assignment was a simple one - remove the code that displayed the website’s creator credits (something like 'developed by xyz') from an external website.

What he found was the code below:

http://thedailywtf.com/articles/you-can-t-fire-us-until-we-quit


Метки:  

CodeSOD: Is Something Happening Right Now?

Понедельник, 08 Декабря 2014 г. 14:00 + в цитатник

Most programmers are familiar with a notion of technical debt. Sometimes all it takes to make or break a project is a single bad decision, questionable design solution, or even a plain old bug that doesn't get fixed early on. The hacks and workarounds keep piling up, slowly turning the project into an unmaintainable mess.

In this regard, David was already off to a head start. He has recently been assigned to maintain a meeting tracking system with – to put it lightly - a bit of history. A year before, the marketing department of his company received the first version from a subcontractor and promptly implemented it – only to find out that the data gathered were a little off. According to the reports, every single meeting lasted exactly 24 hours – from midnight to midnight.

The heads of Marketing found the sudden love for meetings hard to believe. David’s team took a quick look at the code and found out that the original developers used a date type for the columns representing the meeting’s beginning and end in the database – never bothering to store the actual time. David was a little stumped – how did this manage to pass even the most basic tests? – but sent it back for a fix and called it a day.

Fast forward a year later. The subcontracting company delivered a fixed version and promptly went belly-up, so it was up to David’s team to maintain the codebase. But while the original issue was fixed now, looking at the code made David wish it had never been the case…

Instead of converting the startTime and endTime columns to a proper type, the developer had a better idea – he added a startHour and endHour to the table. And just in case David’s office suddenly moves a few millions of timezones away, or makes contact with an alien civilization, they made the column a varchar2(64).

This odd design decision, however, had very interesting effects on other parts of the code. For example, this (single) line determines whether the meeting is happening now:

elseif(($this->meetings[0]['startDate']meetings[0]['endDate']>date('Y-m-d') || ($this->meetings[0]['endDate']==date('Y-m-d') && $this->meetings[0]['endTime']>date('H:i')))) || (($this->meetings[0]['startDate']==date('Y-m-d') && ($this->meetings[0]['startTime']meetings[0]['endDate']>date('Y-m-d') || ($this->meetings[0]['endDate']==date('Y-m-d') && $this->meetings[0]['endTime']>date('H:i'))))))) { //…

And this (again, single-line) query, aside from introducing a nice SQL injection vector, allegedly checks whether there’s an overlapping meeting:

'SELECT * FROM meetings WHERE id!='.$id.' AND (((startDate < ''.$start_date.'' OR (startDate =''.$start_date.'' AND startHour <= ''.$start_hour.''))) AND (endDate > ''.$end_date.'' OR (endDate =''.$end_date.'' AND endHour >= ''.$end_hour.''))) OR (((startDate > ''.$start_date.'' OR (startDate =''.$start_date.'' AND startHour >= ''.$start_hour.''))) AND (endDate < ''.$end_date.'' OR (endDate =''.$end_date.'' AND endHour <= ''.$end_hour.''))) OR (((startDate < ''.$start_date.'' OR (startDate =''.$start_date.'' AND startHour < ''.$start_hour.'')) AND ((endDate > ''.$start_date.'' OR (endDate =''.$start_date.'' AND endHour > ''.$start_hour.'')) AND (endDate < ''.$end_date.'' OR (endDate=''.$end_date.'' AND endHour<''.$end_hour.''))))) OR (((startDate > ''.$start_date.'' OR (startDate = ''.$start_date.'' AND startHour > ''.$start_hour.'')) AND ((startDate < ''.$end_date.'' OR (startDate = ''.$end_date.'' AND startHour < ''.$endHour.''))) AND ((endDate > ''.$end_date.'' OR (endDate = ''.$end_date.'' AND endHour > ''.$end_hour.'')))))';

"All I could do," says David, "was to replace the concatenation with placeholders. I still don’t know what exactly it does, other than making me tremble."

Photo credit: stockerre / Foter / CC BY

[Advertisement] Release! is a light card game about software and the people who make it. Order the massive, 338-card Kickstarter Edition (which includes The Daily Wtf Anti-patterns expansion) for only $27, shipped!

http://thedailywtf.com/articles/is-something-happening-right-now-


Метки:  

Error'd: We're Not in Kansas Anymore

Пятница, 05 Декабря 2014 г. 14:00 + в цитатник

"After signing up to search for jobs at Comcast, I check out their locations map and wondered when Nebraska annexed Kansas," Herb wrote.

"Not an error? Really?!" wrote Kirk R.

"McDonald's Australia is running a Monopoly based promo," writes Tim B., "In keeping with that theme, the entry page uses this cunning anti-bot technique."

"I hope the Dummy department has enough staff to answer in reasonable time!" wrote Fr'ed'eric Q.

Scott T. writes, "When it's this hot, humidity doesn't even matter."

"More proof that the line between computers and humanity continues to blur," wrote Ben.

Louise L. wrote, "I'm sure I could squeeze out many hours of fun on this calculator thing."

Michael W. writes, "Stop referencing the Null Pointer, Oracle!"

http://thedailywtf.com/articles/we-re-not-in-kansas-anymore


Метки:  

The Robot Guys

Четверг, 04 Декабря 2014 г. 14:00 + в цитатник

Business was booming during the formative years of SuperbServices, Inc. It was a blessing and a curse; like any startup, there was more work to do than people to do it. Telling the sales team to be less successful wasnt an option, so the tech team had to adapt.

The CEO of SuperbServices tasked Roland with a major initiative that would save the company, or at least their sanity. We need to automate all of this processing work, so we can focus on service delivery!, the CEO said. Our value proposition is our services, and everything else is busy work. We need to automate that, and thats where you come in. I need you to engage the Robot Guys to work on automating everything: operations approvals, purchasing, money transfers, client emails, everything!

The… Robot Guys?

Roland found a new level of dread. Their server team was unusually colorful, even by the standards of the industry. Only a handful of people had ever seen them, and Roland had only heard strange rumors.

When Roland knocked on the door to the server room, an overhead security camera blinked to life and a robotic voice rumbled, WHAT DO YOU SEEK?

Uh, hi. This is Roland, a project manager. Im supposed to work with you guys, or whatever you are, on automating some tasks?

WHAT DO YOU OFFER US? the ominous metallic voice shot back.

Ummm… do robots like donuts? I brought some. Its all I have.

PROCEED. The electronic lock released the door with a thunk. Roland pulled the door open, and arctic air hissed out. Inside, were thousands of blinking lights and rack mounts, and a small table. A light flicked on above the small table. PLACE THE OFFERING THERE, the automaton said from the shadows.

Roland placed the box of donuts on the table and backed away slowly. THANK YOU! the voice shouted from behind him. Roland jumped. A scrawny man with a voice modulator giggled and helped himself to a donut.

Hey, Roland, Im Roy, he said, setting the voice modulator aside. We dont get many visitors, so we like to mess with them when we do. Youre looking for some automation, eh?

Roland was surprised by how normal Roy was, now that he had revealed himself as an actual human being. Yes, well, the CEO was saying you do a lot of work with robotics, and that we should use those robots to automate as many tasks as we can. Roland laid out the objectives and specifications.

Roy sighed. I hate to disappoint you, but we dont actually do anything with robots, despite what the CEO thinks. He insists that Ruby is the name of a robot, but its just a programming language. But we can automate most of this. Give us two weeks, all the donuts and energy drinks we can handle, and itll be done before you know it.

For the next two weeks, Roland dropped off the required offerings in exchange for status updates and feature demos. Roy and his other Robot Guys hacked away, and soon the pile of paperwork that kept everyone busy upstairs had migrated down to a handful of servers in the basement. Roland made sure the Robot Guys got most of the credit, but the CEO gave him high acclaim.

Roland, masterful job getting those machines to manipulate the pulleys and levers that make our business work. The CEO slapped him on the back. Your reward is a new project- another top-priority project. Our finance team cant handle the transaction volume. Ive talked to the CFO and she wants you and the Robot Guys to build automation around a new product weve purchased, MoneyWorx. Dont let me down!

Roland went back to the server room. Given how easy the last automation project was, this should be the same, right? He showed Roy the requirements.

Roys monitor-tanned skin turned even paler than Roland thought humanly possible. This is bad, very bad! Danger! Roy shouted. He waved his arms in consternation. Its not MoneyWorx, its MoneyDoesntWorx. Even when the services are working, they require RSA-SecurID tokens- someone has to manually enter a code.

Manual? So someone has to be on call to make this work?

Yeah. We have three SecurID tokens, so normally, when MoneyWorx wants a new code, wed have three people on call.

Thats really not going to work. If people have to be getting late night phone calls to keep financials happening, the CEO is going to be pissed. And the CEOs already signed the contract- we have to make this work without anybody being on call.

Roy cracked open an energy drink and shuddered. Give me the weekend to think about it. And Im going to need more of these. He shook the can. And more of those. He pointed at the donut box.

Roland popped by on the weekend to drop off his offerings. Roy accepted them, but said nothing. The Robot Guys were too busy to talk. When Monday rolled around, Roland arrived with extra donuts and energy drinks. Eureka! Roy exclaimed as soon as Roland entered. Let me show you our masterpiece!

The master-piece was an empty donut box, stood on end. The RSA-SecurID tokens were taped to the box. The entire arrangement was set in front of a cheap webcam. When MoneyJerks demands a fresh two-factor token, somebody can remote into this machine, check the tokens, and enter the correct code.


Dont you think we should password protect this box? Roland suggested.

Do you think the users are going to remember how to log in? Roy countered.

It was possibly the dumbest idea that Roland had ever heard, but he ran it upstairs. In the CEOs office, Roland demoed the solution. After he logged off of the web-cam machine, he cringed, expecting a fit.

This is brilliant! Theyve set their robots eyes on these doohickeys, and now anybody in the company can tell MoneyWorx what to do! Top-notch work, Roland. Congratulate the robot guys for me. Their robot is amazing.

Roland was happy the job was done, but he couldnt shake the feeling that hed made a terrible mistake. The companys financial security rested in the hands of a cheap web-cam with absolutely no protection besides not having a public IP.

When disaster finally did strike, it didnt come in the form of fraudulent transaction. The donut box fell over, late on Friday night. Roland had to call Roy, who had to commute into the office to stand the box back up. After doing some root cause analysis, Roy also taped the box to a server rack, thus guaranteeing continual uptime.

http://thedailywtf.com/articles/the-robot-guys


Метки:  

Поиск сообщений в rss_thedaily_wtf
Страницы: 124 ... 18 17 [16] 15 14 ..
.. 1 Календарь