New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BooleanArgumentFlag triggers for a property promoted via a constructor (PHP 8) #924
Comments
I agree the violation could be ignored when it's in |
I started to work on this but the code above does not trigger a violation, it only triggers if the arguments has a default value such as The property being promoted or typed has actually no influence on the rule. While The very presence of the default value (added more often for a new feature over being there by initial design) is still a smell in many cases: class Cat {
public function __construct(
private string $name,
private bool $isActuallyADog = false,
) {}
} This is typically an appendix meant to make a class to support more cases than initially planned. But in this case, CleanCode rule is relevant to warn about this, the best practice is to make some When a bool argument is not a hack for cases like above, they usually don't need a default value: class Cat {
public function __construct(
private string $name,
private bool $isFluffy,
) {}
} In this case it makes sense to always specify It's still open to discussion. |
Yeah it's by design that it triggers if there is a default. |
@kylekatarnls in the case of using promotion in entities, I think it's legal to be able to pass a default value when you want an entity property to be |
https://phpmd.org/rules/cleancode.html
It is to encourage: $a = new Entiry();
$b = new ActiveEntity(); Instead of: $a = new Entity();
$b = new Entity(true); This has nothing to do with them being properties, the constructor, or property promotion. It would fail just as much for a regular argument that is used to set a property by default. class SomeEntity {
public function __construct(bool $someBoolProp = false) {}
} It is just as much an issue as: class SomeEntity {
public function setProperty(bool $someBoolProp = false) {}
} Solution 1: class SomeEntity {
protected $someBoolProp = false;
}
class ActiveEntity extends SomeEntity {
public function __construct() { $this->someBoolProp = true; }
} Solution 2: class SomeEntity {
public function __construct(protected bool $someBoolProp) {}
} |
That's the point of the Cat
|
@AJenbo "Solution 1" is exactly the issue illustration: the |
Please show a real example of this "need". I am actually tempted to believe that we have only 2 categories: 1 is breaking the PSR, the other actually should better not have default value, but maybe there is a third one I didn't identify. |
My main concern here is that the rule in the topic should not force anything other than passing a boolean argument to a method. It indirectly forces us to avoid default values for an entity boolean property OR to avoid promoted properties. If you think a default value for a property is not a good practice, then there should be a separate rule for this. And one can enable it if one thinks it fits the needs. As an example to oppose on
Do you see? The rule indirectly does what it shouldn't. In other words, it forces you to do something it's not about. PHPMD has a set of rules that can be combined based on project needs. Developers can enable some rules and ignore the ones they don't agree with or don't need atm. But here the problem is if we think our entities CAN have default values for boolean properties (for whatever reason), we have no way to keep using the rule for avoiding boolean arguments in usual methods (not constructors promoting properties). It's not configurable and it's not smart enough to distinguish the different cases. And we have to disable it because of no other options not affecting the design. So if you think this rule should still force not using promoted boolean properties with default values, let's maybe consider this behavior to become configurable? |
Just to put this out of the way, it has nothing to do with promoted properties: class SomeEntity
{
protected bool $someBoolProp;
public function __construct($someBoolProp = true)
{
$this->someBoolProp = $someBoolProp;
}
} Should also raise the violation in the current state. And we don't raise violation for Having here an ignore-pattern like we have in some other rules would be OK I think, it would allow project to add |
Promoted properties lets you define both a constructor argument and an associated property in a single line. Setting a default sets the default for the argument NOT the property. BooleanArgumentFlag does not allow for boolean arguments with default values. When setting property during the constructor a default for the property is mostly pointless: class SomeEntity
{
protected bool $someBoolProp = true;
public function __construct($someBoolProp)
{
$this->someBoolProp = $someBoolProp;
}
} (this is not what promoted properties does)
That is exactly the point of the rule. The example here also illustrates two issues with this way of designing things:
I would suggest providing setters for each property instead. It makes the behavior clear, and allows you set individual ones with out forcing you to set others that you do not care about. |
Thanks, @kylekatarnls. |
Current Behavior
A warning for the BooleanArgumentFlag rule is triggered.
Expected Behavior
No warning.
Steps To Reproduce:
Checks before submitting
The text was updated successfully, but these errors were encountered: