PHP 8 just received a major new update and loads of new features were brought to this notorious programming language. In recent years, PHP has received major updates that considerably improved its performance and emphasized the use of OOP. Nonetheless, it looks like PHP is still not letting go of dubious practices. There are many, many nice features in the new version, such as the JIT compiler — which improves performance, constructor property promotion or structured metadata. Still, some of these new features promote bad practices. Below are five examples of such bad practices and how to avoid them.
Null safe operator
This operator is going to save a lot of code lines in applications that have heavy business logic. And it’s straightforward to understand: if something in a chained call is null, then evaluate everything to null. This is also a way to short circuit the whole call. It saves mental effort, lines of code, and prevents expensive calls. It’s also present in other programming languages (javascript and C# have it with short-circuiting). So when does this operator get bad?
In the example above, the operator is overused, and when it comes to debugging, you won’t know which thing is null; thus, tracking down issues takes more effort. What is null? The session or the address? Or maybe it’s the user?
How do you avoid its pitfalls? There are many ways to do that:
Stick to type definition as much as possible. If you know that a variable can’t be null, then use its type accordingly.
Limit the usage of the null safe operator to a maximum of two times per call, so it’s easy to debug
Handle null situations properly by implementing the logic that prevents calls on null operators
Named arguments
I remember a discussion I had a few years ago about what the maximum number of arguments of a method should be. My colleague and I wanted to enforce coding standards and we thought about this rule. We had this bad behavior of just adding more and more parameters to our methods. It was very easy for everybody in the team to do this. New logic? Add a new parameter, build an if around it and that’s it (one of the worst practices). Instead of doing this, the good practice should have been the encapsulation of those parameters inside objects, and that’s how we came up with the rule of three. Maximum three parameters should be defined on a method, everything more than three must be encapsulated inside an object. In PHP 8 the option to use named arguments was just added, which demotes this practice. Instead of creating a nice object with getters, setters, and probably a little logic for null assertions, developers will be tempted to add a new argument just because it’s easier. Without strict standards, there is a danger for methods to grow and generate high complexity code. To prevent this:
Enforce rules for the number of arguments a method can have
Always encapsulate data and logic inside objects.
Union Types
In the most recent versions, PHP showed a powerful direction towards more strict typing, showing that it’s becoming mature and leaving behind its bad behaviors and practices. Namespaces, traits, scalar type declarations, return type declarations, anonymous classes, etc., all showed this. Along come union types:
public function __construct( private int|float|string|null $number ) {}
In my opinion, this is one of the worst features that could be added to PHP 8. It clearly demotes the practice of interfaces. Instead of challenging developers with creating interfaces that enforce abstract thinking, it just lets them run wild. I actually tried to understand a situation in which union types would be good, but I didn’t come up with much. Maybe, it would be good to use union types if you had an ancient application that you tried to migrate to a newer version of PHP 8, but you should be splitting your methods instead of adding weird types. Maybe, it would be good when you want to refactor later, but then, why wouldn’t you refactor right there on the spot?
If I had to upgrade to PHP 8, I would ask my teams to add a rule to their linter that prevents the use of union types or at least limit the use of union types to a maximum of two.
Mixed Types
I saved the best for the end, or better said, the worst. If union types are bad, then the mixed type is a nightmare. It’s PHP’s way of saying that you can do a bad thing in more than one way.
public function __construct( private mixed $number ) {}
or the equivalent of using a really complicated union type
public function __construct( private array|bool|callable|int|float|null|object|resource|string $number ) {}
I know that there are developers out there who will go to the official documentation, read the RFC behind this new type, and go the extra mile and understand why this type was added. But at the same time, I know there are even more developers that will make bad use of this feature and abuse it.
Overall, PHP 8 adds a few dangerous features that might promote bad practices to inexperienced developers. If you don’t know how to use these powerful tools, it’s better to make sure you don’t use them.
4 new features in PHP 8 that promote bad practices
PHP 8 just received a major new update and loads of new features were brought to this notorious programming language. In recent years, PHP has received major updates that considerably improved its performance and emphasized the use of OOP. Nonetheless, it looks like PHP is still not letting go of dubious practices. There are many, many nice features in the new version, such as the JIT compiler — which improves performance, constructor property promotion or structured metadata. Still, some of these new features promote bad practices. Below are five examples of such bad practices and how to avoid them.
Null safe operator
This operator is going to save a lot of code lines in applications that have heavy business logic. And it’s straightforward to understand: if something in a chained call is null, then evaluate everything to null. This is also a way to short circuit the whole call. It saves mental effort, lines of code, and prevents expensive calls. It’s also present in other programming languages (javascript and C# have it with short-circuiting). So when does this operator get bad?
In the example above, the operator is overused, and when it comes to debugging, you won’t know which thing is null; thus, tracking down issues takes more effort. What is null? The session or the address? Or maybe it’s the user?
How do you avoid its pitfalls? There are many ways to do that:
Named arguments
I remember a discussion I had a few years ago about what the maximum number of arguments of a method should be. My colleague and I wanted to enforce coding standards and we thought about this rule. We had this bad behavior of just adding more and more parameters to our methods. It was very easy for everybody in the team to do this. New logic? Add a new parameter, build an if around it and that’s it (one of the worst practices). Instead of doing this, the good practice should have been the encapsulation of those parameters inside objects, and that’s how we came up with the rule of three. Maximum three parameters should be defined on a method, everything more than three must be encapsulated inside an object. In PHP 8 the option to use named arguments was just added, which demotes this practice. Instead of creating a nice object with getters, setters, and probably a little logic for null assertions, developers will be tempted to add a new argument just because it’s easier. Without strict standards, there is a danger for methods to grow and generate high complexity code. To prevent this:
Union Types
In the most recent versions, PHP showed a powerful direction towards more strict typing, showing that it’s becoming mature and leaving behind its bad behaviors and practices. Namespaces, traits, scalar type declarations, return type declarations, anonymous classes, etc., all showed this. Along come union types:
In my opinion, this is one of the worst features that could be added to PHP 8. It clearly demotes the practice of interfaces. Instead of challenging developers with creating interfaces that enforce abstract thinking, it just lets them run wild. I actually tried to understand a situation in which union types would be good, but I didn’t come up with much. Maybe, it would be good to use union types if you had an ancient application that you tried to migrate to a newer version of PHP 8, but you should be splitting your methods instead of adding weird types. Maybe, it would be good when you want to refactor later, but then, why wouldn’t you refactor right there on the spot?
If I had to upgrade to PHP 8, I would ask my teams to add a rule to their linter that prevents the use of union types or at least limit the use of union types to a maximum of two.
Mixed Types
I saved the best for the end, or better said, the worst. If union types are bad, then the mixed type is a nightmare. It’s PHP’s way of saying that you can do a bad thing in more than one way.
or the equivalent of using a really complicated union type
I know that there are developers out there who will go to the official documentation, read the RFC behind this new type, and go the extra mile and understand why this type was added. But at the same time, I know there are even more developers that will make bad use of this feature and abuse it.
Overall, PHP 8 adds a few dangerous features that might promote bad practices to inexperienced developers. If you don’t know how to use these powerful tools, it’s better to make sure you don’t use them.
Archives
Categories
Archives
Recent Post
Using decision trees to map out Architectural decisions
February 23, 2024Moving Beyond Code: From Software Engineer to Architect
June 23, 2023The three perspectives of a software engineering manager
June 4, 2021Categories
Meta
Calendar