Because programming is a technical profession, we often approach it without thought to design. Code is for getting a computer to do what we need, why should design matter? The majority of the programming languages we use were built for the programmer and are transformed into something that is optimized for the computer. As a result, we need to write our code, not just for the compiler or interpreter, but for humans to read. To make code readable, I approach it as an art. When you treat code as art, it becomes quickly digestible and easy to extend. Creative code also reduces bugs because it is easier to understand what it is executing.
The problem with artful coding is that it is not easy to do. Oftentimes, it is hard enough to get the code to work in the first place, much less be creative! However, just like any art form, there are some basic techniques we can follow to write well designed code. I am still exploring the best ways to write beautiful code, but these steps are what I follow to bring a little art to my programming.
Test Driven Development is not universally liked, but I find it to be a very good practice. Not only does it ensure all your code is tested, it also forces you to think about how your code will be used before writing it. In these examples, let’s imagine we are writing an email client in PHP and we want to be creative in the client’s design. Let’s start with a unit test for sending an email:
<?php
class EmailClientTest extends \PHPUnit\Framework\TestCase
{
public function test_sending_an_email()
{
$client = new \Email\Client();
$emailMessage = new \Email\Message('Hello world!');
$result = $client->send('andrew@dev.to', $emailMessage);
$this->assertTrue($result);
}
}
Since we wrote the unit test first, we already know how we want the code to be shaped. We know we will have an Email
namespace with two classes representing the Client
and the Message
. We also know that we will have a send
method for the process of submitting the email message with the client. In the unit test, we also decided how the pieces of our code will be named, which brings us to my next point.
Programmers often joke that naming things is hard and it’s the truth! However, naming a piece of code is not just hard, it’s also very important. How code is named determines how quickly a developer can understand it, reducing bugs and development time. In the above example, we decided to put all of our code in the Email namespace which is very clear about what it contains. Next, we chose Client
to represent the object that sends messages and Message
for the email itself, both descriptive nouns. Finally, we call a send
method which is a verb commonly associated with email. Now, we see a good pattern: use nouns for class names and verbs for methods.
It is tempting to put all the code for an operation in a single function. However, it’s really important to break it up into small chunks for readability and testability. Let’s use the send
method as an example.
<?php
namespace Email;
class Client
{
public function send(string $emailAddress, Message $message): bool
{
// Validate parameters
$validateEmail = filter_var($emailAddress, FILTER_VALIDATE_EMAIL);
$validateMessage = strlen($message->text()) < 1000;
if (!$validateEmail || !$validateMessage) {
return false;
}
// Communicate with email server
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://mail.example.com');
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, [
'to' => $emailAddress,
'text' => $message->text(),
]);
$result = curl_exec($curl);
curl_close($curl);
return $result;
}
}
This method is straightforward, but cluttered. It’s a little difficult to understand, so we added some comments so the reader knows what is happening. However, what if we created a new method instead of a comment?
<?php
namespace Email;
class Client
{
public function send(string $emailAddress, Message $message): bool
{
if (!$this->validateParameters($emailAddress, $message)) {
return false;
}
return $this->sendToMailServer([
'to' => $emailAddress,
'text' => $message->text(),
]);
}
private function validateParameters(string $emailAddress, Message $message): bool
{
$validateEmail = filter_var($emailAddress, FILTER_VALIDATE_EMAIL);
$validateMessage = strlen($message->text()) < 1000;
if (!$validateEmail || !$validateMessage) {
return false;
}
return true;
}
private function sendToMailServer(array $params): bool
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'https://mail.example.com');
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
$result = curl_exec($curl);
curl_close($curl);
return $result;
}
}
Our send
method is now much cleaner. The other functions perform a single task with less than 10 lines of code each, making them easy to read.
Finally, I recommend using a style guide for your chosen programming language. For PHP, I like to use the PSR-2 FIG standard for my code. The FIG standard is widely recognized and used by popular PHP frameworks like Laravel and Symfony. Plus, the Symfony team has released a CLI utility that automagically reformats your code to follow PSR-2: PHP Coding Standards Fixer.
Designing code requires effort and practice, but reaps many rewards. It causes your code to be in smaller, more readable chunks and reduces bugs by bringing clarity and focus. To continue learning more, I recommend reading code that is well designed. The Laravel and Ruby on Rails codebases are both examples of clean code that is treated with an artful touch. Do some source diving in both to learn more!