Simplify your code

klnjmm

Jimmy Klein

Posted on March 8, 2024

Simplify your code

Over the years, I have become very interested in clean code, calisthenics objects, etc. And over time, readings, videos, discussions and katas, my writing of code has changed: less superfluous, more meaningful code (at least for me 😇) and a desire to go to the 'essential. So here is what has evolved in my way of approaching code.

The examples in this article are in PHP, but most of what I describe below is applicable to all languages.


Comments

Commenting on your code can be useful, but it must be done for the right reasons. A comment should say why it was done like that and not what the code does.



// If the user is at least 18 years old
if ($user->getAge() >= 18) {
    ...
}


Enter fullscreen mode Exit fullscreen mode

This comment is completely useless, it is a literal copy of the if statement which can surely make you smile. But I used to write this kind of comment and I wasn't the only one (you just had to see the codebase of the project I'm working on some time ago). Look in your codebase, I'm sure you'll find some.



// If the user is an adult
if ($user->getAge() > 18) {
    ...
}


Enter fullscreen mode Exit fullscreen mode

This comment tells us a little more about what this instruction tests, but I think we can do even better and remove this comment. Many solutions :

  • Put a constant in place of 18 ```php

if ($user->getAge() >= ADULT_AGE) {
...
}


* Extract the test into a function
```php


if (userIsAdult($user)) {
    ...
}
...
...
function userIsAdult(User $user) {
    return $user->getAge() >= ADULT_AGE;
}


Enter fullscreen mode Exit fullscreen mode

This method is useful if you have a fairly complicated test with a sequence of conditions. Instead of putting a comment, try naming your test and extracting it into a function.

  • Ensure that this test is done directly in the object code ```php

if ($user->isAdult()) {
...
}
...
...
class User
{
private $age;

const ADULT_AGE = 18;
...
public function isAdult()
{
    return $this->age >= self::ADULT_AGE;
}
Enter fullscreen mode Exit fullscreen mode

}


---

## PHPDoc

PHP is becoming more and more typed, and honestly I've never had to extract the PHPDoc from my projects. From now on for my personal projects, I no longer generate the PHPDoc of my functions. To return to my `User` class:

Before:
```php


class User
{
    private $name;
    private $firstName;
    private $age;

    /**
     * User constructor
     * @param string $name;
     * @param string $firstName;
     * @param int $age;
     */
    public function __construct($name, $firstName, $age)
    {
        $this->name = $name;
        $this->firstName = $firstName;
        $this->age = $age;
    }

    /**
     * Indique si l'utilisateur est adulte
     * @return bool
     */
    public function isAdult()
    {
         return $this->age >= self::ADULT_AGE;
    }
}


Enter fullscreen mode Exit fullscreen mode

Now:



class User
{
    public function __construct(
        private string $name,
        private string $firstName,
        private int $age)
    {
    }

    public function isAdult(): bool
    {
         return $this->age >= self::ADULT_AGE;
    }
}


Enter fullscreen mode Exit fullscreen mode
  • The names of the methods are quite self-explanatory, no need to describe them (especially when we see the comments generated by the IDE like User constructor!)
  • The constructor parameters are typed, the IDE can very well indicate the type of each parameter
  • The return type of the method is directly in the code
  • And the advantage is that if one day a parameter or a return type has to change, there is no risk of forgetting to update the PHPDoc. (because yes, the problem with comments is that over time, they no longer correspond to the code below, due to forgetting to update 😕)

Getter and setter

The IDE can be very convenient, but can also lead to bad habits. Automatic generation of a class's getter and setter is a good example. We don't know if we're going to need them, but we're going to generate them anyway.

Generating automatically getter and setter

I now try to create the minimum possible getter/setter (if not none if possible):

  • Passing parameters directly into the constructor. Instead of : ```php

class User
{ // The constructor is empty for the example
public function __construct() {}

public function setName(string $name) {...} 
public function setFirstName(string $firstName) {...}
public function setAge(int $age) {...}
Enter fullscreen mode Exit fullscreen mode

}

I do 
```php


class User
{
    public function __construct(
        private string $name,
        private string $firstName,
        private int $age)
    {
    }
}


Enter fullscreen mode Exit fullscreen mode
  • The object itself can have its own business rules. Taking the example from the beginning of the article on the age of the user: Before ```php

if ($user->getAge() > 18) {
...
}

After
```php


class User
{
    ...

    public function isAdult(): bool
    {
        return $this->age >= self::ADULT_AGE;
    }
}


Enter fullscreen mode Exit fullscreen mode

Temporary variables

Like any developer, I learned to do for/foreach/while loops. And most often this included the creation of temporary variables. If I take the first example from my Refactoring with Collection article, here is the kind of code I used to write before:



public function doubleAllValue(array $numbers)
{
    $result = [];
    foreach ($numbers as $number) {
        $result[] = $number * 2;
    }

    return $result;
}


Enter fullscreen mode Exit fullscreen mode

We have a temporary variable here. If I use the definition from Wikipedia:

In computer programming, a temporary variable is a variable with short lifetime, usually to hold data that will soon be discarded, or before it can be placed at a more permanent memory location. Because it is short-lived, it is usually declared as a local variable, i.e., a variable with local scope.

And now here is what I usually write:



public function doubleAllValue(array $numbers)
{
    return array_map(function($number) {
        return $number * 2;
    }, $numbers);
}


Enter fullscreen mode Exit fullscreen mode

The use of temporary variables can be practical in certain debugging cases, on a case-by-case basis depending on the complexity of the code.


Early return

During my studies, I was taught that a method must have only one output. But over the years, I realized that it was possible to use early returns to improve the readability of the code.



function canDriveACar(User $user): bool
{
    $canDriveACar = null;
    if ($user->isAdult()) {
        $canDriveACar = true;
    } else {
        if ($user->learnInAccompaniedDriving) {
            $canDriveACar = true;
        } else {
            $canDriveACar = false;
        }
    }

    return $canDriveACar ;
}


Enter fullscreen mode Exit fullscreen mode

The use of early return will allow:

  • Reduce code indentation
  • To remove the else
  • To have more readable code


function canDriveACar(User $user)
{
    if ($user->isAdult()) {
        return true;
    }

    if ($user->learnInAccompaniedDriving) {
        return true;
    }

    return false;
}


Enter fullscreen mode Exit fullscreen mode

Our practice evolves over the years, sometimes with good ideas, sometimes not so good ones (but we realize it much later!).

What has changed in the way you code over the years? Let's discuss it in the comments.

Thank you for reading, and let's stay in touch !

If you liked this article, please share. Join me also on Twitter/X for more PHP tips.

Header photo by Artem Sapegin on Unsplash

💖 💪 🙅 🚩
klnjmm
Jimmy Klein

Posted on March 8, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Simplify your code
webdev Simplify your code

March 8, 2024