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

Поиск сообщений в 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 ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

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

CodeSOD: An Incomparable Event

Четверг, 26 Июля 2018 г. 13:30 + в цитатник

Sandra’s ongoing battles continue. She currently works for Initrovent, and is doing her best to clean Karl’s dirty fingerprints off their event-planning codebase.

Now, as it turns out, Karl wasn’t their only developer. Another previous developer was a physicist who knew their way around APL and Fortran, then decided to follow the early 2000s money and became a self-taught web developer.

This Einstein decided to solve some problems, common problems, utility problems, the kind of things you might want to put in your central library and reuse in every project.

For example, do you hate comparisons? Does writing if ($x == $y)… make your skin crawl? Don’t you just wish you could write something like, compareValues($x, $y, '==') instead?

Well, have I got news for you.

/**
 * Compares two operands with an operator without using eval. Throws exception
 * of operator is not found.
 * @param mixed  $op1      Operand 1
 * @param mixed  $op2      Operand 2
 * @param string $operator Operator (==, !=, <=, >=)
 * @return bool
 */
function compareValues($op1, $op2, $operator) {
    switch ($operator) {
        case '==': return $op1 == $op2;
        case '!=': return $op1 != $op2;
        case '>=': return $op1 >= $op2;
        case '<=': return $op1 <= $op2;
        default:
            throw new Exception('Operator is not handled: ' . $operator);
    }
}

Now, this particular snippet isn’t the worst thing on Earth, and it actually has a potential use- you might need to decide which operator to compare using, and store it in a variable.

What we really need is a way to route around PHP’s type system. This method does exactly that, but instead of being placed in a central library, it’s copy/pasted in five different places across multiple projects with slightly differing implementations.

    function compareValues($data1, $operator, $data2, $type) {
        if (!$operator)
            return false;
        if ($operator == '=')
            $operator = '==';
        switch ($type) {
            case 'date':
                if (is_array($data1)) {
                    $data1 = $data1['year'] . "-" .
                            $data1['month'] . "-" . $data1['day'];
                }
                if (is_array($data2)) {
                    $data2 = $data2['year'] . "-" .
                            $data2['month'] . "-" . $data2['day'];
                }

                $data1 = strtotime($data1);
                $data2 = strtotime($data2);
                if (empty($data1))
                    return 'empty';
                if (empty($data2))
                    return 'empty';
                return eval('return (' . $data1 . $operator . $data2 . ');');
                break;
            case 'time':
                if (empty($data1))
                    return 'empty';
                if (empty($data2))
                    return 'empty';
                $data1 = (int) str_replace(':', '', $data1); //removing ':'
                $data2 = (int) str_replace(':', '', $data2);
                return eval('return (' . $data1 . $operator . $data2 . ');');
                break;
            case 'money':
                if (empty($data2) || $data2 == 'null') {
                    return 'empty';
                }
                if ($this->options['Request_currency'] != $this->options['Proposal_currency']) {
                    return false;
                }
            default:
                if (empty($data1) && $data1 !== 0)
                    return 'empty';
                if (empty($data2) && $data2 !== 0)
                    return 'epmty';
                if (!is_numeric($data1))
                    $data1 = ''' . $data1 . ''';
                if (is_string($data2))
                    $data2 = ''' . $data2 . ''';
                return eval('return (' . $data1 . $operator . $data2 . ');');
        }
    }

What a nice bit of defensive programming, ensuring that there’s a valid operator. And what a lovely pile of confusing code that may return true, false or FILE_NOT_FOUND empty. Or, sometimes, “epmty”. Bonus points for doing some of the comparisons using eval, thus allowing a code-injection attack. Einstein must have recognized this was bad, because some of the copy/pasted versions of this method instead called the first version of compareValues to avoid using eval.

But I know what you’re thinking. You’re thinking, “This is great stuff, but what good is having in PHP? This is 2018, and we’re writing operating systems in JavaScript now.” Well, don’t worry. This same method has a JavaScript version.

/**
 * compares two values
 *
 *  @fieldId
 *  @operator
 *  @compareData
 *
 */

function compareValues(data,operator,compareData,type,fieldId){
    if(!operator) return;
    if((data == "" || data == null) && (compareData != "" && compareData != null))
        good = false; //when the data is im
    else{
        switch(type){
            case 'date':
                //changing the values to numeric strings
                if(data.constructor == Array){
                    date1 = String(data[0])+String(data[1])+String(data[2]);
                }else{
                    date_arr = String(data).split("-");
                    if(date_arr[0].length == 2){ //swapping the order of the date-string (in case it's wrong)
                        date1 = String(date_arr[2]+date_arr[1]+date_arr[0]);
                    }else
                        date1 = String(data).replace(/-/g,"");
                }
                if(compareData.constructor == Array){
                    date2 = String(compareData[0])+String(compareData[1])+String(compareData[2]);
                }else{
                    date_arr = String(compareData).split("-");
                    if(date_arr[0].length == 2){ //swapping the order of the date-string (in case it's wrong)
                        date2 = String(date_arr[2]+date_arr[1]+date_arr[0]);
                    }else
                        date2 = String(compareData).replace(/-/g,"");
                }
                if(date1.length != 8 || date2.length != 8) //8 is the length of the number 'yyyymmdd'
                    return;
                good = eval(date1+operator+date2);

                break;
            case 'money':
                if (window.Request_currency != window.Proposal_currency)  {
                    good = false;
                    break;
                }
            default:
                if(IsNumeric(data)){
                    good = eval(data+operator+compareData);
                }else {
                    // Compare as strings
                    good = eval('''+data+'' '+operator+ ' ''+
                        compareData+''');
                }
        }
    }
    if(good){
        $('#'+fieldId+'_ico').addClass('icons__check');
        $('#'+fieldId+'_ico').removeClass('icons__caution_sign');
    }else{
        $('#'+fieldId+'_ico').addClass('icons__caution_sign');
        $('#'+fieldId+'_ico').removeClass('icons__check');
    }
}

Like all good spaghetti code, this one is topped with a sauce of global(window) variables, and mixes logic with DOM/UI manipulations. And thank goodness for all those regexes.

The JavaScript version is attempting to create good from eval, which never works, and it breaks the D&D alignment chart.

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/an-incomparable-event


Метки:  

Finding Your Strong Suit

Среда, 25 Июля 2018 г. 13:30 + в цитатник

Anyone with more than a few years of experience has been called upon to interview candidates for a newly opened/vacated position. There are many different approaches to conducting an interview, including guessing games, gauntlets and barrages of rapid-fire questions to see how much of the internet the candidate has memorized.

PositiveFeedbackVicious.png
By DavidLevinson

The best approach is usually just having a friendly conversation as it gives the candidate a chance to illustrate their experience via relating war stories, or shoot themselves in the foot with easily catchable lies.

Tim C. was trying to find a mid-level C# developer to develop games. One guy came in and seemed fantastic- Bert. Bert had done a lot of work with 3D graphics and game development, and was strong on the mathematics of 3D rendering, and the intricacies of the various 3D rendering engines. He was able to explain all the concepts of light sources, shading, and so forth in easy-to-understand terms. He was obviously passionate about programming and was maintaining six open source projects on GitHub, mostly related to 3D work. The strong mathematical background was seen by Tim as a good sign, because their company is all about algorithms.

In an attempt to get at something that would give an indication of Bert's skill, Tim asked to see some of his source-code. Bert picked one of his open source projects at random and showed Tim a C++ header file.

"Headers are fine, but can I see some implementation?" Tim wanted to see some meaty algorithmic code and so asked to see his most complex source file. He showed something which looked like a file full of wrappers (of some 3D rendering library); there wasn't any actual real work being done in there.

At this point, Tim reasoned that asking to see some specific code structures, like classes or even conditionals might get the desired sample work, so he asked to see a file that had some loops in it.

"Oh, this project doesn't have any loops in it."

Tim asked to see a project that did, Bert umm'd, ahh'd and eventually found one of his six open source projects that had a loop. He said apologetically "loops are not my strong point".

While it's extremely reasonable that a candidate might not know the details of some function call in some library, it's equally unreasonable for them to admit to not knowing what is maybe the third thing they teach you in CS-101.

On that point alone, Tim and peers decided not to hire him.

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/finding-your-strong-suit


Метки:  

Announcements: Come Work at Inedo, the Most Non-WTF Company You Know

Вторник, 24 Июля 2018 г. 17:30 + в цитатник

The "Enterprise DevOps" tools market has really been taking off lately, and so has Inedo! We build market-leading tools for package management, deployment automation, and configuration automation space that aids some of the world's best companies in delivering their applications to users faster than ever.

We're looking for some great people to help us continue to grow:

  • Solution Architect/Consultant – work closely with our users to help them adopt DevOps best practices in their organization using our tools
  • Software Development Manager – lead our software development team and help develop our innovative products
  • Software Developer – Build and maintain our products, extensions, and internal systems while identifying bugs and issues with our customers
  • Content creator/writer – communicate the business value aspects of what we do to customers by working closely with our technical teams
  • US events manager – lead our events team and particulate in Inedo and software communities
  • Marketing associate – travel to various events to meet users and introduce new people to Inedo

This is a great opportunity to join a fast-growing but stable company, without all the uncertainty, stress, and unpredictability of a typical start-up. Actually, we're not at all like a San Francisco Startup, and we're proud of that. We're driven by enthusiastic customers who get excited about our next release, not by venture capitalists who are always pushing for that next series of investment.

We work hard, but more importantly, we work smart. This means not only eschewing buzzword-driven development and hacking-till-it-works, but we really focus on making a smart work/life balance a big part of our culture. Release dates are very important, but if it's still not ready at 6PM, chances are whatever gets shipped at 10PM will make life worse for everyone, including our users, who will then have to stay up late to deal with our sloppy software. Instead, we come up with a new plan at 4PM, which usually involves waiting a day or two, notifying users who might expect it, and re-planning other things accordingly.

Some call our work/life culture a "Midwest thing", which makes sense because we're based in Cleveland, Ohio. Not only are the people here friendly – we actually smile and say hi to passerbys – but it's a wonderful place to live, work, and play, whether you're raising a family or single:

  • Greater Cleveland is super affordable compared to other major cities in America.
  • The food and brewery scene is booming, with award winning restaurants opening all across town.
  • We boast three professional sports teams (yes, the Browns are professionals), and have had appearances in both the NBA finals and MLB world series in the last year.
  • Experience the joy of all four seasons! Actual. Seasons. One lasts a little longer than the others, but when you have patio season to look forward to, it's an easy sacrifice.
  • The Cleveland Metroparks spans more than 23,000 acres and has 300+ miles of trails, eight golf courses, eight lakefront parks (one of which is a few minutes walk from our office) and a nationally-acclaimed zoo.
  • Playhouse Square is the second largest theater district in the United States, and attracts more than one million guests per year to its 1,000+ annual events.

And of course, we'll gladly help you with relocation to Cleveland. A lot of our team has already relocated here and absolutely loves it.

If none of the openings are a good fit for you now, not to worry; we'll be posting more soon! In the meantime, please share with friends and family.

[Advertisement] Ensure your software is built only once and then deployed consistently across environments, by packaging your applications and components. Learn how today!

https://thedailywtf.com/articles/come-work-at-inedo-the-most-non-wtf-company-you-know


Метки:  

You'd Need an Oracle to Understand These Docs

Вторник, 24 Июля 2018 г. 13:30 + в цитатник

Documentation is difficult in the best of situations. I've encountered lots of bad documentation. Bad because it's unclear, inaccurate, or incomprehensible. Bad because it's non-existent. Bad because it insists on strictly using the vendor's own in-house terms, carefully chosen to be the most twee little metaphors they could imagine, but never explains those terms, thus being both incomprehensible and infuriating. "Enterprise" packages bring their own quirks and foibles, and tend to be some combination of unclear, inaccurate, or incomprehensible. Unless, sometimes, what we attribute to incompetence probably is actual malice.

An augur, sitting on the hilltop, predicting the future

I've brushed up against a lot of ERP systems in may day, ranging from the home-(over)-grown Excel spreadsheet on the network drive all the way to gigundous SAP build-outs.

On such project involved migrating 12 business units from a mixture of home-grown systems, legacy mainframe systems, and home-grown systems running on legacy mainframes into one, single, cohesive ERP. The product chosen was an offering from a company we'll call "Augur". Augur took one look at our insanely ambitious project, knew it was doomed to failure, and muttered to themselves, "Think about the consulting fees we can rack up!"

Of course, my employer didn't want to pay the consulting fees. They already had Augur domain experts hired in from a much cheaper consultancy, and our in-house developers knew how to read documentation. What could go wrong?

Plenty, but one of the smaller, simpler tasks I tackled delivered the biggest WTF. In a factory, there was a flow meter hooked up to a pipe that could tell us how much raw material flowed through that pipe. That flow meter was hooked up to a proprietary database with a very picky and flaky ODBC driver. I needed to get data out of the proprietary database and pass it off, after a little massaging, to Augur's ERP. Based on whatever product the ERP believed was being made at the time, it would then calculate raw material consumption, cost-of-goods-sold (COGS), losses, and all sorts of other wonderful production statistics.

Talking to the proprietary database involved some DLL hell, but once I was getting the data, it was time to feed it into Augur. The documentation for their consumption APIs said that I should call a method called RM_CONS_IN_FRMLU_FPT. It told me how to structure the data. It told me what other parameters needed to be set. I followed the instructions and checked the results: consumption got updated, but not COGS.

I checked my work. I rechecked the documentation. I skimmed through the underlying tables to understand the schema hiding beneath the API. I cried a little when I saw it, and then I went back to the docs. I twiddled a few parameters, and tried again. This time COGS was right, but consumption wasn't. Tried again, and now it refused to recognize the current production formula, and assumed I was just disposing of material, and only incremented my losses.

Eventually, I discover that RM_CONS_IN_FRMLU_FPT is actually a wrapper method for RM_FPT_CONS_BY_UT. I have to bootstrap a few more complex parameters myself, but I try again. Still doesn't works. Back to the docs, and then I notice a tiny little footnote: "To calculate COGS accurately, the parameter rec_cons_config must have its cogs_behavior property set to 57". So I tried that.

It crashed. It didn't just crash, though, it managed to go romping off down a bad code branch, mangled a bunch of records, committed the changes, and then crashed. I reset my dev environment and went back to the docs.

This time, I trace through a few references, discover another footnote which is itself reference to a white paper, which itself contains a footnote. "If cogs_behavior is set,RM_CONS_BY_UT,RM_CONS_IN_FRMLU_FPT,RM_CALC_FRMLUandCOGS_RM_CALC_USAGE may alter data in an unrecoverable fashion."

Now, Augur's database technology separates the header for a code package from the body. This is great for Augur, as they can distribute the compiled versions of their proprietary stored procedures, but not the code. That was less great for me, as I couldn't just read the code to see what it was doing, but I could read the headers.

And there were so many undocumented parameters, each using undocumented record data types- Augur's equivalent of a struct. Tracing through the headers, I eventually found that there was a flag which was, for all intents and purposes, the secret_make_cogs_work_flag. I flipped that to true, and voila, suddenly everything was calculating.

I can't say, beyond a shadow of a doubt, that the documentation lied to me. It could have been wrong, outdated, or I could have just misread things. But given the problem- a major feature doesn't work or even destroys data- and given the simplicity of the fix, I can't see it as anything but an active attempt to mislead.

"Never attribute to malice what could be explained by incompetence- unless it's a major enterprise product vendor, in which case they really just want to sell you consulting."

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!

https://thedailywtf.com/articles/you-d-need-an-oracle-to-understand-these-docs


Метки:  

NoeTimeToken

Понедельник, 23 Июля 2018 г. 13:30 + в цитатник

Bozen 1 (201)

"Have you had a chance to look at that JIRA ticket yet?"

Marge debated pretending she hadn't seen the Slack message yet—but, if she did, she knew Gary would just walk over to her desk and badger her further. In truth, she didn't want to look at the ticket: it was a low priority ticket, and worse, it only affected a small fraction of one client's customers, meaning it was likely to be some weird edge case bug nobody would ever run into again. Maybe if I ignore it long enough, it'll go away on its own, she thought.

The client was a bookseller with a small but signifigant-to-them online presence; the software they used to sell books, including your standard e-commerce account functionality, was made by Marge's company. The bug was somewhere in the password reset feature: some customers, seemingly at random, were unable to use the password reset link the software emailed out.

Marge pulled up the ticket, looking over the half-hearted triage work that had been done before it landed on her desk to solve. The previous guy had pulled logs and figured out that all the customers who were complaining were using the same ISP based out of Germany. He'd recommended reaching out to them, but had been transferred to another division before he'd gotten around to it.

When Marge realized that the contact information was all in German, she almost gave up then and there. But with the magic of Google Translate, she managed to get in touch with a representative via email. After a bit of back and forth, she noticed this gem in one of his (translated) replies:

We want to display mails in our webmail client as close to the original as possible. Since most mails are HTML formatted, the client supports the full HTTP protocol and can display (almost) all HTML tags. Unfortunately, this means that "evil" JS-Content in such mails can do all kinds of stuff in the browser and therefore on the customer's PC.

To avert this, all mails are processed by a "SafeBrowsing"-module before they are displayed, to recognize and circumvent such manipulations. One of those security measures is the recognition of js-modules that begin with "on...", since that are mostly js functions that are triggered by some event in the browser. Our "countermeasure" is to just replace "on..." with "no..." before the HTML content is sent to the rendering process.

Marge frowned at the answer for a bit, something nagging at her mind. "There's no way," she murmured as she pulled up the access logs. Sure enough, the url for the reset link was something like https://bookseller.com?oneTimeToken=deadbeef ... and the customers in question had accessed https://bookseller.com?noeTimeToken=deadbeef instead.

A few lines of code and it was resolved: a conditional would check for the incorrect query string parameter and copy the token to the correct query string parameter instead. Marge rolled her eyes, merged her change into the release branch, and finally, at long last, closed that annoying low-priority ticket once and for all.

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/noetimetoken


Метки:  

Error'd: Upon Reaching a Certain Age...

Пятница, 20 Июля 2018 г. 13:30 + в цитатник

"Evidently, once you hit 55, LinkedIn thinks you'll age until your buffer overflows," writes Jonathan L.

 

"I started out looking for shower gel, but now, thanks to Google, I'm considering if a GBIC in Cadet Blue is worth the extra money," writes Robin M.

 

Matthew B. wrote, "So, an article about AI shows that the AI behind generating the summary rasied an exception. Maybe the AIs aren't speaking to each other?"

 

"Wait...did I just fail a Turing Test?" writes Daniel.

 

Rob J. wrote, "I got a 2 on a vision test but apparently only people from Krypton or blind people test on it, because there were very large negative and positive scores."

 

Pieter V. writes, "Thankfully this combo error didn't occur on the plane I took."

 

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/upon-reaching-a-certain-age


Метки:  

Classic WTF: Flawless Compilation

Четверг, 19 Июля 2018 г. 13:30 + в цитатник
Just today I was joking with my co-workers: I had written software for which we had no viable test hardware, but the code compiled, therefore I was done. The difference is I was joking… --Remy (Originally)

Back in the heady days of Internet speculation, the giant retailer JumboStores contracted with Fred’s software company, TinyWeb, to develop the region’s first web-based supermarket. Customers would be able to assemble carts online and receive their groceries the next day.

The virtual supermarket had to communicate with JumboStores’s inventory system in real-time. The former was bleeding-edge web technology, the latter a cobweb-laden mainframe with no external point of access.

“How will we get around this?” Fred asked early in the specification process.

“We can stage an intermediate server.” Nick, a programmer from JumboStores IT, assured him around a mouthful of doughnut. “You guys send your requests there, we’ll write software to forward them to the mainframe and back.”
Engine overhauled
Fred was optimistic. Both companies were *nix shops; the JumboStores IT department were his geek kindred. Equally optimistic, JumboStores management scheduled a live media demo several months out, well after the estimated project completion date.

Deadlines slipped, as they are wont to do. The week before the big demo, the online supermarket still wasn’t ready. TinyWeb had implemented the website and database back-end, but JumboStores’ relay software lagged behind. At the urging of multiple strata of nervous managers, Fred took an emergency trip to JumboStores to investigate.

“We don’t know, man, we just don’t know.” The confident Nick of months prior shook now, leading Fred to his cubicle. “We coded the application. We debugged until it compiled without errors. When we run it- core dump!” He threw up his hands, then dropped into his swivel chair. “We’ve been pestering IBM support, but they haven’t been very helpful.”

“Well, why would they be?” Fred frowned, pausing at the cube threshold. “I mean, who knows what might be wrong with the code?”

“Nothing’s wrong with it. It compiles!”

“So? It could still have errors.”

Nick swiveled around to face him. “Dude. It compiles.

Fred faltered in the wake of Nick’s earnest insistence. “That… doesn’t mean the code is perfect.” He all but fell into the spare chair presented to him. “How do I explain this?” Am I actually trying to explain this? To a programmer? “Let’s say you’re building an engine.”

“This isn’t an engine,” Nick said. “It just passes-“

“No, a car engine! OK? You have all the parts spread out on the desk here.” He waved his arm out over a layer of branded cube toys and post-it notes. “You’ve never built an engine from scratch before, but you have a blueprint with pictures and directions, so you grab your wrench and your welder and whatever, and go to town. At the end, all the parts get used up, and the result looks vaguely engine-like. Still, would you expect to drop it under the hood and have it start up flawlessly the first time you turn over the ignition?”

Nick stared. “I… don’t see what this has to do with anything.”

Fred refrained from smacking his forehead. “Uh, OK. Forget the engine. It’s like sheet music. Just because all the dots are on the staff doesn’t mean it’s the song you want.“

“Dude! The compiler would bug out if there were any problems.” Nick graciously omitted the Duh.

Fred took one last chance. “No- it’s like, if you were building a house. Just because all the parts fit together doesn’t mean it will stand up.”

Nick’s face brightened. “It’s like the home inspector! I see what you mean."

“If that works for you…” Fred said, carefully.

After long consideration, Fred took the intermediate server back home to TinyWeb for some down-to-the-wire recoding, resulting in a flawless demo for the press. JumboStores was delighted.

With their collaboration at an end, Fred wondered how JumboStores IT would ever manage on their own.

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

https://thedailywtf.com/articles/classic-wtf-flawless-compilation


Метки:  

Classic WTF: The Mega Bureaucracy

Среда, 18 Июля 2018 г. 13:30 + в цитатник
Part of the reason we need a summer break is because we simply don't have the organizational skills of this particular company. I wonder if they sell consulting. Original -- Remy

Photo credit: 'digicla' at Flickr At my daytime corporate-type job, if I need to even sneeze in the general direction of a production environment, I need both a managerial and customer approvals with documentation solemnly stating that I thoroughly tested my changes and swear on a stack of MSDN licenses and O'Reilly books that I am NOT going to break anything as a result of my changes. Sure, the whole thing is a pain (and admittedly, a necessary evil), but what Bruce W. has to go through beats the pants off of anything I've ever had to go through.

For the most part, Bruce loves his job. He gets to work with a lot of intelligent and motivated people. He has been developing a new system to support a new product that has the possibility of earning his division several million dollars per year and saving the corporate parent several hundred thousand dollars per year. The net effect on the corporate parent's bottom line will be quite nice. He developed a Web front end while a fellow developer put together the data feeds. The initial development work was estimated to take about six weeks; pretty good since we only had eight weeks to work with.

However, Bruce works in a very large corporation (70,000 plus employees through out the US and several countries) and IT for the corporation has been highly centralized to the world headquarters. Smaller IT work, like the development and support for only a single division, isn't centralized but must pass through the central Mega Bureaucracy for approval and placement on the centralized servers.

...and Bruce needs their "help" to officially set up his environments.

You see, while Bruce and his group can test all day long on their local computers and servers, any kind of "live" environments must be created, blessed, and centralized by the Mega Bureaucracy. They're bigger, badder, and have more connections than anybody in your division's rank-and-file. Remember: in the Mega Bureaucracy, processes and procedures are to be followed, respected, and if necessary worshipped. Oh, and forget even thinking of installing Web services on one of the existing centralized servers. That would bring down the wrath of the entire blessed Bureaucracy for changing the purpose of an existing machine without first going through Mega Change Server Process.

Here's a brief overview of what Bruce had to go through to get four (one each for development, testing, staging, and production) Windows-based Web servers:

Week 1 - At the same time Bruce's group started the project he went to procure the servers. He was told that all he needed to do was put in a Service Request with the Windows Server Team and they would get what we needed. However, that request is cancelled because when the Windows Server Team saw that the servers were for a new application they said, "Whoa, you have violated rule #38,991 of the Mega Bureaucracy! New applications must go through the Process for Application Implementation and Navigation."

Bruce starts into the fill the first two PAIN forms (one being 20 pages long with 150 questions), sends them off to the server team, and immediately receives a response that, no, do not directly send PAIN forms to the group they go to. Instead, open a project with the Mega Bureaucracy's project tracking system, attach the forms and THEN assign the project to the group.

A few days later, he receives word that the project has been accepted, slotted, and a project manager assigned. Bruce figures, "Cool, now we are moving! I'll have my servers in no time!" He and his boss have a conference call with the PM and express to him the time critical nature of these servers. The PM agrees to push them forward saying that the request isn't complex and shouldn't take much effort.


Week 2 - Bruce receives the initial project estimate and immediately replies with his approval.


Week 4 - Bruce calls the PM to find out what's going on. He says that due to staffing cuts only a handful of requests are being processed at a time. Despite being reminded that this project is literally worth millions, he says that other projects are ahead of us and that this is simply how things are. Bruce boss escalates the issue to the head of IT for the entire division who just happens to be a member of the Project Approving Council and supposedly has the power to move the project forward.


Week 6 - Only three weeks until the promised delivery date, Bruce learns that the project still has not moved. His boss fires off a series of emails saying that the app is about to go live on a system that will earn the company millions of dollars that is running on a desktop machine sitting in a cubicle.


Week 7 - The system is now fully coded. Bruce is walking around, shaking his head, saying to himself "We have done user testing and end-to-end testing on a desktop machine-based server!"


Week 8 - The new system goes live and is serving dozens of customers daily. The difference between Production and Test environments is a Post-it Note. Power strips and network hub are carefully labeled "DO NOT TOUCH! HIGH VOLTAGE!" to prevent cleaning staff misfeance.


Week 10 - Bruce and the Windows Server Team finally have the project kick off meeting for the servers. About 15 of the 30 minute call was spent with Bruce repeatedly saying, "All I need is a Windows Server with IIS and .NET. I do not need a database server, no access to the mainframe, no massive SAN space, no Internet access, no interplanetary probe, just servers." "BUT", they say, "You stated on page 16, question 113 that your application uses a database. Where will that database come from?" Bruce explains again, "We are using existing databases assigned to our group. The database is outside of the scope of the project of setting up four Web servers."

Week 12 - Bruce and the Windows Server Team get together for their status meeting. The server team says they haven't budged since last meeting. Why? Everyone says, "Well, we're just waiting for the other shoe to drop and this becoming a big, complex, hairy project requiring massive time." Bruce once again states that all they he needs is four Web servers. Nothing more. The server design engineer says, "Wow, that is pretty simple. Shouldn't take too long at all."


Week 14 - Bruce has another status meeting with the PM and the server engineer. The engineer has put together the required diagram of the requested infrastucture and states that he only had to change a handful of things from the initial template. He says that everything should be ok and once they have the infrastructure readiness, the server builds can start. Bruce thinks, "Finally! All the other people initially assigned to the project must have realized that building four web servers isn't that big if a deal! ...haven't they?"


Week 18 - The head of IT for our division finds out that we are still waiting. Heads start rolling...even poor Bruce's. "WHY DIDN'T YOU CALL ME SIX %($$!*& WEEKS AGO???" the IT head blasts.


Week 19 - The servers are built (it only took 2 days to build them!) and are signed off for production support.

Week 20 - Bruce distributes the application URL pointing to the brand new servers.

Through all of this Bruce learned a couple things. First, don't even think of going around the Mega Bureaucracy, even if somebody says you can. The Mega Bureaucracy remembers and brands you a heretic. Second, if you think you will need help from the Mega Bureaucracy, start early, fill out all of the forms, stand in the right lines, sacrifice to the appropriate gods, and don't even hint that you would think of going around them. Finally, he who yells loudest gets move the front of the queue soonest - as holy and almighty as The Mega Bureaucracy is, they're happiest to get rid of their crabbiest customers first.

The silver lining in all of this? Apparently, the Guardians of the Mega Bureaucracy seem to now be willing to consider that there is a different tier of requests that don't require so many stopping points, designed to make sure that users really, REALLY know what they want to request. Bruce remains positive saying that, maybe in a few years, after meetings to plan meetings, forms to request forms, they will have a process that only has an initial questionnaire of 10 pages and 75 questions.

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!

https://thedailywtf.com/articles/classic-wtf-the-mega-bureaucracy


Метки:  

Classic WTF: The Source Control Shingle

Вторник, 17 Июля 2018 г. 13:30 + в цитатник
Our summer break continues. I once worked on a team which made "shingles"- software modules that were layered on top of a packaged product. There were a lot of WTFs in those shingles, but nothing that can compare to this once. Original--Remy

The year was 1999 and the dot-com boom was going full-throttle. Companies everywhere were focused on building revolutionary applications using nothing but top-shelf hardware and state-of-the-art software tools. Developers everywhere were trying to figure out if they should play more foosball, more air hockey, or sit back down on their Aeron and write more code. Everywhere, that is, except Boise, Idaho. Or at least, Dave's small corner of it.

At Dave's company, developers worked at a solid pace, using reliable tools, for a stable industry. They were sub-sub-contractors on a giant project commissioned by the U.S. Navy to condense naval vessel documentation. Generally speaking, the complete documentation required for a modern warship-from the GPS calibration instructions to the giant 130-millimeter cannon repair guide-is measured in tons. By condensing the documentation into the electronic equivalent, they could not only save tremendous physical space, but they could make it much easier to navigate.

A Simple Plan

Dave's company's small piece of the pie involved writing a very specific application for a particular group of users. Their application needed to track who moved which box of classified documentation from where to where, and why. Given the very simple requirements, the entire application was assigned to Mark.

Mark believed in keeping things simple: he rarely left the command line, his text editor was notepad and his source repository was a few backup folders on a network drive. He didn't need or want more than that. It was a simple task that called for his simple methodologies.

As their app neared completion, a whole new set of requirements came in. Now, they had to add in security and logging. When Dave joined Mark's one-man team to help out with this, the current system of source control -- nothing -- became inconvenient for collaborating.

Dave suggested they set up a source-control repository, but Mark wanted to keep things simple. He devised a solution called the "source-control shingle."

Roofing and Revisions

The source-control shingle was literally that: an actual shingle from someone's house that somehow ended up in their office. It acted like a "talking stick," in that only he who possessed the shingle was allowed to edit the common libraries.

As time went on, the project's scope grew immensely. More and more developers came on board, and the source-control shingle was pushed to its limits. Despite not being in possession of the shingle, some developers broke protocol and edited the library files on the share drive. Finally, Mark agreed to use a simple source repository. He wanted to use the only source-control system that guaranteed file locks: Visual Source Safe.

Unfortunately, Source Safe was so painful to license and manage that Mark had no choice but to explore other options, some of which involved a piece of painted wood. After much arguing and cajoling, Mark agreed to try out open source CVS. Things went well for the first few days, but quickly took a turn for the worse.

"What happened to my code?" Mark asked. "I just did a CVS UPDATE and everything I wrote this morning is gone!"

"It's working fine for me," one of the developers replied.

"Same here," another joined in. "I just checked in my changes a few minutes ago, and they're still here."

"Wait," a third one questioned, "did you do an UPDATE before the COMMIT?"

"Did I what?" the second developer replied. "Oh. Crap."

Exasperated, Mark jumped. "That's it! We're going back to the shingle!"

Fortunately, some of the other developers managed to convince Mark to stick with CVS, at least for a little while longer. One of the developers even managed to enforce better source control practices using some server-side scripts. And despite Mark's constant reservations, they ended up staying with CVS throughout the project. But the whole while, Mark kept the shingle handy, just in case.

[Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!

https://thedailywtf.com/articles/classic-wtf-the-source-control-shingle


Метки:  

Classic WTF: The Virtudyne Saga

Понедельник, 16 Июля 2018 г. 13:30 + в цитатник
As we usually do around this time of year, it's summer break season for TDWTF. This week, we're going to rerun some old classics, starting with this legend from 2006, compiled into a single article. --Remy

The Virtudyne saga (published 2006-Oct-10 through 2006-Oct-13) is my all time favorite. It tells the story of the rise and fall of Virtudyne, one of the largest privately-financed ($200M) disasters in our industry. Like most articles published here, all names have been changed to protect the guilty, and I've worked very closely with Rob Graves (the submitter) to ensure that this presentation is as close to how it happened as possible.


Part I - The Founding

By most people's standard, The Founder was very wealthy. A successful entrepreneur since age seventeen, he built several multi-million dollar companies and amassed a fortune larger than that of most A-list Hollywood celebrities. He prided himself on having one of the largest private collections of Egyptian artifacts in the world and prominently displayed many of them in his Great Room. And it truly was a great room: having been to The Founder's mansion several times, Rob recalls that his two-story, four-bedroom home could easily fit inside the Great Room.

The Founder was at home one day, doing whatever retired rich people did in 1999, and became extremely aggravated with how slow his brand-new, top-of-the-line computer was running. While cursing Microsoft Office, he had an "ah-ha" moment: he could build a better Microsoft Office.

Recalling his days as a Digital PDP-11 programmer, he knew that he could write financial software that would support fifty users, perform great, and run in 256-bytes of memory. Given the monumental advances in the twenty-years since he coded, he was elated just to think what would be possible with a bunch of top-notch programmers such as himself. He wondered just how many people it would take to build a Microsoft Office killer.

One thing led to another and Virtudyne was born. Its goal was modest: become the next Microsoft Office killer. The Founder hired his long-time colleague as the Chief Information Officer and together, they would create The Plan. It was simple: develop an internet/intranet based Office/Collaboration system that would deliver "90% of functionality that 90% of [Microsoft Office] users use."

An avid programmer himself, the CIO knew exactly how they could accomplish this. He convinced The Founder that, with a handful of programmers helping him, he could develop a client/server Microsoft Office Killer using Visual Basic 6. And with the latest hardware available, their application could easily scale to support twenty million users using one, maybe two servers. And best of all, it would all take only six months to create.

It was the perfect opportunity to jump on the .com bandwagon. They just could feel the IPO beckoning them. The Founder invested a few million of his own dollars and the CIO started hiring.

One of the first people the CIO approached was Rob Graves. He wanted Rob to become the database administrator, telling him only that Virtudyne was a pre-IPO startup bankrolled by The Founder. As tempting as it was, Rob had a second kid on the way and declined the offer. The CIO would have to find another DBA for the project.

What better place to find a DBA than the same place he turned for the rest of the initial hiring: the local Visual Basic special interest group. In fact, not only did he find a DBA at the SIG, he found one that proclaimed to be one of the greatest DBA in the world. And not because he possessed extensive database administration skills, but because he was willing to admit to The Truth: with the GUI-tools and automagic processes that modern databases offer, all those extensive database administration skills are meaningless.

Sadly, the DBA was one of the more talented members of the initial Virtudyne team.

Part II - The Gathering

The Founder had little trouble convincing his millionaire friends to invest in Virtudyne. It wasn't so much the idea of a Microsoft Office Killer, but that fact that it was 1999 and just about anyone with an internet company could go public and become an overnight billionaire. Within one month of The Founder's grandiose idea, he had secured an impressive eleven million in funding.

While The Founder solicited investors, the Chief Information Officer solicited employees. The CIO knew it would take "only a handful of strong programmers" to develop the Microsoft Office Killer and hired ten of the best programmers he could find. He promised a high salary, good stock options, and the chance to beat the market leader at their own game. Though his team's competence was minimal, their confidence was as strong as ever. They were all eager to build the Microsoft Office Killer.

It was the opportunity of a lifetime handed to the CIO on a silver platter: millions in capital and a dedicated team of developers. It was up to him to get busy with a clear vision, detailed requirements, a throughout market analysis, an extensive design, and solid architecture. Instead, he discovered something much more important: Magic: The Gathering.

The CIO dedicated his "lunch break" to his Magic card collection. This, of course, meant that he'd spend much of his day thinking up new deck concepts, building them, and testing them out. He even got some of his developers hooked: they'd all get together during their "lunch break" and play, trade, and chat about the latest happenings in the world of Magic: The Gathering.

Don't get me wrong, Magic wasn't the Chief Information Officer's only focus. With his new job title, he was eligible to receive executive-level trade publications for free. In fact, one of his first acts as CIO was to purchase a top-of-the-line solid ink printer. In addition to producing sharp full-color graphs for presentation packets, it printed up some wicked high-quality "proxy cards" for everyone's Magic decks.

Days turned into weeks, weeks turned into months, and next thing they knew, six months had passed and not a single line of code had been written. What made this especially bad was the fact that the investors were flying in to town to check on everyone's progress. They were all eager to see just how their Microsoft Office Killer was coming along.

Thank goodness that the Chief Information Officer chose Visual Basic 6 as their platform. Real magic ensued when the following were combined: a handful of developers, a caffeine-filled all-nighter, and VB6's wonderful ability to drag & drop controls onto Windows form and "hard code" what shows in the labels, text boxes, drop downs, etc.

The investors were not impressed. They were astonished. In fact, the demonstration convinced them that, not only the project was on track, but that Virtudyne was poised to take on Microsoft and its ubiquitous office suite. Word spread fast and even more investors signed up. Tens of millions of dollars started pouring into Virtudyne.

The new investment might have been the CIO's motivation to finally get cracking on the project. Or it could have been the fact that the .com bubble was starting to burst and that meant they'd have to make a real attempt at making a product. He immediately started hiring again. And I mean hiring. A massive recruiting campaign was initiated and developers from all over the country were brought in. Within a year, the Virtudyne CIO commanded an army of I.T. professionals whose skill levels ranged between complete ineptitude and moderate competence.

The Chief Information Officer also purchased the best server he could find advertised in his executive trade publications: the Unisys ES7000. It was a thirty-two processor beast with sixty-four gigabytes of RAM and an attached EMC CLARiiON storage server. This $1.3M machine would be the single production server for their anticipated 20,000,000 users.

With all the new talent and the fancy new hardware, development of the Microsoft Office Killer finally began. The biggest hurdle that faced the developers was the new requirements. You see, one of the major selling points to investors was that Virtudyne's office suite already had every feature they asked for: it ran on Windows, Linux, and even Palm OS. All the developers had to do was make it actually do that.

Rob Graves joined Virtudyne around its second-year anniversary. He had been contacting part-time, off-and-on since day one, and they finally made him an offer he could not refuse: lead role in a company of 100+ developers, top-of-the-line development hardware, a dedicated QA team, and most of all, a $50,000 raise with five weeks paid vacation. No one could top that in the post .com-bubble.

In the year that followed, Rob found himself in the middle of quite a few political battles between the "do it right" and the "do it now" developers. Nothing too spectacular, especially in the context of this entire Virtudyne saga, but Rob did note who won the argument over whether or not to use the special coding techniques recommended by Unisys and Microsoft to utilize the server's full potential. I'll let you guess which side that was.

Despite all this, Virtudyne lacked one thing: customers. Allow me to clarify that because saying that they lacked "customers" might imply they had "a" customer. They didn't. The sales department of eight was unable to find a single organization willing to license their product.

This was especially problematic because their initial $94M war chest had dwindled to less than $10M. Investors were starting to wonder about their "six-months-to-develop Microsoft Office Killer" and stopped pouring money into Virtudyne. Something needed to be done.

Part III - The Savior Cometh

Virtudyne's first three years are best summed up with a single word: disastrous. Nearly $90M had been spent developing a product that was barley functional and completely unsalable. Most would call that "miserable failure" and encourage all involved to salvage what they could, abandon ship, scuttle the remains, and never look back. But one person saw it as the golden opportunity; he was known as The Savior

The Savior was a self-made billionaire who struck it rich doing the type of business that makes unregulated industries regulated. He heard about Virtudyne's struggles and wanted to help out. He contacted the powers that be and offered some very reasonable terms. In exchange for investing $100M, he would take over operations and sit as chairman on the board of directors. It seemed to be a a win-win for everyone.

Even the Virtudyne employees were excited. They welcomed their new overlord with open arms and truly believed that The Savior would turn the company around with his "new management team of highly-qualified executives with a proven track record." Such statements tend to be very convincing when accompanied with a hundred million dollar investment.

Unfortunately, employee confidence wore off almost immediately. It wasn't so much that the fact that the superstar executives consisted primarily of The Savior's immediate family, but more the fact that they managed to set the bar of incompetence even higher. I suspect that, given yesterday's article, this might seem impossible, so I'll share my favorite three people that The Savior brought in.

First and foremost, there was the new chief of operations, heralded as a "brilliant innovator" and "technological wizard." He was also The Savior's eldest son. Junior's grasp on technology is best illustrated with this simple anecdote: one day, Junior was walking past Rob Graves' office and saw a graph actively moving around on the screen. He got incredibly exited and wanted to know how he could get the cool looking monitoring software Rob was using to watch their World Wide Server. Rob just didn't have the heart to tell him it was the "Bars and Waves" visulization from Windows Media Player.

One of Junior's first acts as operations chief was to partner up with a major hardware vendor peddling another completely unsalable product. It was a massively-parallel server that featured a proprietary operating system with an integrated database. The sales rep told them that "reliability, not speed, is our primary concern" and they meant it. The $350,000 development server had the same processing power as a 600MHz Pentium II that even a charity organization would refuse as a donation.

Perhaps Junior's logic was that anyone stupid enough to buy the hardware would be stupid enough to buy their Microsoft Office Killer. Unfortunately, Virtudyne seemed to hold a monopoly on the world's supply of stupidity. The expensive hardware and vast amount of effort to port the software resulted in only a single sale, and it was a sale for the hardware vendo to Virtudyner.

The next person on the list was known as The VP of Nothing. I don't that's a very fair title because he actually did two things. First and foremost, despite having no direct reports or job responsibilities, he collected a six-figure paycheck. And secondly, he was allowed to bypass the proxy filter to surf the web; it was no secret why. A curious network administrator looked in the logs and discovered that The VP of Nothing spent a lot of time looking at pictures of large Amazonian women wrestling with little men. Seriously.

My personal favorite that The Savior brought in was The Janitor. Now it may seem odd that the chairman of the board would insist upon changing cleaning companies, but it's even stranger what the new "cleaning company" consisted of: The Savior's youngest son. The Janitor was a trust-fund baby and wealthier than most of us will ever be. It became pretty apparent why he couldn't keep a job anywhere else: after a few months of his cleaning service, ants and cockroaches were everywhere, the VB team had a gnat infestation, and the restrooms became so dirty that most managers allowed their employees to go home if they needed to use the facilities.

Amazingly, this new team was able to find a paying customer. It was The City. Virtudyne's office suite was to be installed at all libraries and made available for download by city residents. All it took was some lobbying at city council, a few calls to the local media, and a sizable march on city hall with "unemployed" protestors demanding the city provide free office software. Although the majority of the protesters were Virtudyne employees, the city finally agreed and signed an $8,500,000 three-year contract, collectable upon timely delivery of the software specified in the contract.

The main problem (well, aside from the fact that Virtudyne's Office Killer was a joke compared to any office suite) was that the contract called for a product that would replace Microsoft Access. In fact, it was a major selling point: the sales VP gave a demo of a product that didn't exist.

It fell on Rob Graves and a handful of other developers to create an application in two weeks that would "allow users with no database and minimal computer knowledge to: build applications; add users and groups to access the application; set security at the form-, record-, and field- level;" and so on. Rob is embarrassed to report that they actually managed to deliver a completely useless application that met every word in the ambiguous requirements to technically fulfill the contract.

None of tha mattered, though. Employee morale was at an all time high and things were finally starting to look good. It only took three and half years and nearly $150M dollars, but they finally made eight and half million dollars. Unfortunately, the sale also brought something else to the Virtudyne: paranoia.

Junior held a company-wide meeting to discuss a very serious issue: Microsoft was onto them. They were shaking in their boots and saw Virtudyne as a major threat. They would stop at nothing to get their grubby hands on the product and might even try to steal the source code. Of course, at that point, about half the people at Virtudyne realized that all one would have to do to "get their grubby hands" on their Microsoft Office Killer was to go into any of The City's public libraries and ask for an installation disk. Obviously, Junior wasn't in that half.

Within days, Junior ordered cameras to cover every square inch of the Virtudyne facility. Fingerprint scanners were installed at every door, both inside and out, and full-time security guards were placed at key locations throughout the building. All exterior windows were covered with a translucent film to prevent Microsoft from peeping in and, just to be safe, computer monitors could no longer face outside windows. Key employees were issued with special pagers that allowed them to discretely press a button to alert the private investigator if they found themselves being followed by Microsoft's white vans.

The draconian security measures didn't help the recent boost in employee morale. In fact, over the next year, employee morale sunk to an all-time low, leading to a mass exodus from the company. Key employees were dropping like flies and all Junior would do to maintain headcount was to hire more employees.

Eventually, Junior struck a good balance between tight security and employee indifference and managed to stabilize the loss. Unfortunately, that didn't help business much. Almost two years had passed since the single sale to The City and Virtudyne couldn't even give away their product. It's hard to say whether it was the terrible product itself or the fact that the Virtydune's contract with The City sparked a state-wide scandal with accusations of impropriety going all around.

What Virtudyne needed was a new market. A market that hadn't heard of Virtudyne before. And preferably, one that wouldn't do any research before spending millions to license their product.

Part IV - The Digital Donkey

After three years of full-time employment at Virtudyne, Rob Graves finally decided to call it quits. Most of Rob's friends and family thought he was insane to leave a cushy job where he was making 30% more than he could anywhere else in town. But then again, most of his current and former coworkers thought he was insane for staying so long.

Virtudyne had blown through nearly $200,000,000 of investor capital over five years to develop their Microsoft Office Killer. All they had to show for it was a barely functional product with a small subset of Microsoft Office's features and a single $8.5M sale. And technically, they only collected $5.8M on the sale because their customer withdrew the contract.

The sales and marketing department were desperate for ideas. They literally couldn't give their software away; anyone with even the most basic knowledge of Google could find out how well Virtudyne's first customer worked out. No one wanted to be their second.

But just then, it dawned on the sales team. They needed to find a market where the Internet had not yet reached. In such a market, their office suite would develop interest and that interest would lead right in to sales. One of the executives knew exactly how to find and penetrate such a market. They would use The Digital Donkey.

The CEO was a bit skeptical at first, but eventually realized how great of an idea it was. It was the perfect plan to sell their product to a market that no one else has ever tapped before. He signed off on the project.

Virtudyne engineers were tasked with figuring out a way to attach a satellite dish, laptops, and solar cells to a donkey. This Digital Donkey would then take Virtudyne's software along with a satellite internet connection to disenfranchised villagers living in the rural parts of India. The villagers would then be able to surf the 'net and use Virtudyne's software suite to create documents and communicate with "God knows who."

Everything would go through Virtudyne's server and they would eventually start billing the local governments for usage. I think it goes without saying that, like virtually every idea coming from Virtudyne's management team, the Digital Donkey was a miserable failure.

Virtudyne's offices are still open to this day, but no one's sure for how long. They've slightly improved their product over the years and tried to sell it under many different names to many different people. But still, nothing seems to work. Rob keeps in touch with a programmer at Virtudyne and confirmed that, as of two or three months ago to this day, there has yet to be a second sale.

Addendum

Several readers had a hard time believing that Virtudyne actually tried to create a Digital Donkey. It's important to note how ubiquitous donkeys/mules/camels/etc are in everyday tasks and transportation in the third world. So much so that the idea of a "Digital Donkey" did not even originate at Virtudyne. Consider this successful experiment from the International Federation of Library Associations and Institutions:

"The mobile units are Donkey Drawn Electro-Communication Library Carts. Besides functioning as a mobile library with a collection of books and other printed works, it works as a centre for electric and electronic communication: radio, telephone, fax, e-mail, Internet."
-- http://www.ifla.org/V/press/pr0225-02.htm (with pictures, thanks to Antitorgo for finding)

Obviously the Digital Donkey illustration is hyperbolized for fun. What should strike you as unbelievable is not the digital donkey, but the fact that Virtudyne actually considered trying to profiting from such a market. But then again, looking at their track record, that part is not so hard to believe ...


Happy New Year, All! I'll be back on Tuesday, January 2nd with some fresh, new content =-)

[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/classif-wtf-the-virtudyne-saga


Метки:  

Error'd: All the Way from Sweden

Пятница, 13 Июля 2018 г. 13:30 + в цитатник

"And to think, this price doesn't include assembly," wrote Adam G.

 

Martin B. writes, "Don't worry...I'm sure you'll find your group eventually."

 

"As always I appreciate Google's relevant search results for dealing with specific issues in the office," Michael T. wrote.

 

Bruce W. writes, "How exactly were podcasts distributed in 1938? 45 RPM Record-of-the-Month club? Also, anyone have have some of those 2038 podcasts?"

 

"I realize the page says it's 'free', but I don't really think you should be selling that," writes Rob W.

 

Peter L. writes, "So, does the 's' stand for 'segfault'?"

 

[Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!

https://thedailywtf.com/articles/all-the-way-from-sweden


Метки:  

CodeSOD: A Symbol of Bad Code

Четверг, 12 Июля 2018 г. 13:30 + в цитатник

As developers, when we send data over the network, we can usually safely ignore the physical implementation of that network. At some level, though, the bits you’re sending become physical effects in your transmission medium, whether it’s radio waves or electrical signals.

You can’t just send raw bits over the wire. Those bits have to be converted into a symbol suitable for the transmission medium. Symbols could be the dots-and-dashes of morse code, tones transmitted over a phone line, or changing duty cycles on a pulse-width-modulated signal. The number of symbols per second is the baud rate of the channel. What this means for digital transmission is that even if your channel has a potential bit rate of one gigabit per second, the actual baud rate may be different- either much larger or much smaller. For example, modems might send 4-bits per symbol, meaning a 2,400 baud modem actually can transmit 9,600 bits per second. GPS, on the other hand, can transmit 50 bits/s, but over one million symbols per second thanks to spread spectrum broadcast.

Marnie works for a telcoms company which greatly cares about these sorts of details. There’s a variety of client-side web apps which accrued over time which can help with things like symbol rate calculations.

For their environment, this calculation is straightforward: whatever the bits-per-second of the channel is, divide by 1.25 to find the symbol rate. Of course, this simple calculation can’t be performed without regexes. Marnie found this code in the code base:

private bandwidthList = [6.4, 3.2, 1.6];
private symbolRateList = [5.12, 2.56, 1.28]; 

public getSymbolRate(_bandwidth: number): string {
	let BW1DecimalPoint = _bandwidth.toString().match(/^-?\d+(?:\.\d{0,1})?/)[0];
	let symbolRate = this.symbolRateList[0];
	let symbolIndex = this.bandwidthList.indexOf(parseInt(BW1DecimalPoint));

	if (symbolIndex > 0) {
		symbolRate = this.symbolRateList[symbolIndex];
	}

	return formatValue(symbolRate);
}

Now, this is TypeScript, so there is no guarantee that, at runtime, _bandwidth will actually be a number. But there’s no need to convert it to a string, match against a regex, slice up the results, only to parse it back into a an int later. Which, it’s important to note, because they use parseInt inside of the indexOf call, this will never find the target entry inside of bandwidthList- 6 is not 6.4.

So, as written, this method only ever returns 5.12. It’s been in use, in production, for a few years now. Not only is in overly complex, it also just doesn’t work.

Marnie fixed the code with a much simpler version:

public getSymbolRate(_bandwidth: number): string {
	let symbolRate = _bandwidth / 1.25;
	return formatValue(symbolRate);
}
[Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.

https://thedailywtf.com/articles/a-symbol-of-bad-code


Метки:  

Reproducible Heisenbug

Среда, 11 Июля 2018 г. 13:30 + в цитатник

Illustration of Heisenberg Uncertainty Principle

Matt had just wrapped up work on a demo program for an IDE his company had been selling for the past few years. It was something many customers had requested, believing the documentation wasn't illustrative enough. Matt's program would exhibit the IDE's capabilities and also provide sample code to help others get started on their own creations.

It was now time for the testers to do their thing with the demo app. Following the QA team's instructions, Matt changed the Debug parameter in the configuration file from 4 (full debugging) to 1 (no debugging). Build and deploy completed without a hitch. Matt sent off the WAR file, feeling good about his programming aptitude and life in general.

And then his desk phone rang. The caller ID revealed it was Ibrahim, one of the testers down in QA.

Already? Matt wondered. With a mix of confusion and annoyance, he picked up the phone, assuming it was something PEBKAC-related.

"I've got no descriptors for the checkboxes on the main page," Ibrahim told him. "And the page after that has been built all skew-whiff."

"Huh?" Matt frowned. "Everything works fine on my side."

What could be different about Ibrahim's setup? The first thing Matt thought of was that he'd disabled debugging before building the WAR file for QA.

That can't be it! But it was easy enough to test.

"Hang on one sec here." Matt muted his phone, then changed the Debug parameter on his local deployment from 4 to 1. Indeed, upon refreshing, the user interface went wonky, just as Ibrahim had described. Unfortunately, with debugging off, Matt couldn't check the logs for a clue as to what was going wrong.

Back on the phone, Matt explained how he was able to do reproduce the problem, then instructed Ibrahim on manually hacking the WAR file to change the Debug parameter. Ibrahim reported that with full debugging enabled, the program worked perfectly on his end.

"OK. Lemme see what I can do," Matt said, trying not to sound as hopeless as he felt.

With absolutely no hints to guide him, Matt spent hours stepping through his code to figure out what was going wrong. At long last, he isolated a misbehaving repeat-until loop. When the Debug parameter was set to 4, the program exited the loop and returned data as expected. But when Debug was set to anything less than 4, it made an extra increment of the loop counter, leading to the graphical mayhem experienced earlier.

Horror crept down Matt's spine. This problem would affect anyone using repeat-until loops in conjunction with the IDE. Such programs were bound to fail in unexpected ways. He immediately issued a bug report, suggesting this needed to be addressed urgently.

Later that day, he received an email from one of the IDE developers. I found where it was testing the wrong boolean. Should we raise this as a defect?

"Yes! Duh!" Matt grumbled out loud, then took to typing. And can we find out where this bug crept in? All projects released since that time are compromised!!

As it turned out, the bug had been introduced to the IDE 2 years earlier. It'd been found almost immediately and fixed. Unfortunately, it'd only been fixed in one specific branch within source control—a branch that had never been merged to the trunk.

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

https://thedailywtf.com/articles/reproducible-heisenbug


Метки:  

CodeSOD: Is the Table Empty?

Вторник, 10 Июля 2018 г. 13:30 + в цитатник

Sean has a lucrative career as a consultant/contractor. As such, he spends a great deal of time in other people’s code bases, and finds things like a method with this signature:

public boolean isTableEmpty()

Already, you’re in trouble. Methods which operate directly on “tables” are a code-smell, yes, even in a data-driven application. You want to operate on business objects, and unless you’re a furniture store, tables are not business objects. You might think in those terms when building some of your lower-level components, but then you’d expect to see things like string tableName in the parameter list.

Now, maybe I’m just being opinionated. Maybe there’s a perfectly valid reason to build a method like this that I can’t imagine. Well, let’s check the implementation.

public boolean isTableEmpty()
{
    boolean res = false;
    Connection conn = cpInstance.getConnection();
    try (PreparedStatement ps = conn.prepareStatement("select * from some_table")) {
        try (ResultSet rs = ps.executeQuery()) {
            if (rs.first()) {
 	        res = true;
            }
        }
    catch (SQLException e) {
        e.printStackTrace();
    } finally {
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    return res;
}

Even if you think this method should exist, it shouldn’t exist like this. No COUNT(*) or LIMIT in the query. Using exceptions as flow control. And the best part: returning the opposite of what the method name implies. false tells us the table is empty.

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/is-the-table-empty


Метки:  

Walking on the Sun

Понедельник, 09 Июля 2018 г. 13:30 + в цитатник

In 1992, I worked at a shop that was all SunOS. Most people had a Sparc-1. Production boxes were the mighty Sparc-2, and secretaries had the lowly Sun 360. Somewhat typical hardware for the day.

SPARCstation 1

Sun was giving birth to their brand spanking new Solaris, and was pushing everyone to convert from SunOS. As with any OS change in a large shop, it doesn't just happen; migration planning needs to occur. All of our in-house software needed to be ported to the new Operating System.

This planning boiled down to: assign it to snoofle; let him figure it out.

This was before Sun made OpCom available to help people do their migrations.

I took the latest official code, opened an editor, grepped through the include files and compiled, for each OS. Then I went into a nine month long compile-edit-build cycle, noting the specifics of each item that required different include files/syntax/whatever. Basically, Sun had removed the Berkeley libraries when they first put out Solaris, so everything signal or messaging related had to change.

Finally, I naively thought the pain was over; it compiled. I had coalesced countless functions that had nearly identical multiple versions, deleted numerous blocks of dead code, and reduced 1.4 million LOC to about 700K. Then began the debugging cycle. That took about 3 weeks.

Then I was told not to merge it because another subteam in our group was doing a 9-month sub-project and couldn't be interrupted. Naturally, they were working in the main branch, which forced me to keep pulling and porting their code into mine several times a week, for months. Ironically, they were constantly changing dead code as part of trying to fix their own code.

You can only do this for so long before getting fed up; I'd had it and let it be known to boss+1 (who was pushing for Solaris) that this had to end. He set a date three months out, at which time I would do the merge and commit; other tasks be damned! The subteam was repeatedly informed of this drop-dead date.

So I put up with it for 3 months, then did the final merge; over 3,500 diffs. I went through them all, praying the power wouldn't cut out. After fixing a few typos and running the cursory test, I held my breath and committed. Then I told everyone to pull and merge.

It turns out that I missed 3 little bugs, but they were suffiently visible that it prevented the application from doing anything useful. The manager of the sub-team ordered me to roll it back because they were busy. I handed her the written memo from B+1 ordering me to do it on this date and told her to suck it up and give me a chance to debug it.

An hour later, it was working and committed.

I instructed everyone to pull and build, and to follow the instructions in my handout for coding going forward. Anything that broke the Solaris build would be summarily rolled back per orders from B+1.

It took a few months and hundreds of rollbacks for them to start to follow my instructions, but when they finally did, the problems ceased.

Then the managers from the other teams took my instructions and all my global edit scripts (it wasn't a perfect parser, but it at least left syntax errors if it tried to change code that was really badly formatted, so you could trivially find them and fix them very quickly).

Using my scripts and cheat sheets, my peers on the other projects managed to do their ports in just a couple of hours, and mercilessly rode me about it for the next 3 years.

[Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!

https://thedailywtf.com/articles/walking-on-the-sun


Метки:  

Error'd: Is Null News Good News?

Пятница, 06 Июля 2018 г. 13:30 + в цитатник

"The Eugene (Oregon) Register-Guard knows when it's a slow news day, null happens," Bill T. writes.

 

"12 months for free or a year for not free...so hard to choose!" writes Paige S.

 

Rodrigo M. wrote, "GlobalProtect thinks the current version I have installed is not very good, so why not upgrade by downgrading?"

 

"After flying with Norwegian airways I got a mail asking to take the survey," Nathan K. wrote, "Now I apparently need to find out how to file a ticket with their sysadmins."

 

"So...my name is 'Marketing' now?" wrote Anon and totally not named Marketing.

 

Brad W. writes, "For having 'Caterpillar,' 'Revolver,' and 'Steel Toe' in the description the shoe seems a bit wimpy."

 

[Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!

https://thedailywtf.com/articles/is-null-news-good-news


Метки:  

CodeSOD: To Read or Parse

Четверг, 05 Июля 2018 г. 13:30 + в цитатник

When JSON started to displace XML as the default data format for the web, my initial reaction was, "Oh, thank goodness." Time passed, and people reinvented schemas for JSON and RPC APIs in JSON and wrote tools which turn JSON schemas into UIs and built databases which store BSON, which is JSON with extra steps, and… it makes you wonder what it was all for.

Then people like Mark send in some code with a subject, "WHY??!??!". It's code which handles some XML, in C#.

Now, a useful fact- C# has a rich set of API- for handling XML, and like most XML APIs, they implement two approaches.

The simplest and most obvious is the DOM-style approach, where you load an entire XML document into memory and construct a DOM out of it. It's easy to manipulate, but for large XML documents can strain the available memory.

The other is the "reader" approach, where you treat the document as a stream, and read through the document, one element at a time. This is a bit trickier for developers, but scales better to large XML files.

So let's say that you're reading a multi-gigabyte XML file. You'd want to quit your job, obviously. But assuming you didn't, you'd want to use the "reader" approach, yes? There's just one problem: the reader approach requires you to go through the document element-by-element, and you can't skip around easily.

public void ReadXml(XmlReader reader) { string xml = reader.ReadOuterXml(); XElement element = XElement.Parse(xml); … }

Someone decided to give us the "best of both worlds". They load the multi-gigabyte file using a reader, but instead of going elementwise through the document, they use ReadOuterXml to pull the entire document in as a string. Once they have the multi-gigabyte string in memory, they then feed it into the XElement.Parse method, which turns the multi-gigabyte string into a multi-gigabyte DOM structure.

You'll be shocked to learn that this code was tested with small testing files, not multi-gigabyte files, worked fine in those conditions, and thus ended up in production.

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

https://thedailywtf.com/articles/to-read-or-parse


Метки:  

Classic WTF: Common Sense Not Found

Среда, 04 Июля 2018 г. 13:30 + в цитатник
It's the Forth of July in the US, where we all take a day off and launch fireworks to celebrate the power of stack based languages. While we participate in American traditions, like eating hot dogs without buns, enjoy this classic WTF about a real 455hole. --Remy

Mike was a server admin at your typical everyday Initech. One day, project manager Bill stopped by his cube with questions from Jay, the developer of an internal Java application.

“Hello there- thanks for your time!” Bill dropped into Mike’s spare chair. “We needed your expertise on this one.”

“No problem,” Mike said, swiveling to face Bill. “What can I help with?”

Bill’s pen hovered over the yellow notepad in his lap. He frowned down at some notes already scribbled there. “The WAS HTTP server- that’s basically an Apache server, right?”

HTTP Error 455 - User is a Jackass

“Basically,” Mike answered. “Some IBM customizations, but yeah.”

“So it has a… HT Access file, or whatever it’s called?” Bill asked.

He meant .htaccess, the config file. “Sure, yeah.”

“OK.” Bill glanced up with wide-eyed innocence. “So we could put something into that file that would allow a redirect, right?”

“Um… it’s possible.” Uneasiness crept over Mike, who realized he was about to discuss a custom solution to a problem he didn’t know about, on a server he was responsible for. “What’s going on?”

“Well, Jay wants a redirect in there to send people to another server,” Bill replied.

Mike frowned in confusion. “We just stood this server up. Now he wants another domain?”

“Huh? Oh, no, It’s not our domain. It’s someone else’s.”

“OK… I’m lost,” Mike admitted. “Let’s start at the beginning. What’s the problem Jay wants to fix?”

“Well, he has this broken link in his app, and he wants to redirect people to the correct site,” Bill explained.

Mike stared, dumbfounded for several moments. “Excuse me?”

“Yeah. He has this link that points off to some external federal website- IRS, I think- and the link is broken. He wants to automatically redirect users to the correct site so they don’t get a 404 error. We started looking into it, and found that Apache has this HT Access file thingy. It looks like that’s what we need.”

“You’re kidding, right?” Mike blurted ahead of discretion.

“No. Why?” Bill’s eyes widened. “Something wrong?”

Mike swiveled around to retrieve his coffee mug, and a measure of composure. “Why doesn’t he just fix the link within the app so it points to the right URL?”

“Well, that’s what I asked him. But he thinks it’d be more convenient to redirect people.”

“If the link is updated, they won’t need to be redirected.”

“I realize that.”

Mike took a long swig. “That’s not what the .htaccess file is for. It’s meant to redirect an incoming request to a different server of your own, not someone else’s.”

“Oh.” Bill scribbled this down on his notepad, then stared hard at the scribbles. Every moment of silence ratcheted Mike’s nervousness higher.

“So you’re saying we can’t do the HT Access thing?” Bill finally asked, looking up again.

“To fix a broken link?”

“Yeah!” Bill’s eyes lit up. Apparently, Mike’s clarifying question had given him new hope.

“No.” Mike crushed that hope as mercilessly as he could.

“OK, so the HT Access thing won’t work. Hmm, OK.” Bill frowned back down at his notes, falling silent again. Mike sensed, and dreaded, another inane line of questioning about to follow.

“Well, another thing Jay mentioned was a custom error page,” Bill’s next foray began. “Can we do that in Apache?”

Mike hesitated. “…Yes?”

“Great! I’ll tell him that. He can develop a custom 404 page with some Javascript in it or something to redirect people to the correct site.”

“Huh?”

“Not the prettiest solution, I know, but Jay said he can make it work.”

Mike spoke slowly. “He’s going to create a custom 404 error page… for that broken link of his?”

“Yeah.”

“And that 404 page is supposed to display… when his broken link sends users off to some IRS web server?”

“Yeah.”

“The IRS web server, when it gets a request for a page that doesn’t exist, is gonna display Jay’s custom 404 error page. Is that what you’re telling me?”

Bill’s confidence faltered. “Um… I think so.”

Mike dropped the bomb. “How’s he gonna get that custom page onto their server?”

“Well, it’d be on our server.”

“Right! So how would that custom 404 error get displayed?”

“When the user clicks the broken link.”

“I asked how. You just answered when.”

“Well, OK, I don’t know! I’m not the developer here.” Bill’s hands rose defensively. “Jay said he could make it work.”

“He’s wrong!” Mike snapped.

“He was pretty confident.”

Mike hesitated a moment before his shoulders dropped. Facts and common sense were not to prevail that day. “OK then. Lemme know when it works.”

Bill perked up. “Really? You’ll put it on the server?”

“Sure. Just have him fill out a service request and I’ll deploy it.”

“Excellent! Thank you!” Bill jumped up with pleasant surprise, and left the cube.


A few days later, Mike was completely unsurprised to find Jay frowning into his cube. “My 404 page isn’t displaying!”

Mike created a new email addressed to Jay, then copied and pasted a link to the IRS Help and Resources page. “Sorry- you’ll have to take it up with the taxman.”

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/classic-wtf-common-sense-not-found


Метки:  

Flobble

Вторник, 03 Июля 2018 г. 13:30 + в цитатник

The Inner Platform Effect, third only after booleans and dates, is one of the most complicated blunders that so-called developers (who think that they know what they're doing) do to Make Things Better.™ Combine that with multiple inheritance run-amok and a smartass junior developer who thinks documentation and method naming are good places to be cute, and you get todays' submission.

A cat attacking an impossible object illusion to get some tuna from their human

Chops,an experienced C++ developer somewhere in Europe, was working on their flagship product. It had been built slowly over 15 years by a core of 2-3 main developers, and an accompanying rotating cast of enthusiastic but inexperienced C++ developers. The principal developer had been one of those juniors himself at the start of development. When he finally left, an awful lot of knowledge walked out the door with him.

Enormous amounts of what should have been standard tools were homegrown. Homegrown reference counting was a particular bugbear, being thread dangerous as it was - memory leaks abounded. The whole thing ran across a network, and there were a half-dozen ways any one part could communicate with another. One such way was a "system event". A new message object was created and then just launched into the underlying messaging framework, in the hopes that it would magically get to whoever was interested, so long as that other party had registered an interest (not always the case).

A new system event was needed, and a trawl was made for anyone who knew anything about them. Nobody had any idea how they worked, or how to make a new one. The documentation was raked over, but it was found to mostly be people complaining that there was no documentation. The code suffered from inheritance fever. In a sensible system, there would be only one message type, and one would simply tag it appropriately with an identifier before inserting the data of interest.

In this system, there was an abstract base message type, and every specific message type had to inherit from it, implement some of the functions and override some others. Unfortunately, each time it seemed to be a different set of functions being implemented and a different set being overridden. Some were clearly cut and paste jobs, copying others, carrying their mistakes forward. Some were made out of several pieces of others; cut, paste and compiled until the warning messages were disabled compiler stopped complaining.

Sometimes, when developing abstract base types that were intended to be inherited from to create a concrete class for a new purpose, those early developers had created a simple, barebones concrete example implementation. A reference implementation, with "Example" in the name, that could be used as a starting point, with comments, making it clear what was necessary and what was optional. No such example class could be found for this.

Weeks of effort went into reverse-engineering the required messaging functionality, based on a few semi-related examples. Slowly, the shape of the mutant inside became apparent. Simple, do-nothing message objects were created and tested. Each time they failed, the logs were pored over, breakpoints were added, networks were watched, tracing the point of failure and learning something new.

Finally, the new message object was finished. It worked. There was still some voodoo coding in it; magic incantations that were not understood (the inheritance chain was more than five levels deep, with multiple diamonds, and one class being inherited from six times), but it worked, although nobody was certain why.

During the post development documentation phase, Mister Chops was hunting down every existing message object. Each would need reviewing and examination at some point, with the benefit of the very expensive reverse engineering. He came across one with an odd name; it wasn't used anywhere, so hadn't been touched since it was first committed. Nobody had ever had a reason to look at it. The prefix of the name was as expected, but the suffix - the part that told you at a glance what kind of message it was - was "Flobble". Chops opened it up.

It was a barebones example of a concrete implementation of the abstract base class, with useful explanatory comments on how to use/extend it, and how it worked. Back at the start, some developer, instead of naming the example class "Example" as was customary, or naming it anything at all that would have made it clear what it was, had named it "Flobble". It sat there for a decade, while people struggled to understand these objects over and over, and finally reverse engineered it at *significant* expense. Because some whimsical developer a decade previously had decided to be funny.

[Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!

https://thedailywtf.com/articles/flobble


Метки:  

CodeSOD: An Eventful Career Continues

Понедельник, 02 Июля 2018 г. 13:30 + в цитатник

You may remember Sandra from her rather inglorious start at Initrovent. She didn't intend to continue working for Karl for very long, but she also didn't run out the door screaming. Perhaps she should have, but if she had- we wouldn't have this code.

Initrovent was an event-planning company, and thus needed to manage events, shows, and spaces. They wrote their own exotic suite of software to manage that task.

This code predates their current source control system, and thus it lacks any way to blame the person responsible. Karl, however, was happy to point out that he used to do Sandra's job, and he knew a thing or two about programming. "My fingerprints are on pretty much every line of code," he was proud to say.

if($showType == 'unassigned' || $showType == 'unassigned' || $showType == 'new') { ... }

For a taster, here's one that just leaves me puzzling. Were it a long list, I could more easily see how the same value might appear multiple times. A thirty line conditional would be more of a WTF, but I can at least understand it. There are only three options, two of them are duplicates, and they're right next to each other.

What if you wanted to conditionally enable debugging messages. Try this approach on for size.

foreach($current_open as $key => $value) { if ($value['HostOrganization']['ticket_reference'] == '400220') { //debug($value); } }

What a lovely use of magic numbers. I also like the mix of PascalCase and snake_case keys. But see, if there's any unfilled reservation for a ticket reference number of 400220, we'll print out a debugging message… if the debug statement isn't commented out, anyway.

With that in mind, let's think about a real-world problem. For a certain set of events, you don't want to send emails to the client. The planner wants to send those emails manually. Who knows why? It doesn't matter. This would be a trivial task, yes? Simply chuck a flag on the database table- manual_emails and add a code branch. You could do that, yes, but remember how we controlled the printing of debugging messages before. You know how they actually did this:

$hackSkipEventIds = array('55084514-0864-46b6-95aa-6748525ee4db'); if (in_array($eventId, $hackSkipEventIds)) { // Before we implement #, we prefer to skip all roommate // notifications in certain events, and just let the planner send // manual emails. return; }

Look how extensible this solution is- if you ever need to disable emails for more events, you can just extend this array. There's no need to add a UI or anything!

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!

https://thedailywtf.com/articles/an-eventful-career-continues


Метки:  

Поиск сообщений в rss_thedaily_wtf
Страницы: 124 ... 67 66 [65] 64 63 ..
.. 1 Календарь