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

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

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

Announcements: Sponsor Announcement: Hired

Вторник, 17 Января 2017 г. 18:00 + в цитатник

There are certain tropes that show up in our articles, and judging from our comments section, our readers are well aware of them. For example, if a manager in a story says, Youre going to love working with $X, theyre very smart, its a pretty clear sign that the character in question is not very smart, and is almost certainly sure to be TRWTF in the story.

Part of this is narrative convenience- we try and keep our articles coffee-break length, and dropping a few obvious signals in there helps keep it concise. Most of it, however, really boils down to the fact that reality is full of certain patterns. The world is full of people who arent half as smart as they think they are. There are legions of PHBs ready to micromanage even if they havent a clue what theyre doing. And there are a lot of employers that can make a terrible job sound really great for the duration of the interview process.

Lets focus on that last bit: finding a new job is hard. Finding a good job is even harder. At its worst, you end up suffering your way through a horror story that ends up on this site (so hey, Internet fame, its not all bad, right?). Maybe you just end up trading hours of your life for a paycheck, doing work that you dont hate but you dont love. If youre really lucky, you land something that you really care about doing, and you get paid exactly what youre worth.

And lets not even get into the job search process- its stressful and eats enough time to be a job in itself. You have to dance around recruiters who just want the commission and dont care if the jobs a fit for anyone involved. You chuck your resume on job sites, which might as well be a black hole. You can end up investing countless hours into a companys interview process only to get an offer that isnt sufficient, or to discover that the company culture isnt what you were looking for.

Which brings us to our newest sponsor, Hired. Hired flips the script on the traditional job site. Once you fill out a simple application, employers start applying to interview you, instead of you applying for an interview. Whether youre looking for a full-time or a contract gig, whether youre looking for engineering, development, design, product management or data-science- Hired will match you up with top employers.

And top doesnt mean gigantic or corporate. Sure, theres companies like Facebook on there. But in their pool of over 6,000 employers, they have everything from titans of industry to small startups, spread across 17 major cities in North America, Europe, Asia, & Australia.

Okay, sure, there are lots of companies you might work for there, but what does this apply to interview you stuff mean? It sounds like marketing copy that Remy just pasted into this article to make the sponsor happy, and youre right- but its also so much more.

Once you have filled out Hireds application, employers who are interested in your profile will send you a personalized interview request which includes salary information up front. Hireds going to provide a talent advocate who can provide unbiased career advice to help you put the best foot forward. And Hired solves one of the worst problems of the job search: they hide your profile from current and past employers, so your boss will never find out youre searching for a new job until youre ready to tell them.

And most important: youll never pay a dime for this service. So try it out and plan your next career change.

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

http://thedailywtf.com/articles/sponsor-announcement-hired


Метки:  

The 3,000 Mile Commute

Вторник, 17 Января 2017 г. 14:30 + в цитатник
A true story, recounted from personal experience by our own Snoofle.

Many decades ago, DefCon Inc, a defense contractor working for the US military was attempting to get awarded a new contract to build some widget needed for combat. As part of their proposal, they wished to demonstrate that they had the available staff to dedicate to the project. Toward this end, they hired more than 1,000 assorted programmers, project leads, managers and so forth. The military folks that were evaluating the various proposals saw a slew of new employees that were completely unfamiliar with the relevant processes, procedures and requirements, and awarded the contract to another firm. In response, the contractor laid off all 1,000 folks.

A few months later, another such contract came up for grabs. Again, they hired 1,000 folks to show that they had the staff. A few months later, that contract was also awarded to another contractor, and again, all 1,000 folks were laid off.

A map showing the routes between Newark Airport and LAX

This repeated a few times over two years.

After all of this, the base of available employees was wise to the very short repeating hire/fire cycle, and the contractor was unable to attract anyone beyond folks fresh out of school. Finally, some C-level executive realized that all of these people just out of school were far cheaper than the experienced developers that were on staff and those that they had previously hired and fired for the potential projects, and so issued an edict that all in-house senior staff was to be cycled into cheap young employees. It took two years, but it happened.

Now that their payroll was drastically reduced, and they had royally pissed off the potential pool of experienced developers, they could increase their permanent headcount without increasing their long term payroll costs - by hiring only young, inexperienced developers - which enabled them to finally get awarded a contract.

Unfortunately, all those junior developers had very little experience, and there was nobody at the firm who had been through the war to guide them. As a result, their two year contract yielded a flaky project that frequently crashed, acted unpredictably and could not be modified. When you're dealing with a system that can shoot at and blow things up, these are not desirable or tolerable attributes.

At some point, some high level exec realized what had happened, and forced the company to stick a crowbar into its pocket and hire some highly paid consultants. Unfortunately, the HPCs remembered the hire/fire cycle and wanted nothing to do with the place. After some time, this led to substantial sweetening of the pot until a few experienced folks finally agreed to come on board as full time employees. This happened in New Jersey.

After management got the new folks up to speed on the project, the new folks said Hold on; there's a gaping hole in the middle of this project! Management replied that this part of the project was classified and could only be viewed by folks with secret clearances, and from the facility in California. OK, so relevant clearances were applied for and granted, and the senior folks were assigned to go to the CA facility for two weeks.

Before agreeing to go, the developers wanted some information as to how they'd be able to access this stuff after being familiarized with it since it could only be accessed from CA, and they all lived and worked in NJ. They were told that they'd be advised of the details when they got to CA.

OK, they all fly to the Left Coast, get settled in their hotels and go to the office.

At this point, they were informed about all of the problems that had to be fixed. On Thursday of the second week, it was determined that there was about two years of work to do all of the retrofitting that needed to be done. Again, the developers all asked How will we access this stuff from NJ? The managers replied that it had to be done locally, and that they would all be located locally for the next two years. Starting Monday.

Wait; they don't get the opportunity to discuss it with their spouses? How it might affect the kids to have one parent away 90+% of the time? Would they be willing to live in hotels and airports for two years? Why the F*** didn't they just hire talent at the CA location instead of NJ?

It turns out that because the contractor is based in NJ, the personnel they hired needed to be based there as well. Of course, had any of this been mentioned before people were hired, most (if not all) of the folks they hired wouldn't have accepted the jobs. If they had known, none of the folks would have even gotten on the plane to go for the briefing and ramp-up required to familiarize themselves with the project.

Needless to say, Thursday afternoon was spent with managers barking demands about sacrificing for the company, and developers saying WTF?! Thursday evening was spent with countless phone calls home. Friday morning was spent with everyone resigning and heading for the airport to go home.

The representatives of the military acted as decent folks and were very understanding as to why people wouldn't just leave their homes and families for two years. They were far less sensitive when it came to holding the contractor to their promise of an on-site experienced staff to do the work.

In the end, the contractor was fired and a new one was hired to clean up the mess.

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

http://thedailywtf.com/articles/the-3-000-mile-commute


Метки:  

CodeSOD: Eventful Timing

Понедельник, 16 Января 2017 г. 14:30 + в цитатник

I once built a system with the job of tracking various laboratory instruments, and sending out notifications when they needed to be calibrated. The rules for when different instruments triggered notifications, and when notifications should be sent, and so on, were very complicated.

An Anonymous reader has a similar problem. Theyre tracking Events- like seminars and conferences. These multi-day events often have an end date, but some of them are actually open ended events. They need to, given an event, be able to tell you how much it costs. And our Anonymous readers co-worker came up with this solution to that problem:

public class RunningEventViewModel : SingleDataViewModel
{
    private DateTime _now;

    private readonly Timer _timer;

    public RunningEventViewModel(EventData data)
        : base(data)
    {
        _now = DateTime.Now;

        _timer = new Timer(x =>
        {
            _now = DateTime.Now;
            NotifyOfPropertyChange(() => DurationDays);
            NotifyOfPropertyChange(() => DurationHours);
            NotifyOfPropertyChange(() => DurationMinutes);
            NotifyOfPropertyChange(() => DurationSeconds);
            NotifyOfPropertyChange(() => DurationString);
            NotifyOfPropertyChange(() => TotalCost);
        });

        if (!Stop.HasValue)
        {
            _timer.Change(900, 900);
        }
    }

    public int DurationSeconds
    {
        get
        {
            return ((Stop ?? _now) - Start).Seconds;
        }
    }

    public decimal TotalCost
    {
        get
        {
            var end = Stop ?? _now;
            const int SecsPerDay = 3600 * 24;
            decimal days = ((int)(end - Start).Duration().TotalSeconds) / (decimal)SecsPerDay;

            return (DailyCosts.HasValue ? DailyCosts.Value : 0) * days;
        }
    }

    public int DurationDays
    {
        get
        {
            return ((Stop ?? _now) - Start).Days;
        }
    }

    public int DurationHours
    {
        get
        {
            return ((Stop ?? _now) - Start).Hours;
        }
    }

    public int DurationMinutes
    {
        get
        {
            return ((Stop ?? _now) - Start).Minutes;
        }
    }

    public TimeSpan Duration
    {
        get
        {
            return (Stop ?? _now) - Start;
        }
    }

    public string FromTo
    {
        get
        {
            var res = String.Empty;
            if (Data.EventStart.HasValue)
            {
                res += Data.EventStart.Value.ToShortDateString();

                if (Data.EventStop.HasValue)
                {
                    res += " - " + Data.EventStop.Value.ToShortDateString();
                }
            }

            return res;
        }
    }

    public string DurationString
    {
        get
        {
            var duration = ((Stop ?? _now) - Start).Duration();
            var res = new StringBuilder();
            if (DurationDays > 0)
            {
                res.Append(duration.Days).Append(" days ");
            }

            if (DurationHours > 0)
            {
                res.Append(duration.Hours).Append(" hours ");
            }

            if (DurationMinutes > 0)
            {
                res.Append(duration.Minutes).Append(" minutes");
            }

            return res.ToString().TrimEnd(' ');
        }
    }

    public DateTime Start
    {
        get
        {
            return Get(Data.EventStart.Value, x => x.ToLocalTime().ToUniversalTime());
        }
    }

    public DateTime? Stop
    {
        get { return (DateTime?)null; }
    }

    public decimal? DailyCosts
    {
        get { return Data.DailyCost; }
    }

    private static TResult Get(TItem item, Func resultSelector)
    {
        // this method is actually an extension method from our core framework, it's added here for better understanding the code
        if(Equals(item, null))
        {
            return default(TResult);
        }

        return resultSelector(item);
    }
}

Is null a mistake? Well, it certainly makes this code more complicated. Speaking of more complicated, I like how this class is responsible for tracking a Timer object so that it can periodically emit events. So much for single-responsibility, and good luck during unit testing.

The real WTF here, however, is that .NET has a rich and developer-friendly date-time API, which already has pre-built date difference functions. Code like this block in TotalCost:

            const int SecsPerDay = 3600 * 24;
            decimal days = ((int)(end - Start).Duration().TotalSeconds) / (decimal)SecsPerDay;

… is completely unnecessary. Similarly, the FromTo and DurationString functions could benefit from a little use of the TimeSpan object, and a little String.format. And its clear that the developer knows these exist, because theyve used them, yet in TotalCost, its apparently too much to bear.

But the real topper, on this, is the Stop property. Once you look at that, most of the code in this file becomes downright stupid.

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

http://thedailywtf.com/articles/eventful-timing


Метки:  

Error'd: Banking on the Information Super Highway

Пятница, 13 Января 2017 г. 14:00 + в цитатник

"Good to see Santander finally embracing modern technology!" writes Sam B.

"I imagine the text could read 'Welcome user! Launch the game since you have no friends anyway and are beyond help'. Yay," writes Ruff.

Alister wrote, "Getting on the wifi with the 'network' cable was a snap but I found the range to be very limited."

"Seriously guys? WTF. They all look defined to me," B.J. wrote.

"Apparently my package had to travel back in time before it could get to me. Did I order a TARDIS by mistake?" writes Patrick.

While standing in line at customer service at Walmart, I spotted this on the customer facing screens on all of the registers at customer service. I wonder if someone wanted to buy tickets, would they be allowed?

Betsy R. writes "I once heard IBM's documentation described as sounding as if it had been translated from a foreign language by a bored high-school student. Maybe that's what happened here?"

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

http://thedailywtf.com/articles/banking-on-the-information-super-highway


Метки:  

CodeSOD: Extended Conditions

Четверг, 12 Января 2017 г. 14:30 + в цитатник

Every programming language embodies in it a philosophy about how problems should be solved. C reduces all problems to manipulations of memory addresses. Java turns every problem into a set of interacting objects. JavaScript summons Shub-Niggurath, the black goat of the woods with a thousand young, to eat the eyes of developers.

Just following the logic of a language can send you a long way to getting good results. Popular languages were designed by smart people, who work through many of the problems you might encounter when building a program with their tools. That doesnt mean that you cant take things a bit too far and misapply that philosophy, though.

Take this code, sent to us by Kogad. Their co-worker understood that objects and interfaces were fundamental to Java programming, so when presented with the challenge of three conditional statements, they created this:

package com.initrode.account.framework.process.specification;

import com.initrode.account.framework.process.CustomerRequest;

public interface ProcesSpecification {
        boolean isSatisfiedBy(CustomerRequest req);
}
//--------------
package com.initrode.account.framework.process.specification;

public abstract class CompositeProcesSpecification implements ProcesSpecification {

        public ProcesSpecification and(ProcesSpecification specification){
                return new AndProcesSpecification(this, specification);
        }

        public ProcesSpecification or(ProcesSpecification specification){
                return new OrProcesSpecification(this, specification);
        }

        public ProcesSpecification not(ProcesSpecification specification){
                return new NotProcesSpecification(specification);
        }

}
//--------------
package com.initrode.account.framework.process.specification;

import com.initrode.account.framework.process.CustomerRequest;

public class NotProcesSpecification extends CompositeProcesSpecification {

        private ProcesSpecification spec;

        public NotProcesSpecification(ProcesSpecification specification) {
                spec = specification;
        }

        @Override
        public boolean isSatisfiedBy(CustomerRequest req) {
                return !spec.isSatisfiedBy(req);
        }

}

//--------------
package com.initrode.account.framework.process.specification;

import com.initrode.account.framework.process.CustomerRequest;

public class AndProcesSpecification extends CompositeProcesSpecification {
        private ProcesSpecification specOne;
        private ProcesSpecification specTwo;

        public AndProcesSpecification(ProcesSpecification specificationOne, ProcesSpecification specificationTwo) {
                specOne = specificationOne;
                specTwo = specificationTwo;
        }

        @Override
        public boolean isSatisfiedBy(CustomerRequest req) {
                return specOne.isSatisfiedBy(req) && specTwo.isSatisfiedBy(req);
        }

}
//--------------
package com.initrode.account.framework.process.specification;

import com.initrode.account.framework.process.CustomerRequest;


public class OrProcesSpecification extends CompositeProcesSpecification {
        private ProcesSpecification specOne;
        private ProcesSpecification specTwo;

        public OrProcesSpecification(ProcesSpecification specificationOne, ProcesSpecification specificationTwo) {
                specOne = specificationOne;
                specTwo = specificationTwo;
        }

        @Override
        public boolean isSatisfiedBy(CustomerRequest req) {
                return specOne.isSatisfiedBy(req) || specTwo.isSatisfiedBy(req);
        }

}
//--------------
package com.initrode.account.framework.process.specification;

import com.initrode.account.framework.process.CustomerRequest;
import com.initrode.account.framework.process.CustomerType;

public class TypeOneProcesSpecification extends CompositeProcesSpecification {

        @Override
        public boolean isSatisfiedBy(CustomerRequest req) {
                return null != req && CustomerType.ONE == req.getType();
        }

}

//--------------
package com.initrode.account.framework.process.specification;

import com.initrode.account.framework.process.CustomerRequest;
import com.initrode.account.framework.process.CustomerType;

public class TypeTwoProcesSpecification extends CompositeProcesSpecification {

        @Override
        public boolean isSatisfiedBy(CustomerRequest req) {
                return null != req && CustomerType.TWO == req.getType();
        }

}
//--------------
package com.initrode.account.framework.process.specification;

import com.initrode.account.framework.process.CustomerRequest;

public class VerifyProcessSpecification extends CompositeSpecification
    @Override
        public boolean isSatisfiedBy(CustomerRequest req) {
                return req.hasVerificationCode();
        }
}

//--------------
// Usage:

public class ActionOne {
        private ProcesSpecification procesSpec;

        @PostConstruct
        protected void postInitialize() {
                setProcesSpecification(new VerifyProcessSpecification().and(new TypeOneProcesSpecification()));
        }

    @Override public boolean canHandle(CustomerRequest req) {
        return procesSpec.isSatisfiedBy(req);
    }

    @Override
    void doAction(...);
}

public class ActionTwo {
        private ProcesSpecification procesSpec;

        @PostConstruct
        protected void postInitialize() {
                setProcesSpecification(new VerifyProcessSpecification().and(new TypeTwoProcesSpecification()));
        }

    @Override public boolean canHandle(CustomerRequest req) {
        return procesSpec.isSatisfiedBy(req);
    }

    @Override
    void doAction(...);
}

public class ActionThree {
        private ProcesSpecification procesSpec;

        @PostConstruct
        public void postInitialize() {
                procesSpec = new NotProcesSpecification(new VerifyProcessSpecification().and(
                                new TypeOneProcesSpecification().or(new TypeTwoProcesSpecification())));
        }

    @Override public boolean canHandle(CustomerRequest req) {
        return procesSpec.isSatisfiedBy(req);
    }

    @Override
    void doAction(...);
}

This is certainly Peak Java™. Its… extensible, at least. Not that youd want to. Kogad replaced this masterpiece with a much simpler, if less extensible, chain of conditionals that were also more closely mapped to their actual requirements.

[Advertisement] Otter enables DevOps best practices by providing a visual, dynamic, and intuitive UI that shows, at-a-glance, the configuration state of all your servers. Find out more and download today!

http://thedailywtf.com/articles/extended-conditions


Метки:  

A Case of Denial

Среда, 11 Января 2017 г. 14:30 + в цитатник

RGB color wheel 72

On his first day at his new job, Sebastian wasn't particularly excited. He'd been around the block enough times to have grown a thick skin of indifference and pessimism. This job was destined to be like any other, full of annoying coworkers, poorly thought out requirements, legacy codebases full of spaghetti. But it paid well, and he was tired of his old group, weary in his soul of the same faces he'd grown accustomed to. So he prepared himself for a new flavor of the same office politics and menial tasks.

It didn't faze him much when he walked into the IT office to pick up his credentials and heard the telltale buzzing and clicking of old Packard Bell servers. He simply adjusted his expectations for his own developer machine downward a few notches and walked back to his new office. Yes, this job came with a private office, and pay to match. For that, he could put up with a lot of BS.

His login worked on the first try, which was pleasantly surprising. He expected Windows XP; when Vista loaded, he wasn't sure if he should be pleased that the OS was newer, or horrified that it was Vista. He could pretend it was 7 for a while at least, once he finished getting admin privileges and nerfing UAC. It'll take more than that to scare me off, he thought to himself as he fired up Outlook.

Already, he had mail: a few welcome messages with new employee information, as well as his first assignment from his manager. Impressed with the efficiency in assigning work, if nothing else, he opened the message from his new boss.

That first email went a little something like this:

Hi Sebastian, welcome to our super-clean environment. We do everything right here. You will use Bonk-Word (a IBM documentation web app) for design documents. Remember to save your work often! If Bonk-Word crashes, you'll need to send an email to IT to have it restarted.

We do design documentation right here. Be sure to write everything in passive voice, use Purple for chapter headings and Green for section headings. We have document review with the company president every day at 9AM so be ready for that. It's a black mark on your permanent record to have any headings wrong.

Please start designing how you are going to fix our 4-year old Macintosh font issues. We need a six-page design document by 9AM tomorrow. Thanks.

Six pages by tomorrow? worried Sebastian. Maybe I rejoiced too soon on that efficiency thing. Well, at least I won't be bored. He cracked his knuckles, opened Bonk-Word, and set about examining these so-called font issues.

The first thing he learned was that his manager wasn't kidding when he said to save often. By the end of the day, he was mentally betting with himself on which would crash first: Bonk-Word or Vista itself. They both crashed approximately every half hour. But it was somehow soothing to keep count, making tally marks on a post-it note. It reminded him that something in this world still worked. Basic math wasn't impressive, but it was reliable. Steady. Solid.

Maybe he was a little lonely in his office. But it was quiet, and private, and even if the crashing was frustrating, he made progress. He stayed late to turn out his treatise on "Delving into the diverse and varied literature that exists on the subject of font rendering, including but not limited to the Postscript specification, accompanying literature indicating the best practices for the use thereof, and extant informational centers within the World Wide Web that have been created to gather wisdom from the best minds the industry has to offer in a familiar and comforting question-and-answer format." Lather, rinse, and repeat for "Writing a Python program to render each character." He took two pages to explain the fact that he would, essentially, eyeball the results.

If they want six pages, they're getting six pages, he thought.

A strange first day, but Sebastian could see himself sticking this out for a few years at least. He took his time as he walked through the building (which smelled suspiciously of old leather undergarments) to his "free assigned ramp parking spot" (another perk he told himself made the job worth it). Walking slowly was a good idea anyway, as the ramp had terminal rust-rot and there were many places where the concrete had completely fallen off, exposing the rebar in the floors and columns.

The next morning, at 9:00 sharp, Sebastian found himself in his manager's office for his first design review with the company president, held via conference call. Sebastian was uneasy about meeting with the president directly, given the company had sixty employees, but he took it in stride.

I did as they asked, wordy as it was. Probably this is a formality and then I can get to work.

A humiliated, exhausted Sebastian crawled back to his office an hour later, his ears ringing from the nonsensical yet harsh critique he'd received. According to the president, his headings were merely "greenish" instead of the company-mandated Green, and his chapter headings were unforgivably "reddish" rather than the expected Purple. Furthermore, he'd been informed in no uncertain terms that it was "impossible" to debug the font using Python. Instead, he was to work in C++, using the company's "marvelous" software libraries. Sebastian's manager had praised the document while they were waiting for the president, but had failed to utter a single word once the review began, his eyes fixed firmly on the brick wall behind his desk.

Sebastian closed the door to his office, blocking out the rest of the company. He sat in his plush leather chair, staring at the machine that barely worked. He opened his document again, then rebooted his machine once Vista decided to crash. When the machine came back up again, he checked his bank balance, thought of his mortgage, and gritted his teeth.

"All right," he said aloud to his empty office. "Let's see about those libraries."

The first thing he looked for was documentation. Surely, in a company as document-focused as this one, the documentation for the "marvelous" libraries would be exactly the right shade of exactly the right font, with exactly the right chapter headings and section names. Instead, it appeared to be ... missing. There were design documents galore, and their greens were more green and their purples showed far less red. But they only spelled out the methodology behind the development of the library, and said nothing of its proper usage.

Am I going mad? Sebastian asked himself as his machine restarted for the third time. Maybe the code is self-documenting ...

To his horror, but not particularly his surprise, the libraries simply consisted of poorly thought out wrappers around basic string functions from the standard library.

Sebastian gave it his all despite the setbacks. Every day, he was summoned for another round of verbal browbeating. The company had made no progress in the past four years with this font issue, and yet, nothing he did was good enough for the president. Sebastian gave up on the custom library, sticking with the Python he knew; after all, if he was going to be berated anyway, why bother trying to do as he was told? But no matter whether he used his own font tester in Python, or Microsoft's tester, or Apple's, or Adobe's, the font was an absolute mess. 488 intrinsic, unfixable, unkludgable design errors.

The president flatly denied the truth before him. It had to be Sebastian's fault for not using the wonderful C++ libraries.

Out of options, Sebastian left the key to the rusting, collapsing wreck of a garage on his manager's desk along with a letter of resignation. He kissed his lovely office with its decrepit pile of crap they called a machine goodbye. He took a deep breath, letting that disturbing leather smell permeate his nostrils one last time. Then he left, never to return.

Somehow, he doubted he'd miss the place.

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

http://thedailywtf.com/articles/a-case-of-denial


Метки:  

CodeSOD: Mapping Every Possibility

Вторник, 10 Января 2017 г. 14:30 + в цитатник

Capture all

Today, Aaron L. shares the tale of an innocent little network mapping program that killed itself with its own thoroughness:

I was hired to take over development on a network topology mapper that came from an acquisition. The product did not work except in small test environments. Every customer demo was a failure.

The code below was used to determine if two ports on two different switches are connected. This process was repeated for every switch in the network. As the number of switches, ports, and MAC addresses increased the run time of the product went up exponentially and typically crashed with an array index out of bounds exception. The code below is neatly presented, the actual code took me over a day of repeatedly saying "WTF?" before I realized the original programmer had no idea what a Map or Set or List was. But after eliminating the arrays the flawed matching algorithm was still there and so shortly all of the acquired code was thrown away and the mapper was re-written from scratch with more efficient ways of connecting switches.


public class Switch {
    Array[] allMACs = new Array[numMACs];
    Array[] portIndexes = new Array[numPorts];
    Array[] ports = new Array[numPorts];

    public void load() {
        // load allMACs by reading switch via SNMP
        // psuedo code to avoid lots of irrelevant SNMP code
        int portCounter = 0;
        int macCounter = 0;
        for each port {
            ports[portCounter] = port;
            portIndexes[portCounter] = macCounter;
            for each MAC on port {
                 allMACs[macCounter++] = MAC;
            }
        }
    }

    public Array[] getMACsForPort(int port) {
        int startIndex;
        int endIndex;
        for (int ictr = 0; ictr < ports.length; ictr++) {
            if (ports[ictr] == port) {
                startIndex = portIndexes[ictr];
                endIndex = portIndexes[ictr + 1];
            }
        }
        Array[] portMACS = new Array[endIndex - startIndex];
        int pctr = 0;
        for (int ictr = startIndex; ictr < endIndex - 1; ictr++) {
            portMACS[pctr++] = allMACs[ictr];
        }
        return(portMACS);
    }
}

...
for every switch in the network {
    for every other switch in the network {
        for every port on switch {
            Array[] switchPortMACs = Switch.getMACsForPort(port);
            for every port on other switch {
                Array[] otherSwitchPortMACs = OtherSwitch.getMACsForPort(other port);
                if (intersect switchPortMACs with otherSwitchPortMACs == true) {
                   connect switch.port with otherSwitch.port;
                }
            }
        }
    }
}

[Advertisement] Onsite, remote, bare-metal or cloud – create, configure and orchestrate 1,000s of servers, all from the same dashboard while continually monitoring for drift and allowing for instantaneous remediation. Download Otter today!

http://thedailywtf.com/articles/mapping-every-possibility


Метки:  

Healthcare Can Make You Sick

Понедельник, 09 Января 2017 г. 14:30 + в цитатник

Every industry has information that needs to be moved back and forth between disparate systems. If you've lived a wholesome life, those systems are just different applications on the same platform. If you've strayed from the Holy Path, those systems are written using different languages on different platforms running different operating systems on different hardware with different endian-ness. Imagine some Java app on Safari under some version of Mac OS needing to talk to some version of .NET under some version of Windows needing to talk to some EBCIDIC-speaking version of COBOL running on some mainframe.

Long before anyone envisioned the above nightmare, we used to work with SGML, which devolved into XML, which was supposed to be a trivial tolerable way to define the format and fields contained in a document, with parsers on every platform, so that information could be exchanged without either end needing to know anything more than the DTD and/or schema for purposes of validation and parsing.

In a hopelessful attempt at making this somewhat easier, wrapper libraries were written on top of XML.

Sadly, they failed.

A hand holding a large pile of pills, in front of a background of pills

In the health care industry, some open-source folks created the (H)ealthcare (API), or HAPI project, which is basically an object oriented parser for text-based healthcare industry messages. Unfortunately, it appears they suffered from Don't-Know-When-To-Stop-Syndrome™.

Rather than implementing a generic parser that simply splits a delimited or fixed-format string into a list of text-field-values, the latest version implements 1205 different parsers, each for its own top-level data structure. Most top level structures have dozens of sub-structures. Each parser has one or more accessor methods for each field. Sometimes, a field can be a single instance, or a list of instances, in which case you must programmatically figure out which accessor to use.

That's an API with approximately 15,000 method calls! WTF were these developers thinking?

For example, the class: EHC_E15_PAYMENT_REMITTANCE_DETAIL_INFO can have zero or more product service sections. So right away, I'm thinking some sort of array or list. Thus, instead of something like:

    EHC_E15_PAYMENT_REMITTANCE_DETAIL_INFO info = ...;
    List prodServices = info.getProductServices();
    // iterate

... you need to do one of these:

    // Get sub-structure
    EHC_E15_PAYMENT_REMITTANCE_DETAIL_INFO info = ...;
	
    // Get embedded product-services from sub-structure

    // ...if you know for certain that there will be exactly one in the message:
    EHC_E15_PRODUCT_SERVICE_SECTION prodSvc = info.getPRODUCT_SERVICE_SECTION();
	
    // ...if you don't know how many there will be:
    int n = infos.getPRODUCT_SERVICE_SECTIONReps();
    for (int i=0; i/ use it
    }

    // ...or you can just grab them all and iterate
    List allSvcs = info.getPRODUCT_SERVICE_SECTIONAll();

...and you need to call the correct one, or risk an exception. But having multiple ways of accomplishing the same thing via the API leads to multiple ways of doing the same thing in the code that is using the API, which invariably leads to problems.

So you might say, OK, that's not SO bad; you just use what you need. Until you realize that some of these data structures are embedded ten+ levels deep, each with dozens of sub-structures and/or fields, each with multiple accessors. With those really long names. Then you realize that the developers of the HAPI got tired of typing and just started using acronyms for everything, with such descriptive data structure names as: LA1, ILT and PCR.

The API does attempt to be helpful in that if it doesn't find what it's expecting in the field you ask it to parse, it throws an exception and it's up to you to figure out what went wrong. Of course, this implies that you already know what is being sent to you in the data stream.

Anonymous worked in the healthcare industry and was charged with maintaining a library that had been wrapped around HAPI. He was routinely assigned tasks (with durations of several weeks) to simply parse one additional field. After spending far too much time choking down the volumes of documentation on the API, he wrote a generic single-class 300 line parser with some split's, substring's, parseDate's and parseInt's to replace the whole thing.

Now adding an additional field takes all of ten minutes.

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

http://thedailywtf.com/articles/healthcare-can-make-you-sick


Метки:  

Error'd: Errors for Everyone!

Пятница, 06 Января 2017 г. 14:00 + в цитатник

"All I wanted to do was to unsubscribe from Credit Sesame emails, but instead I got more than I bargained for," writes Shawn A.p>

Mike R. wrote, "Sure, Simon Rewards, I'll click the button to update GlassWire, but only if there's a reward in it for me."

"This blue screen ad campaign is really convincing. I'm sold!" writes Roger K.

"I hope it's just a quick coffee run," wrote Jeremy E.

Ben writes, "It's good to see Windows XP reliably running ticket machines in the Southern Rail region of the UK ( picture credit to Gil Tompkinson from Brighton)"

"Jerusalem Central bus station has installed new automatic ticket machines which is nice," Eugene F. wrote, "I certainly would like the interface to be at least a little bit more descriptive though."

Phil wriktes, "A colleague was driving behind a van labelled with farmersmeats.co.uk - so we decided to check out their site. However based on the 'Latin' descriptions alone it is difficult to tell each meat apart."

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

http://thedailywtf.com/articles/errors-for-everyone


Метки:  

A Font of Misery

Четверг, 05 Января 2017 г. 14:30 + в цитатник

After his chilling encounter in the companys IT Cave, new hire George spent some time getting his development workstation set up. Sadly, his earlier hope that the PC in his office was a short-term placeholder until something better comes in was dashed to pieces. This PC was a small-form-factor budget system, relying on an old dual-core processor, 2 GB RAM, a 5400 RPM green disk drive, and integrated graphics with a single output port, to which was connected an aging 17" LCD monitor with a failing backlight.

A preview of a glitchy font

George got to work installing software packages from a network drive, presumably clicking itself to death in the dark IT office. With a PC nearly ten years behind the curve, George had plenty of time, several days, in fact, to drink coffee while exploring the building. His unease from the encounter with the IT guy eventually faded as he met other employees who seemed as normal as he, discovering conference rooms with normal-looking Scrum boards, and offices and cubicles that would not appear out-of-place in any modern, successful software company. A friendly member of the Marketing Department even gave him some swag: logod pens and stress balls and notepads. Perhaps the unusual IT guy and his dark, precarious office was just an anomaly to an otherwise excellent organization.

A week into his new job, George finally had his system set up enough to look around at the software products hed be working on. During his interview, hed been told everything was superbly documented.

A coworker emailed him links to their developer documentation which was hosted on an internal server somewhere. George followed the link, and his web browser sat on a loading page for way too long. As he waited, and waited, and waited for the page to load, he almost thought he could hear the clicking and clunking of failing disk drives from whichever ancient pile of failing hardware served as the companys documentation server, but eventually a SharePoint page presented itself on his screen.

The Developer Documentation was unexpectedly short. In fact, George read through it faster than it took to load, feeling a sense of dread once he realized what it actually was: three pages of buzzword-laden marketing material! He read about how superb the application is and how it has helped millions of companies leverage new synergies for key wins. Nowhere could he find a simple, developer-centric description of the application. When he pressed for more documentation, his coworkers shrugged. That is the documentation, they explained. The bosses say its good enough and its a waste of time to write more.

Georges sense of dread continued to increase.

And so he did all he could. He checked out the application from source control and went spelunking.

On his first run, he noticed the applications text did not look right. Characters were glitched in various ways, with bad kerning, inconsistent alignment, and missing/extra pixels, though it was still generally readable with some effort.

Thinking he was missing a dependency, he asked his coworkers for their opinion. No, it normally does that, they explained with a shrug. Most of the time.

Do we have unit tests for this? he asked, but deep down in his gut he knew he wouldnt like the answer.

Testing programs are in the design and planning stage, they responded, even though the application had been on the market for eight years now. The bosses dont like to spend too much time on testing.

He still had no direction on what tasks to perform, so George took it upon himself to dig into the font issue, if nothing else to learn more about the codebase. He downloaded a few third-party font test programs from some prominent tech companies and they all agreed that the application had nearly 1,300 basic font rendering errors.

His sense of dread was starting to overwhelm him as he considered his future. How could an application possibly have millions of sales and installs with nearly-unreadable fonts? And how could it possibly be maintained with no testing and no documentation?

He wrote a memo explaining some of his findings and forwarded it to several coworkers, and asking various questions about it before putting too much effort into fixes that could cause issues unforseeable by a newbie who was not familiar with the history behind the applications overly-complex font-handling codebase.

Later that day, he received a long email directly from the company president. In tirade form, it explained that George was wasting time, there cant possibly be that many bugs, and if anything like this happens again the time would be deducted from his paycheck. It ended with the president explaining that George was obviously a f***up who would never amount to anything at the company, but he was willing to give him another chance.

George didnt want another chance. As he walked past the IT Office on his way to the HR Office to announce his resignation, he briefly wondered how much damage his foam stress ball could do to already-failing disk drives if he were to chuck it through the door into the darkness within.

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

http://thedailywtf.com/articles/a-font-of-misery


Метки:  

CodeSOD: Sche-ma

Среда, 04 Января 2017 г. 14:30 + в цитатник

In the early 2000s, it was a time of darkness, a world of fear, it was the age of XML. As someone who was just entering the industry at the time, you couldnt type three lines of code without a PHB asking, Have you considered using XML for this? Since this was 2002, this was likely trying to find a way to emulate the marquee tag in JavaScript, the answer was usually, No, at which point youd be reminded that we should be using XML for everything, so throw it out and start over in XML.

One of the key selling points of the grand power of XML was the idea of schemas. These magical little files allowed you to use XML to specify the structure of some other XML, and then validate various XML documents against that schema. Combined with the ability to use namespaces, this was truly the One Format to Rule Them All™.

The real magic, of course, was that since XML was a text based format with a clear (if complicated) parsing mechanism, it could be produced and consumed by any system, including those pesky legacy mainframes that were sure to be replaced any year now. Vendor after vendor came up with new and interesting ways to bolt XML onto your mainframe, so that you could wire modern applications up to those legacy back ends, and when you wanted to replace that legacy backend (theyre going away, any year now! Really!), you could slap a modern backend behind the same XML interface.

I bring up this history lesson because John B works for a very large, government-type organization. He maintains an XML data-feed that passes around location data. I strongly suspect that the schema for that XML data-feed was generated based off of an older flat-file dataset from a legacy system. Why? Well, lets look at a sample file.

    
            01
            01.6122
            N
            -
            001
            001.1641
            W
        

Theres something odd there- I cant quite put my finger on it- theres a strange character- just jammed into the middle- what?

Yes, there is a element. And not only is this element there, its absolutely required. Heres the schema for the LatitudeAndLongitudeMinutes04DecimalPlaces:

        
                
                        
                                LATITUDE AND LONGITUDE, MINUTES, 0-4 DECIMAL PLACES
                                THE INTERSECTING LINES OF LATITUDE AND LONGITUDE WHICH DETERMINE THE GEOGRAPHICAL POSITION OF ANY PLACE ON THE EARTH'S SURFACE, EXPRESSED UP TO ONE TEN THOUSANDTH OF A MINUTE.
                                2571
                                1
                                2.0
                                
                                
                        
                
                
                        
                                
                                        
                                                1
                                        
                                
                        
                        
                                
                                        
                                                2
                                        
                                
                        
                        
                                
                                        
                                                3
                                        
                                
                        
                        
                                
                                        
                                                4
                                        
                                
                        
                        
                                
                                        
                                                5
                                        
                                
                        
                        
                                
                                        
                                                6
                                        
                                
                        
                        
                                
                                        
                                                7
                                        
                                
                        
                
        

If you havent worked with XML schemas before, count your blessings, and dont try and make sense out of this. Just pay attention to this tag: , which actually references an external schema. Thats right, this isnt just a Hyphen element, its a whole datatype just to represent hyphens.

        
                
                        
                                HYPHEN
                                
                                1025
                                2
                                1.0
                                1
                                1
                                Fixed
                                String
                                
                                
                                Individual
                        
                
                
                        
                                
                                        
                                                String
                                                
                                                -
                                                HYPHEN
                                                1
                                        
                                
                        
                
        

Not only is there a HyphenType, but the HyphenType contains an enumeration! This makes it extensible, for if you ever need to add different kinds of hyphen-like characters, like –, —, or −.

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

http://thedailywtf.com/articles/sche-ma


Метки:  

The Helpful Manager

Вторник, 03 Января 2017 г. 14:30 + в цитатник

Computer-security-incident-initial-process.png

Git is a divisive piece of technology. There's a number of people who insist that it's the best of all possible version controls, often citing the fact that a complete repo copy is on everyone's computers in case of emergency. There are also a lot of horror stories of people screwing up commands and ending up neck-deep in tutorials, desperately trying to undo what they did. Recently, I was involved in a discussion about the merits of Mercurial. The usual git fans stopped by to ridicule the lack of history-rewriting in Mercurial, insisting that it's a necessary part of any version control. Which reminded me of this reader submission ...

Toni worked at a certain company that worked on inventory systems, and was also a defense contractor. Her manager quit out of protest; the new boss—whose name was Alexander, but he insisted on being called "Lex"—was assigned to the team from upon high. Lex was a dopey corporate puppet who liked to talk about Bob Dole a lot. The best the team could hope for was that he'd stay out of their way, making vague promises about the future but not actually accomplishing anything. After all, they had done just fine without a boss for eight months.

What they didn't know? Lex had been given the keys to the kingdom: their server git repository, and everything in it.

One fateful morning, Toni woke up at 4:00 AM to an SMS saying that the code repository at work had been accessed by "a new member of the compliance team."

... What? she wondered, groggily. There was no new member on the "compliance team." That wasn't even a real department name! Damn it, we've been hacked.

She rushed to the office, wide awake at this point, praying for no cops with speed guns on the way there.

Did someone break in? she wondered. Or worse, hack into the local code repository from one of the ports the IT guys kept forgetting to close? Surely a randomly generated password longer than a bible couldn't have been cracked, right?

By 8:00 AM, she hadn't found any sign of intrusion. She was asleep at her desk from exhaustion when her co-worker, Clarissa, came in. Clarissa had just wiped her MacBook Pro clean the night before due to a botched OS X update. She had also gotten a text message, but had assumed it was Toni, as she'd been working late the night before.

Clarissa was able to discover what Toni had overlooked: to their horror, two new people, with names 20 characters long, had been "invited" into the team, and the team had been "renamed" to Compliance.

That was when they both got an email from Lex. I thought you could use some help! :)

That "help" came in the form of two dimwits from the Chennai, India branch, recently acquired by merger a year before. Through Slack, they admitted to the existing team members that they had never used a version control system before.

Toni was already seeing red at this point, but the day was just beginning to reveal the depths of insanity that were in store for them.

The two new team members had decided that the color of the web-based inventory front-end wasn't "good enough." Now, this had just gone through a redesign; the colors matched the official design guideline, and had been agreed on by numerous stakeholders. Not only did the newbies change the colors, they decided to deploy those changes to the main Internet-facing servers without going through QA.

Toni was still processing that little gem when she heard the fires of hell erupt from Clarissa's cubicle.

Clarissa told Toni that their "friends" had pushed code to master, bypassing QA, while also tinkering with her custom branches. As if that wasn't bad enough, they'd used an editor that had converted all the source code files on her branch to Windows format, which screwed up all the line endings. Immediately, this caused conflicts with the existing frameworks, and one of their parsers no longer worked.

In a fit of brillance, the two new helpers had decided a force push would do the trick. Surely it couldn't be their color tweak breaking things, right? Apparently, they'd figured out that it was. Shortly after, they'd copied over the files from master, pasted them in the working folder, and force pushed with a fake name, erasing all history on said branch in a terrible attempt to cover their tracks.

Remember how Clarissa had wiped her MacBook the night before? If Toni hadn't cloned the entire repository to her ThinkPad for Thanksgiving tinkering, Clarissa would've lost four to eight months of work.

They received word that the interim manager, on vacation in Tampa, had hopped on a plane after getting the same SMS they did. He could've flown in with his own two arms given the level of pissed-off he was when he slammed open the office door. Lex walked in with coffee to see the door nearly fly off the hinges.

It turned out that the website had been inoperable for eight hours. With worldwide clients, this was a bad, bad thing. After the interim manager finished steamrolling Lex with expletives, he told the team that, due to US regulations, using foreign workers without security clearances could bring up to $10K of fines per infraction.

Salespeople barged in behind him with questions about why the interface had changed without any notification. The QA team followed the salespeople, also demanding answers.

Lex turned the color of wax paper. "Well, I guess I should remove the other twenty guys I just added to the repository, then."

Lex is no longer with the company.

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

http://thedailywtf.com/articles/the-helpful-manager


Метки:  

CodeSOD: Do You Think This is a Game?

Понедельник, 02 Января 2017 г. 14:30 + в цитатник

Weve passed Christmas and made our way through a Steam sale with our wallets mostly intact, and now most of us have a pile of games that well probably never actually play.

Game programming is hard. Setting aside the cultural problems in the industry- endless crunches, compensation tied to review scores, conflicts between publishers and studios, and a veneer of glamour over unglamorous work- the actual work of developing a game is a hard job.

Building a game engine is even harder. Not only do you have to build highly performant code, you have to build a system flexible enough so that game developers can build a game on top of it. You need to provide a set of high-level abstractions that make it easy for them to build a game, and this is where the problems come in.

For example, I went through a brief period of playing Frozen Cortex, an interesting approach at a turn-based sports game. I was stunned at how badly it performs, though. Weirdly, its not during gameplay that performance stinks, but when staring at the menus. I was puzzling over this for some time, when Anonymous sent us a message.

You see, Frozen Cortex is build on the Torque engine, and our anonymous submitter is working on a different game that also uses the Torque engine. And theyve encountered a few… special warts.

First, take a look at this code:

    a = getWords("The quick brown fox jumped over the lazy programmer.", 3);
    b = getWords("The quick brown fox jumped over the lazy programmer.", 3, 5);
    c = getWords("The quick brown fox jumped over the lazy programmer.", 3, 2);

getWords is a substring function, taking a string, the starting index and the ending index. Now, what would you expect to happen if the ending index comes before the starting index? Would you expect it to throw an exception? Well, bad news- TorqueScript has no concept of exceptions. It just crashes the entire game. This is a great tool to teach you how to be a better defensive programmer.

Now, you could argue that prohibiting exceptions is a pretty clever optimization- exceptions and stack unwinding are expensive operations. We have to wonder though, because heres a performance comparison between calling a function and in-lining the operation:

    ==>%r=getRealTime();for(%i=0;%i<999999;%i++)%d=getMin(getRandom(),getRandom());echo(getRealTime()-%r);
    7040
    ==>%r=getRealTime();for(%i=0;%i<999999;%i++)%d=(%a=getRandom()

http://thedailywtf.com/articles/do-you-think-this-is-a-game


Метки:  

Best of…: Best of 2016: Tern Around…

Пятница, 30 Декабря 2016 г. 14:30 + в цитатник
While looking at our most popular CodeSODs this year, I noticed we had two popular ones that both involved the ternary operator. So, what the heck, this one's a twofer. Originally, "As the World Ternaries" and, "Returnary". -- Remy

As the World Ternaries

Ah, the ternary operator. At their worst theyre a way to obfuscate your code. At their best, theyre a lovely short-hand.

For example, you might use the ternary operator to validate the inputs of a function or handle a flag.

Adam Spofford found this creative use of the ternary operator in a game hes developing for:

    this.worldUuid = builder.worldId == null ? null : builder.worldId;
    this.position = builder.position == null ? null : builder.position;
    this.rotation = builder.rotation == null ? null : builder.rotation;
    this.scale = builder.scale == null ? null : builder.scale;

    this.worldUuid = builder.worldId;
    this.position = builder.position;
    this.rotation = builder.rotation;
    this.scale = builder.scale;

Curious about how this specific block came to be, Adam poked through the Git history. For starters, the previous version of the code was the last four lines- the sane lines. According to git blame, the project lead added the four ternary lines, with a git comment that simply read: Constructing world details. That explains everything.


Returnary

Theres a certain class of bad code weve all seen before:

boolean someFunction() {
    if (someBooleanExpression) {
        return true;
    } else {
        return false;
    }
}

Its dumb, but largely harmless. Weve posted variations on this idea in the past. Scott P, however, found a new variation that may be the pinnacle of this kind of simple-minded programming. Ill let him introduce it.

I inherited a project that was developed in isolation by a lone developer that didnt do code reviews. I find something new to be horrified about every day. The developer responsible has a knack for adding unnecessary complexity to what should have been a much simpler application. This method perfectly sums up what the architecture of this application is like on every level. Its layer upon layer of obfuscation or redundant code.

boolean hasFeatures() {
        if (license.getFeatures().size() > 0 ? true : false) {
                return true;
        }
        return false;
}

Honestly, I think the ternary operator doesnt get enough use. We should just start putting ternary expressions all over our code, even if it means writing things like: myvar = true ? valueReturningFunction() : valueReturningFunction();. Isnt that pretty great? I love it.

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

http://thedailywtf.com/articles/best-of-2016-tern-around


Метки:  

Best of…: Best of 2016: Dude, Where's My Hard Drive

Четверг, 29 Декабря 2016 г. 14:30 + в цитатник
Instead of our standard workplace fare, this story is a bit different, because TRWTF is the Windows Registry. --Remy

Hard disk head crash

What, again? Michael stared at the Explorer window in disbelief. The free disk space bar was glowing red, and the text underneath reported that his half-terabyte system partition had a measly few gigs left before filling up.

When it had first happened, he hadn't thought twice about it. In fact, he'd been rather glad; at least he'd had the motivation to finally discard all the games and software he would never use again. But when the disk space ran out again the next month, and again the month after, he started getting more and more worried. Was he really using that much space, or was something else going on?

Curious, he decided to finally investigate the issue. A cursory look at his hard drive with WinDirStat confirmed his suspicions. With over 80 percent of his hard drive space labelled as "unknown", something was definitely amiss. He kept searching, manually scouring through his folders and files, until finally he managed to pinpoint the culprit: an innocuously named "C:\Windows\System32\Config" folder filled with hundreds of thousands of files, taking up 420 gigabytes in size.

A quick trip to Google and a bit of playing with Process Monitor revealed the answer to the mystery. As it turned out, every modification to Windows Registry—the oft-derided database of all the Windows and Windows application settings—generated a transaction log file to ensure the data integrity, prevent corruption, and allow rollback of changes. Usually those small 512KB files weren't much of an issue. They got deleted after a clean reboot, and most software only modified the registry during installation or after a configuration change.

However, some applications and drivers—among them, Nvidia's 3D service—didn't play nice with the registry, shuffling the values around every few seconds or minutes. That, together with Michael's habit of not turning the computer off too often, resulted in cluttering the disk with more and more files until it filled up completely.

The solution, luckily, was rather simple. Michael purged the folder of all but the most recent log files, then uninstalled all the unnecessary bloatware from Nvidia, hoping it was the last thing he'd be deleting for a long while.

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

http://thedailywtf.com/articles/best-of-2016-dude-where-s-my-hard-drive


Метки:  

Best of…: Best of 2016: The Website Hacker

Среда, 28 Декабря 2016 г. 14:30 + в цитатник
This week, we're reviewing the best WTFs of the year. In this installment, overreactions from management are their own WTF. --Remy

Test Case Added

An investment bank had just completed development on a new digital retailing platform. Daniel was assigned to a cross-functional automated test team, gearing up to test the platform's web application—or at least trying to. Charlie, a veteran manual tester from QA, had been vocal in his opposition.

"Automated tests need to be tested themselves, which means the testers need to test the tests, so automation doesn't save anything. If anything, it creates more work! Besides, we should always be striving to recreate the user experience as closely as possible!"

Daniel and the other developers insisted that manual testing was valuable, but automation needed to happen too. The conflict marched up the org chart, culminating in a meeting with Charlie's boss, Daniel's boss, their bosses, their bosses' bosses, all the way up to where these branches of the organization finally joined.

The verdict was handed down. Charlie was appointed the leader on testing the web application, running through the same test cases in a manual fashion to catch any problems that fell through the cracks.

The team—developers, QA, and a tech lead—all abandoned their cubes to huddle together in a large conference room. Everything went smoothly until one afternoon, when Charlie piped up with the nervousness of one staring down a cobra poised to lash out.

"Fellas? I don't know how I did it, but I hacked into the website somehow. I see all of the code."

The people seated closest to him glanced up from their work to trade frowns.

"What do you mean?" Daniel asked, glancing across the table at Charlie.

"I'm in the browser, and I can see all of the code!" Charlie explained. "I've hacked into the website. I see stuff like, 'div class equal sign—'"

In other words, the HTML source. Those who were listening in burst into relieved laughter, prompting everyone else in the room to quit their work and pay attention to the faux emergency.

The far more patient tech lead bit her bottom lip to hide her grin. "Charlie, it sounds like you opened the developer tools in Chrome by accident. Press F12, it'll go away."

Charlie hunted down the key and pecked it with a single loud stroke. "OK, it's gone," he said as though he’d just diverted a nuclear strike. His gaze swept over the room with a mix of urgency and confusion. "I'm still really concerned. That shouldn't happen!"

"It's supposed to do that," Daniel explained. "Go to any website you want, you can do that on any of them."

"What?!" Charlie flipped to a different browser tab, then pressed F12 again. "What?! No!"

Another burst of laughter drowned out his concern.

"Check out the leet haxxor here," one of the developers cracked.

"Step away from the computer, Charlie, before you hack the whole Internet!" another developer commanded, pointing a finger-gun at the hapless tester.

"Charlie, it's just—" Daniel tried to say.

"We can't keep using this browser!" Charlie declared. "I'm raising a defect for this!"

"All browsers have something like that for debugging purposes," Daniel explained. "It's not just Chrome."

But as the giggles continued around him, Daniel's plea seemed to fall on deaf ears. Charlie tabbed over to their bug tracker and took to some furious hunting and pecking.

Daniel shook his head. Let Charlie log his defect if it made him feel better. Surely no one would take it seriously.

Unfortunately, QA heads and project leads took "security threats" very seriously. The conflict escalated up through bosses, bosses' bosses, and eventually, the verdict was handed down. To avoid exposing code to users, further web development and testing involving Chrome was suspended company-wide.

[Advertisement] Application Release Automation – build complex release pipelines all managed from one central dashboard, accessibility for the whole team. Download and learn more today!

http://thedailywtf.com/articles/best-of-2016-the-website-hacker


Метки:  

Best of…: Best of 2016: The Inner JSON Effect

Вторник, 27 Декабря 2016 г. 14:30 + в цитатник
As we review this year's greatest hits, let's revisit the latest incarnation of the dreaded "Inner Platform Effect". --Remy

Jake eagerly stepped into his new job, grateful for more experience and new challenges, craving to learn new software stacks and see what his new company had to teach him about the world of software.

They told him hed be working on some websites, dealing with JavaScript, Node.js, JSON, and the like. It sounded pretty reasonable for web development, except for the non-technical interviewers comment that it was all built on top of Subversion which he assumed was a simple misunderstanding.

A mockup of JSON and its visual representation

Then he was thrust into a project using the companys custom JSON-based Domain Specific Language, or JDSL. His boss told him to check out a copy of the project hed be assigned to, and spend a week or two getting familiar with it. Just ask anyone for help if you have questions, but you shouldnt have any trouble judging from your experience.

So Jake began an SVN checkout&and long story short it took two days to complete. When he asked about it, his coworker Scott told him, Oh thats normal. Just play Solitaire or something until it finishes.

Two days later he started poking around. He started with a seemingly-innocuous file called customers.json and stared in confusion at its contents:

    {
        "File" : "Customers.json",
        "Class" : "Customers",
        "Author" : "redacted@redacted.com",
        "Purpose" : "",
        "Functions" : [
            568,
            899,
            900,
            901,
            902,
            1877,
            2880
        ]
    }

The project was full of such files, along with some apparently-incomplete code files such as this one called customers.js:

    Customers.prototype.UpdateBillingInfo = function(info)
    {
        this.cc = info.cc;
        this.type = info.type;
        this.name = info.name;
        this.expM = info.expM;
        this.expY = info.expY;
        this.ccv = info.ccv;

        /* snip a bunch of similar lines */
        this.saveToDatabase();
    };

After a couple days of spelunking through the codebase, and not finding even a single code comment, Jake could make no sense of what he was seeing, and finally asked for help. A coworker named Scott was available and sat with him to walk through some things.

Oh, you just dont get it yet, he began. JDSL was written by Tom. Hes a super-genius and wrote JDSL himself. So basically that customers.json is just metadata used to put together the Customers class. He waited for Jake to get it.

He didnt. So&how do I run it? he asked.

Scott laughed. You wouldnt want to just run it. It takes a couple days for a new deployment to finish starting up. JDSL can be a little slow, but its really powerful. Really powerful. Like I said, Tom is a genius.

Jake still wasnt getting it. So walk me through this metadata file. What does it do?

Scott laughed again. This is the genius part. See here where it says Class?

Uh-huh.

Well thats the class name. Now, see down here where it says functions?

Yeah.

Well those are subversions link to all the functions that make up the class!

&I still dont understand& Jake responded. Inwardly he thought he started to understand, but prayed he was wrong.

So you have customers.json and customers.js. The JSON file is the metadata and the JS file has all the code. So the list of functions in the JSON file tells JDSL to look up those revisions of the JS file to find what functions are available. In this case the actual code is in revisions 568, 899, 900, 901, and so on.

Jake blinked slowly, hoping he was just being hazed. Um&

Each revision of customers.js has one function, so to add functions all you have to do is check in your new code and update the JSON metadata file with the new revisions!

Jakes confusion turned into incredulity.

Whenever something makes a function call on a Customer object, JDSL uses the list of function revisions to check out all the actual functions until it finds a match! Understand?

&I think so&

Like I said, Tom is a genius! This lets you track every function that has ever existed. You can add new functions by overwriting the JS file and adding a new revision to the JSON, and you can remove a function just by removing its revision number from the function list. And its still there in history, inactive but never lost! Scott stood. Let me know if you have any more questions, he said as he left Jakes desk.

Armed with Scotts insight into JDSL, Jake slowly began to understand the system, checking out multiple revisions of each file so he could piece them together and see what was going on at runtime. He soon realized it was merely a web portal to allow customers to update their personal information, but thanks to the complexity of JDSL it took days to do coding work that should only take minutes.

As he went through the code, still familiarizing himself with it, he started checking in code comments to help him and his coworkers map together the convoluted mess, and even fixed a few obvious bugs he found just by reading the code. He did this one class at a time, and at the end of the week he updated and checked in all the JSON metadata files to use the new function revisions.

Monday morning, he showed up to a virtual firestorm. Everyone was in a panic. Something broke with JSDL and our customer database got scrambled! Scott quickly explained as he passed Jake in the hallway.

You! a voice boomed.

Jake stopped and turned to face a tall, lanky, pale blond man who was obviously angry. Are you Jake? The new guy?

Yes, he answered carefully.

Im Tom. You broke JDSL!

Uh, what? Jake had only been looking at the customer portal. How could he have caused any problems?

You broke JDSL! he screamed. Im reporting you to the bosses and having you fired! And Tom turned and stormed off, leaving Jake standing confused.

Shortly afterwards, Jake was summoned to a small conference room. Tom, an employee from HR, and a couple Vice Presidents waited for him. Tom looked like he was stewing and could boil over any minute.

Tell us what you did to JDSL, one of the VPs asked.

I dont think I did anything, Jake answered. Ive only been here two weeks, trying to learn JDSL and how the customer portal works. I dont even know how to deploy it!

You made a few commits to Subversion! Tom shouted.

Well, yes. I added a few code comments, trying to

You cant use comments in JDSL! Tom shouted. THATS WHAT BROKE IT!!

Jake stayed silent, trying to process how code comments could wipe out a customer database. Tom continued after a pause. I havent added comment support to JDSL, so the runtime executes comments like normal code! You must have had database updates in some comments?!

Well, yeah, I put a couple short syntax examples in a comment to clarify

Tom burst to his feet. I knew it! You BROKE IT! He turned to face the VPs. I cant deal with coders who dont understand the system! You will either fire Jake&or I quit! And he stormed out of the room.

The VPs turned to the HR representative and talked as if Jake wasnt even in the room. I think our course of action is pretty clear. Toms a programming virtuouso and our best resource, and Jake did delete the database. We have to fire Jake.

And so Jake moved on to greener pastures. Much greener pastures. Ones where production systems didnt do dozens of SVN file checkouts for each function call at runtime. Ones where production systems didnt automatically use the latest trunk. And ones that didnt come to a complete standstill because a newbie checked in a code comment.

[Advertisement] Incrementally adopt DevOps best practices with BuildMaster, ProGet and Otter, creating a robust, secure, scalable, and reliable DevOps toolchain.

http://thedailywtf.com/articles/best-of-2016-the-inner-json-effect


Метки:  

Best of…: Best of 2016: Overpowered

Понедельник, 26 Декабря 2016 г. 14:30 + в цитатник
Merry Holidays, and as we coast into the new year, it's time for us to reflect on some of the best/worst moments of the past one. Today, we start things off with a BANG, and a reminder that electricity is a complicated beast. --Remy

Mike had a different perspective on wiring and cable management- because he worked at a factory which made wires and cables. It was the early90s, and he was in charge of babysitting a couple of VAXes and their massive, 85lb hard drives. It was an easy job: the users knew the system and needed very little support, the VAXes were practically unstoppable, and the backup battery system could keep the entire thing running for over an hour.

The computers supported HR and accounting, which meant as the year ticked towards its end, Mike had to prep the system for its heaviest period of use- the year end closing processes. Through the last weeks of December, his users would be rushing to get their reports done and filed so they could take off early and enjoy the holidays.

A 3-phase power-breaker

Mike had been through this rodeo before, but Reginald, the plant manager, called him up to his office. There was going to be a wrench in the works this year. Mike sat down in Reginalds cramped and stuffy office next to Barry, the chief electrician for the plant.

Our factory draws enough power from the main grid that the power company has a substation thats essentially dedicated to us, Reginald explained. But theyve got a problem with some transformers loaded with PCBs that they want to replace, so they need to shut down that substation for a week while they do the work.

The factory portion was easy to deal with- mid-December was a period when the assembly line was usually quiet anyway, so the company could just shift production to another facility that had some capacity. But there was no way their front-office could delay their year-end closing processes.

So, to keep the office running, well be bringing in a generator truck, Reginald said. And that means were going to need to set up a cut-over from the main grid to the generator.

From the computer-room side, the process was easy, but that didnt stop Mike from writing up a checklist, taping it to the wall beside his desk and sharing a copy with Barry. Before the generator truck arrived, hed already tested the process several times, ensuring that he could go from mains power to battery and back to mains power without any problem.

The generator truck arrived a week before the changeover. The electricians ignored it for a few days. Just as Mike was starting to get worried about deadlines, he looked out a window and saw a trio of electricians, lead by Barry, starting to connect cables to it. Later that day, when Mike left to go to lunch, he walked past the generator truck, and noticed something odd about the cables- they were clearly single phase power cables.

Typical residential power systems are single-phase alternating current- one peak, one trough. This creates dead moments in the cycle, where no work is being done. Thats fine for residential use- but industrial systems need three-phase power- three offset AC cycles that, when added together, guarantee current is always flowing.

Hey, Mike said to one of the electricians loitering near the truck, youre planning to run some three-phase cabling, right?

Nope. The factorys shut down- this thing is just gonna run lights and heating.

And computers, Mike said. The hard drives need three-phase power.

Well have to order some parts, the electrician said.

A few more days ticked by with no three-phase connections, and Mike checked in with the electricians again.

The parts are coming.

At this point, Reginald came down from his office to the computer room. Mike, Barrys telling me youre being a disruption.

What?

Look, theres a chain of command, Reginald said. And you cant tell the electricians how to do their job.

Im no-

From now on, if you have any concerns, bring them to me.

The day of the cut-over, the three-phase cabling finally arrived. Barry and his electricians quickly strung those cables from the generator. Mike wasnt exactly watching them like a hawk, but he was worried- there was no way they could test the configuration while they were working so hastily. Unlike single-phase power, three-phase power could be out-of-sync, which would wreak havoc on the hard drives. He thought about bringing this up to the electricians, but recalled Reginalds comments on the chain of command. He went to Reginald instead.

Mike, Reginald said, shaking his head. I know you computer guys think you know everything, but youre not an electrician. This is a factory, Mike, and youve got to learn a little about what its like to work for a living.

Now, the electricians and Mike needed to coordinate their efforts, but Reginald strictly enforced the idea of the chain of command. One electrician would power on the generator and announce it, Generators running. Another electrician would relay this to Barry: Generators running. Barry would relay that to Reginald. Generators on. Reginald, finally, would tell Mike.

At 1PM, the electric company cut the power to the factory. The lights went out, but the computers kept humming along, running off battery power. A few minutes later, and a few games of telephone between electricians and Reginald, the lights came back on.

Mike stopped holding a breath that he didnt know hed been holding. Maybe hed been too worried. Maybe he was jumping at shadows. Everything was going well so far.

Tell the computer guy to switch back to mains power, called one of the electricians.

Tell the computer guy to switch back to the mains, Barry repeated.

Mike, switch back to the mains, Reginald ordered.

Mike threw the switch.

BOOOOOOOOOOOOOOMMMMMM

The computer room shook so violently that Mike briefly thought the generator had exploded. But it wasnt the generator- it was the hard drives. They didnt literally explode, but 85lbs of platter spinning at about 3,000 RPMs had a lot of momentum. The motor that drove the spindle depended on properly sequenced three-phase power. The electricans had wired the power backwards, and when Mike switched to mains power, the electric motor suddenly reversed direction. Angular momentum won. The lucky drives just broke the belt which drove the spindle, but a few of them actually shrugged their platters from the spindle, sending the heavy metal disks slamming into the sides of the enclosure with a lot of energy.

For the first and only time in his career, Mike slammed a fist into the emergency stop button, cutting all power from the computer room.

Year end closing got delayed. It took the better part of a month for Mike to recover from the disaster. While he focused on recovering data, the rest of the organization kept playing their chain-of-command telephone.

The electricians couldnt be at fault, because they took their orders from Barry. Barry couldnt be at fault, because he took his orders from Reginald. Reginald couldnt be at fault, because he followed the chain of command. Mike hadnt always followed the chain of command. Therefore, this must be Mikes fault.

Once the data recovery was finished, he was fired.

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

http://thedailywtf.com/articles/best-of-2016-overpowered


Метки:  

Error'd: What's my Age Again?

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

"For your information, Walmart, no, I'm not too old to buy this game, no matter how many years old you think I should be," wrote Ryan F.

"The first rule of placeholders is, don't post about placeholders," writes Bruce R.

Eric L. wrote, "I knew that I'd get ripped off buying an HDMI cable from my TV provider."

"Thanks for letting me know my password will expire soon," writes Scott L., "Yeah, I'll get right on that..."

"Yeah, maybe it should take a user to an active games," writes Matkyas.

Marius E. wrote, "Our server installation of Automate 10 is aware of its many errors, so much so that it needs to tell us when something actually works!

"Maybe the people at RENFE cranked up the AC too much?" Blanca wondered.

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

http://thedailywtf.com/articles/what-s-my-age-again


Метки:  

'Twas the Night Before Go-Live

Четверг, 22 Декабря 2016 г. 14:30 + в цитатник
Once again, we're hitting the holiday season. I had fun doing The PM Who Stole Christmas last year, so I decided to try my hand at another holiday classic. Expect your regularly scheduled Error'd tomorrow, but next week, we'll be revisiting our classic and best articles of the year. Happy Holidays! -- Remy

Twas the night before go-live, and all throughout git,
Not a coder was coding, no single commit;
The release was planned by DevOps with care,
In hopes that userbase would soon be there.

The PMs were nestled all snug with their charts,
While dreams of big bonuses danced in their hearts;
My team in the team room, and I with donuts,
Cracked wise about our PM being a putz;

When out from my inbox screamed a massive alert,
The PM cried, Weve disaster to avert!
I opened the ticket, filled out nice and proper;
A user filed a bug, twas a show-stopper.

A moon faced PM cried out to us Oh woe!,
We must make this release, or our jobs, theyll go!
When, what to my wondering eyes should appear,
But a pair of suspenders and a stained grey beard.

What a creaky old coder, a grumbly old troll,
I knew in a moment he must write COBOL.
Its a legacy backend, I know it quite well,
He said, I can fix it, and launched a new shell.

Now, punch cards! Now, zOS! Now, GOTO and VAXEN!
On MUMPS! On PIC(9)! on Tandem and FORTRAN!
To the top of the stack! to the top of the call!
Now compile away! Compile away! Compile -Wall!

An old-timey photo of Santa Claus where a punch-card has been awkwardly photoshopped in so it looks kind of like he's writing on a punch card. It's a stupid visual gag, and not very good.

As tape-drives that turn before the hard disk can crash,
When met with a bug, his keyboard he did mash;
Up to the function keys, his fingers did scramble,
He cut through code tied thick as a bramble.

His cursor  how it flashed! his typing how merry!
His keyboard clattered, for the switches were Cherrys.
His droll little code was fixed up in a rush,
And the beard of his chin was the color of slush.

He was chubby and plump, a right jolly old elf,
And I laughed when I saw him, in spite of myself;
A wink of his eye and a twist of his head,
Soon gave me to know I had nothing to dread;

He grumbled a curse, but went straight to his work,
Then muttered, Whoever wrote this code was a jerk.
And pinching his fingers cross the bridge of his nose,
He said, This function in particular blows.

He sprang from his desk, to the team gave a whistle,
And fled the room like the down of a thistle.
But I heard him exclaim, ere he drove out of sight,
I FIXED THE DAMN THING, BUT WHOS BRIGHT IDEA WAS IT TO HAVE A GODDAMN GO-LIVE BEFORE A HOLIDAY WEEKEND? I SWEAR TO GOD, IVE BEEN HERE FOR THIRTY YEARS, AND NEVER IN MY TIME HAVE I SEEN SUCH A GODDAMN ASS-HEADED IDEA. IVE SEEN SOME DUMB PROJECT PLANS OVER THE YEARS, BUT THIS REALLY TAKES THE CAKE. AND DONT TELL ME, OH, MARKETING SAID WE HAVE TO, BECAUSE THATS A LOAD OF CRAP. AND I BETTER NOT GET A PHONE CALL THIS WEEKEND TELLING ME THE RELEASE FAILED. HAPPY GO-LIVE TO ALL, AND TO ALL A GOOD-NIGHT

Source image for Punch-Card
CC BY-SA 3.0, Link

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

http://thedailywtf.com/articles/twas-the-night-before-go-live


Метки:  

Поиск сообщений в rss_thedaily_wtf
Страницы: 124 ... 46 45 [44] 43 42 ..
.. 1 Календарь