Simple code

07 Oct, 2022
929 words | 5 min to read | 2 hr, 47 min to write

This article is a part of the programming concepts series. First, is not entirely accurate to put it inside the series, as it’s not a programming concept per-se. But it’s definitelly a part of conceptual thinking when writing code, so I decided it still belong inside the series. Secondly, it’s not entirely accurate to call it an article, it’s more of a small essay. Enjoy ;)

I’m a smartass!

Yeah! That’s what a rookie developer feel when they pull off a very smart piece of code. Perhaps, a one-liner that uses functional programming techniques, lambda-functions, and some language-specific features. I’m speaking from the experience of course. Impostor syndrome will come later… maybe :)

Unfortunatelly I haven’t been writing smart code since circa 2012. It was back then when I realised “smart code” is not worth writing. So, I don’t have an exmplate at hand, so I will improvise and come up with something… Hmmm… how about this:

$sqlInsertData = [
['name' => "John Doe", 'dob' => DateTime::createFromFormat('Y/m/d', '2001/01/01'), 'balance' => 1000],
['name' => "Jane Doe", 'dob' => DateTime::createFromFormat('Y/m/d', '2004/05/07'), 'balance' => 550.5],
['name' => "Chris O'Donnel", 'dob' => DateTime::createFromFormat('Y/m/d', '2004/05/07'), 'balance' => -200],
];
$inserts = implode(", ", array_map(
function ($record) {
return '(' . implode(', ', $record) . ')';
},
array_map(
function ($record) use ($db) {
$quote = function ($s) use ($db) {
return sprintf(
'%s%s%s',
is_int($s) ? '' : '"',
is_int($s) ? (int)$s : $db->escape($s),
is_int($s) ? '' : '"',
);
};
return array_map($quote, $record);
},
array_map(function ($entry) {
return [explode(' ', $entry['name'])[0], explode(' ', $entry['name'])[1], $entry['dob']->format('Y-m-d'), $entry['balance'] * 100];
}, $sqlInsertData)
)
));
$sql = sprintf(
"INSERT INTO people (first_name, last_name, dob, balance_cents) VALUES %s",
$inserts
);

What the highlighted code does is it takes data as an array and converts it to a list of SQL insert statements parts. It takes care of several things such as:

  • adding quotes,
  • converting dates,
  • splitting up full name into first name last name,
  • converting dollars to cents so that we are storing balance in an integer field,
  • escaping string values in the final sql,
  • adding parentheses and commas
echo $sql;
> INSERT INTO people (first_name, last_name, dob, balance_cents) VALUES
> ("John", "Doe", "2001-01-01", 100000),
> ("Jane", "Doe", "2004-05-07", "55050"),
> ("Chris", "O\'Donnel", "2004-05-07", -20000)

But even though this code is pretty well formatted, it’s dead hard to read! And yes - this IS a variable assignment that spans over a dozen of lines of code. Quite ridiculous.

How being a smartass and writing smart code is detrimental?

Let me remind you a simple fact.

Code is read more often than it is written

You see, if you write smart code that may be (oddly, I must say) satisfying, poor that person who’s going to read it. Or worse - those people. Or even you in the future. Did you ever stumble upon your own code you wrote a while back and thought “what the heck, who writes code like that?” followed by the cold shower of git blame?

Yeah! The simpler the better. 20 lines of well-formatted, readable, semantically correct code over a really smart one-liner? I’ll take the first any day.

Let’s fix it

In our example we need to turn this

$sqlInsertData = [
['name' => "John Doe", 'dob' => DateTime::createFromFormat('Y/m/d', '2001/01/01'), 'balance' => 1000],
['name' => "Jane Doe", 'dob' => DateTime::createFromFormat('Y/m/d', '2004/05/07'), 'balance' => 550.5],
['name' => "Chris O'Donnel", 'dob' => DateTime::createFromFormat('Y/m/d', '2004/05/07'), 'balance' => -200],
];

into this:

> INSERT INTO people (first_name, last_name, dob, balance_cents) VALUES
> ("John", "Doe", "2001-01-01", 100000),
> ("Jane", "Doe", "2004-05-07", "55050"),
> ("Chris", "O\'Donnel", "2004-05-07", -20000) 

And we already know what it takes:

  • adding quotes,
  • converting dates,
  • splitting up full name into first name last name,
  • converting dollars to cents so that we are storing balance in an integer field,
  • escaping string values in the final sql,
  • adding parentheses and commas

Isn’t this list a perfect list of methods?

Adding quotes

function addQuotes(string $str, $quotes = '"'): string
{
return sprintf('%%%', $quotes, $str, $quotes);
}

Converting dates

function dateTimeToSqlDate(DateTime $dateTime): string
{
return $dateTime->format('Y-m-d');
}

Splitting up full name into first and last name

function fullNameToFirstAndLastName(string $fullName): array
{
// Yes! It's super-dull. But this is not the point of the article.
return explode(' ', $fullName);
}

Converting dollars to cents so that we are storing balance in an integer field

function dollarsToCents(float $dollars): int
{
return (int)($dollars * 100);
}

Gluing it all up together

function recordToSqlValuesList(array $record): string
{
[$firstName, $lastName] = fullNameToFirstAndLastName($record['name']);
$dob = dateTimeToSqlDate($record['dob']);
$balanceInCents = dollarsToCents($record['balance']);
return sprintf(
"(%s, %s, %s, %d)",
addQuotes($db->escape($firstName)),
addQuotes($db->escape($lastName)),
addQuotes($dob),
$balanceInCents
);
}
function insertDataToSqlValues($sqlInsertData, db $db): string
{
$sqlValues = array_map('recordToSqlValuesList', $sqlInsertData);
return sprintf(
"INSERT INTO people (first_name, last_name, dob, balance_cents) VALUES %s",
implode(', ', $sqlValues)
);
}

So we did split up massive variable assignment in a bunch of functions. Not only the readability drastically improved, we also made reusable codepoints in convenient methods such as addQuotes, dollarsInCents, and dateTimeToSqlDate.

Readability improved by:

  • slitting up the code in digestable pieces
  • removing nesting (array_map inside array_map inside array_map, etc.)
  • giving methods proper names
  • using type hints for both arguments and returns

Conclusion

Write simple code even if you see how can you write the same code “smart”. You will enjoy your “smart” code for a day or two. Who else will?

  1. Generators
  2. Simple code