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

Поиск сообщений в 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: "Performant" ""Development""

Среда, 31 Августа 2016 г. 13:30 + в цитатник

Birthday cake in ice cream shop in Basking Ridge New Jersey

Good intentions are never enough. If they aren't coupled with the wisdom to follow through properly, they can result in a horrible mess. Today’s Anonymous submitter has learned this the hard way:

I'm working on this particular 500k LOC monster for a few years now, and I consider this code to be a "representative function". It's a performance-critical server application crunching huge amounts of data through its bowels, and its development started around 2001 on a desktop computer. For this reason, the original developer chose to '"'develop'"' with performance being the primary concern (see, I put the quotes into quotes to let you know that the original developer was very creative about "developing"; he "made things work", you know).

He was very agile and customer-driven ("Yeah, refresh the page a few times, and if the right thing comes out, I'll put that live on all systems."). He was environment-aware (he did variable recycling). He kept the code clean and simple ("char*" and "int*" is all you ever need). He wrote easy-to-use interfaces (query parameters are mostly bit-flags, unless you query with a few special values like "format=100" or "format=3", which do something very useful). He wrote an easy-to-use line-based output format (sometimes switching between "\n" and "\r\n", and the lines themselves even had context-sensitive formats, alternating between pipe- and semicolon-separated lists). Users didn't have to cope with errors (if the first line of the output was "0" or "-1", something went wrong). [He] even showed different results in consecutive requests if there were too many results to fit into the size-limited list, so the user had the chance to see everything [that] might be of interest to him!

int GetAgeFromBirth(time_t nBase, int nBirth)
{
    tm tms;
#if _MSC_VER >= 1400
    localtime_s(&tms,(time_t*)&nBase);
#else
    tms = *localtime((time_t*)&nBase);
#endif

    tms.tm_year+=1900;
    tms.tm_mon+=1;
    char strConv[8];
    sprintf(strConv,"%06d",nBirth);

    int nD,nM,nY;
    if(sscanf(strConv,"%2d%2d%2d",&nD, &nM, &nY)==3){
        nY+=2000;if(nY>tms.tm_year)nY-=100;
        int nRet=tms.tm_year-nY;
        if(tms.tm_moncode>

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

http://thedailywtf.com/articles/performant-development


Метки:  

The Legend

Вторник, 30 Августа 2016 г. 13:30 + в цитатник

Old Peters company has a legend. It has been passed down through generations of programmers and staff through an oral tradition. Oh, from time to time, someone would be inspired to record the tale for posterity, but inevitably, the hard copy was recycled, the digital copy was lost.

It was 1982, and the German tech industry was booming. Old Peters company manufactured a line of 8-bit computers that were targeted towards businesses. Their targets were generally larger companies and government organizations- like Frequenzhof Busgesellschaft.

2013 in Bonn. BYD ebus (electrical bus). Bus facing left

Frequenzhof Busgesellschaft - the bus company of Frequenzhof - served a bustling metropolis in the heart of Germany. They had a growing ridership and a growing need to automate their accounting processes. They bought one cabinet-sized 8-bit microcomputer and if they liked it, planned to buy another. With the addition of tape drives and other accessories, the Busgesellschaft was going to be a very valuable client.

So when the director of the bus company called support, people jumped to solve their problem. Unfortunately, it was easier said than done:

When we use your computer to run our weekly batch process, all of our radios stop working. We cannot communicate with our drivers! This is unacceptable!

The technician tried to clarify the problem. Im sorry, but… if you run an accounting job, the radios stop working? Our computer doesnt have anything to do with your radios!

And yet, when we turn on your computer, the radios stop working! We think it must be interference.

That… that really cant be. A computer, of course, does throw off some electromagnetic fields- anything using electrical current did. But to kill a voice radio network? That seemed implausible.

The technician gathered more details, and then escalated. Management didnt want to lose future sales, and got defensive about their system. It relatively well shielded, and the frequencies it generated- all harmonics of the 1MHz chip running in the system, or of the 50Hz mains power- were nowhere near common voice frequencies.

Over the next few months, a series of radio and electronics technicians examined the situation. They tested a computer right as it came off the assembly line, proving that it didnt radiate any significant EM noise, especially not at the bands the radios used (

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


Метки:  

CodeSOD: Real Money

Понедельник, 29 Августа 2016 г. 13:30 + в цитатник

Paulo F was doing a little online banking with one of the largest banks in Brazil. He wanted to buy a pre-paid debit-card. He chose a value from the drop-down, for example R$50,00- fifty Reals. The site promised him a card loaded with R$200,00. It didnt matter what he chose, the site offered him a completely different value.

Curious, he pulled up the element in the inspector.

If you dont speak Portugese, you might not be seeing the problem. Cem is the word for one hundred. Duzentos for two hundred. And so on. Its not even that they screwed up a decimal point, this isnt a minor detail, and clearly breaks the ability to purchase debit cards.

Paulo purchased his card from a different bank.

[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/real-money


Метки:  

Error'd: Just Another Slow News Day

Пятница, 26 Августа 2016 г. 13:00 + в цитатник

"All the news that's fit to print, eh?" Jared S. writes.

"And now, here comes Yahoo! Finance with a blast from the past," writes Norman D.

"When attempting to set up a user on a work-related website that's managed by a 3rd party vendor, this was the result," Pixel E. wrote, "I'm not sure how I should notify their help desk."

"Pocket really makes articles ...interesting," Nathan wrote.

"Adobe kindly let me know that my PDF needed some time being 'prepared for,'" writes Colin S-J, "I can only assume that when the progress bar was full, the PDF was no longer prepared for."

Chris D. writes, "Trying to install the SQL Server 2016 Express edition for a customer, apparently Microsoft didn't want me to succeed!"

"The job: Write a fast SIMD atan2() function that calculates 8 at a time. The result: First time ever I've gotten away with calling a function 'satan'," Nils C. writes.

[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/just-another-slow-news-day


Метки:  

It's Dark In Here

Четверг, 25 Августа 2016 г. 13:30 + в цитатник

Gustave Dor'e - Dante Alighieri - Inferno - Plate 8 (Canto III - Abandon all hope ye who enter here)

September 17, 20XX

Dear Susanna,

I hope the fresh start of a new college semester finds you well. I have great news! I've just signed a 2-year contract with one of the world's largest investment banks, and will be helping to maintain a next-generation trading platform.

This is the sort of programming assignment I've dreamt of since being in your shoes, imagining what post-college life might bring. In these first few years, my naivet'e was rewarded with arcane VB6 apps and moldering SharePoint servers—but no more! I can't wait to start.

I shall log my experiences for your edification. Whenever you feel discouraged, remember my example and know it won't be much longer before you, too, realize your dreams.

-Frederic


Day 1. I expected the words to flow from my fingers with electric thrill, dear sister. Instead, I write to you now in a mood of deep bemusement.

The morning began well enough. My cubicle, laptop, phone, and network credentials were furnished to me straight away: a true rarity in the business world. Then my new boss took me to meet the genius behind the cutting-edge trading platform I'd been told so much about. He's a man they simply call The Architect.

The moldy smell of expired sandwiches hung about his cubicle. The man himself had sharp, beady eyes and a patronizing smile. He's either plumbed the universe's darkest machinations firsthand, or he believes he has.

My boss asked The Architect to give me a quick preview of the trading platform. I was genuinely excited to see what cutting-edge, next-gen software looked like.

The Architect obliged, remoting into the server hosting the application and launching it. On his monitor, the splash screen appeared, displaying a Greek soldier posing like Zeus. I realized he looked familiar.

It was The Architect's face Photoshopped onto a warrior's body.

A spine-curling cringe settled over me, which I struggled to suppress. This was no sign of world-class software, rather the opposite. I don't recall anything else. Now I'm alone in my cube, shuddering in dread of all that's yet to come.

No, I mustn't succumb to pessimism. Perhaps The Architect simply has a bad sense of humor. Worry not for me, Susanna. The next time I write, it will be in much higher spirits.


Day 2. Can this be real? I've sat down with my first coffee and have barely begun to look into the code base, and I'm already horrified by what I see. The main file, which is just for bootstrapping, contains over 10,000 lines of spaghetti code. The comments and log files contain multiple instances of Who cares?, Bah, and other expressions of futility.

The other developers are starting to filter into the office now. Peeking over the cubicle walls, I see plainly the hopelessness in their eyes.

I feel as though I stand at the edge of an abyss. Though I can't see the vast chasm below, I'm aware it's terribly far down, and the darkness stretching in between is fraught with uncertainty.


Day 5. It gets worse. Further dealings with The Architect's code have revealed more horrors, Susanna, things you must promise me never to permit within your own software projects:

  • The Listener interface has a publish() method.
  • There is a class named NothingIsSomethingElse with a single method, wireUp().
  • Many functions and constructors require 256 parameters- or more!
  • The container classes follow no standard convention. Map has as the template arguments.
  • There are templated functions that take up to 12 template arguments.
  • Instead of using conventional terms like "source" and "sink," The Architect insists upon terms like "faucet" and "basin."

And the trading platform is every bit as horrific as the code lurking beneath. Running in production, each process requires 48 GB of RAM, consumes 350% CPU when the system is idle, and spawns anywhere from 10,000-20,000 threads. During full garbage collection, a process may stall for as long as 3 minutes.

People depend upon this monstrosity for their financial futures? God help them. God help us.

I've spoken to some of the other developers. They say The Architect's code is so complicated that only he can modify it. They're resigned to the application being this way.

I'm not. For my own sanity's sake, I shall start listing all the things we can improve, and take it to the next status meeting.


Day 10. Alas, all hope is lost. When I'm not looking at eye-bleeding code, I'm looking at my inbox—currently full of emails from The Architect, scathing emails shaming any member of the dev team who dares to make a mistake or question him. One of these emails is addressed to me. Another is addressed to an unfortunate soul who'd dared to use inheritance in her latest work.

720 more days of this nightmare. It's too late for me, Susanna, but not for you!

Change your major!

SAVE YOURSELF!

[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/it-s-dark-in-here


Метки:  

Representative Line: Accuracy in Comments

Среда, 24 Августа 2016 г. 13:30 + в цитатник

Comments are rough. I always take the stance that code should always be clear enough to explain what it does, but youll may need a comment to explain why it does that. I recently attended a talk by Sean Griffin (maintainer of Rails) who argued that commit messages should accomplish that goal, since they can contain far more content than a code comment, and while code comments and code can drift apart and cease to be accurate, commit messages are always linked to the point-in-time when they were made. Donald Knuth, on the other hand, might argue that code should annotate comments instead of the opposite.

Regardless of the method we use, I think most of us would agree that code needs some documentation in the same way it needs tests: it should exist, but we dont want to have to create it.

Stephania found herself in the situation where she was creating the documentation. In this case, I dont think we have to worry about the comment ceasing to be an accurate description of the code. This comment doesnt need to be linked to a specific point in time- it tells us everything we need to know about the entire codebase.

# Note: The parameters "backup_freq" below do not actually refer to how frequently the backup script runs.  
# It's just a tag so that the retention scripts know what kind of backup the created snapshot is.
# How often the script runs is determined by the name of the generated output file.


[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/accuracy-in-comments


Метки:  

Your Code Might Be Unmaintainable…

Вторник, 23 Августа 2016 г. 13:30 + в цитатник

Lets talk about maintainability.

Those of you that know me know that in my civillian identity, I work as a SQA professional. QA gets a bum rap sometimes; manual functional testing can be one of the most boring parts of software engineering, but while theres plenty of button-pushers who will be happy to poke at an application for minimum wage, theres a lot more to quality than simply functionality. One of the commonly overlooked aspects is maintainability: the ease with which changes can be made to the software system.

Jeff Foxworthy at Resch Center

Now, maintainability can be measured. You can track how long it takes to discover the root cause of an issue, or how long it takes to work a simple enhancement request. You can track the number of groans or WTFs per minute in code review. You can track the cylcomatic complexity of the codebase or, if youre a masochist, the Halstead complexity. But theres a number of informal, gut feel warning signs you can use to tell if your application is maintainable. Heres a sampling Ive collected from various programmers in the industry. I like to call it Your code might be unmaintainable if&

Your code might be unmaintainable if the programmers give it nicknames like the monster or the barge or utter the words there be dragons

Your code might be unmaintainable if you can tell how old a file is by what revision of the coding standards it follows  within 3 seconds of opening the file

Your code might be unmaintainable if requesting a dependency map from the database server chugs for 30 minutes then crashes with an out of memory exception

Your code might be unmaintainable if youre the most senior dev on the team& six months out of uni

Your code might be unmaintainable if you cant localize the text of dropdowns for a new locale because that would break the existing 400-line if-else chain that lists out every localized string and keys functionality based on it

Your code might be unmaintainable if management dictates the design of the codebase  down to the nitty-gritty tactical level. Bonus points if the manager is a non-technical VP who responds to criticism by firing the developer on the spot.

Your code might be unmaintainable if half the variable names are in a different language and nobodys quite sure which

Your code might be unmaintainable if youre serving 20MB of CSS files on every request

Your code might be unmaintainable if your dependency graph is unreadable when printed on a single sheet of 8.5 x 11 paper. Or a single sheet of A4. Or a single sheet of A3.

Your code might be unmaintainable if your variable naming convention is u734, u12342, u623, etc& and variables all change names between files

Your code might be unmaintainable if you have a single function webservice with 17 layers of abstraction between the entry point and where the business logic lies. Apparently the developer had never heard of YAGNI

Your code might be unmaintainable if you re-order the properties of an object and the code breaks

Your code might be unmaintainable if Microsoft Access forms a critical part of your business workflow. Or Microsoft Excel. Bonus points for unreadable Excel macros that fall victim to other traps in this article

Your code might be unmaintainable if it includes the line #defined ONE_HUNDRED 100 unironically

Your code might be unmaintainable if you find the source code! &in a folder marked DEV_BACKUP_2013

Your code might be unmaintainable if you cant find the malfunctioning bit of code because its monkeypatched onto a class you control from god knows where

Your code might be unmaintainable if you go to debug a production issue and not only can you not reproduce, the entire functionality isnt present in the codebase on the development servers.

Your code might be unmaintainable if you go to debug a production issue and not only can you not reproduce in dev, you cant find the functionality even in production. Bonus points if you finally chase down a series of redirects and end up on some server somewhere, named after a flower, that was meant to have been decomissioned years ago. Double bonus points if youre pretty sure it shells out to a Minecraft server in the process.

Your code might be unmaintainable if its full of comments that simply read //BUGBUG. Or //TODO (with no further explanation)

Your code might be unmaintainable if theres a header at the top of every page served up in production that reads


// [Decompiled](http://thedailywtf.com/articles/variables-everywhere-but-not-a-stop-to-think) with JetBrains decompiler
// Type: FloorPlanCLR.EventManagementService.Triggers
// Assembly: FloorPlanCLR, Version=1.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 55C2F875-6F43-4FDE-A2C6-6CD7F464A43B
// AssemblyLocation: C:\Users\SomeGuy\Pictures\FloorPlanCLR.dll

Your code might be unmaintainable if its in a proprietary langauge your company invented. Or a blend of two such languages.

[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/your-code-might-be-unmaintainable


Метки:  

CodeSOD: An Angular Watch

Понедельник, 22 Августа 2016 г. 13:30 + в цитатник

Lets talk a little bit about front-end development. Even at its best, its terrible- decades of kruft mixed with standards and topped off with a pile of frameworks that do their best to turn this mess into a cohesive whole.

Jameson is suffering through this, and his suffering is the special level of front-end suffering known as Angular. Angular bolts Model-View-Controller semantics on top of HTML/JS/CSS, and its big selling point is that it makes two-way data-binding trivially easy.

Under the hood, that two-way data-binding is implemented using a concept of watchers. Essentially, these abstract out the event handling and allow Angular- or your own custom code- easily detect changes in the various UI widgets. These watchers also implement nice features, like automatically detecting if a form field is $pristine or if the form (or any given field) happens to be $valid.

So, for example, if you wanted to have a submit button automatically disable itself if the form were untouched or invalid, you might do something like this:

        

Of course, thats only if you wanted to actually get some benefit out of the ten-thousand line framework you just baked into your application. Jamesons fellow developers have a very different approach:

var watchers =
        'paymentOptions.PrimaryCreditCardActive,' + //0
        'paymentOptions.PrimaryCardOwnerName,' + //1
        'paymentOptions.PrimaryCardNumber,' + //2
        'paymentOptions.PrimaryCardMonth,' + //3
        'paymentOptions.PrimaryCardYear,' + //4

        'paymentOptions.SecondaryCreditCardActive,' + //5
        'paymentOptions.SecondaryCardOwnerName,' + //6
        'paymentOptions.SecondaryCardNumber,' + //7
        'paymentOptions.SecondaryCardMonth,' + //8
        'paymentOptions.SecondaryCardYear,' + //9

        'paymentOptions.ECheckDirectWithdrawlActive,' + //10
        'paymentOptions.ECheckBankAccountNumber,' + //11
        'paymentOptions.ECheckBankRoutingNumber'; //12

$scope.$watchCollection('[' + watchers + ']', function(newValues){
        $scope.companyProfileForm.$pristine = true;

        if(newValues[0] && newValues[1] && newValues[2] && newValues[3] && newValues[4]){
                $scope.companyProfileForm.$pristine = false;
        }

        if(newValues[5] && newValues[6] && newValues[7] && newValues[8] && newValues[9]){
                $scope.companyProfileForm.$pristine = false;
        }

        if(newValues[10] && newValues[11] && newValues[12]){
                $scope.companyProfileForm.$pristine = false;
        }

        if(newValues[0] && ( !newValues[1] || !newValues[2] || !newValues[3] || !newValues[4])){
                $scope.companyProfileForm.$pristine = true;
        }

        if(newValues[5] && ( !newValues[6] || !newValues[7] || !newValues[8] || !newValues[9])){
                $scope.companyProfileForm.$pristine = true;
        }

        if(newValues[10] && ( !newValues[11] || !newValues[12])){
                $scope.companyProfileForm.$pristine = true;
        }
});

The initial watchers string represents an Angular expression which is a fancy way of saying, JavaScript scope is too complicated, so were just not going to do it and require developers to use our own custom expression language. This string is passed to $watchCollection, which will execute the callback function if the value of any one of those fields changes.

Then, inside of a batch of cryptic if statements, it makes its own decisions about whether or not the Angular-controlled $pristine property should be a certain value or not- decisions that arent in any way based on the requirements for this application.

Jameson fixed the code to look something more like my suggested version.

[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/an-angular-watch


Метки:  

Error'd: A Birthday You'll Never Forget

Пятница, 19 Августа 2016 г. 13:00 + в цитатник

"Look like Microsoft really, really wants me to celebrate Windows 10's birthday," wrote Andrew.

Brandon R. writes, "Think you'll need to cancel? No problem! Just make sure you booked 999 days in advance."

"I imagine someone in an office far away saying 'We can't waste precious computer cycles on a string equality check! Utter prodigality!! We'll just ask the user to confirm'," writes Al.

"Here's a poliwag that I caught in Pokemon Go. Or, what's left of him," writes Mark B.

"I guess it makes sense that Microsoft doesn't really 'do' CSS, but at least they know someplace that does," Jos wrote.

"I wasn't sure if $50 from $79.95 was 62% off," wrote Ben R., "But I was fairly sure that 50$ from 89.95$ wasn't 77% off at the same time."

"So, if I don't have an SSH key, click on 'No, you must load an SSH key'?" write Shahim M.

[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/a-birthday-you-ll-never-forget


Метки:  

Injection By Design

Четверг, 18 Августа 2016 г. 13:30 + в цитатник

Computersicherheit.jpg

As web developers, we spend a fair amount of time protecting our valuable server resources from the grasping tentacles of Internet ruffians and malfeasants. Occasionally, we're tasked with exposing data endpoints to the public Internet. This is generally a carefully crafted solution of whitelists, authentication, authorization, escaping input, limiting access and other protective measures.

But we are not, and cannot be, the domain experts for the system. There is always an inherit tension between our area of expertise, namely software development, and the needs of our business users for their own purposes. Never is this more true than when the problem domain is something that borders on our own area of expertise.

Kit was a quantitative analyst; he knew enough Ruby to be dangerous, but nothing of software engineering as a discipline. Nevertheless, his understanding of the problem domain was deep and thorough. He knew what he needed to accomplish, and enough of how to do so that all he required from Karlas company was server maintenance for his analysis and the accompanying big data SQL database. He was spending more time than he wanted to be administrating the machine sitting in his closet. Since his group had an existing relationship with Karlas company, it made sense to delegate to her team.

Karla was tasked with examining the code to ensure it would pose no threat to their other existing clients. The code was typical of new programmers who understand the problem better than the solution: inconsistently spaced, with a coding style that matched no known format, and weak in places—but it would work, and it wasnt just a rootkit disguised as an app. Karla was about to advise accepting the code when something caught her eye: it was designed to take in POST requests and execute them as dynamic SQL queries.

post "/" do
 content_type :json
  payload=request.body.read
connection=Vertica.connect({

})
    query=payload
output = Array.new
connection.query( query) do |row|
        output.push row
        end
connection.close

We can hardly say no, Karlas boss responded when advised of the risk.

What? Why not? Karla demanded.

Every customer is important to us. Kits group does millions of dollars of business with us annually."

Ah, yes. Every customer was equal, but the spendiest ones were the most equal.

"We need to make this work," the boss continued. "Why dont we just move his machine into our datacenter?

Absolutely not! Are you insane? Sirel, the sysadmin, was just as adamant as Karlas boss. You want to install some random piece of kit into my datacenter? For all we know, this has been sitting on his desk, talking to God-knows-what. Its probably infested with trojans and keyloggers. I wont have it in my nice clean network!

Okay, but the boss wants us to help this guy, Karla pointed out, feeling a bit desperate.

So take it to Dave," Sirel said. "He can figure something out, Im sure.

Dave was in charge of Devops. It was his job to ensure that the code Karlas team developed was deployed and maintained in their environment. If anyone could make this walking time-bomb play nicely with their existing environment, Dave could.

He, of course, was having nothing of this either. Its an obvious security risk, Karla. No, more than that: the entire design is inherently unsecurable. Itd compromise everything else in our database cluster. Cant be done.

Come on, Dave. I know youre good at this stuff, Karla pleaded.

"Just last week, I promoted a SQL injection risk your team let past code review," Dave countered. "It took me three days to track down. Do you even understand how many alarm bells were going off? I'd be skinned alive if I let you put this into prod."

Karla trudged back to her boss. Theres just no way. Nobody wants this thing in our environment. Well have to refuse until Kit can find a more secure way to implement it.

Nonsense!" the boss cried. "The customer wants it, and the customer is always right!

Dave fought long and hard, but in the end, Karlas boss outranked him; the code was put into production unchanged. Karlas boss didnt even have the decency to buy Dave a drink first—though he did manage to look surprised when Dave left six months later to pursue a career in finance instead. You see, Dave had learned a valuable lesson: its always better to be the client than the hapless souls supporting him.

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

http://thedailywtf.com/articles/injection-by-design


Метки:  

CodeSOD: Location Not Found

Среда, 17 Августа 2016 г. 13:30 + в цитатник

Lets say you have a collection of objects which contain geographic points. You want to find a specific item in that collection, and then extract the lat/lon of that item. You might write code like:

    var point = userGeoPositions.Where(x => x.userId = userId);
    decimal lat = point.Latitude;
    decimal lon = point.Longitude;

Of course, this means writing getters and setters for the Latitude and Longitude properties; getters/setters are somewhat repetitive, and repetitive code is a code smell, so obviously, this cant be the correct solution.

Codys company outsourced this problem, and they got back a solution that is obviously much better.

    public static decimal? GetPosition(string endpointId, ICollection userGeoPositions, bool isLatitude)
    {
        var position = userGeoPositions.FirstOrDefault(x => endpointId.Contains(x.UserID));
        return position != null
            ? (decimal?)Convert.ToDecimal(isLatitude ? position.GeoLatitude : position.GeoLongitude)
            : null;
    }

Instead of writing separate getters for each property, this is one function that can get either property. Thats reusability! And you dont even have to filter the collection before you call this function! Now, when you want the lat/lon of a point, you simply write:

    decimal lat = GetPosition(endpointId, geoPositions, true);
    decimal lon = GetPosition(endpointId, geoPositions, false);

Thats one fewer lines of code than my initial solution. Now, since this function filters on each call, getting the latitude and longitude requires two searches through the whole list, but hey- CPU time is cheap. Programmer time is expensive.

[Advertisement] Infrastructure as Code built from the start with first-class Windows functionality and an intuitive, visual user interface. Download Otter today!

http://thedailywtf.com/articles/location-not-found


Метки:  

Technical Debt

Вторник, 16 Августа 2016 г. 13:30 + в цитатник

If you get the rare luxury to start a new project from scratch, there's something deep down inside you that makes you want to do it right. You pick the right people, equipment and tools so that you have the best chance of success. Unfortunately, sometimes incorrect decisions are innocently made and a technical time bomb is placed in the code.

About 20 years ago at Big Money Inc., such a project was started and such a mistake was made. In this case, the mistake revolved around choosing a messaging platform that failed miserably when asked to pump more messages than was intended. The original developers knew not of this otherwise widely-known limitation.

Compounding things was the choice of implementation. Usually, when you build a transport layer, you do something like this:

  public interface ICallback {
    void callback(Record rec);
  }

  public class Handler implements ICallback {
    public void callback(Record rec) {
      // do something with it
    }
  }

  public interface ITransport {
    void connect();
    void disconnect();
    void retryConnectionWithDegradingFrequencyAndAlerts();
    void publish(Record rec);
    void registerCallback(ICallback callback, String subject);
    // ...
  }

  public class ConcreteTransport implements ITransport {
    // Implementation here
  }

You instantiate it with relevant parameters for each transport instance you need, and inject or pass the concrete object - by the interface - wherever it's needed. This way, when a new transport comes along tomorrow, you only need to implement a new concrete interface, once, instantiate the new wrapper and inject or pass it in lieu of the previous one.

This is not a new way of doing things. Encapsulation is not a new concept. Many souls far wiser than us documented this in great detail a very long time ago.

But the original developers were unaware of such sorcery as encapsulation, interfaces or (Spring) injection, so the system was built with all of the code to connect, publish and subscribe hard wired into every single class that needed to send or receive messages. Literally more than 800 of them. Decapsulation at its finest!

Fast forward more than a decade and there's an economic event that caused the volume being pushed through the messaging system to spike; the messaging system collapsed and brought everything that depended on it to a screeching halt. In the middle of business. World wide. Naturally, high level managers suddenly pushed this issue to the top of their priorities: This MUST be fixed IMMEDIATELY!

Of course, when the current developers on the team looked into it, they had to report unpleasant news regarding 800+ places where code needed to be changed. Rather than attempt to factor it out into encapsulated classes and merely use it where required, management decided that they could not afford to risk introducing bugs by rearranging code, and that they should keep things as they are and fix it everywhere it's used. The available staff of two people reported that this would take a while. Management roared: Unacceptable! Start coding post-haste! Type, young minions - TYPE!

And type they did. Until one of them gave up on IT and left to pursue a career as a florist. The lone remaining developer assigned to the task slogged forward, but at the pace of a single developer. When management queried why the pace of progress was now 50% of what it was, he reported: You KNOW that the other guy is no longer here, right?

Management realized they had to do something, so they did what they do best; they ignored reality and barked orders, leading to many conversations along the lines of...

  Manager: We MUST maintain the planned rate of fixes or we won't meet the schedule!

  Developer:: The schedule assumes two folks, already up to speed, working on it full
  time - if you maintain the scheduled level of resources, we can maintain
  the expected throughput

  M: But we don't have time to find and train someone new

  D:...but you have time to miss your deliverable?
...and downhill it went from there.

To complicate matters, there was a new corporate-wide directive to move off of the messaging system (to which they were moving) onto yet another corporate-mandated tool, implying that all of the in-line rework would need to be re-reworked.

Management insisted that development had no choice but to proceed as they had been instructed.

The lone developer realized that he was being assigned full responsibility for numerous earlier management failures, that he was in a corner and had no choice but to go for broke. He pointed out that this was an unreasonable approach that was guaranteed to fail. If he had been allowed to refactor the code into an encapsulated/injected model, it would be relatively trivial to change messaging systems. Until a sane direction was to be adopted, he was through being set up to pay for technical debt that the project had amassed while he was still in high school.

They ordered him to do as they said, and that he needed to own this problem and do whatever it took to get it fixed.

He pointed out that before he would take ownership of a problem, it had to be reasonably fixable, and that he needed to get some say in how the solution would be implemented. While there are many ways to succeed, some paths are guaranteed to fail, and he would not accept responsibility for 12 years of someone else's bad decisions and accumulated technical debt.

M: You don't have a choice!

D: Yes I do. I resign effective 2 weeks from today!

They really couldn't argue with that, so over the next 2 weeks, he wrote down everything he knew about it, mostly in an attempt to warn the next poor soul inflicted with this mess. Then he halted the remaining 50% of the development effort on the project by saying goodbye and walking out.

[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/technical-debt


Метки:  

CodeSOD: Drugsort

Понедельник, 15 Августа 2016 г. 13:30 + в цитатник

I did a brief contract with Hershey, the candy manufacturer, once. The biggest thing I recall from the experience was that they had bowls full of candy all over the place. You could just grab them by the handful.

I bring this up, because Brenda worked for a pharmaceutical company, and I can only assume that there are bowls full of random drugs scattered around, and someone has been chowing down on them by the handful. Thats the most logical explanation for the following code:

'From ...(7/21/2008 3:18:30 PM): Sort the additional additives in alphabetical order

'Albumin
'Ascorbic Acid
'Chromium
'Cysteine + Acetate
'Cysteine - NoAcetate
'Epogen
'Famotidine
'Fervens Canis (aquaeous)
'FolicAcid
'Heparin
'Insulin *R* Human
'IronDextran
'Levocarnitine
'MVI - Adult Without Vitamin K
'MVI Pediatric
'Metoclopramide
'Ped-Trace 4
'Phytonadione-K1
'Ranitidine
'Selenium
'Selenium > 5years
'Zinc

Dim additivescount As Integer = Me.treeIngredients.Nodes(4).GetNodeCount(True)

Dim node_albumin As TreeNode = Nothing
Dim node_ascorbic As TreeNode = Nothing
Dim node_chromium As TreeNode = Nothing
Dim node_cysteineplus As TreeNode = Nothing
Dim node_cysteineminus As TreeNode = Nothing
Dim node_epogen As TreeNode = Nothing
Dim node_famotidine As TreeNode = Nothing
Dim node_folic As TreeNode = Nothing
Dim node_heparin As TreeNode = Nothing
Dim node_insulin As TreeNode = Nothing
Dim node_iron As TreeNode = Nothing
Dim node_levocarnitine As TreeNode = Nothing
Dim node_lipids3in1 As TreeNode = Nothing
Dim node_mviadult As TreeNode = Nothing
Dim node_mviped As TreeNode = Nothing
Dim node_metoclopramide As TreeNode = Nothing
Dim node_pedtrace4 As TreeNode = Nothing
Dim node_phytonadione As TreeNode = Nothing
Dim node_ranitidine As TreeNode = Nothing
Dim node_selenium As TreeNode = Nothing
Dim node_selenium5 As TreeNode = Nothing
Dim node_zinc As TreeNode = Nothing
Dim node_hotdogwater As TreeNode = Nothing

For cnt = 0 To additivescount - 1

    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Albumin") Then
        node_albumin = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Ascorbic") Then
        node_ascorbic = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Chromium") Then
        node_chromium = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Cysteine + Acetate") Then
        node_cysteineplus = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Cysteine - No Acetate") Then
        node_cysteineminus = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Epogen") Then
        node_epogen = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Famotidine") Then
        node_famotidine = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Fervens Canis (aquaeous)") Then
        node_hotdogwater = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Folic") Then
        node_folic = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Heparin") Then
        node_heparin = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Insulin") Then
        node_insulin = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Iron") Then
        node_iron = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Levocarnitine") Then
        node_levocarnitine = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Lipids (3-In-1)") Then
        node_lipids3in1 = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("MVI - Adult") Then
        node_mviadult = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("MVI Pediatric") Then
        node_mviped = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Metoclopramide") Then
        node_metoclopramide = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Ped-Trace") Then
        node_pedtrace4 = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Phytonadione-K1") Then
        node_phytonadione = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Ranitidine") Then
        node_ranitidine = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Selenium") Then
        If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.IndexOf(">") > 0 Then
            node_selenium5 = Me.treeIngredients.Nodes(4).Nodes(cnt)
        Else
            node_selenium = Me.treeIngredients.Nodes(4).Nodes(cnt)
        End If
    End If
    If Me.treeIngredients.Nodes(4).Nodes(cnt).Text.StartsWith("Zinc") Then
        node_zinc = Me.treeIngredients.Nodes(4).Nodes(cnt)
    End If

Next
    For cnt = 0 To additivescount - 1
        Me.treeIngredients.Nodes(4).Nodes(0).Remove()
    Next

If Not node_zinc Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_zinc)
If Not node_selenium5 Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_selenium5)
If Not node_selenium Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_selenium)
If Not node_ranitidine Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_ranitidine)
If Not node_phytonadione Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_phytonadione)
If Not node_pedtrace4 Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_pedtrace4)
If Not node_metoclopramide Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_metoclopramide)
If Not node_mviped Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_mviped)
If Not node_mviadult Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_mviadult)
If Not node_lipids3in1 Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_lipids3in1)
If Not node_levocarnitine Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_levocarnitine)
If Not node_iron Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_iron)
If Not node_insulin Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_insulin)
If Not node_heparin Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_heparin)
If Not node_folic Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_folic)
If Not node_hotdogwater Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_hotdogwater)
If Not node_famotidine Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_famotidine)
If Not node_epogen Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_epogen)
If Not node_cysteineminus Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_cysteineminus)
If Not node_cysteineplus Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_cysteineplus)
If Not node_chromium Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_chromium)
If Not node_ascorbic Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_ascorbic)
If Not node_albumin Is Nothing Then Me.treeIngredients.Nodes(4).Nodes.Insert(0, node_albumin)

The comment does us the courtesy of telling us what the goal of this code is: sort the list of possible additives.

Understanding how it accomplishes that goal is a bit trickier, and to do that, we need to understand something about old-timey VisualBasic. Prior to .NET, VisualBasic was a terrible language, and did not have a particularly rich set of collection primitives, and the API wasnt that clear. Many VB programmers didnt even bother to learn about them, since VisualBasic was all about slapping form controls together on a designer and then wiring code up to them. This meant that, instead of fighting their way through collection types, many VB developers used the hammer they were already familiar with to solve problems. Developers that learned this habit when it was common in, say, 1998, often continued in this habit until, say, 2008, when this code was written.

With that in mind, Me.treeIngredients is a TreeView control, meant to be used like well, a tree-view. Each variable declaration (the Dim statements) is creating a new TreeNode, which are the individual branches and leaves we want to see in the tree. This particular set of nodes is never actually used in a display (theres a separate TreeView for that).

So, section by section, lets look at what this does. First, it creates a pile of TreeNode objects. Then, for each element currently in the TreeView, we run a loop and check: if it starts with, say, Metoclopramide, grab that node and put it in the variable node_metoclopramide. Then loop across the TreeView again, but this time, remove all the nodes. Finally, look at that set of variables you just created, and if each one of them has a value, insert it into the first position in the list. So long as we do those inserts in reverse alphabetical order, the end result will be that items are added to the list in alphabetical order.

As you can imagine, this wasnt written as a reusable function, but instead, was copied and pasted everywhere additives needed to be sorted. This kept Brenda very busy when she needed to add a few dozen new additives to the application.

[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/drugsort


Метки:  

Error'd: A Model of a Modern Modal Window

Пятница, 12 Августа 2016 г. 13:00 + в цитатник

Nick writes, "Well, it just goes to show you - don't under estimate the cultural significance of modal windows."

"I was trying to buy a costume, but it seems that I'm about to buy some modal text instead," Medalla writes.

Mort writes, "It's the personal touches that make me want to play the lottery."

"I thought 2006 was a good year for me, shame it has been erased," wrote Mitch.

Cynthia wrote, "Received new XPS 15 laptop from Dell which attempted to mash a US keyboard into a UK chassis."

"I'm only going to be in Belgium for three weeks, but I want to make sure my prepaid card doesn't run out," Dug S. wrote, "This should be enough, right?"

Andre writes, "Next time, just play it safe and go with Lorem Ipsum."

[Advertisement] BuildMaster integrates with an ever-growing list of tools to automate and facilitate everything from continuous integration to database change scripts to production deployments. Interested? Learn more about BuildMaster!

http://thedailywtf.com/articles/a-model-of-a-modern-modal-window


Метки:  

CodeSOD: Constantly Extended

Четверг, 11 Августа 2016 г. 13:30 + в цитатник

Imagine youre a financial institution. Youve built an application that processes financial transactions, and there are a number of flags that need to be set as constants to determine application behavior.

You might choose to write code like this:

  public static final boolean CreateNewReferenceFolderAndFiles = true;

But then your boss would say, Bro, do you even object-orient? before firing you, because that isnt enterprise-y.

Skyfyre sent us this excerpt, from a four-million line application, which is definitely very enterprise-y.

First, you need to define several classes, and since this is Java, each of them must be in its own file:

  public abstract class ArchiveCreateNewReferenceFolderAndFiles
  {
  }

  public class ArchiveCreateNewReferenceFolderAndFilesTrue extends ArchiveCreateNewReferenceFolderAndFilesAbstract
  {
  }

  public class ArchiveCreateNewReferenceFolderAndFilesFalse extends ArchiveCreateNewReferenceFolderAndFilesAbstract
  {
  }

Then, youve got to create your actual constants:

public static final ArchiveCreateNewReferenceFolderAndFilesAbstract ARCHIVE_CreateNewReferenceFolderAndFiles_TRUE = new ArchiveCreateNewReferenceFolderAndFilesTrue();
public static final ArchiveCreateNewReferenceFolderAndFilesAbstract ARCHIVE_CreateNewReferenceFolderAndFiles_FALSE = new ArchiveCreateNewReferenceFolderAndFilesFalse();
/// later…
public static final ArchiveCreateNewReferenceFolderAndFilesAbstract archiveCreateNewReferenceFile = ARCHIVE_CreateNewReferenceFolderAndFiles_TRUE;

Now, youre ready to write some real conditionals based on flags:

  if(archiveCreateNewReferenceFile instanceof ArchiveCreateNewReferenceFolderAndFilesTrue) {
    //do stuff…
  }

Its simplicity itself, and just think about how maintainable it is. When you finally need to support FileNotFound, you simply need to inherit from the ArchiveCreateNewReferenceFolderAndFiles class to produce ArchiveCreateNewReferenceFolderAndFilesFileNotFound. Think of the extensibility! Think of the readability!

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

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


Метки:  

Aged Like Vinegar

Среда, 10 Августа 2016 г. 13:30 + в цитатник

It was Brians first day at AutoDetective, a website for comparing listed car prices vs. blue book values. His work inbox was overflowing with style guides, best practices, and notes from the dozen or so other developers he would be working with. His interviewer, Douglas, had mentioned that the site ran on a substantial chunk of legacy code, but Brian had experience with plenty of old code.

He spent most of the day digging through the source, getting a feel for the in-house development style. It didnt take long before he noticed how & off the code was.

An old car mouldering in a rotting garage

It wasnt just legacy code. It was obtuse legacy code.

Just Dont Touch It

Douglas came to debrief Brian at the end of the day. Brian explained how he spent the afternoon going through the codebase, looking for a project to get his hands wet. Theres a lot of inefficient code, he said. I figured Id fix something small. He pointed to a bit of code:

if (isset($_SESSION['relogin_data'])) {
 $a_relogin_data = $_SESSION['relogin_data'];
 $arr_keys = array_keys($_SESSION);
 for ($i=0; $i < sizeof($arr_keys); $i++) {
 unset($_SESSION[$arr_keys[$i]]);  
 }  
 $_SESSION['relogin_data'] = $a_relogin_data;
}

Why are we unsetting the entire array like this? Ive pared this down in my local branch. I was about to send a pull request

No, Douglas said. Thats our legacy code. We cant change a single line in that.

But its inefficient

It doesnt matter. None of us who still work here understand this code. Its like a house of cards: if we change something little, the whole thing could come crashing down.

Oh-kay. Brian quietly deleted his local branch.

Stovepipes Attached to Stovepipes

Every day, when he finished his assigned trouble tickets, Brian would attempt to make sense of the huge lump of legacy code that no one in the company could ever touch. For instance, this ultra-robust array building method, which skips simple assignation for laborious key/value reassignments:

while ($row = mysqli_fetch_assoc($result))
{
 $array_keys = array_keys($row);
 $array_values = array_values($row);

 for ($i=0; $i < sizeof($array_keys); $i++)
 $dataset[$count][$array_keys[$i]] = $array_values[$i];
 $count ++;
}

The code below checks if theres a connection already open with a given name. All database errors in the legacy codebase return false, so theres no way to tell if its a bad password, a server outage, or trying to reuse the same connection name twice:

if (isset(DBClass::$open_connections_[$conn_name])) {
 // connection is already open
 return false;
}

Everything, and one means everything, was stored in $_SESSION. Dumping session data was almost useless with how much was stored in it on a regular basis:

public function getUserInfo()
{
 return $_SESSION['logged_in'];
}
$user_info = $login->getUserInfo();
$_SESSION['user_info'] = $user_info;

// ...

$_SESSION['logged_in'] = $this->a_logged_in_;
$_SESSION['view_mode'] = $_SESSION['logged_in']['view_mode'];
$_SESSION['user_info'] = $_SESSION['logged_in'];

Then there was the utterly useless, such as a defined destructor that only calls its parent (unnecessary in PHP):

 public function __destruct()
 {
 parent::__destruct();
 }

A Unit Test Too Far

One afternoon, Brian willed himself to Douglass office. When his boss asked what the trouble was, Brian pointed him to a bit of code he had been staring at for hours. I was working on #75693, and trying to figure out where $this->SERIAL was getting set. It wasnt in the class definitions, which would be natural. Instead, I found it in this out-of-the-way include.

http://thedailywtf.com/articles/aged-like-vinegar


Метки:  

Representative Line: Compatibly Backward

Вторник, 09 Августа 2016 г. 13:30 + в цитатник

I took my first official programming class circa 1997, and that year was notable, only because it was the last years that class was taught using Turbo Pascal. In future years, it was taught in C++. For the teacher, this was quite the transition. To help her make the transition, at the end of the course, she spent a few days teaching us basic C++, so shed be more ready for the following class, and we got a little bonus education.

As far as I know, future runs of the class went just fine. I bring this up, because Frank had some co-workers who needed to make the exact same transition, from Turbo Pascal to C++. They may have done it a bit less gracefully. When reviewing some of the C++ they wrote, Frank spotted lots of code like:

if (counter > 0) then
{
  // do something in here
}

It was the then that caught his eye. It took some hunting around, but buried deep in a header file included in every other file, everywhere, he found this:

#define then

Yes, they defined an empty, do-nothing macro just so they could still type then with their if statements.

[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/compatibly-backward


Метки:  

Best Practices

Понедельник, 08 Августа 2016 г. 13:30 + в цитатник

In this world, there are those with common sense, and there are managers. In the world of high finance, there are only those with power and those without it. Those who have power make decisions - regardless of their familiarity with the relevant subject matter, or their ability to prioritize things involved in the decision. Those who don't have power (aka: us) live with the aftermath.

A tape measure with some blood splattered on it. Or maybe rust.

James T. joined a major financial company. Because they have over $1B in revenue a year, he was under the impression that these folks knew what they were doing. They paid very lucrative salaries. They all seemed intelligent. They talked a good game about best practices and doing things right. They hit all the right buzzwords during the interview.

What James didn't realize is that they were power brokers who used words without understanding what they actually meant.

We do Modular Development. Translation, each person works in a vacuum to build their own little modular piece of the system. There is no need to talk of interfaces because management doesn't know there's a need for different pieces of the application to communicate with each other. It just has to work. (Magic happens here).

We design our programs so that they lend themselves to code reuse. Translation, find some piece of code that is close to what you need, make whatever changes are necessary and cut-n-paste it into the new program.

We discuss different approaches and the Best Idea Wins. Translation, the boss has the best idea because he has the most experience, so we do it his way.

We build Frameworks. Translation, a framework is just an application to perform a certain task. It does not need to be generic because it only needs to do one or two things, so we just hard-wire everything.

OK, so programming application-specific code might not be the antithesis of framework development, but it's close enough. When trying explain the value and difference of framework code to application code his boss literally asked Why would anyone ever need that?

As it turned out, most of their "developers" were really engineers and traders. Like most businesses they're ingrained into their current paradigms. Like some engineers, they're very resistant to doing things differently.

So James is building his little single-purpose reusable module and has some questions about the specifics of what it's supposed to do. In response, his management advises him that the details are unknown at that point, but that he should forge ahead, and they'll figure out what it's supposed to do after he delivers it and they see if it's useful to the end users in production!

Forget measure twice, cut once; these folks threw away the tape measure and grabbed a power saw, leaving mountains of scrap lumber all over the place. Then they wonder why it takes so long to get anything useful delivered.

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


Метки:  

Error'd: Google Maps Delivers

Пятница, 05 Августа 2016 г. 13:00 + в цитатник

"I wonder how many packages end up in rural Alabama?" Andreas wrote.

"Add-ons were causing a problem with Internet Explorerk, so I thought disabling them would help," John S. writes, "Oh how wrong I was."

Kevin L. writes, "I would really like to log out. Really!"

"Got this message when I wanted to close the screen. I wasn't sure what to do, so I left the message open until all tasks were complete," Rick D. writes.

Alain wrote, "Huh. Paula Bean is now into the ringtone making business. Who knew?"

"Someone I know was going to Paypal me some money. Good on Paypal for being vigilant, seeing how they are trying to withdraw $180k instead!" writes Sergey S.

"The perfect side to any kabob is a tall, cool glass of grey," wrote Ben S.

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

http://thedailywtf.com/articles/google-maps-delivers


Метки:  

Coded Smorgasbord: A Comment On Comments

Четверг, 04 Августа 2016 г. 13:30 + в цитатник

PICOL Comment

Today, programmers, let us celebrate all the varied and wonderful facets of code commenting: an art that too few of our brethren bother with, and even fewer master. Those who do stand to leave their mark on untold generations to come!

There are the comments that make us laugh out loud, as Hopsas illustrates:


//  ( 

http://thedailywtf.com/articles/a-comment-on-comments


Метки:  

Поиск сообщений в rss_thedaily_wtf
Страницы: 124 ... 41 40 [39] 38 37 ..
.. 1 Календарь