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
Fixes 7: Fix defaults #13
Fixes 7: Fix defaults #13
Conversation
+1 LGTM. I just want to do a bit of testing with Robo to ensure there's no b/c problem, but implementation looks like it should be compatible. |
My initial robo command to test the default functionality and showed it wasn't working now works properly. I initially made a modification that I didn't realize was part of Robo not Config, which is why I found the backward compatibility issue. I'm planning on submitting a PR to Robo to update it's config class so it uses But I did make sure my PR didn't break the current functionality. :) |
…ter. This allows sub-classes to ensure $defaults remains the proper type, while not providing additional functionality to classes using this class.
Just updated visibility of the |
Better define type returned in an attempt to fix the Scrutinizer error.
I'm done making changes now. |
src/Config.php
Outdated
*/ | ||
protected function getDefaults() | ||
{ | ||
// Ensure $this->defaults is a Data object (not an array) | ||
if (is_array($this->defaults)) { | ||
$this->setDefaults($this->defaults); | ||
return $this->getDefaults(); | ||
} elseif ($this->defaults instanceof Data) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor style point: avoid elseif
when if
will do. (if
block above exits when true.)
src/Config.php
Outdated
return $this->getDefaults(); | ||
} elseif ($this->defaults instanceof Data) { | ||
return $this->defaults; | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor style point: avoid else
/ extra indentation when unnecessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I completely agree with both of these points and had a version working that didn't have either the elseif
or the else
. The problem is that Scrutinizer said there was a "major" error introduced because it couldn't detect that $defaults
wasn't an array, and array|Dflydev\DotAccessData\Data
didn't match the return type of Dflydev\DotAccessData\Data
.
I would prefer the simpler version of the code, but also don't want to introduce problems that don't go away with the code checking that's in place.
Your recommendation for the final solution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if there is a solution to convince Scrutinizer that the return values are correct here, but it is permissible to ignore Scrutinizer inspection results if they are wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My previous code just checked if $this->defaults
was an array, and if so set it using $this->setDefaults($this->defaults)
then returned $this->defaults
(now set as a Data
object).
This is what was causing problems in Scrutinizer.
As a solution to not using elseif
and else
but still solving the Scrutinizer issue, I could use an if
in place of the elseif
and simply throw and \Exception()
without the else, because both if statements return
if they are true.
Correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's what I was advocating -- if
in place of elseif
. No change to logic of the function, only to the representation, to make it easier to read.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Found this: https://scrutinizer-ci.com/docs/reviews/filtering_issues_and_false_positives So I'm reverting unnecessary logic and going to attempt that. Hopefully that keeps the problem out of further Scrutinizer reviews down the road. |
The issue is back in Scrutinizer. I don't have permission to dismiss it (should have thought of that), but hopefully the instructions in the link above work for you and you are able to ignore the issue. Either way the code is back to the point prior to my attempt to fix that problem. |
My experience with the Scrutinizer "false positive" feature is that it never remembers false positives, and continues to report the issue regardless of your stated preferences. It is not necessary (nor desirable) to change the code to work around Scrutinizer advice that is incorrect. |
…g as covered in code coverage report
Updated to fix code coverage for protected methods. Done making changes. Ready for merge per your manual tests. |
Any update on the testing this? |
src/Config.php
Outdated
@@ -124,6 +126,7 @@ public function setDefault($key, $value) | |||
* TODO: remove Data object validation in 2.0 | |||
* | |||
* @return Data | |||
* @codeCoverageIgnore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You shouldn't @codeCoverageIgnore
here. There is no reason why this shouldn't be covered; if it isn't, that fact should be reflected in the stats and coverage logs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you rather just have this uncovered? or do you have a recommendation for how to test this? My research shows that private/protected methods should only be covered by what can be tested publicly. Since these methods are only for use to ensure the $defaults
property is a Data
object and not an array, they aren't called by any public methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did try subclassing the method to initially create the $defaults
property as an array, and test using that class, but since that appeared to only test the subclass and didn't change the code coverage for the actual Config
class.
Unless I'm missing the right way to do this (totally possible 😕 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's possible to test private / protected methods by using php reflection to set the access level to public, and then call the method indirectly through the reflection object. I do this in some tests (not necessarily in this project, though). That said, I am a fan of testing the just the public methods of a class. If the protected / private methods become really complex and need their own direct testing, that's generally a sign that they should be factored out into another class.
Also, if a protected or private method exists to serve any useful function, then they should be reachable by some public methods, if called with the right input values. If they are never called, that might be an indication that they can be completely removed. Some functions just happen to not be called in tests, e.g. public function getFoo() { return $this->foo; }
does not necessarily require a test.
These methods look simple enough, and I'm okay with leaving them untested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, thanks. I'll remove the @codeCoverageIgnore
directives. I think the only part that wasn't getting tested was the parts that validate the $defaults
property is not an array. I'll try creating a test using reflection that tests this by modifying the $defaults
property directly and then calls the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that you need to use reflection just to call a protected method with bad values to ensure that the sanity checks work. This is testing the specific implementation over the behavior. Either figure out how to cover that code block through the public methods, or leave it untested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand your concern with testing implementation instead of behavior, in this case I think it is important to test since these methods are what prevent breaking backward compatibility.
Also in creating the test I found a flaw that I would not have otherwise readily noticed. 😀
Thanks for merging and for the experience. I have learned a lot through this PR.
Sort of backlogged due to the holidays. Will try to get to this shortly. |
This looks all good. Just remove the |
This forces any non-Data objects to use setter, and uses the Exception in the setter.
Thanks for that tip on using reflection. Code coverage for the |
Fixes issue #7
Dflydev\DotAccessData\Data
to solve the problem.getDefaults()
andsetDefaults($defaults)
methods to keep backwards compatibilityTODO
comments for steps to enforce$defaults
class parameter being aDflydev\DotAccessData\Data
object and not an array in version2.0
(however this breaks backwards compatibility.