-
Notifications
You must be signed in to change notification settings - Fork 280
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
Collect all violations while validating NumberSchema #118
Conversation
@@ -109,6 +111,8 @@ public static Builder builder() { | |||
|
|||
private final boolean requiresInteger; | |||
|
|||
private final List<ValidationException> validationExceptions; |
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.
This shouldn't be a member field, because this way the NumberSchema
instance won't be thread-safe. I suggest handling it as a local variable in the validate()
method and change the signatures of the check*
methods to return an Optional<ValidationException>
(or a List<ValidationException>
if there are possible multiple errors checked).
You can work from StringSchema as an example.
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.
@erosb thank you for feedback, I did not know it should be thread safe. do you think that with the approach like StringSchema you generate to way many unnecessary objects? For example, you create 3 ArrayLists even though it is possible they will be never used and I did not count call to addAll, which does copy of arrays.
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.
Correctness first. I wouldn't go into too much micro-optimizations here. At least not as long as it isn't verified with a perf. test that this is a bottleneck.
This entire aspect should be refactored at some time anyway (I would like to make it configurable to collect all errors or fail immediately with the first one), so I really don't see the point in putting too much effort into reducing the GC load here.
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.
- create list before hand and pass it as argument to check* (save 2 list creations)
- (A bit ugly) create function:
private List<ValidationException> getList(List<ValidationException> validationExceptions,
ValidationException validationException) {
if (validationExceptions == null) {
validationExceptions = new ArrayList<>();
}
validationExceptions.add(validationException);
return validationExceptions;
}
Once you encountered an error in the check*, you call that function by passing listA and then assign the result of that function back to the listA, and so forth.
private List<ValidationException> checkMaximum(final double subject) {
List<ValidationException> validationExceptions = null;
if (maximum != null) {
if (exclusiveMaximum && maximum.doubleValue() <= subject) {
validationExceptions = getList(validationExceptions, failure(subject + " is not less than " + maximum, "exclusiveMaximum"));
} else if (maximum.doubleValue() < subject) {
validationExceptions = getList(validationExceptions, failure(subject + " is not less or equal to " + maximum, "maximum"));
}
}
if (exclusiveMaximumLimit != null) {
if (subject >= exclusiveMaximumLimit.doubleValue()) {
validationExceptions = getList(validationExceptions, failure(format("is not less than " + exclusiveMaximumLimit),"exclusiveMaximum"));
}
}
return validationExceptions;
}
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.
If anything, then it makes more sense to optimize for the initial size of the list. new ArrayList<>()
allocates space for 10 objects. In case a check*
method can find at most 2 errors, you can create the list with new ArrayList<>(2)
.
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.
Okay, I see your point, I did it a little bit different from StringSchema. Please, check it out.
Thank you for raising this PR, this is definitely a bug. I added my concerns to the diff. Overall the change looks good, so I will merge it if you address my comments. |
@erosb moved the instance field into the method to keep thread safety , please, check it out. |
Looks good, thank you @adyach for your contribution. |
It is stated that Starting from version 1.1.0 the validator collects every schema violations (instead of failing immediately on the first one), but for some reason it was not like that for NumberSchema. This PR addressed this minor issue by introducing instance field with the list of violations.