Remy Porter

Computers were a mistake, which is why I'm trying to shoot them into space. Editor-in-Chief for TDWTF.

Jun 2023

Join Us Again

by in CodeSOD on

Submitter "Anonymouse Lee" inherited a Pascal program that started its development back in 2002. It's seen some rough handling over the years, and that alone has bred some WTFs, but this particular block was created by the founder of the company, who bills themself as a "highly technical founder".

The goal is this: the program needs to display a data grid, and depending on the recordType of each row in the grid, that row needs to be displayed slightly differently.


Sensing a Problem

by in CodeSOD on

Talking to external hardware is often hard. Especially niche hardware devices, which frequently have terrible documentation, bad APIs, and many undocumented quirks that can only be learned by working with them.

For example, Sandra, still with InitAg frequently has to work with hardware. As Sandra puts it: "Most people tend to imagine agriculture as Farmer Bob and his tractor, these day's it's as much drones and high-precision GPS as it is tractors and manure." Which, the technological focus in agriculture is one of the key drivers of right to repair laws, but that's a whole different class of WTF.


An Interview Resolution

by in Tales from the Interview on

Jack's team was hiring a new web developer. As part of their interview process, they asked for some code samples- whether a public Github or just snippets to review. The goal isn't to be one of those companies that requires a super active Github history, but it's just helpful to get a sense of how someone approaches writing code before diving into some of the deeper interview challenges. No one has ever been disqualified for not being able to provide code, it just can streamline the interview process.

As it turns out, it's also a pretty great filter for excluding candidates that probably shouldn't move on to the next round, or in this case, shouldn't be allowed to program at all.


A Modular Week

by in CodeSOD on

Don't write your own date functions. Don't write your own date functions. Erich sends us this beauty, which is meant to adjust a date based on the starting day of the week- which might be a day other than Sunday, for a variety of reasons.

_getAdjustedDay: function(/*Date*/dateObj) {
  //summary: used to adjust date.getDay() values to the new values based on the current first day of the week value
  var days = [0,1,2,3,4,5,6];
  if(this.weekStartsOn>0){
    for(var i=0;i<this.weekStartsOn;i++){
      days.unshift(days.pop());
    }
  }
  return days[dateObj.getDay()]; // Number: 0..6 where 0=Sunday
}

Searching for a Perl

by in CodeSOD on

When I was young and dumb, my freshman year college CS program taught us Scheme. Now, thinking myself a rather accomplished C++ programmer by that point (I was not), I thought this was a bit of an insult. But I was still interested in learning new languages, so I chose to dabble in Perl.

And I remember having the audacity to suggest to my professors that Scheme was a terrible introduction to programming, and instead we should start the students with an easy and accessible language, like Perl.


Dented

by in CodeSOD on

At many a workplace, I've had the fortune to step into the company around when they were starting to get serious about standards, code quality, and generally pivoting into a mature development organization.

When it comes to coding standards, everyone has strong opinions, though frankly consistency matters more than the standard itself. For example, with indenting, it doesn't really matter if you're doing Allman or something more K&R. Though we can all agree that anyone using [Whitesmiths] style has been hurt, and hurt deeply.


Underscoring the Importance of Good Naming

by in CodeSOD on

An eternal problem in programming is "empty strings are basically nulls, right?" Frequently, when someone hands us "", we know that represents "no value", and thus is basically null. Well, sometimes. Other times it's not. Tracking this chaos is a common source of bugs and WTFs.

Martin's team had a problem in PHP. See, the is_null function is, well, checking for nulls. It isn't checking for empty strings. Being PHP, the empty function also doesn't check for empty strings, it checks for strings that can coerce to false (which includes the empty string, but also includes '0'). The "best" way in PHP to check for empty strings is just a direct comparison- $val == ''.


Assumption is the Mother of all Segfaults

by in CodeSOD on

We return to Stefano Z, who once upon a time was a lowly junior developer surrounded by Very Smart™ and Very Senior™ developers.

Some of their code was written in a not-C language. It had to process many hundreds of millions of data points, and while it was fast, it wasn't fast enough. The senior devs had a solution: rewrite it in C, the fastest of all languages.


PHP Error Logging

by in CodeSOD on

Today's anonymous submitter sends us some PHP exception logging code. This particular code shows a surprising understanding of some clever PHP tricks. Unfortunately, everything about it is still wrong.

try {
    // do stuff that might throw an exception
} catch (Throwable $th) {
    ob_start(); // start buffer capture
    
    echo($th->getMessage()); // dump the values
    var_dump($th); // dump the values
    $ob = ob_get_contents(); // put the buffer into a variable
    
    ob_end_clean(); // end capture
    
    error_log($ob); 
}

VBitMask6

by in CodeSOD on

Bitwise operations are one of those things that experienced developers find easy (if not intuitive), but are a fairly bad way to expose functionality without real careful design. After all, flags & 0x02 doesn't really mean much if you don't know what 0x02 is supposed to represent.

But with named constants and careful thought, a bitmask can be a great way to pass flags around. At least, they can be if you understand how to use your language's bitwise operators.


Double Toss

by in CodeSOD on

Once upon a time, a company had several huge Delphi applications. These applications were pretty fundamental to company operations. And then those developers left, as they often do. Which means Darren has inherited multi-decade old Delphi code.

Most of the problems in the code are structural. The average procedure itself is usually pretty okay, but the way they get strung together is an obscene nightmare of kruft. But this little snippet gives us a picture of what life is like here:


Split the Domain

by in CodeSOD on

Eva's co-worker needed to strip the domain name off an email address, and then separate out the subdomains. The goal was that they wanted to be able to match foo.bar.com and bar.com as being the same domain.

Now, for most of us, this would seem like a pretty straightforward application of a split function. If we're feeling like over-engineering it, we could break out a regex. (Please, don't use a regex for tasks like this)


Base-36 Conversion

by in CodeSOD on

Johannes needed to convert some data from Base-36. A helpful peer offered this solution, which… works.

int getBase36(char c) {
        std::map<char, int> b36;
       
        b36.insert(std::pair<char, int>( '0', 0 );
        b36.insert(std::pair<char, int>( '1', 1 );
        b36.insert(std::pair<char, int>( '2', 2 );
        b36.insert(std::pair<char, int>( '3', 3 );
        b36.insert(std::pair<char, int>( '4', 4 );
        b36.insert(std::pair<char, int>( '5', 5 );
        b36.insert(std::pair<char, int>( '6', 6 );
        b36.insert(std::pair<char, int>( '7', 7 );
        b36.insert(std::pair<char, int>( '8', 8 );
        b36.insert(std::pair<char, int>( '9', 9 );
        b36.insert(std::pair<char, int>( 'a', 10 );
        b36.insert(std::pair<char, int>( 'b', 11 );
        b36.insert(std::pair<char, int>( 'c', 12 );
        b36.insert(std::pair<char, int>( 'd', 13 );
        b36.insert(std::pair<char, int>( 'e', 14 );
        b36.insert(std::pair<char, int>( 'f', 15 );
        b36.insert(std::pair<char, int>( 'g', 16 );
        b36.insert(std::pair<char, int>( 'h', 17 );
        b36.insert(std::pair<char, int>( 'i', 18 );
        b36.insert(std::pair<char, int>( 'j', 19 );
        b36.insert(std::pair<char, int>( 'k', 20 );
        b36.insert(std::pair<char, int>( 'l', 21 );
        b36.insert(std::pair<char, int>( 'm', 22 );
        b36.insert(std::pair<char, int>( 'n', 23 );
        b36.insert(std::pair<char, int>( 'o', 24 );
        b36.insert(std::pair<char, int>( 'p', 25 );
        b36.insert(std::pair<char, int>( 'q', 26 );
        b36.insert(std::pair<char, int>( 'r', 27 );
        b36.insert(std::pair<char, int>( 's', 28 );
        b36.insert(std::pair<char, int>( 't', 29 );
        b36.insert(std::pair<char, int>( 'u', 30 );
        b36.insert(std::pair<char, int>( 'v', 31 );
        b36.insert(std::pair<char, int>( 'w', 32 );
        b36.insert(std::pair<char, int>( 'x', 33 );
        b36.insert(std::pair<char, int>( 'y', 34 );
        b36.insert(std::pair<char, int>( 'z', 35 );
       
        return b36.find(c)->second;
}

Copy Serialization

by in CodeSOD on

Twenty years ago, Stefano Z was a lowly junior developer, working with a set of senior developers, who had rules. A lowly junior developer, for example, couldn't be trusted to do something risky and dangerous, like serialize data to a buffer. Not without a safe API to keep them from foot-gunning themselves.

The API interface went thus:


Enterprise Estimates

by in Feature Articles on

Mary's company makes an enterprise product. Like many enterprise products, it shipped as a large pile of features that could potentially solve every problem any business could ever have, along with a suite of APIs that allowed customers to patch in their own custom functionality for their business needs. Also like many enterprise products, those features were only turned on or off based on how much the customer paid.

The arithmetic of all of these factors summed up to a set of function calls in the form IsFeatureXAvailable, with an added twist: the business side of the company was constantly changing the rules. "What the market will bear," and all that, meant that the IsFeature class of functions were some of the most volatile in the codebase.


Weakly Miles Calculation

by in CodeSOD on

Emma found a function called get_mileage_per_year. The purpose of the function is to apply some business rules around travel expenses, and while I'm sure it does that… it also makes some choices.

def get_mileage_per_year(self):
    # Mileage not set yet
    if not self.mileage_per_day:
        return 0

    weekly_miles = self.mileage_per_day

    extra_miles = 60 - self.mileage_per_day if self.purposes == ["special"] else 25

    # Add in extra miles for 'special' purpose is selected

    weekly_miles += extra_miles if "special" in self.purposes else 0

    #   where average daily miles are given by the weekly miles variable
    annual_miles = (weekly_miles * 365) + 2000
    if "special" in self.purposes:
        annual_miles = max(annual_miles, 24000)

    # Return annual miles bound to range 4,000 < mileage < 50,000
    mileage = int(min(max(annual_miles, 4000), 50000))
    return mileage

The Delete Procedure

by in CodeSOD on

Daniel recently found this pair of stored procedures. While the code within them is simple, they hint at horrors just beyond the edge of the stage, the kinds of things that might drive one mad.

CREATE PROCEDURE [dbo].[sp_SomeProc]
@ID       VARCHAR(6)

AS

IF @ID = '109369'
        BEGIN
                DELETE FROM table1
                WHERE ID = '109369'
        END
IF @ID = '100976'
        BEGIN
                DELETE FROM table1
                WHERE ID = '100976'
        END
GO

CREATE PROCEDURE [dbo].[sp_SomeOtherProc]
@ID       VARCHAR(6)

AS

IF @ID = '109369'
        BEGIN
                DELETE FROM table2
                WHERE ID = '109369'
        END
IF @ID = '100976'
        BEGIN
                DELETE FROM table2
                WHERE ID = '100976'
        END
GO