Feed the-daily-wtf The Daily WTF

Favorite IconThe Daily WTF

Link http://thedailywtf.com/
Feed http://syndication.thedailywtf.com/TheDailyWtf
Updated 2024-07-03 12:02
Error'd: Go Home Google News, You're Drunk
"Well, it looks like Google News was inebriated as well!" Daniel wrote.
Improv for Programmers: Just for Transformers
We're back again with a little something different, brought to you by Raygun. Once again, the cast of "Improv for Programmers" is going to create some comedy on the fly for you, and this time… you could say it's… transformative. Today's episode contains small quantities of profanity.Raygun provides a window into how users are really experiencing your software applications.Unlike traditional logging, Raygun silently monitors applications for issues affecting end users in production, then allows teams to pinpoint the root cause behind a problem with greater speed and accuracy by providing detailed diagnostic information for developers. Raygun makes fixing issues 1000x faster than traditional debugging methods using logs and incomplete information.Now’s the time to sign up. In a few minutes, you can have a build of your app with Raygun integrated, and you’ll be surprised at how many issues it can identify. There’s nothing to lose with a 14-day free trial, and there are pricing options available that fit any team size. [Advertisement] ProGet can centralize your organization's software applications and components to provide uniform access to developers and servers. Check it out!
Business Driven Development
Every now and then, you come across a special project. You know the sort, where some business user decides that they know exactly what they need and exactly how it should be built. They get the buy-in of some C-level shmoe by making sure that their lips have intimate knowledge of said C-level butt. Once they have funding, they have people hired and begin to bark orders.About 8 years ago, I had the privilege experience of being on such a project. When we were given the phase-I specs, all the senior tech people immediately said that there was no way to perform a sane daily backup and data-roll for the next day. The response was "We're not going to worry about backups and daily book-rolls until later". We all just cringed, made like good little HPCs and followed our orders to march onward.Fast forward about 10 months and the project had a sufficient amount of infrastructure that the business user had no choice but to start thinking about how to close the books each day, and roll things forward for the next day. The solution he came up with was as follows:
Representative Line: Aggregation of Concatenation
A few years back, JSON crossed the “really good hammer” threshold. It has a good balance of being human readable, relatively compact, and simple to parse. It thus has become the go-to format for everything. “KoHHeKT” inherited a service which generates some JSON from an in-memory tree structure. This is exactly the kind of situation where JSON shines, and it would be trivial to employ one of the many JSON serialization libraries available for C# to generate JSON on demand.Orrrrr… you could use LINQ aggregations, string formatting and trims…
The New Guy (Part I)
After working mind-numbing warehouse jobs for several years, Jesse was ready for a fresh start in Information Technology. The year 2015 brought him a newly-minted Computer and Networking Systems degree from Totally Legit Technical Institute. It would surely help him find gainful employment, all he had to do was find the right opportunity.Seeking the right opportunity soon turned in to any opportunity. Jesse came across a posting for an IT Systems Administrator that piqued his interest but the requirements and responsibilities left a lot to be desired. They sought someone with C++ and Microsoft Office experience who would perform "General IT Admin Work" and "Other Duties as assigned". None of those things seemed to fit together, but he applied anyway.During the interview, it became clear that Jesse and this small company were essentially in the same boat. While he was seeking any IT employment, they were seeking any IT Systems admin. Their lone admin recently departed unexpectedly and barely left any documentation of what he actually did. Despite several red flags about the position, he decided to accept anyway. Jesse was assured of little oversight and freedom to do things his way - an extreme rarity for a young IT professional.Jesse got to work on his first day determined to map out the minefield he was walking in to. The notepad with all the admin passwords his predecessor left behind was useful for logging in to things. Over the next few days, he prodded through the network topology to uncover all the horrors that lie within. Among them:
Error'd: Perfectly Technical Difficulties
David G. wrote, "For once, I'm glad to see technical issues being presented in a technical way."
Improv for Programmers: Inventing the Toaster
We always like to change things up a little bit here at TDWTF, and thanks to our sponsor Raygun, we've got a chance to bring you a little treat, or at least something a little different.We're back with a new podcast, but this one isn't a talk show or storytelling format, or even a radio play. Remy rounded up some of the best comedians in Pittsburgh who were also in IT, and bundled them up to do some improv, using articles from our site and real-world IT news as inspiration. It's… it's gonna get weird.Thanks to Erin Ross, Ciarán Ó Conaire, and Josh Cox for lending their time and voices to this project.Music: "Happy Happy Game Show" Kevin MacLeod (incompetech.com)Licensed under Creative Commons: By Attribution 3.0 Licensehttp://creativecommons.org/licenses/by/3.0/Raygun gives you a window into the real user-experience for your software. With a few minutes of setup, all the errors, crashes, and performance issues will be identified for you, all in one tool. Not only does it make your applications better, with Raygun APM, it proactively identifies performance issues and builds a workflow for solving them. Raygun APM sorts through the mountains of data for you, surfacing the most important issues so they can be prioritized, triaged and acted on, cutting your Mean Time to Resolution (MTTR) and keeping your users happy.Now’s the time to sign up. In a few minutes, you can have a build of your app with Raygun integration, and you’ll be surprised at how many issues it can identify. There’s nothing to lose with a 14-day free trial, and there are pricing options available that fit any team size. [Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
CodeSOD: Return of the Mask
Sometimes, you learn something new, and you suddenly start seeing it show up anywhere. The Baader-Meinhof Phenomenon is the name for that. Sometimes, you see one kind of bad code, and the same kind of bad code starts showing up everywhere. Yesterday we saw a nasty attempt to use bitmasks in a loop.Today, we have Michele’s contribution, of a strange way of interacting with bitmasks. The culprit behind this code was a previous PLC programmer, even if this code wasn’t running straight on the PLC.
CodeSOD: A Bit Masked
The “for-case” or “loop-switch” anti-pattern creates some hard to maintain code. You know the drill: the first time through the loop, do one step, the next time through the loop, do a different step. It’s known as the “Anti-Duff’s Device”, which is a good contrast: Duff’s Device is a clever way to unroll a loop and turn it into a sequential process, while the “loop-switch” takes a sequential process and turns it into a loop.Ashlea inherited an MFC application. It was worked on by a number of developers in Germany, some of which used English to name identifiers, some which used German, creating a new language called “Deunglish”. Or “Engleutch”? Whatever you call it, Ashlea has helpfully translated all the identifiers into English for us.Buried deep in a thousand-line “do everything” method, there’s this block:
CodeSOD: CONDITION_FAILURE
Oliver Smith sends this representative line:
Error'd: Kind of...but not really
"On occasion, SQL Server Management Studio's estimates can be just a little bit off," writes Warrent B.
CodeSOD: A Quick Replacement
Lucio Crusca was doing a bit of security auditing when he found this pile of code, and it is indeed a pile. It is PHP, which doesn’t automatically make it bad, but it makes use of a feature of PHP so bad that they’ve deprecated it in recent versions: the create_function method.Before we even dig into this code, the create_function method takes a string, runs eval on it, and returns the name of the newly created anonymous function. Prior to PHP 5.3.0 this was their method of doing lambdas. And while the function is officially deprecated as of PHP 7.2.0… it’s not removed. You can still use it. And I’m sure a lot of code probably still does. Like this block…
Exponential Backup
The first day of a new job is always an adjustment. There's a fine line between explaining that you're unused to a procedure and constantly saying "At my old company...". After all, nobody wants to be that guy, right? So you proceed with caution, trying to learn before giving advice.But some things warrant the extra mile. When Samantha started her tenure at a mid-sized firm, it all started out fine. She got a computer right away, which is a nice plus. She met the team, got settled into a desk, and was given a list of passwords and important URLs to get situated. The usual stuff.After changing her Windows password, she decided to start by browsing the source code repository. This company used Subversion, so she went and downloaded the whole repo so she could see the structure. It took a while, so she got up and got some coffee; when she got back, it had finished, and she was able to see the total size: 300 GB. That's... weird. Really weird. Weirder still, when she glanced over the commit history, it only dated back a year or so.What could be taking so much space? Were they storing some huge binaries tucked away someplace that the code depended on? She didn't want to make waves, but this just seemed so... inefficiently huge. Now curious, she opened the repo, browsing the folder structure.Subversion bases everything on folder structure; there is only really one "branch" in Git's thinking, but you can check out any subfolder without taking the whole repository. Inside of each project directory was a layout that is common to SVN repos: a folder called "branches", a folder called "tags", and a folder called "trunk" (Subversion's primary branch). In the branches directory there were folders called "fix" and "feature", and in each of those there were copies of the source code stored under the names of the branches. Under normal work, she'd start her checkout from one of those branch folders, thus only pulling down the code for her branch, and merge into the "trunk" copy when she was all done.But there was one folder she didn't anticipate: "backups". Backups? But... this is version control. We can revert to an earlier version any time we want. What are the backups for? I must be misunderstanding. She opened one and was promptly horrified to find a series of zip files, dated monthly, all at revision 1.Now morbidly curious, Samantha opened one of these zips. The top level folder inside the zip was the name of the project; under that, she found branches, tags, trunk. No way. They can't have-- She clicked in, and there it was, plain as day: another backups folder. And inside? Every backup older than the one she'd clicked. Each backup included, presumably, every backup prior to that, meaning that in the backup for October, the backup from January was included nine times, the backup from February eight times, and so on and so forth. Within two years, a floppy disk worth of code would fill a terabyte drive.Samantha asked her boss, "What will you do when the repo gets too big to be downloaded onto your hard drive?His response was quick and entirely serious: "Well, we back it up, then we make a new one." [Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!
Yes == No
For decades, I worked in an industry where you were never allowed to say no to a user, no matter how ridiculous the request. You had to suck it up and figure out a way to deliver on insane requests, regardless of the technical debt they inflicted.Users are a funny breed. They say things like I don't care if the input dialog you have works; the last place I worked had a different dialog to do the same thing, and I want that dialog here! With only one user saying stuff like that, it's semi-tolerable. When you have 700+ users and each of them wants a different dialog to do the same thing, and nobody in management will say no, you need to start creating table-driven dialogs (x-y coordinates, width, height, label phrasing, field layout within the dialog, different input formats, fonts, colors and so forth). Multiply that by the number of dialogs in your application and it becomes needlessly pointlessly impossibly difficult.But it never stops there. Often, one user will request that you move a field from another dialog onto their dialog - just for them. This creates all sorts of havoc with validation logic. Multiply it by hundreds of users and you're basically creating a different application for each of them - each with its own validation logic, all in the same application.After just a single handful of users demanding changes like this, it can quickly become a nightmare. Worse, once it starts, the next user to whom you say no tells you that you did it for the other guy and so you have to do it for them too! After all, each user is the most important user, right?It doesn't matter that saying no is the right thing to do. It doesn't matter that it will put a zero-value load on development and debugging time. It doesn't matter that sucking up development time to do it means there are less development hours for bug fixes or actual features.When management refuses to say no, it can turn your code into a Pandora's-Box-o-WTFâ„¢However, there is hope. There is a way to tell the users no without actually sayingno. It's by getting them to say it for you and then withdrawing their urgent, can't-live-without-it, must-have-or-the-world-will-end request.You may ask how?The trick is to make them see the actual cost of implementing their teeny tiny little feature.
CodeSOD: CHashMap
There’s a phenomenon I think of as the “evolution of objects” and it impacts novice programmers. They start by having piles of variables named things like userName0, userName1, accountNum0, accountNum1, etc. This is awkward and cumbersome, and then they discover arrays. string* userNames, int[] accountNums. This is also awkward and cumbersome, and then they discover hash maps, and can do something like Map<string, string>* users. Most programmers go on to discover “wait, objects do that!”Not so Brian’s co-worker, Dagny. Dagny wanted to write some C++, but didn’t want to learn that pesky STL or have to master templates. Dagny also considered themselves a “performance junkie”, so they didn’t want to bloat their codebase with peer-reviewed and optimized code, and instead decided to invent that wheel themselves.Thus was born CHashMap. Now, Brian didn’t do us the favor of including any of the implementation of CHashMap, claiming he doesn’t want to “subject the readers to the nightmares that would inevitably arise from viewing this horror directly”. Important note for submitters: we want those nightmares.Instead, Brian shares with us how the CHashMap is used, and from that we can infer a great deal about how it was implemented. First, let’s simply look at some declarations:
Error'd: Version-itis
"No thanks, I'm holding out for version greater than or equal to 3.6 before upgrading," writes Geoff G.
CodeSOD: The Same Date
Oh, dates. Oh, dates in Java. They’re a bit of a dangerous mess, at least prior to Java 8. That’s why Java 8 created its own date-time libraries, and why JodaTime was the gold standard in Java date handling for many years.But it doesn’t really matter what date handling you do if you’re TRWTF. An Anonymous submitter passed along this method, which is meant to set the start and end date of a search range, based on a number of days:
CodeSOD: A Password Generator
Every programming language has a *bias* which informs their solutions. Object-oriented languages are biased towards objects, and all the things which follow on. Clojure is all about function application. Haskell is all about type algebra. Ruby is all about monkey-patching existing objects.In any language, these things can be taken too far. Java's infamous Spring framework leaps to mind. Perl, being biased towards regular expressions, has earned its reputation as being "write only" thanks to regex abuse.Gert sent us along some Perl code, and I was expecting to see regexes taken too far. To my shock, there weren't any regexes.Gert's co-worker needed to generate a random 6-digit PIN for a voicemail system. It didn't need to be cryptographically secure, repeats and zeros are allowed (they exist on a keypad, after all!). The Perl-approach for doing this would normally be something like:
An Obvious Requirement
Requirements. That magical set of instructions that tell you specifically what you need to build and test. Users can't be bothered to write them, and even if they could, they have no idea how to tell you what they want. It doesn't help that many developers are incapable of following instructions since they rarely exist, and when they do, they usually aren't worth the coffee-stained napkin upon which they're scribbled.That said, we try our best to build what we think our users need. We attempt to make it fairly straightforward to use what we build. The button marked Reports most likely leads to something to do with generating/reading/whatever-ing reports. Of course, sometimes a particular feature is buried several layers deep and requires multiple levels of ribbons, menus, sub-menus, dialogs, sub-dialogs and tabs before you find the checkbox you want. Since us developers as a group are, by nature, somewhat anal retentive, we try to keep related features grouped so that you can generally guess what path to try to find something. And we often supply a Help feature to tell you how to find it when you can't.Of course, some people simply cannot figure out how to use the software we build, no matter how sensibly it's laid out and organized, or how many hints and help features we provide. And there is nothing in the history of computer science that addresses how to change this. Nothing!Dimitri C. had a user who wanted a screen that performed several actions. The user provided requirements in the form of a printout of a similar dialog he had used in a previous application, along with a list of changes/colors/etc. They also provided some "helpful" suggestions, along the lines of, "It should be totally different, but exactly the same as the current application." Dimitri took pains to organize the actions and information in appropriate hierarchical groups. He laid out appropriate controls in a sensible way on the screen. He provided a tooltip for each control and a Help button.Shortly after delivery, a user called to complain that he couldn't find a particular feature. Dimitri asked "Have you tried using the Help button?" The user said that "I can't be bothered to read the instructions in the help tool because accessing this function should be obvious".Dimitri asked him "Have you looked on the screen for a control with the relevant name?" The user complained that "There are too many controls, and this function should be obvious". Dimitri asked "Did you try to hover your mouse over the controls to read the tooltips?" The user complained that "I don't have the time to do that because it would take too long!" (yet he had the time to complain).Frustrated, Dimitri replied "To make that more obvious, should I make these things less obvious?". The user complained that "Everything should be obvious". Dimitri asked how that could possibly be done, to which the user replied "I don't know, that's your job".When he realized that this user had no clue how to ask for what he wanted, he asked how this feature worked in previous programs, to which the user replied "I clicked this, then this, then this, then this, then this, then restarted the program".Dimitri responded that "That's six steps instead of the two in my program, and that would require you to reenter some of the data".The user responded "Yes, but it's obvious".So is the need to introduce that type of user to the business end of a clue-bat. [Advertisement] Ensure your software is built only once and then deployed consistently across environments, by packaging your applications and components. Learn how today!
CodeSOD: Philegex
Last week, I was doing some graphics programming without a graphics card. It was low resolution, so I went ahead and re-implemented a few key methods from the Open GL Shader Language in a fashion which was compatible with NumPy arrays. Lucky for me, I was able to draw off many years of experience, I understood both technologies, and they both have excellent documentation which made it easy. After dozens of lines of code, I was able to whip up some pretty flexible image generator functions. I knew the tools I needed, I understood how they worked, and while I was reinventing a wheel, I had a very specific reason.Philemon Eichin sends us some code from a point in his career where none of these things were true.Philemon was building a changelog editor. As such, he wanted an easy, flexible way to identify patterns in the text. Philemon knew that there was something that could do that job, but he didn’t know what it was called or how it was supposed to work. So, like all good programmers, Philemon went ahead and coded up what he needed- he invented his own regular expression language, and built his own parser for it.Thus was born Philegex. Philemon knew that regexes involved slashes, so in his language you needed to put a slash in front of every character you wanted to match exactly. He knew that it involved question marks, so he used the question mark as a wildcard which could match any character. That left the ’|" character to be optional.So, for example: /P/H/I/L/E/G/E/X|??? would match “PHILEGEX!!!” or “PHILEGEWTF”. A date could be described as: nnnn/.nn/.nn. (YYYY.MM.DD or YYYY.DD.MM)Living on his own isolated island without access to the Internet to attempt to google up “How to match patterns in text”, Philemon invented his own language for describing parts of a regular expression. This will be useful to interpret the code below.PhilegexRegexMaskableMatchesp1Pattern / RegexBlock(s)Token(s)CTCharTypeSplitLineParseRegexCCcurrentCharauf_zuopenParenthesisCharsCharClassificationWith the preamble out of the way, enjoy Philemon’s approach to regular expressions, implemented elegantly in VB.Net.
Error'd: Billboards Show Obvious Disasters
"Actually, this board is outside a casino in Sheffield which is next to the church, but we won't go there," writes Simon.
CodeSOD: If Not Null…
Robert needed to fetch some details about pump configurations from the backend. The API was poorly documented, but there were other places in the code which did that, so a quick search found this block:
The Search for Truth
Every time you change existing code, you break some other part of the system. You may not realize it, but you do. It may show up in the form of a broken unit test, but that presumes that a) said unit test exists, and b) it properly tests the aspect of the code you are changing. Sadly, more often than not, there is either no test to cover your change, or any test that does exist doesn't handle the case you are changing.This is especially true if the thing you are changing is simple. It is even more true when changing something as complex as working with a boolean.Mr A. was working at a large logistics firm that had an unusual error where a large online retailer was accidentally overcharged by millions of dollars. When large companies send packages to logistics hubs for shipment, they often send hundreds or thousands of them at a time on the same pallet, van or container (think about companies like Amazon). The more packages you send in these batches the less you pay (a single lorry is cheaper than a fleet of vans). These packages are lumped together and billed at a much lower rate than you or I would get.One day, a particular developer saw something untidy in the code - an uninitialized Boolean variable in one of the APIs. The entire code change was from this:
The Big Balls of…
The dependency graph of your application can provide a lot of insight into how objects call each other. In a well designed application, this is probably mostly acyclic and no one node on the graph has more than a handful of edges coming off of it. The kinds of applications we talk about here, on the other hand, we have a name for their graphs: the Enterprise Dependency and the Big Ball of Yarn.Thomas K introduces us to an entirely new iteration: The Big Ball of MandelbrotThis gives new meaning to points “on a complex plane”.What you’re seeing here is the relationship between stored procedures and tables. Circa 1995, when this application shambled into something resembling life, the thinking was, “If we put all the business logic in stored procedures, it’ll be easy to slap new GUIs on there as technology changes!”Of course, the relationship between what the user sees on the screen and the underlying logic which drives that display means that as they changed the GUI, they also needed to change the database. Over the course of 15 years, the single cohesive data model ubercomplexificaticfied itself as each customer needed a unique GUI with a unique feature set which mandated unique tables and stored procedures.By the time Thomas came along to start a pseudo-greenfield GUI in ASP.Net, the first and simplest feature he needed to implement involved calling a 3,000 line stored procedure which required over 100 parameters. [Advertisement] Otter - Provision your servers automatically without ever needing to log-in to a command prompt. Get started today!
Representative Line: The Truth About Comparisons
We often point to dates as one of the example data types which is so complicated that most developers can’t understand them. This is unfair, as pretty much every data type has weird quirks and edge cases which make for unexpected behaviors. Floating point rounding, integer overflows and underflows, various types of string representation…But file-not-founds excepted, people have to understand Booleans, right?Of course not. We’ve all seen code like:
Error'd: Placeholders-a-Plenty
"On my admittedly old and cheap phone, Google Maps seems to have confused the definition of the word 'trip'," writes Ivan.
CodeSOD: A Problematic Place
In programming, sometimes the ordering of your data matters. And sometimes the ordering doesn’t matter and it can be completely random. And sometimes… well, El Dorko found a case where it apparently matters that it doesn’t matter:
The Proprietary Format
Have you ever secured something with a lock? The intent is that at some point in the future, you'll use the requisite key to regain access to it. Of course, the underlying assumption is that you actually have the key. How do you open a lock once you've lost the key? That's when you need to get creative. Lock picks. Bolt cutters. Blow torch. GAU-8...In 2004, Ben S. went on a solo bicycle tour, and for reasons of weight, his only computer was a Handspring Visor Deluxe PDA running Palm OS. He had an external, folding keyboard that he would use to type his notes from each day of the trip. To keep these notes organized by day, he stored them in the Datebook (calendar) app as all-day events. The PDA would sync with a desktop computer using a Handspring-branded fork of the Palm Desktop software. The whole Datebook could then be exported as a text file from there. As such, Ben figured his notes were safe. After the trip ended, he bought a Windows PC that he had until 2010, but he never quite got around to exporting the text file. After he switched to using a Mac, he copied the files to the Mac and gave away the PC.Ten years later, he decided to go through all of the old notes, but he couldn't open the files!Uh oh.The Handspring company had gone out of business, and the software wouldn't run on the Mac. His parents had the Palm-branded version of the software on one of their older Macs, but Handspring used a different data file format that the Palm software couldn't open. His in-laws had an old Windows PC, and he was able to install the Handspring software, but it wouldn't even open without a physical device to sync with, so the file just couldn't be opened. Ben reluctantly gave up on ever accessing the notes again.Have you ever looked at something and then turned your head sideways, only to see it in a whole new light?One day, Ben was going through some old clutter and found a backup DVD-R he had made of the Windows PC before he had wiped its hard disk. He found the datebook.dat file and opened it in SublimeText. There he saw rows and rows of hexadecimal code arranged into tidy columns. However, in this case, the columns between the codes were not just on-screen formatting for readability, they were actual space characters! It was not a data file after all, it was a text file.The Handspring data file format was a text file containing hexadecimal code with spaces in it! He copied and pasted the entire file into an online hex-to-text converter (which ignored the spaces and line breaks), and voilà , Ben had his notes back! [Advertisement] Forget logs. Next time you're struggling to replicate error, crash and performance issues in your apps - Think Raygun! Installs in minutes. Learn more.
CodeSOD: Breaking Changes
We talk a lot about the sort of wheels one shouldn’t reinvent. Loads of bad code stumbles down that path. Today, Mary sends us some code from their home-grown unit testing framework.Mary doesn’t have much to say about whatever case of Not Invented Here Syndrome brought things to this point. It’s especially notable that this is Python, which comes, out of the box, with a perfectly serviceable unittest module built in. Apparently not serviceable enough for their team, however, as Burt, the Lead Developer, wrote his own.His was Object Oriented. Each test case received a TestStepOutcome object as a parameter, and was expected to return that object. This meant you didn’t have to use those pesky, readable, and easily comprehensible assert… methods. Instead, you just did your test steps and called something like:
CodeSOD: All the Things!
Yasmin needed to fetch some data from a database for a report. Specifically, she needed to get all the order data. All of it. No matter how much there was.The required query might be long running, but it wouldn’t be complicated. By policy, every query needed to be implemented as a stored procedure. Yasmin, being a smart prograammer, decided to check and see if anybody had already implemented a stored procedure which did what she needed. She found one called GetAllOrders. Perfect! She tested it in her report.Yasmin expected 250,000 rows. She got 10.She checked the implementation.
Error'd: Surgeons, Put Down Your Scalpels
"I wonder what events, or lawsuits, lead TP-Link to add this warning presumably targeted individuals who updated firmware just ahead of performing medical procedures," writes Andrew.
To Suffer The Slings and Arrows of Vendor Products…
Being a software architect is a difficult task. Part of the skill is rote software design based upon the technology of choice. Part of it is the very soft "science" of knowing how much to design to make the software somewhat extensible without going so far as to design/build something that is overkill. An extreme version of this would be the inner platform effect.Way back when I was a somewhat new developer, I was tasked with adding a fairly large feature that required the addition of a database to our otherwise database-less application. I went to our in-team architect, described the problem, and asked him to request a modest database for us. At the time, Sybase was the in-house tool. He decreed that "Sybase sucks", and that he could build a better database solution himself. He would even make it more functional than Sybase.At the time, I didn't have a lot of experience, especially with databases, but intuition told me that Sybase had employed countless people for more than a decade to build and tweak Sybase. When I pointed this out, and the fact the it was unlikely that he was going to build a better database than all that effort - by himself - in only a few days, I received a full-on dressing down because I didn't know what was possible, and that a good architect could design and build anything. While I agreed that given enough time it might be possible, it was highly unlikely that it would happen in the next three days (because I needed time to do my coding against the database to meet the delivery schedule). I was instructed to wait and he would get it to me in time.My Spidy-Senseâ„¢ told me not to trust him, so I went to the DBAs that day and told them what I needed. Since I had little relevant experience with setting up a database, I told them of my inexperience with such things and asked them to optimize it with indices, etc. They created it for me that day. Since it was their implementation of my (DB) requirements, I knew that it would at least pass their review. I then coded the required feature and delivered on time. Was it perfect? No. Could it have been designed better? In retrospect, sure. But I was new to databases and it was fast enough for the need at the time.At every meeting for the next three months, our manager asked the architect how his Sybase-replacement was coming along. He sheepishly admitted that while it was coming along well, coming up with a design that would support all of the features provided by Sybase was proving to be a bit more involved than he had imagined, and that it would take a while longer.Several months after that, he was still making schematics and flow diagrams to try and build a new and improved Sybase.Our manager never did do anything to stop him from wasting time.As for me, I learned an important lesson about knowing when to write code, and when not to write code. [Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!
Sponsor Post: Make Your Apps Faster With Raygun APM
Your software is terrible, but that doesn’t make it special. All software is terrible, and yes, you know this is true. No matter how good you think it is, bugs and performance problems are inevitable.But it’s not just the ugly internals and mysterious hacks and the code equivalent of duct-tape and chewing gum which make your software terrible. Your software exists to fill some need for your users, and how do you know that’s happening? And worse, when your application fails, how do you understand what happened?In the past, we’ve brought your attention to Raygun, which allows you to add a real-time feedback loop that gives you a picture of exactly what’s happening on their device or their browser. And now, Raygun is making it even better, with Raygun APM.Raygun Application Performance Monitoring (APM) tackles the absolute worst part of releasing/supporting applications: dealing with performance issues. With Raygun APM, you can get real-time execution stats on your server-side code, and find out quickly which specific function, line, or database call is slowing down your application.You won’t have to wait for someone to notice the issue, either- Raygun APM proactively identifies performance issues and builds a workflow for solving them. Raygun APM sorts through the mountains of data for you, surfacing the most important issues so they can be prioritized, triaged and acted on, cutting your Mean Time to Resolution (MTTR) and keeping your users happy.In addition to all this, Raygun is adding tight integration with source control, starting with GitHub.Request access to the beta here. Or if you’re already tired of searching logs for clues in an effort to replicate an issue, try out Raygun’s current offerings and resolve errors, crashes and performance issues with greater speed and accuracy. [Advertisement] ProGet supports your applications, Docker containers, and third-party packages, allowing you to enforce quality standards across all components. Download and see how!
A Comment on the Military Industrial Complex
Simon T tugged at his collar when the video played. It wasn’t much, just a video of their software being tested. It wasn’t the first time they’d tested Simon’s most recent patch, but it was going to be the last time. There were a lot of eyes in the conference room, and they were all turned on him.Simon worked for the kind of company which made missiles. The test in the video was one of the highly expensive tests of a real missile under real-world conditions. Several of these had already been done with this software package, so Simon hadn’t expected any problems to crop up. In this case, though, the missile left its launcher and sailed in a perfect parabolic arc into the ground 5 meters away from the launch site.Missiles diving headfirst into the ground mere meters from their launch site was officially considered a bad thing. There were all sorts of checkpoints and automated tests and simulations that were supposed to keep this thing from happening. It didn’t take long to find the problem.
CodeSOD: Without Context
When writing up a Code SOD, a big part of the goal is to provide context for the bad code. Why is it bad, what would be better,, etc. In other words, we need to… ShowContext. Vasco O has exactly the method for that.
Another Bitmask Fail
As we've seen previously, not all government jobs are splashy. Someone has to maintain, for example, the database that keeps track of every legal additive to food so that paranoid hippies can call them liars and insist they all cause cancer and autism. Today's submitter, Cass, had just released an update when users started getting the dreaded blue Internal Error screen—never a good start to the week.Everything that's added to food is added for a reason; otherwise, why spend money doing it? The additive website allows searching by function, as well as by name. For example, some items might be alternative sweeteners, while others might be coloring agents. The problem of the week turned out to be in the stored procedure related to this particular search, which was intuitively titled prc_AdditiveRegulation_GetResults_NEW. Not to be confused with the entirely unused prc_AdditiveRegulation_GetResults, prc_AdditiveRegulation_GetResults_DEV, or prc_AdditiveRegulation_GetResults_PROD.As Cass quickly discovered, prc_AdditiveRegulation_GetResults_NEW is a hefty chunk of code. 1044 lines, to be precise, all dedicated to returning a list of additives and their functions. After hours of searching, Cass managed to isolate the portion that was causing the problem:
Error'd: Heed this Warning
Sam B. writes, "Only £11.99 for a call_user_func_array() warning? What a bargain!"
Works for Us
Containers make deployment easy, or at least that’s what it says on the label. It makes intuitive sense, though- instead of wrangling all your dependencies on a host OS, and then trying to understand why your app can’t see them, you bundle all the dependencies into a container and push that around when you want to deploy. It Just Works™.Sandra had just left a company which didn’t use containers, but containers wouldn’t have helped: the didn’t have a working deployment process, period. They didn’t even try deploying before the production push 9 months into the project, and the first twelve attempts consistently failed because someone hadn’t tested something, or someone didn’t update the script, or the requirements changed and were signed off but nobody told the development team. It meant a lot of nights, a lot of weekends, and a lot of meetings which devolved into circular firing squads.Enter Initrovent™, a cutting edge, SaaS provider which serviced the event planning industry. Karl, the Big Boss, assured Sandra that he completely understood the importance of deployments. “Oh, you don’t have to tell me,” he said. “I’ve seen so many failed deployments. We’re actually moving our platform into dockerized microservices with continuous deployment. We’ve build a process which works for us.”Overall, the gig sounded like a good fit, so Sandra started a few Mondays later. She spent most of the day “on boarding”, so it wasn’t until late in the afternoon that she tried to get her development environment set up. Based on her conversation with Karl, Sandra had assumed she’d pull down a container and be ready to go.She was half right. The company had one standard container. It had nothing in it. The install guide walked Sandra through spinning up one container and installing Apache, then another container for MySQL, then another for Memcache, then another for something only called “queue”, which reeked of some sort of inner-platform attempt at being “enterprise”, but Karl could only explain as being required “because of Docker”.That was Sandra’s first day. On her way out, she stopped by Karl’s office. “Hey, since I’ve got those containers set up, should I put them somewhere so other devs don’t have to set them up?”“What do you mean?” Karl asked.“Y’know, so they don’t have to set up from scratch every time? They can just use the containers I set up?”Karl nodded, as if he understood. “Oh, I don’t think that’s necessary. Besides, in my experience, every developer wants to set their environment up themselves. It’s fine.”“That’s not how containers work.”“Well, it works for us,” Karl said.The next day, Sandra pulled down the code. The install guide, in bright red text, loudly announced that it must be placed in the /projects/intirovent/planner folder, because the Docker container was hard-coded to use that mount point, and no other. Once she had the code downloaded, she tried to test it, and discovered nothing but error messages. She went back through the install guide, just to be certain, and then took a glance at the code.It was not microservices. It was a PHP monolith written using a 2012 release of CakePHP which had been endlessly tweaked in the intervening years. Lining up the errors she was seeing with the code, it quickly became obvious that unless a user was very careful with the application, they would see lots and lots of error messages. With a little practice, Sandra managed to get through the sign up process with only one cryptic 500 error, and even created an event.In that code there was a folder called microservices. It was a bunch of RESTful endpoints. Karl explained: “They’re small, and they’re web services.”“That’s… that’s not how microservices work.”“Well, it works for us.”That was Sandra’s second day. The week ground on like three fully interlocked gears, but by the end of the week, Sandra had not only cleaned up a few of the nastier bugs, but had finished off a new and rather large feature. She closed the ticket, and then Karl followed up: “Swing by, and I can show you how deployments work.”“Deployments? On a Friday afternoon?” Sandra asked when she got to Karl’s office.“Well, I did say we do continuous deployment.”“That’s… not how continuous deployment works.”“Well, it-”“-works for us?” Sandra took a seat to watch the show. She wasn’t surprised by what she saw.The purpose of containers is to have a single unit, with all its dependencies, which can be deployed, possibly to many different machines or VMs. That’s, at its core, how containers work. They’re easy to test, they’re easy to automate, and they’re easy to deploy.Karl didn’t test, didn’t automate, and the deployment… well. Karl SSHed into the one server which constituted their production environment, and then went over to /projects/intirovent/planner, where he issued a git pull. Karl pulled up the site in his browser, hit refresh a few times, and smiled when he saw the landing page. “Great work.”“That’s your deployment process?”“Yep. Works pretty great, doesn’t it?”The deployment process may have worked for Karl, but Sandra didn’t plan to work for him much longer. [Advertisement] Continuously monitor your servers for configuration changes, and report when there's configuration drift. Get started with Otter today!
CodeSOD: 30 Days
Tim B did a little work with an e-learning vendor, with some very old code. The code in question happened to be so old that “this is server side JavaScript” was a horrifying novelty when they wrote it, instead of a standard deployment option via Node.The code in question is bad date handling code, which isn’t impressive. What is impressive is that it demonstrates a terrible approach to dates which I’ve never seen before. It doubles as a terrible approach to arrays which I have seen before, but… it remains special.
CodeSOD: A Repeated Save
Ian S was going through the portfolio of applications maintained by his company, and stumbled across one that… well, from what he could tell, wasn’t written by a developer so much as spawned by an accident. 90% of the code was copy-pasted from somewhere else in the code, flow-of-control mostly used Exceptions as an attempt at doing GOTO-style logic, and there were piles of unused variables or variables used before initialization. Some modules/packages in the application were full of syntax errors, which implied that they weren’t actually included or used anywhere.From that mess, Ian extracted this.
AI-Driven Articles
If you've looked at job postings, you know that there's one thing really big and trendy right now, and that's blockchains. But the other trendy thing is Machine Learning! We'll talk about the Daily WTF's Initial Coin Offering at a later date, but for right now, we're excited to announce our new ML efforts.Specifically, we recognize that there's a certain structure and pattern to our articles, and instead of paying human writers, we can instead employ the latest machine learning systems to generate new articles that will be indistinguishable from the articles you know and love. The ideal tool, of course, would be an Recurrent Neural Network, which we could train based off previous articles. Unfortunately, that involves a lot of GPU power, and we're already using our GPUs to get ready for that ICO I mentioned. Shhhh. It's a secret.In any case, since we couldn't use an RNN, we opted for the next best thing: a Markov Chain. I'm sure what follows will be a perfectly good article.>actually all the saw the IP address the variable night Saving stream(r).collectors.toMap(x -&gt; {try{return x.getInputStream(file != null, because the that can handle the servers were of the users who cannoying to times, they know how company he made a case where I might the mess of correct time. But oncept would financial time. While the time issues had to be users were off for it in their IDE was assigned to be used as that exchange. The server1 with it. The arrays.stream&gt; m = Arrays.stream(r).collectors.toMap(x -&gt; {try{return x.getFile%3AVictory!_Congress pass, which is night. This point.
Error'd: Visual Studio? Whatever!
TZ wrote, "Looks like somebody at Microsoft doesn't like static web pages!"
CodeSOD: Attack of the WASPs
Werner sent us some code from the telcom industry. Before we even get to the code, we have to look at one of the comments.
CodeSOD: A Unique Solution
Ruby is a nice little language, but I think it wouldn’t have exploded in popularity like it did without Rails. Nowadays, Ruby still seems to be the first choice of early-stage startups. A big part of that is how easy ActiveRecord makes database access.Adrian was doing some code reviews, when he came across this line:
CodeSOD: The Truth About Internationalization
Booleans. One would think that simple true and false would be sufficient to represent all the possible values. However, even more than dates, they are one of the most difficult things to master in all of computer science. There are all manner of possible values and many different ways of comparing different entities.Compounding everything is another dimension to boolean-ness: internationalization. After all, not every language uses English spellings of true and false. In high school, they made me take French, so it'd be vrai and faux. For most of us, we'd put the language-specific spelling in an application-phrases file, cache it and pick the appropriate spelling based upon the meaning of the required phrase. However, the underlying core values of truth/falsehood would still be programming-language-specific.For most of us...
CodeSOD: Authentication Failure
There are certain programming problems that I generally say you shouldn’t try and solve yourself. Dates, of course, are a big one. They’re more complicated than you think, and unless you want to make managing a date handling library your life’s work, just use someone else’s.Encryption is another. There are so many subtle ways to do it wrong that unless it’s your specialty, you’re going to screw it up. Another similar problem is authentication.Artyom was having a bit of an authentication problem. He had inherited a Web Portal, written by a “security minded” developer. Since this developer was “security minded”, they took “common sense” security measures, like using JavaScript to prevent copy/pasting into the password field, and to prevent password managers from running. That was annoying enough, especially considering Artyom favored a 34 character password, but strangely… it never worked on the first attempt. Artyom always had to enter the password twice.Fortunately, the authentication method was well documented, and explained exactly what was going on:
Error'd: Mistakes From Out of the Blue
"I got this email out of the blue from TI. By the way, my name isn't ALFONSO," writes Jamie.
CodeSOD: Randomly Functional
Jonathan T. had recently been afforded the opportunity to go back and tweak the very first Python-based CMS he'd ever built. Years earlier, he and another junior developer had been forced to cobble this site together with no code reviews, oversight, or help of any kind. Terrible choices had been made in the name of getting their work done.Jonathan rebuilt every page in the CMS and made sure the forms and plugins cooperated with the new structural elements he introduced. In the process, he got stuck trying to figure out how a "col-sm-6" was showing up on a particular form. He found nothing in the CSS, LESS files, or page-specific JS controlling the form. In desperation, he ran a project-wide search for the randomClass.This was the result Jonathan found in project/scripts.js, authored by the other junior dev. It explained why, for the past several years, new images on the site had randomly not worked for any discernible reason.
Representative Line: An HTTP Code
Peter B’s company didn’t have the resource availability to develop their new PHP application entirely in-house, and thus brought in a Highly Paid Contractor™ to oversee that project. This story could end here, and you could fill in the rest, but Peter found an… interesting block of code during the autopsy on this disaster.Now, I want you to imagine that someone has handed you an integer. You need to know if that integer constitutes a valid HTTP status code. Now, this could get difficult, as just because a number falls between 100 and 599 doesn’t mean that it’s actually a defined status code. Then again, services may define their own status codes, and clients should understand the class of a status code, even if they don’t understand the number, so getting a 147 code isn’t wrong, so we can just probably assume any n where 100 <= n < 600 is valid enough.Sorry, I’ve gotten off track, because I really just can’t believe this code is the solution someone came up with.
Bank $Security
Banks. They take your money and lend it to others. They lend money deposited by other people to you, either as a car loan, mortgage, or for credit card purchases. For this privilege, you give them all of your personal information, including your social security number. Implicit in that exchange is the fact that the bank should keep your personal information confidential. Security is important. One might think that such a concept would be important to banks. One would be wrong.To be fair, the high ranking people at the banks probably believe that all of their customer information should be - and is - secure and protected. Unfortunately, there are multiple layers of middle and lower management (that we all know all too well) that might not comprehend that point.The other thing that banks do is nightly batch processing to keep assorted records updated, generate TPS reports, issue bills, update financial inventory, credit usage and so forth. Since customers tend to hit ATMs at all hours of the day and night, you want your systems-update processing to be able to occur while the system is live. To that end, date and timestamp ranges of transactions to be processed for a given business period usually come into play in some form. The point is that you shield your ongoing transactions from reconciliation activity by excluding it from the reconciliations. The beat business goes on.Randy worked at a major bank in the Pittsburgh, PA area. Considering that it's a major bank, it seemed odd that their customer facing website was often down for more than an hour at a time during business hours. When he started in 2016, it took about a month to get permissions to get the development tools he needed installed. Hmmm, perhaps they are vigilant about controlling access to their environments, even development; possibly a good, if bureaucratic sign. Once set up, he was assigned to work on their Web Banking app which was written not in MVC but in ASP.NET WebForms. OK, maybe they're slow to adopt newer technologies because they want someone else to beta test them. Caution can be a good sign.As part of doing his work, Randy sent SOAP messages to the mainframe to retrieve test data for developmental testing. One day, he deduced that the test social security number was that of his boss. He verified this by asking his boss what he had for lunch that day. Sure enough, there were debit card charges for it in the test environment. Uh oh.That's right; live data in the test environment. Anyone with even novice skills could have gotten social security, routing and account numbers for every customer of the bank! Rather than fight with the, ahem, highly knowledgeable individuals that thought that this was a good setup - and potentially be blamed for any breaches, Randy chose to jump ship and head for saner pastures.Interestingly, I went to their website, which states that their business hours are M-F 8AM-8PM and Sat 9AM-3PM. At 1:15 on a clear, dry Saturday when the bank should have been open for business, I called the bank posing as a potential customer to ask why their website is often down for more than an hour at a time almost every single night. The auto attendant said to try back during business hours.Hmmm... [Advertisement] ProGet can centralize your organization's software applications and components to provide uniform access to developers and servers. Check it out!
...29303132333435363738...