You are here

Fun/Other

Error'd: Never ASSume that You're Free from Errors

The Daily WTF - Fri, 11/17/2017 - 12:30

"This was in an email from Nest. I'm sure in some other font this shows a heartwarming image of fluffy bunnies frolicking in an energy saving Utopia, but instead, we get this," wrote Matthew W.

 

"Um...yeah, sure I guess?" writes Chris U.

 

Stuart L. wrote, "Looks like the weather has made an 8-bit turn for the worse."

 

"I had no idea that the success of entering my enrollment depended on whether or not my donkey was nearby," writes Ernie D.

 

Jamie S. writes, "What exactly are you trying to smuggle in, Fujitsu updater?"

 

"I'm the fastest man alive. Don't believe me? Check this out," writes John W.

 

[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.
Categories: Fun/Other

CodeSOD: Delebation

The Daily WTF - Thu, 11/16/2017 - 12:30

When faced with an API or programming paradigm that requires repetitive, boilerplate code, a developer is left with two options. They may refine or adapt the API/paradigm, using the idioms of their language to make something tedious and verbose into something elegant and clear.

Or they just automate it. If you have a mile of boilerplate that’s mostly the same across the application, just generate that. It’s like copy/paste, but, y’know… automatic.

Which is why Derf Skren found this pile in their codebase:

public abstract class ExchangeSingleData : IExchangeData { private readonly string mName; private readonly int mLength; private Dictionary<string, string> mMapValidData; private byte[] mBuffer; void AddValidValue(string name, string value) { mMapValidData[name] = value; } //... //... } public class NetChangeSign : ExchangeSingleData { public const string Plus = "+"; public const string Minus = "-"; public NetChangeSign() : base("NetChangeSign", 1) { AddValidValue("Plus", Plus); AddValidValue("Minus", Minus); } } public class BidPriceSign : ExchangeSingleData { public const string Plus = "+"; public const string Minus = "-"; public BidPriceSign() : base("BidPriceSign", 1) { AddValidValue("Plus", Plus); AddValidValue("Minus", Minus); } } public class AskPriceSign : ExchangeSingleData { public const string Plus = "+"; public const string Minus = "-"; public AskPriceSign() : base("AskPriceSign", 1) { AddValidValue("Plus", Plus); AddValidValue("Minus", Minus); } } // ... and 7 more versions of the same class

The goal of this code is so that they can prepend a “+” or a “-” to a transaction’s value. Note the mBuffer in the base class- they don’t use strings (or, y’know… numbers) to represent the transaction value, but a byte array instead. The “value” is that it lets them write a line like this:

lMessage.NetChangeSign.SetValue(GeneratePriceSign(lPrice));

Which allows the instance stored in NetChangeSign to flip that +/- based on the return value of GeneratePriceSign. Obviously, this lets the NetChangeSign instance have full control of the logic of how the sign gets set, right? I mean, each instance has its own map that contains all the allowed values, right? Well… sure, but how do they decide? Based on GeneratePriceSign… which looks like this:

private static string GeneratePriceSign(Side aSide) { if (aSide.Equals(Side.Buy)) return "+"; else return "-"; }

In design patterns terms, we call this “delebation”. It’s like delegation, but only the person doing it to themselves enjoys it.

hljs.initHighlightingOnLoad(); [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!
Categories: Fun/Other

The For While Loop

The Daily WTF - Wed, 11/15/2017 - 12:30

Alex R. was the architect of a brand spanking new system that was to read inputs from numerous other internal systems, crunch a whole bunch of numbers, record everything in a database and spew forth a massive report file. He spent months designing the major details of the system, and more months designing the various sub-components. From all this came a variety of business-level data structures which spawned POJOs and the underlying DB tables to store assorted inputs, flags and outputs. He did a fairly thorough job of documenting all the interfaces, and provided detailed specifications for all of the next-level methods that were left as TBDs in the design.

The project manager then assigned units of work to numerous offshored junior developers who managed to get virtually everything wrong. If they couldn't understand what a spec required, they changed the spec to reflect what they actually wrote. This caused Alex to start versioning the requirements document in order to catch the changes by the junior developers so that they could be rolled back.

After a while, the number of junior-developer-caused issues was piling up and Alex suggested some training sessions on certain ways of doing things to reduce the chaff he had to deal with. Management turned him down because they couldn't afford to take developers off of coding tasks for purposes of training; there was a schedule to keep! The fact that oodles of time were being wasted on them building the wrong stuff only to have to have why it was wrong explained and then have them go back and re-do it - sometimes 6 or 7 times - was irrelevant.

So how does one deal with idiotic management like this?

Alex thought that he had found a way to expose the problem and (hopefully) force something to be done. He would put in something (that any experienced developer should be able to spot as a simple code formatting issue) that the junior developers would never spot. The code would work correctly, but it would stymie them so that they had to first understand it before they could change it. He used the following coding style in a variety of locations throughout the codebase and waited:

List<Widget> widgets; for (int i=0; i<limit; i++) { // Do stuff } while ((widgets = getWidgets()) == null);

For those not familiar with Java, the closing brace of a for-loop is followed by an implicit semicolon, so the while (expression); statement is unrelated to the for-loop. However, the junior developers didn't know this, and couldn't find any documentation on a for-while statement. Although they were able to create little test programs, they didn't understand how the while-expression controlled the for-loop (it doesn't). In this case, the underlying DAO either returned a populated list or threw an exception, so it was effectively while-false (the function call and assignment occurred once) and was just syntactic nonsense that confused the junior developers.

They couldn't recognize a Java 101 code format issue and they were sufficiently stubborn that they refused to simply ask Alex what the code was doing. They were even foolish enough to openly discuss it amongst themselves on a conference line - agreeing not to ask for help until they figured it out - before a meeting with Alex and his boss began.

After 6 weeks of them floundering around on it, the offshore manager finally brought the issue up with Alex and his boss, at which time Alex explained what running the code formatter would show. He then pointed out that since they didn't know the basics of reading Java code and preferred to waste massive amounts of time rather than just asking about something they didn't understand, it was clear that they didn't have the wherewithall to make technical decisions on a larger scale, or change the design documents as they saw fit.

He continued to point out that until the junior developers showed marked improvements in their understanding of simple code, they should concentrate on learning to do basic programming instead of trying to be architects. To this end, he again offered to have ongoing training sessions where he would attempt to raise their skill level.

Of course management backed the cheap offshore labor. It was at this point that Alex realized it was a lost cause, so he fixed all the for-while snippets and updated the latest version of the detailed design document with a new opening paragraph:

To Whomever Inherits This System: Detailed design documents were created by experienced people. Management decreed that junior developers could ignore them, at will and without penalty. The state of the code reflects this. Fair Warning!

Then he committed it, secure in the knowledge that the junior developers would never bother to look at it again once he was gone. Then he gave two weeks notice.

[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!
Categories: Fun/Other

CodeSOD: One's Company

The Daily WTF - Tue, 11/14/2017 - 12:30

The more you learn about something, the less confident you often become in making statements about it, because you understand the complexities of the matter. If, for example, I asked you to help me refine my definition of how dates and times work, you know that many assumptions are wrong. Or if we tried to define what makes a string a person’s name, we’ll run into similar problems. This is even true for a value we’ve all probably seen implemented as a boolean value: gender. The more you learn about these subjects, the more complex and nuanced your understanding of them becomes. More and more, your answers start with, “It’s complicated…”.

Eugene was going through some code at a customer’s site, and he found that their business logic depended heavily on a flag ISCOMPANY, but there was no ISCOMPANY field anywhere in the database. There was, however, a SEX field on the customer records, implemented as an integer.

Digging through the queries, Eugene found a new approach to defining a company:

SELECT …, CASE ISNULL(c.SEX, '') WHEN '6' THEN '-1' WHEN '9' THEN '-1' ELSE '0' END AS ISCOMAPNY, … FROM customers WHERE …

Like I said, it's complicated.

hljs.initHighlightingOnLoad(); [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!
Categories: Fun/Other

Representative Line: An Exceptional Contract

The Daily WTF - Mon, 11/13/2017 - 12:30

The life of a contractor can be precarious. Contracts end- sometimes suddenly, and you rarely know what the organization you’re working for is actually like until it’s too late.

Ian S, for example, was contracting for a platform-as-a-service (PAAS) company, adding new features to their existing infrastructure automation system. It was the kind of place that had two copies of the same code-base, maintained side-by-side, just so that a single customer could use a script they’d written eight years prior.

That wasn’t too much of a challenge. The real challenge was that when things went wrong, there was almost no logging, and what little logging they got contained helpful, “[10:14:17] An error occurred” messages.

It wasn’t hard to see why that happened:

try { // Entry point to most of the program here } catch (Exception e) { if ( e instanceof ProcessingException ) { throw new ProcessingException("An error occurred"); } else if (e instanceof BatchException ) { throw new BatchException("An error occurred"); } //… more types of exceptions }

Ian describes this as “Pokemon Exception Handling”: you wrap the entire main method of your app in a single try, so you’re left with a single catch block that’s “gotta catch ’em all”. The use of instanceof is a nice touch, in the awfulness of it.

The developer responsible, John, was involved in a lot of important architectural decisions. For example, John decided “DevOps” and “Agile” meant that any code placed in the production branch needed to go to production, automatically. There were no checks around this, anyone with access to the main repo could merge-and-push.

“We enforce it by practice,” John explained. “We know that all of our developers, even the contractors, will follow the best practices.”

Late, on Friday afternoon, John was working on making some configuration file changes. Among other things, his changes caused the whole program to crash on startup- but not before messing up some rows in the database. That was no problem, he was working on a branch, and running against a local dev environment.

It what John claimed was a “simple mistake”, he merged that branch with master. Then he pushed to the central repo. “It could happen to anyone,” he said. At 4:59PM, on Friday, their entire PAAS configuration and management suite went down. Garbage data was thrown into the database, repeatedly, and since there was no exception handling, the only information they had was “An error occurred.”

Truly, the life of a contractor is perilous, and for management, this became a 4-alarm, hair-on-fire emergency. All hands on deck! Even the contractors!

There was just one problem. The PAAS company had decided that they weren’t going to renew the contract. They had gone further, and announced that with a day’s notice, which left a number of the contractors flapping in the wind, between gigs, Ian included. So at 5:00PM, when he officially didn’t work there anymore, he wished John the best and went home.

hljs.initHighlightingOnLoad(); [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!
Categories: Fun/Other

Error'd: It Doesn't Mean What You Think it Means

The Daily WTF - Fri, 11/10/2017 - 12:30

"TRWTF here is I can't believe they shorted me on my change!" writes Diane B.

 

"I'm trying to order a shirt but I can't decide on which size to pick," writes Mark L., "I mean, is 03-XL bigger than 02-XL?"

 

Alex wrote, "So, Slack, exactly what would you say isn't working here?"

 

"I have a lot of questions about this agreement, but not nearly as many as it seems to have about itself," writes Dan B.

 

Josh writes, "Go figure. Here I thought 19 characters was between 6 and 30."

 

"Nevermind the national meterological services, Outlook has the most precise weather around!" wrote Kris L.

 

[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!
Categories: Fun/Other

Theory Versus Reality

The Daily WTF - Thu, 11/09/2017 - 12:30

I went to college at the State University of New York at Albany, where back then, most of the Computer Science curriculum courses were entitled Theory of xxx. The programming assignments were the usual small-scope demonstrations of some feature of programming, typically something an experienced developer would code in 15-20 LOC.

My Masters project was to modify the TeX typesetting system (by Knuth) to leverage the more advanced features of a new typesetting system. It took me about two months to reverse engineer it only to find that the entire required modification amounted to a single character change.

The theory sunk in, but there was no practical application of it to reality.

Fast forward to my first programming job, where one of my tasks was to write a stand alone program that would read connection names from a file, verify that they were valid, and use them for something. There were about 350 different connection names, but they didn't follow any discernible pattern. There were a variety of letters and numbers in no particular ordering. However, there was a lot of substring duplication within the names.

Being a clueless but diligent noob, it dawned on me that I could leverage those semi-duplications so I wrote a huge progressive if-then-else statement to determine whether a name was valid.

For example, the list contained names like:

AXLP1122 AXLP1133 BCXQ5566 BCYZ7788

The code was in FORTRAN IV, so I'll just use pseudo code here. The logic for that little sub list looked like this:

if (name.startsWith("AXLP11")) if (name.substring(6) = "22 or name.substring(6) = "33") name is valid else if (name.startsWith("BC") if (name.substring(2) = "XQ5566" or name.substring(2) = "YZ7788") name is valid else ...

This proceeded to about 5 levels deep and comprised several hundred lines of code. I even built a test case to verify every single one of the names.

Then I proudly turned it in to my boss, who instantly proceeded to laugh in my face. He pointed out that it would take forever to run through all of that logic for each of the millions of records (back then, the CPUs ran at a little below 4MHz with very little RAM), and that perhaps I should consider using an array and a binary search lookup.

It was at that moment that I realized the fallacy of taking only courses entitled Theory of xxx, that perhaps my college tuition didn't buy me all I had hoped, and started a years-long effort to learn Practical Application of xxx to make myself better at what I did.

[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!
Categories: Fun/Other

CodeSOD: Lowest-Bidder Conversion

The Daily WTF - Wed, 11/08/2017 - 12:30

Circa 2003, or so, Annie’s employer contracted a lowest-bidder to produce a relatively massive .NET Web Forms project. The code was built, signed off, and chucked into production without any of the in-house developers being involved, despite being the team that would support it in the long term. There was no documentation, no knowledge transfer, and no code review.

Over the next few years, there was a rush of feature requests as gaps in functionality were found. A series of in-house developers passed through, doing their best to patch them in, but the original project’s code quality didn’t exactly make it maintainable, and since they were operating in a rush, they weren’t exactly improving the code quality.

Fast forward to 2017, and the code is finally unmaintainable enough that someone put together the budget for a ground-up rewrite in .NET MVC, and once again shopped it around to a different lowest-bidder, who would do the conversion. This time, at least, Annie gets to review the code before they accept it. It isn’t going well.

private string AddOne(int DecimalPlace) { string Outpout = "."; for (int i = 1; i < DecimalPlace; i++) { Outpout = Outpout + "0"; } Outpout = Outpout + "1"; return Outpout; }

Yes, that’s a stringly-typed operation to create a number in the form “.00001”.

But don’t worry, we can also get the integer value of any string (or any object), nice and easy:

/// <summary> /// Get Integer Value. /// </summary> /// <param name="obj">Object type obj</param> /// <returns></returns> public int GetIntegerValue(object obj) { return GetIntegerValue(obj, 0); } public int GetIntegerValue(object obj, int defaultReturnValue) { try { if (obj != null && obj.ToString().Length > 0) { string objvalue = ClearSpecialChar(Convert.ToString(obj)); defaultReturnValue = Convert.ToInt32(objvalue); } //else //{ // defaultReturnValue = Convert.ToInt32(obj); //} } catch { } return defaultReturnValue; }

module also needs to handle rounding, and yes, that’s also stringly-typed.

/// <summary> /// This Methods for round off item weight for(USPS) /// EX: .15 Pound =1 Pound /// </summary> /// <param name="inPutVal"></param> /// <returns></returns> public int MakeRoundOffDecimal(string inPutVal) { int contenerVal = 0; int intValAfterPoint = 0; string ValBeforePoint = inPutVal.Substring(0, inPutVal.IndexOf('.')); string valAfterPoint = inPutVal.Substring(inPutVal.IndexOf('.') + 1); try { contenerVal = Convert.ToInt32(ValBeforePoint); intValAfterPoint = Convert.ToInt32(valAfterPoint); if (intValAfterPoint > 0) { contenerVal += 1; } } catch { contenerVal += 1; } return contenerVal; } /// <summary> /// This Method Can make decimal value with desiger /// length with updating last number (if last number after decimel point >=5 then 6 and lessthan <5 then /// the same value /// Ex:- 10.012547 will be 10.01255 if i call this method with GetDecimalPlaceValue("10.012547",5) /// and 12.012351 will be 12.01235 if i cakll this method with GetDecimalPlaceValue("12.012351",5) /// </summary> /// <param name="Value"></param> /// <param name="DecimalPlace"></param> /// <returns></returns> public virtual decimal GetDecimalPlaceValue(string Value, int DecimalPlace) { decimal RetunValue = 0.00M; int NextToDecimalPlaceValue = 0; int DecimalPlaceValue = 0; string InputValue = Value; try { RetunValue = Convert.ToDecimal(InputValue.Substring(0, (InputValue.IndexOf('.') + DecimalPlace + 1))); NextToDecimalPlaceValue = GetIntegerValue(InputValue.Substring(RetunValue.ToString().Length, 1)); if (NextToDecimalPlaceValue > 4) { RetunValue = RetunValue + Convert.ToDecimal(AddOne(DecimalPlace)); } } catch { RetunValue = GetDecimelValue(Value); } return RetunValue; }

If you note, the GetDecimalPlaceValue method claims to round (despite not being named anything like it), but will round numbers off incorrectly- the input 1.9 yields 1.

Calls to these various methods are peppered throughout the code base. It appears to be a common utility library that’s simply dropped into every project by this lowest-bidder contractor, and everyone on their team knows to use this for data type conversions.

Annie raised her issues with management, who raised it with their lowest-bidder. Unfortunately, as the lowest-bidder, they’ve already been paid for the first milestone, and are perfectly happy to drag their feet until the code quality issues are forgotten before they bother delivering the second.

hljs.initHighlightingOnLoad(); [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!
Categories: Fun/Other

Replacement Trainwreck

The Daily WTF - Tue, 11/07/2017 - 12:30

There's an old saying about experience in IT: Some people have 10 years of experience, and some have 1 year 10 times. Every day, someone learns the hard way how true this statement really is.

Raquel returned from holiday, only to get a call from above saying her contract would not be renewed, giving her 2 weeks' notice to find a new placement. The boss explained it was a budget thing, since contractors are often more expensive than salaried employees, especially ones working remotely in the Asia-Pacific region. C'est la vie.

Raquel's big project was a perl module to talk to a high-end but aging storage system. The hardware had no API, and the CLI was arcane, with wildly inconsistent formats in the command output. Raquel abstracted that all away to give a programmatic interface for the other developers. The downside of this approach was that every time they put out a firmware update, she had to modify the perl script to match the changes. The module had grown to 1600 lines of code through 400+ commits in the 3 years she'd been working there. The other developers would include this as a git submodule so they could pull in changes in an automated way and re-release their tooling.

Raquel was asked to hand off the module to John, who assured her he knew git really well and enough perl to figure things out. It seemed reasonable ... at first. She got John set up with another, smaller tool she'd written: a plugin for a popular monitoring system to read the storage drives. It used the library she'd written as a backend, so she figured it'd give him some understanding of the functionality. Since some of their customers used Windows, she taught him how to compile to an executable. Once John was compiled and running, Raquel sent him to their lab environment to test the plugin.

A few hours later, she got her first bit of bad news: the plugin was failing, and John didn't know why. He attached the error message:

SSH connection to 192.168.1.10 (22/TCP) failed after 1 attempt(s).

Now, the library used SSH to connect to the drive, so Raquel's first suggestion was to make sure John could SSH into the storage system from the host he was working on. Things went quiet after that, so she figured he'd sorted it out—likely a loose cable or a disabled Ethernet driver—and went on with her day.

The next day, however, she came in to a more urgent message: John was still having problems. She asked for more details, and this was all she got:

SSH connection to 192.168.1.10 (22/TCP) failed after 1 attempt(s).

Maybe he forgot what he was doing? Raquel reminded John about checking the connection, and he replied that he could SSH just fine from the machine.

Weird.... She fired up a WebEx call so she could see what was going on in the lab. Sure enough, John could SSH from that machine to the storage device ... but he was running the plugin on his laptop. He was genuinely puzzled why that mattered.

Over the next half hour, Raquel dug up a network architecture diagram to show how only the lab machines could talk to the lab storage devices. Finally, still confused, John agreed to just do his development on the machines in the lab and they hung up.

That afternoon, Raquel's favorite type of ticket came in: a nice easy feature add for the monitoring program. It'd require a new method in the library and a handler for the Nagios plugin; it was perfect for John to get his feet wet. She assigned it to him and attached a link to a method in the library that was about 97% similar to what was needed, for him to study (read: copy and paste).

Several days slipped past in silence. Since there'd been no commits, Raquel dropped John a note to say that her contract was almost up. If he wanted a code review, he should push his changes and let her know.

John replied that the code was "almost complete" and would be checked in "shortly."

Fair enough, Raquel figured, and let it go.

Her second-to-last day, John sent a note saying he'd checked in his changes. He also included a link—to a different git repo.

Maybe it's a fork? No such luck. It was a brand new repo with exactly 1 commit. Not only had John made a new repo, that repo contained both the library code and the Nagios plugin code, with no submodules in sight.

Raquel could hardly believe it. How am I supposed to review without a diff?

She set up another WebEx for early the next morning—her last day—and explained to John how the lack of history was a critical problem. He agreed with her and assured her she'd get the diff she wanted.

Now what, dear reader, do you think Raquel actually received? If you guessed an email with bullet points outlining "At line 75 in foo.pl, I changed A to B. At line 89 I changed C to D ...", you're today's lucky winner.

Glancing at the clock, Raquel decided she had time for one last good deed before departing forever. She ran diff on the 2 repos, then typed up a polite, precise email outlining her comments. John's code wasn't all that bad really; he needed to code more defensively, since the storage system would sometimes throw errors, and he probably shouldn't loop over output that would always be exactly 0 or 1 lines of code, but it functioned well enough. Oh yeah, and the big chunk in the middle of the original method that he'd elected not to copy over? That handled the fact that the storage system was a cluster, so you may not be on the host you want when you first SSH into the machine. But otherwise, it was decent code.

Raquel's final email arrived soon after that, from John's manager. Apparently, John had complained that she was unprofessional.

She wrote back to wish them both the best of luck, collected her things, and laughed her way home.

code { font-family: Consolas, monospace; } [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!
Categories: Fun/Other

CodeSOD: The Distract Factory Pattern

The Daily WTF - Mon, 11/06/2017 - 12:30

The Gang-of-Four design patterns have an entire category of creational patterns, to handle the complexities of creating objects. And yes, it can get complicated, especially when we think in terms of the single-responsibility principle. Often, creating an instance of an class is itself so complex that we need a new class to do it.

Thus, we have the Factory pattern. And the Abstract Factory Pattern. And the Abstract Factory Factory Abstract Provider Bean pattern, if you’re using Spring. The purpose of these patterns is to add indirection between the client, calling code, and the creation of the objects- different concrete implementations can be instantiated, without the client code needing to worry about what actual type it received. Polymorphism wins the day. Code is more loosely coupled, because the client code never needs to name the concrete type it uses.

Unless you want to do it wrong, in which case Jen M found this particular solution:

public abstract class TaskBase { public static TaskBase CreateInstance( Manager manager, Type TaskType) { object[] args = {manager, -1}; return Activator.CreateInstance(TaskType, args) as TaskBase; } public static TaskBase CreateInstance( Manager manager, int taskId, string fullyQualifiedTypeName) { var TaskType = TypeLoader.GetType(fullyQualifiedTypeName, true); object[] args = {manager, taskId}; var taskInstance = Activator.CreateInstance(TaskType, args) as TaskBase; return taskInstance; } }

In this version, you can specify the concrete child of TaskBase that you want an instance of, and this will helpfully call the constructor for you. That means you could write:

var task = TaskBase.CreateInstance(mgr, TypeOf(MyDll.MyPackage.BasicTask))

Which is obviously far more loosely coupled than:

var task = new BasicTask(mgr);

As Jen puts it: “Some of the code I see makes me want to quit my job and go hunt down the people who wrote it. This is one of those instances.” Instead, Jen replaced this code with an actual version of the Factory pattern.

hljs.initHighlightingOnLoad(); [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!
Categories: Fun/Other

Error'd: Going for the Gold!

The Daily WTF - Fri, 11/03/2017 - 11:30

"Starting from one star, I'm almost at that gold five-star rating," writes Sam K.

 

"The octopus in the exhibit was a no show, but hey, at least I have a desktop to play around in," wrote Steve W.

 

Mike N. "Thanks Walgreens! I'm looking forward to spending my $[mi_reward]."

 

"Salesforce Apex Code deployment is such a joy," Bruce C., "Turns out my 9 components are 11 in Salesforce's eye - maybe they're counting in octal?"

 

"That's so true of PayPal, those [object:Object] fees will get you every time," wrote Brian K.

 

Shahim M. writes, "Yeah. I'm going to have to pass on that offer to save Rs. 0.68."

 

[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.
Categories: Fun/Other

CodeSOD: Switching the Search

The Daily WTF - Thu, 11/02/2017 - 11:30

We return to Virginia N’s refactoring efforts (previously: here, and here).

This code is elegant in its stupidity, combining two anti-patterns in one glorious, “No, don’t do that, whyyyyyyyyyy!”. To wit, the for-switch, and the “build SQL statements through string concatenation”:

for (int i = 0; i < 16; i++) { StringBuilder commandText = new StringBuilder(); command = new OracleCommand(); switch (i) { case 0: commandText.Append(searchbuyer); parameter = new OracleParameter(":BUYER_DEP", OracleDbType.Char, 2); parameter.Value = depBuyer; command.Parameters.Add(parameter); break; case 1: commandText.Append(searchStock); break; case 2: commandText.Append(searchArbo1+"E"+searchArbo2); break; case 3: commandText.Append(searchArbo1+"V"+searchArbo2); break; case 4: commandText.Append(searchArbo1+"M"+searchArbo2); break; case 5: commandText.Append(searchArbo1+"P"+searchArbo2); break; case 6: commandText.Append(searchArbo1+"S"+searchArbo2); break; case 7: commandText.Append(searchArbo1+"O"+searchArbo2); break; case 8: commandText.Append(searchArbo1+"T"+searchArbo2); break; case 9: commandText.Append(searchArbo1+"A"+searchArbo2); break; case 10: commandText.Append(searchArbo1+"I"+searchArbo2); break; case 11: commandText.Append(searchDemandeur); break; case 12: commandText.Append(searchDoc); break; case 13: commandText.Append(searchForm); break; case 14: commandText.Append(searchCertif); break; case 15: commandText.Append(searchFormV); break; } //… use the query }

And for bonus points, this takes a round trip to the database for every iteration of the loop, for 16 hits per search. EVMPSOTAI, indeed.

hljs.initHighlightingOnLoad(); [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!
Categories: Fun/Other

CodeSOD: An Academic Consideration

The Daily WTF - Wed, 11/01/2017 - 11:30

Becky is not a programmer, but a physicist. She works in academia, alongside other scientists. Modern science generally requires some sort of heavy computation, which means scientists write code. It’s often not very good code, but that’s just the nature of the beast. The code exists to provide an analysis, not to be deployed as an app to the masses.

Most of the time. A few civil engineers were working on a brand new Android app for traffic analysis, with plans to distribute it. Unfortunately, they had some problems, and wanted more experienced eyes. Becky set aside the Fortran77 she was working on to trace through their Java code, and found this:

public class MainActivity extends Activity { private static double GpsLon = 0.00; public double getGpsLon() { return GpsLon; } public void setGpsLon(double value) { GpsLon = value; } private static boolean saveComLogeFile = true; public boolean getSaveComLogeFile() {return saveComLogeFile;} public void setSaveComLogeFile(boolean saveComLogeFile) {this.saveComLogeFile = saveComLogeFile;} // more than 70 similar static variables with non-static getters and setters } public class GpsWlan implements Runnable { static MainActivity ma = new MainActivity(); @Override public void run() { ma.setGpsLon(1.234); } }

At this point in the article, I’d normally explain to you what this code is trying to do, and why it’s bad. Honestly though, I can’t even answer the first question. MainActivity is a megaclass of properties- and those properties are all static. That’s a fine approach for configuration settings, but you usually pair it with static getters aand setters.

But the place where they actually set these variables is the really weird part of this. By implementing Runnable, they’re implying that GpsWlan should be run as its own thread- great if you’re doing heavy I/O or something, but… for setting a property? A static property? With no syncing or locking? Sure, they are setting it to a literal value, so we apparently don’t need to be too worried about race conditions, but… why?

Well, there isn’t a reason. Becky explains the process used to develop this code: “Here, Researcher N learns to program by asking Researcher N–1 for their code, learning from it and tweaking what they had.” I'm going to add a little correction: they're not learning anything from the code. This is cargo cult programming- the code they borrowed did this, so their code does it too.

hljs.initHighlightingOnLoad(); [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!
Categories: Fun/Other

With the Router, In the Conference Room

The Daily WTF - Tue, 10/31/2017 - 15:00

This is a follow-up to With the Router, In the Conference Room, revealing the… STUNNING CONCLUSION!

How It Really Ended

Darren took the case up to his boss, and then to their boss, up the management chain. No one was particularly happy with Cathy’s tone, and there was a great deal of tut-tutting and finger-wagging about professional conduct.

But she was right. It was Mr. Green who failed to follow instructions, it was Mr. Green who cost the company thousands, along with the customer relationship problems caused by Cathy’s sudden emergency trip back to the home office.

In what can only be considered a twist ending by the standards of this site, it was Mr. Green who was escorted out of the building by security.

The killer was Cathy, in the issue tracking system, with the snarky bug report.

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

With the Router, In the Conference Room

The Daily WTF - Tue, 10/31/2017 - 11:30

One of the most important aspects of software QA is establishing a good working relationship with developers. If you want to get them to take your bug reports seriously, you have to approach them with the right attitude. If your bugs imply that their work is shoddy, they are likely to fight back on anything you submit. If you continuously submit trivial “bugs”, they will probably be returned right away with a “not an issue” or “works as designed” status. If you treat any bug like it’s a critical showstopper, they will think you’re crying wolf and not immediately jump on issues that actually are critical.

Then there’s people like Mr. Green, a former coworker of submitter Darren A., that give QA a bad name. The Mr. Greens of the QA world are so incompetent that their stupidity can cause project delays, rack up thousands of dollars in support costs, and cause a crapstorm between managers. Mr. Green once ran afoul of Darren’s subordinate Cathy, lead developer on the project Mr. Green was testing.

Cathy was en route to the United States from London for a customer visit when her phone exploded with voicemail notifications immediately upon disabling airplane mode. There were messages from Darren, Mr. Green, and anyone else remotely involved with the project. It seemed there was a crippling issue with the latest build that was preventing any further testing during an already tight timeline.

Instead of trying to determine the cause, Mr. Green just told everyone “Cathy must have checked something in without telling us.” The situation was dire enough that Cathy, lacking the ability to remotely debug anything, had to immediately return to London. Mr. Green submitted a critical bug report and waited for her to cross the Atlantic.

What happened next is perfectly preserved in the following actual bug report from this incident. Some developers are known for their rude and/or snarky responses to bug reports that offend them. What Cathy did here takes that above and beyond to a legendary level.

==== Raised: 14/May/2015 Time: 09:27 Priority: Critical Impact: Severe Raised By: Mr. Green Description =========== No aspect of GODZILLA functions at present. All machines fail to connect with the server and we are unable to complete any further testing today. All screens just give a funny message. Loss of functionality severely impacts our testing timescales and we must now escalate to senior management to get a resolution. 15/May/2015 22:38 User: Cathy Scarlett Updated: Status New Value: Resolved - User Error Updated: Comment New Value: Thank you for this Mr. Green. I loved the fact that the entire SMT ordered me back to head office to fix this - 28 separate messages on my voicemail while I was waiting for my baggage. I was of course supposed to be fixing an issue our US customer has suffered for over a year but I appreciated having to turn around after I'd landed in New Jersey and jump back on the first return flight to Heathrow. Do you remember when you set up the Test room for GODZILLA Mr. Green? Do you remember hanging the WIFI router on a piece of string from the window handle because the cable wasn't long enough? Do you remember me telling you not to do this as it was likely to fall? Do you remember telling me that you sorted this out and got Networks to setup a proper WIFI router for all the test laptops? I remember this Mr. Green and I'm sure you'll remember when I show you the emails and messages. I walked into the test room at 10 o'clock tonight (not having slept properly for nearly 3 days) to find the WIFI router on the floor with the network cable broken. ROOT CAUSE: The string snapped There was a spare cable next to it so I plugged this one in instead. Then, because this was the correct cable, I put the WIFI unit into the mounting that was provided for you by networks. As if by magic, all the laptops started working and those 'funny messages' have now disappeared. GODZILLA can now carry on testing. I'm struggling to understand why I needed to fly thousands of miles to fix this given that you set this room up in the first place. I'm struggling to understand why you told the SMT that this was a software error. I'm struggling to understand why you bypassed my manager who would have told you all of this. I'm closing this as 'user error' because there isn't a category for 'F**king moron' 72 hours of overtime to cover an aborted trip from London to New York and back: £3,600 1 emergency return flight: £1,500 1 wasted return flight £300 1 very nice unused hotel room that has no refund: £400 1 emergency taxi fare from Heathrow: £200 16 man days of testing lost £6,000 Passing my undisguised contempt for you onto SMT: Priceless

Mr. Green was obviously offended by her response. He escalated it to his manager, who demanded that Cathy be fired. This left Darren in a precarious position as Cathy’s manager. Sure, it was unprofessional. But it was like getting a call from your child’s school saying they punched a bully in the nose and they want your child to be disciplined for defending themselves. Darren decided to push back at the QA manager and insist that Mr. Green is the one who should be fired.

This story might have ended with Mr. Green and Cathy forced into an uneasy truce as the company management decided that they were both too valuable to lose. But that isn’t how this story ended. Or, perhaps Darren's push-back back-fired, and he's the one who ends up getting fired. That also isn't how the story ended. We invite our readers to speculate, extrapolate and fabricate in the comments. Later this morning, we’ll reveal the true killer outcome…

[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!
Categories: Fun/Other

CodeSOD: Drain the Swamp

The Daily WTF - Mon, 10/30/2017 - 11:30

You may remember Virginia N from An Extinction Event, where she struggles to refactor a legacy project with some… unusual design principles. ReSharper still continues to choke to death on their codebase, but her management haas let her know, this won’t be a problem going forward.

“You see,” her boss explained, “we’re going to move the logic into stored procedures. That way, we can more easily re-use the logic between the Windows Forms client and the Web app.”

“Oh, there’s going to be a web app, now?” Virginia asked.

“Yes! They’re going to use best practices, like unit testing, so that they don’t end up with the same kind of mess we have,” her boss said.

Virginia was halfway to filing a request for a transfer when she heard more about the web project. Then she heard about their plan. They weren’t going to simply build a web-client for their backend, but instead were going to build an inner platform. The page logic would be a simple template, and all of the rules, styling, data and display logic would be stored as data in the database. “It’s gonna be really flexible!”

Virginia decided to stick with the fetid field she knew, instead of the “green field” which was going to be a fetid swamp in a matter of weeks.

In Virginia’s swamp, she has many, many 40,000 line classes. That much code means the code has no real cohesion, so it leads to Virginia finding variables named thus:

public bool IReallyDontWantToFetchTheDataOnLoadButDontWantToChangeTheOtherVariablesCauseWhoKnowsWhatWillHappen=false;

It’s at least descriptive. It also exists in the class side-by-side with variables like blnGetData, GetDataOnFormLoad, and GetDataOnFormrLoadS.

Elsewhere in the same file, they have a different problem. They added a control to the view, and needed an accessor method to decide whether it was visible or not. Actually, they needed a few, and they knew that the form would be changing over time, so they needed something that was “dynamic”.

Now, they could have simply added properties and getters/setters as the form changed and dealt with the follow on changes, but someone decided it was time to stress “Closed for Modification” was a good object-oriented practice. They left out the “Open for Extension” part of the open/closed principle, so they used this code instead, which uses a few index properties to decide which control should be modified.

private void SetVisiblePicNdt() { string NomBtnNDT=""; string NomBtnChant=""; if (m_IndexChant>0) { NomBtnNDT="btn"+(m_IndexChant+1).ToString(); NomBtnChant="btn"+(m_IndexChant).ToString(); } else { NomBtnNDT="btn"+(m_IndexLB+1).ToString(); } Control sectMain=null; for (int i=0;i<ctlRecherche.Controls.Count;i++) { if (ctlRecherche.Controls[i].Name=="sectMain") { sectMain=ctlRecherche.Controls[i]; break; } } if (sectMain!=null) { for (int i=0;i<sectMain.Controls.Count;i++) { if (sectMain.Controls[i].Name=="panFilterSection") { panFilterSection=sectMain.Controls[i]; break; } } } if (panFilterSection!=null) { for (int i=0;i<panFilterSection.Controls.Count;i++) { if (panFilterSection.Controls[i].Name==NomBtnNDT) { panFilterSection.Controls[i].Visible=false; break; } } } }

Virginia has many more horrors to share, so expect more examples from this code base.

hljs.initHighlightingOnLoad(); [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!
Categories: Fun/Other

Error'd: Trick or Treat? Smell My Feet

The Daily WTF - Fri, 10/27/2017 - 12:30

"Sorry, but 4.2 billion Microsoft points sounds like 'all tricks' to me," writes Ergin S.

 

"Most paints are air-drying, but with this one, you apparently need to, um, assist with the air flow a bit," wrote Peter G. (Side Note: For fun, go ahead and google the item title.)

 

Dave P. writes, "Um, The US Supreme Court is patching Android within to decide Microsoft email privacy dispute!? Thanks Slashdot!"

 

"Why yes, it's the first time that I've see this network at the workplace," wrote Wouter.

 

Adam L. writes, "And here I thought you only got to celebrate a trip around the sun only once per year. Neat!"

 

"You guys! My iPhone is DAMAGED! Thankfully there's an app on the Google Play store that can fix it!" I found this one.

 

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

CodeSOD: 10001 Problems

The Daily WTF - Thu, 10/26/2017 - 12:30

Our Anonymous submitter's first job was helping to support a distributed system running in a low-energy embedded platform. Interesting on its face, the platform was actually a bloated, outdated monstrosity made worse by the decision to use C++ in conjunction with a homemade (read: unsafe) binary data format.

The platform had one mysterious, catastrophic flaw in particular: once a cluster was up and running for a few weeks, it would sometimes fail with a series of random segfaults, with several nodes crashing at once. Serial port debugging showed that many of these failures were proceeded by an ominous log message, a single line with the number 10001 and nothing else.

After pondering the mystery for some time, someone thought to search for the number 10000 within the code base. Thus they found their culprit within the very core of their application: the code that read each record stored in their homemade binary files and copied it to memory.

#define END 0xFFFF while (header->recordType != END) {     // unknow (sic) loop times     if (recordNum > 10000) {         log(recordNum);         return 0;     } else {         *header = *recordPtr;         memcpy(memoryPtr, recordPtr + HEADER_SIZE, header->recordSize)         *recordPtr += header->recordSize;     }     recordNum++; }

Whenever one of the binary files got corrupted in some way, this code never found an END record, and thus proceeded to copy random memory chunks to other random memory chunks until its incredible security measures kicked in after just 10000 iterations. Even worse, the code would also alter other files read into memory. Those corrupted files were then transferred to other nodes, cutting a swath of destruction and fail across the entire platform.

Our submitter and his cohorts resolved immediately to switch to an industry-standard, resilient, checksum-protected data format in the near future. And then, knowing full well what that implied ... they added a log message.

hljs.initHighlightingOnLoad(); [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!
Categories: Fun/Other

Re-Authenticated

The Daily WTF - Wed, 10/25/2017 - 12:30

Sometime back, our friend Fred told us about his experiences with homegrown PK/FK relationships. Today, he regales us with a tale of trying to get users to use their new-and-improved sso mechanism, even if they don't want to.

His company currently runs a legacy reporting portal service that has an old-school sso which is used by several third party systems. This mechanism stores user names and passwords as clear text in the DB. It also passes them in clear text in a hidden HTML form. The third party code would create the hidden form with the user name and password in clear text and JavaScript-submit it to the login page - without HTTPS. OK, it was the way things were set up way back then.

Nowadays, his employer knows better and has created a new and improved system with slightly more sophisticated security. They encourage their end users to make the switch and use the shiny new platform. Unfortunately, the third party systems still have hard-coded embedded links to the old system, and although switching to use the new system would improve security, the users are in no rush to make changes to their software.

When you have lemons, make lemonade.

Fred was unwilling to succumb to the laissez-faire attitude of lazy customers, and so wrote a URL-rewrite rule for the IIS server that was running their old VB6-era system. It redirected posts to login.asp to /hijack/login.aspx. The new page contains logic to check if the user is configured on the new platform. This magic was accomplished by using the 307 Temporary Redirect, which maintains the POSTed payload; something which is not done by a standard 302 (perhaps this is a Dark Secret™ of IIS - who can say?) If the user was found in the new application, an access token was fetched from IdentityServer3 and the incoming user was redirected to the new platform. Otherwise, /hijack/login.aspx output the same old fool-proof hidden HTML form with clear text user name and password and JavaScript-submitted it - without SSL - to the renamed login2.asp page of the old system.

Upon pondering his creation, Fred winced at the plethora of Biblical-Level WTF in this set up, but in some curious way the solution is kind of cool and he thought the world should know about it.

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

CodeSOD: The Key to Lookups

The Daily WTF - Tue, 10/24/2017 - 12:30

After some “miscommunications about coding standards”, Nicolas’s company decided that they should have one of their internal developers do code reviews on anything that came from their external, third-party developers. Nicolas drew the short straw on the most recent project.

The specific problem in play is that they had config-data, structured as nested dictionaries. You know the kind of data-structure- something like:

{ database: { connString: "someDb:abc:123", pageSize: 50 }, api: { url: "https://foo/data", defaultHeaders: { "X-Api-Key": "d0908ad1-3e28-419f-ab05-0c74eae1ca37" } } }

In their specific configuration, keys could be nested to any arbitrary depth. Someone wanted a helper method, that, given an array of keys: ["api", "defaultHeaaders", "X-Api-Key"], could return the value associated with the key.

You might be thinking of some iterative or recursive approach for walking the tree, but a smart Python programmer knows that unrolling a loop boosts performance… right? Is that how it works? Well, no matter:

def getObjectValue( listObj): """ returns the value of the required object by construction the object from the list of string values """ x = len(listObj) if x == 1: return config_data_list[listObj[0]] if x == 2: return config_data_list[listObj[0]][listObj[1]] if x == 3: return config_data_list[listObj[0]][listObj[1]][listObj[2]] if x == 4: return config_data_list[listObj[0]][listObj[1]][listObj[2]][listObj[3]] if x == 5: return config_data_list[listObj[0]][listObj[1]][listObj[2]][listObj[3]][listObj[4]] if x == 6: return config_data_list[listObj[0]][listObj[1]][listObj[2]][listObj[3]][listObj[4]][listObj[5]] if x == 7: return config_data_list[listObj[0]][listObj[1]][listObj[2]][listObj[3]][listObj[4]][listObj[5]][listObj[6]]

Good thing their config file doesn’t have 8 nested levels of configuration data. Then again, why does someone’s config data have 7 nested levels?

hljs.initHighlightingOnLoad(); [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!
Categories: Fun/Other

Pages

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer