To docblock or not to docblock

What are docblocks?

Docblocks are comment blocks that describe a class or method and document its parameters and return types.

Unfortunately, they're often overused and are outdated compared to the code they're describing, or repeat the same information again.

For example, here's some PHP code:

function sayHello(string $name, array $options = ['shout' => false]): void {
echo 'Hello, ' . $name;
}

sayHello('');
sayHello('Oliver', ['shout2' => true]);
sayHello('Oliver', ['shout' => 'banana']);

It's readable and understandable.

It has types.

We know that the name needs to be a string and that an array of options can be passed.

This is how I like to write my code. In a clear and readable way with minimal comments.

This code works, but there are issues with it.

Do we want the name to potentially be an empty string?

What if different options are passed in?

Step 1

If you use PHPStan (a PHP static analysis tool), you won't get any errors until you test against level 6.

Then you'll get this error:

Function sayHello() has parameter $options with no value type specified in iterable type array.

Now, we can use a docblock to provide more information to PHPStan to describe the structure of the $options array and that it has strings for keys and boolean values.

/**
* @param array<string, bool> $options
*/

Although it's not erroring, we can add the $name parameter and declare it as a string.

/**
* @param string $name
* @param array<string, bool> $options
*/

Now, the docblock adds some context and value but essentially repeats the defined types.

Step 2

We can do more with the docblock and tell PHPStan more about what we want the values to be.

We don't want an empty string for a name and want the correct options and values.

Let's change the docblock to this:

/**
* @param non-empty-string $name
* @param array{shout: bool} $options
*/

This specified the name cannot be an empty string and the shape of the options array.

With this, we get these errors that weren't included before:

Parameter #1 $name of function sayHello expects non-empty-string, '' given.

Parameter #2 $options of function sayHello expects array{shout: bool}, array{shout2: true} given.

Parameter #2 $options of function sayHello expects array{shout: bool}, array{shout: 'banana'} given.

Here's the thing

While I like to write minimal, readable and "self-documenting" code and not overuse docblocks by adding them everywhere, I only add them and comments where needed and provide value, either to someone reading the code in the future or to tools like PHPStan that help me make the code better.