Yeah. Some of you can blame php. Especially folks that are using scala/kotlin/haskel and even typescript. You cannot achieve full strict types and write lovely code. But Php is the huge elephant, that holds our web. It has its pros and cons. Today we will learn how to write the accurate php code with the help of the small plugin PhpClean.

Php elephant
Php elephant

Some rules are good to follow. They are straightforward to describe. But incredibly powerful with their strategy of the great code.

Missing parameter type declaration.

This rule is more often applicable to junior or even middle-level programmers. They think in the following way: we can have bool|array parameter, and this is fine. But unfortunately, it is not. In most cases, you need to have the core type, and sometimes you can extend it to the nullable type. Every time you see a method without a type definition, you need to think twice before using it. Only in rear cases, you need to have mixed in the parameter type. Be a good programmer - always write type definitions. Missing return type - stands for the same idea - the simplicity of the function and ease of maintainability.

1
2
3
4
5
class Url {
 // Missing parameter type
 // Missing return type
 public function withPort($post) { }  
}

Prefer composition over the inheritance.

I was very skeptical about inheritance (extends keywords in php). Once I found a way of using this word intelligently. When I override constructor or add some unique public methods, like extending the type, then I’m using this word in the right way. Imagine I have a class called CompositeValidator

1
2
3
class CompositeValidator{
 public function __construct(ValidatorInterface ...$name){}
}

Now, I need to create a validator with multiple rules, but I do not want to describe it every time. So I can extend it.

1
2
3
4
5
6
7
8
9

class GroupIdValidator extends CompositeValidator {
  public function __construct(Db $db){
    parent::__construct(
       new IsOnlyLetters(),
       new IsUniqueGroupField(Db $db),
    )
  }
}

As you can see, I’m using the extends keyword, but I can redefine only the constructor method. To do so, I always follow the next rules:

When I see the public method in an open class (the non-final one), I always think about the right design. Is it ok to override it or not? If I can override it, the core class will work correctly, or will it be broken? It is like defensive programming that can stand against future bugs.

Legacy ninja

We are working in the real world full of pain and feature requests. Legacy code is a core part of it. How to make it better?

I follow some rules to make my code less “legacebly”.

Private property is must-have.

The algorithm is very primitive:

if the class is not extendable, and I’m not extending anyone - then my protected properties can be private - yes? YES!

I have created the rule PropertyCanBePrivate. Tiny feature with a bright future.

Virtual type check.

You know that comments may lie, right?

Code never lies, comments sometimes do. - Ron Jeffries

In one project, I had a real life problem:

1
/** @var $user \Some\Name\Space\User **/

$user was not an object of the user :(. Actually, it was, but from another namespace. IDE cannot figure it out - so I had a bug with it (undefined property error).

That’s why I have decided to replace comments with assert statements. This rule called VirtualTypeCheck.

1
assert($user instanceof User);

Avoid visual noise

Developers who complain about the code size are not professionals. Sometimes having two extra lines is better than shorten them and having non-readable code. However, everything should have some logic. If you are writing something because everyone is doing this - then you are not professional either. It would be best if you stood for every symbol of the code and fight for it.

In php comments, we always repeat ourselves.

/** @param int #port **/
public function withPort(int $port) : self

Can you explain what important information did you get from the comment? Can you understand the code without it? You can always complain about consistency: sometimes we need to have phpdoc, and it is better to write it for all functions. It has sense, but IMHO it is less critical in this case.

These are the main rules that I follow. The most important one is the composition over inheritance. Make everything final, private, and do not modify the behavior, allowing to change it only by contracts. Have fun and try this PhpClean plugin in our lovely IDE by Jetbrains.