Updated with PHPStan rules available in Symplify 8.
Do you have 2 class with the same name? App\Entity\Product
and App\Entity\Product
? Of course not. But I bet you have at least 2 classes with the same short name *\Product
and *\Product
.
And that smells... Why?
In recent projects, I consult I start to notice an interesting pattern. It's how important are uniquely named short classes. Short class name = the part after last \
.
How would you like to use this code?
When I ask why the programmer picked such a naming, more often than not they refer DDD patterns, where you don't care if the element is interface, trait or abstract. The naming is always the same. Do you know which of them is class, interface, category Query and product Query?
Query
Query
Query
Query
Now the programmer has to become a detective.
Query
→ see the namespace, oh it's a /Contract
, that's probably an interfaceQuery
→ oh, the namespace is /Behavior
, that's probably a traitQuery
→ see the file location, it's in /Model/Category
, that's probably a category queryQuery
→ see the file location, it's in /Model/Product/Contract
, that's probably a product query interfaceGood job! The code starts to steal time and energy the reader 🤦.
Luckily, there is a band-aid to this problem, aliases!
<?php
namespace App;
use App\Behavior\Query as QueryTrait;
use App\Model\Category\Query as CategoryQuery;
use App\Model\Product\Contract\Query as ProductQueryInterface;
use App\Contract\Query as QueryInterface;
final class ProductQuery implements ProductQueryInterface, QueryInterface
{
use QueryTrait;
public function findByCategoryQuery(CategoryQuery $categoryQuery)
{
// ...
}
}
Now we have 200 % more code and but it's a bit more clear.
When you see an alias, and it's not for 3rd party code,
you have a code smell in there.
Get rid of it!
If you see a car of Tesla, you'd probably name it "Tesla car". Not a "car".
Get rid of aliases and name your classes in a unique and clear way:
<?php
namespace App;
use App\Behavior\QueryTrait;
use App\Model\Category\CategoryQuery;
use App\Model\Product\Contract\ProductQueryInterface;
use App\Contract\QueryInterface;
final class ProductQuery implements ProductQueryInterface, QueryInterface
{
use QueryTrait;
public function findByCategoryQuery(CategoryQuery $categoryQuery)
{
// ...
}
}
Do you need to help to find these smells? Just add NoDuplicatedShortClassNameRule
to your coding standard:
# phpstan.neon
rules:
- Symplify\CodingStandard\Rules\NoDuplicatedShortClassNameRule
Happy coding!
Do you learn from my contents or use open-souce packages like Rector every day?
Consider supporting it on GitHub Sponsors.
I'd really appreciate it!