News
Entertainment
Science & Technology
Life
Culture & Art
Hobbies
News
Entertainment
Science & Technology
Culture & Art
Hobbies
7 | Follower
Gavin continues work on the old C++ app he inherited. Today we get a delightful smattering of bad choices. HRESULT CExAPI::GetPageCacheForFolder( IN CEntryID *p_cio_Folder, OUT CPageCache **pp_PC ) { CEntryID *p_cio_Local = new CEntryID( this, p_cio_Folder ); switch ( p_cio_Folder->m_uiType ) { case EID_TYPE_EMPTY: return S_OK; break; case EID_TYPE_NORMAL : return GetPageCacheForNormalFolder(p_cio_Folder, pp_PC ); break; case EID_TYPE_ADDRESSBOOK : return GetPageCacheForABFolder(p_cio_Folder, 0, pp_PC ); break; } return S_OK; DeleteIfNotNULL( p_cio_Local ); }
"The attached class connects to an Access database," writes Nicolai. That's always a good start for a WTF. Let's take a look. public class ResultLoader { private static Logger sysLog = Logger.getLogger(ResultLoader.class); private static String url = "somePath"; /** * get the ResultTable from the Access database * * @param tableName * @return */ private static Table getResultTable(String tableName) { try { // create a new file with the path to the table File db = new File(url); // let Jackcess open the file and return a table return Database.open(db).getTable(tableName); } catch (IOException e) { e.printStackTrace(); } return null; } /** * load result from DB */ public static void loadResult() { String tableName = "Result"; Table resultTable = getResultTable(tableName); if (!resultTable.equals(null)) { Map<Integer, Float> yearConsumption = new HashMap<Integer, Float>(); for (Map<String, Object> row : resultTable) { /* * [snip] does something with the table's rows */ } Result result = new Result(00, new Date(), consumptions); } else { sysLog.info("There is no data object in the Access Database!"); } } }
While Java didn't invent putting a toString method in the base class of every object, it certainly made it mainstream. The nice thing about the method is that it allows you to turn any object into a string, though it's up to the implementor to decide what a good string representation is. But what if you want to ensure that the object you're handed is really and truly a string, not just something you can convert to a string? teknopaul's co-worker found their own solution:
While poring through some VB .Net code, John noticed some odd things in their datamodel. For example, a different process would scan files, and log any "suspicious" files into a database. The program John supported would then report on that data. One of their classes had a property which looked like this:
An anonymous friend sent us our frist test in prod for this week. And then there will be more, and more, and more. "This came up in Kaspersky's Blog's RSS. If you're lucky they might still have the error up in the original URL." I don't know if "chron" is just how "cron" translates to Russian and back, but the test appears to have succeeded.
Meta-programming- programs which generate programs- is a delightful hobby, but usually shouldn't be used in production code. Usually. I mean, if you're working in LISP, 90% of your program is going to be macros. But if you're using PHP and JavaScript, there's good odds that someone you work with has decided to combine these two tastes together to create something nobody wants to taste.
Zeke sends us a C# snippet from an extract-transform-load process his company uses. It's… special. private void ResizeColumn(string table, string column, int minSize) { if(null == _connection) return; string sqlReadSize = "SELECT DATA_LENGTH,DATA_TYPE,DATA_PRECISION,DATA_SCALE FROM USER_TAB_COLS WHERE TABLE_NAME = '" + table.ToUpper() + "' AND COLUMN_NAME = '" + column.ToUpper() + "'"; string data_length = ""; string data_type = ""; string data_precision = ""; string data_scale = ""; string sizeInfo = minSize.ToString(); IDataReader r = null; try { r = _connection.DbAccessor.ExecuteSqlText.ExecuteReader(sqlReadSize); if(null != r && r.Read()) { if(!r.IsDBNull(0)) data_length = Convert.ToString(r[0]); if(!r.IsDBNull(1)) data_type = Convert.ToString(r[1]); if(!r.IsDBNull(2)) data_precision = Convert.ToString(r[2]); if(!r.IsDBNull(3)) data_scale = Convert.ToString(r[3]); r.Close(); r = null; } } catch(Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); return; } finally { if(null != r) { r.Close(); r = null; } } if(data_type == "NUMBER") { return; } if(data_type == "DATE") { return; } if(data_type == "CLOB") { return; } if(data_type == "BLOB") { return; } if(minSize <= Convert.ToInt32(data_length)) { return; } string sqlAlterSize = "ALTER TABLE " + table + " modify " + column.ToUpper() + " " + data_type + "(" + sizeInfo + ")"; try { _connection.DbAccessor.ExecuteSqlText.ExecuteScalar(sqlAlterSize); } catch(Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); return; } }
Ulvhamne sends us some bad code that, well, I think at this point we should really coin a name for this particular anti-pattern. @Override public int getNumOfItemsInDataContainer(int parDataId) { int numberOfItems = 0; for (Integer x : myTransactionDataContainerMap.keySet()) { numberOfItems ++; } return numberOfItems; }
Bob's employer had a data-driven application which wasn't performing terribly well. They had some in-house database administrators, but their skills were more "keep things running," and less "do deep optimizations". The company opted to hire a contract DBA to come in, address the performance problems, and leave. In actual fact, the DBA came in, ran some monitoring, and then simply wrote some guidance- generic, and frankly useless guidance. "Index on frequently queried fields," and "ensure database statistics are gathered on the appropriate schedule."
Marcus's team was restructuring the API, and the architect thus wanted a number of methods marked obsolete, to encourage developers to move to the new version of the API. So the architect created a Jira task, assigned it to a dev, and moved on. Somehow, this C# code got committed and merged, despite being code reviewed:
As oft discussed, null-terminated C-style strings are an endless source of problems. But there's no problem so bad that it can't be made worse by a sufficiently motivated developer. Today's rather old code comes from Mike, who inherited an old, MFC application. This code is responsible for opening a file dialog, and the key goal of the code is to configure the file filter in that dialog. In MFC, this is done by passing a delimited string containing a caption and a glob for filtering. E.g., "Text Files (.txt) | *.txt" would open a dialog for finding text files.
This week we have a special visit from a mythical beast: the snarklemma. But first, a non-error Error'd. Obsessive Optimizer Ian K. "Walmart's nationwide network of warehouse stores means they can save time and money by shipping locally. FedEx has them covered: Their nationwide shipping fleet determined the shortest path from Houston to its largest suburb goes via Georgia." Not the shortest path, nor the fastest, but surely the cheapest one that meets the delivery date requirement. It's probably not an error, and I believe it, but I still can't believe it!
Yesterday we talked about bad CSS. Today, we're going to talk about bad HTML. Corey inherited a web page that, among other things, wanted to display a bulleted list of links. Now, you or I might reach for the ul element, which is for displaying bulleted lists. But we do not have the galaxy sized brains of this individual:
There is a surprising amount of debate about how to use CSS classes. The correct side of this debate argues that we should use classes to describe what the content is, what role it serves in our UI; i.e., a section of a page displaying employee information might be classed employee. If we want the "name" field of an employee to have a red underline, we might write a rule like: .employee .name { text-decoration: underline red; }
Once upon a time, I was tuning a database performance issue. The backing database was an Oracle database, and the key problem was simply that the data needed to be partitioned. Great, easy, I wrote up a change script, applied it to a test environment, gathered some metrics to prove that it had the effects we expected, and submitted a request to apply it to production. And the DBAs came down on me like a sledgehammer. Why? Well, according to our DBAs, the license we had with Oracle didn't let us use partitioning. The feature wasn't disabled in any way, but when an Oracle compliance check was performed, we'd get dinged and they'd charge us big bucks for having used the feature- and if we wanted to enable it, it'd cost us $10,000 a year, and no one was willing to pay that.
As oft stated, the specification governing email addresses is complicated, and isn't really well suited for regular expressions. You can get there, but honestly, most applications can get away with checking for something that looks vaguely email like and call it a day. Now, as complicated as the "accurate" regex can get, we can certainly find worse regexes for validating emails. Morgan did, while on a contract.
There are an infinite variety of ways to be wrong, but only very small number of ways to be right. Patient Peter W. discovers that MS Word is of two minds about English usage. "Microsoft Word just can't seem to agree with itself on how to spell paycheck/pay check." Faithful readers know it's even worse than that.
So many languages eschew "truth" for "truthiness". Today, we're looking at PHP's approach. PHP automatically coerces types to a boolean with some fairly simple rules: the boolean false is false the integer 0 is false, as is the float 0.0 and -0.0. empty strings and the string "0" are false arrays with no elements are false NULL is false objects may also override the cast behavior to define their own everything else is true
Strings in C are a unique collection of mistakes. The biggest one is the idea of null termination. Null termination is not without its advantages: because you're using a single byte to mark the end of the string, you can have strings of arbitrary length. No need to track the size and worry if your size variable is big enough to hold the end of the string. No complicated data structures. Just "read till you find a 0 byte, and you know you're done." Of course, this is the root of a lot of evils. Malicious inputs that lack a null terminator, for example, are a common exploit. It's so dangerous that all of the str* functions have strn* versions, which allow you to pass sizes to ensure you don't overrun any buffers.
Gloria was a senior developer at IniMirage, a company that makes custom visualizations for their clients. Over a few years, IniMirage had grown to more than 100 people, but was still very much in startup mode. Because of that, Gloria tried to keep her teams sized for two pizzas. Thomas, the product manager, on the other hand, felt that the company was ready to make big moves, and could scale up the teams: more people could move products faster. And Thomas was her manager, so he was "setting direction." Gloria's elderly dog had spent the night at the emergency vet, and the company hadn't grown up to "giving sick days" yet, so she was nursing a headache from lack of sleep, when Thomas tried to initiate a Slack huddle. He had a habit of pushing the "Huddle" button any time the mood struct, without rhyme or reason.
It's incredibly common to convert objects to dictionaries/maps and back, for all sorts of reasons. Jeff's co-worker was tasked with taking a dictionary which contained three keys, "mail", "telephonenumber", and "facsimiletelephonenumber" into an object representing a contact. This was their solution: foreach (string item in _ptAttributeDic.Keys) { string val = _ptAttributeDic[item]; switch (item) { case "mail": if (string.IsNullOrEmpty(base._email)) base._email = val; break; case "facsimiletelephonenumber": base._faxNum = val; break; case "telephonenumber": base._phoneNumber = val; break; } }
A twitchy anonymous reporter pointed out that our form validation code is flaky. He's not wrong. But at least it can report time without needing emoticons! :-3 That same anon sent us the following, explaining "Folks at Twitch are very brave. So brave, they wrote their own time math."
In the late 90s into the early 2000s, there was an entire industry spun up to get businesses and governments off their mainframe systems from the 60s and onto something modern. "Modern", in that era, usually meant Java. I attended vendor presentations, for example, that promised that you could take your mainframe, slap a SOAP webservice on it, and then gradually migrate modules off the mainframe and into Java Enterprise Edition. In the intervening years, I have seen exactly 0 successful migrations like this- usually they just end up trying that for a few years and then biting the bullet and doing a ground-up rewrite. That's is the situation ML was in: a state government wanted to replace their COBOL mainframe monster with a "maintainable" J2EE/WebSphere based application. Gone would be the 3270 dumb terminals, and here would be desktop PCs running web browsers.
It's good to handle any exception that could be raised in some useful way. Frequently, this means that you need to take advantage of the catch block's ability to filter by type so you can do something different in each case. Or you could do what Adam's co-worker did. try { /* ... some important code ... */ } catch (OutOfMemoryException exception) { Global.Insert("App.GetSettings;", exception.Message); } catch (OverflowException exception) { Global.Insert("App.GetSettings;", exception.Message); } catch (InvalidCastException exception) { Global.Insert("App.GetSettings;", exception.Message); } catch (NullReferenceException exception) { Global.Insert("App.GetSettings;", exception.Message); } catch (IndexOutOfRangeException exception) { Global.Insert("App.GetSettings;", exception.Message); } catch (ArgumentException exception) { Global.Insert("App.GetSettings;", exception.Message); } catch (InvalidOperationException exception) { Global.Insert("App.GetSettings;", exception.Message); } catch (XmlException exception) { Global.Insert("App.GetSettings;", exception.Message); } catch (IOException exception) { Global.Insert("App.GetSettings;", exception.Message); } catch (NotSupportedException exception) { Global.Insert("App.GetSettings;", exception.Message); } catch (Exception exception) { Global.Insert("App.GetSettings;", exception.Message); }
April Fool's day is a day where websites lie to you or create complex pranks. We've generally avoided the former, but have done a few of the former, but we also like to just use April Fool's as a chance to change things up. So today, we're going to do something different. We're going to talk about my Day Job. Specifically, we're going to talk about a tool I use in my day job: cFS.
We've got some of the rarer classic Error'd types today: events from the dawn of time, weird definitions of space, and this absolutely astonishing choice of cancel/confirm button text. Perplexed Stewart found this and it's got me completely befuddled as well! "Puzzled over this classic type of Error'd for ages. I really have no clue whether I should press Yes or No."
We've seen loads of bad date handling, but as always, there's new ways to be surprised by the bizarre inventions people come up with. Today, Tim sends us some bad date sorting, in PHP. // Function to sort follow-ups by Date function cmp($a, $b) { return strcmp(strtotime($a["date"]), strtotime($b["date"])); } // Sort the follow-ups by Date usort($data, "cmp");
As a general rule, I will actually prefer code that is verbose and clear over code that is concise but makes me think. I really don't like to think if I don't have to. Of course, there's the class of WTF code that is verbose, unclear and also really bad, which Thomas sends us today:
One of the perks of open source software is that it means that large companies can and will patch it for their needs. Which means we can see what a particular large electronics vendor did with a video player application. For example, they needed to see if the URL pointed to a stream protected by WideVine, Vudu, or Netflix. They can do this by checking if the filename contains a certain substring. Let's see how they accomplished this…