-
Notifications
You must be signed in to change notification settings - Fork 8
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
Simplify Property type validation #189
Comments
PhET-iO uses Also, if we combine all of this checking into one place, we may need a better name than |
+1. Look to lodash for a better name than |
It seems lodash uses the term |
It would be nice to have nice enumeration support here. What is the recommended way to port validValues? |
Depending on how formal we want to get, I like one of the following two ways:
predicate: ( value )=>{
return value === value1 || value === value2 . . .;
}
predicate: Validators.predicateForValidValues( [value1, value2]) Maybe the second is a bit clunky, not sure which one I prefer. |
Validation is not always an equality comparison. E.g.:
So validation needs to support general boolean expressions. I don't think the |
With our new Enumeration library, we could use: predicate: MyEnumeration.includes.bind(MyEnumeration) |
If we flatten Property validation into one
|
This was discussed in the meeting today. A large focus was trying to see how the phet-io needs would fit into a general case. There seemed to be a consensus that moving to a pattern that only accepted functions as predicates seemed ok. This goes against what @pixelzoom recommended above, and instead looked at converting all of the above list into functions to be passed in as the predicate option (whereas before they were "converted" into predicate functions in Property. Then the
While the predicate option would accept an arbitrary anonymous function, for PhET-iO support it would be important to use the Validator options so that they could send along metadata to the wrapper frame about what the function is doing. A main con of this to me is the verbosity. Instead of having the option to just pass That doesn't look very appealing to me, especially because for simple cases like above (where we aren't testing complex opperations like "vale is null or less -4") we likely can get at the PhET-iO metadata from other places. We decided to talk about it more next week. |
@zepumph said:
To clarify, my recommendation was based on the requirements that @zepumph established in the first comment of this issue:
If you want to change the requirements and convert everything to predicate functions, I might have a different recommendation. |
See also #195, proper handling of |
Marking as high priority so that we get to it next dev meeting. A fair bit of work for emitter and property is blocked by this issue. |
Again this was discussed again today. Most of the conversation was taken up in just understanding the current limitations, as well as the variety of potential solutions that we could go with. Right now we are basically trying to determine a general, and consistent way to conduct value validation. In Property we want to have a value validated in the same way as for each argument for Emitter, as well as testing values in TypeIOs. At one point, there was a thought to make generic value validation only ever accept a There was some consensus that it is really nice to be able to specify simple typeof strings and Type constructors as well as predicate functions. I.e basically what At one point there was talk of having an option in Emitter to support the arg value validations, and then when instrumenting this Emitter, to convert those over to where the So for next week. I'm going to implement a solution that involves just using Note that @pixelzoom expressed concern in how we are conflating the phetioType with the accepted value validation, which seemed weird. We weren't able to finish that piece of the discussion before the dev meeting ended. |
Pushed to next week. |
I'm sorry I didn't get to this again. I will work on it this afternoon and we will talk next week. |
Right! That is what we were questioning. I think right now I am leaning toward getting rid of the complexity (for example in Property's option extend call) because this performance hit is only realized with assertions enabled. On the other hand. We know that @jonathanolson has implemented some tests/checks under |
From Property.js - // By default, check the options once in the constructor, not on each subsequent value validation, to improve
// performance in requirejs mode
validateOptionsOnValidateValue: false The default is not to validate?... We might as well not validate anything if this is the default. |
I thought this too! But notice that property is validating options in the constructor still. Then @samreid showed me the possibilities for generality with usages in wave interference. After looking there, how do you feel about the option? |
Property's constructor is validating initialization only. That's better than nothing, but close to nothing, and certainly not an appropriate default when assertions are enabled.
What am I looking at in Wave Interference? I see that Scene is using Validator for some validation that's not related to Property, and that's nice. But what justification does that provide for not validating Property after initialization? |
The implementation of Property.set is: set: function( value ) {
assert && Validator.validate( value, this.validatorOptions );
if ( !this.equalsValue( value ) ) {
this.setValueAndNotifyListeners( value );
}
return this;
}, If assertions are enabled, the Property value is validated every time the value changes. The thing that Property only validates once in the constructor are the validation options, such as // By default, always check the provided options. Can be turned off for cases where the same options are used
// repeatedly, such as in Property
validateOptionsOnValidateValue: true Since the validation options do not change once a Property is constructed, they do not need to be validated more than once (certainly not 10,000 times per second). |
OK... |
Couldn't Also recommend to rename |
I was worried it would be confusing. I considered omitting it altogether but wasn't ready to incur an up to 1%
There are two types of use cases of Validator.validate(). Type A (exemplified in Property and will also be seen in Emitter) is called repeatedly with the same options but different values. Type B is called only once, like this example in Wave Interference's Scene.js: // @public (read-only) {number}
this.numberOfSources = Validator.validate( config.numberOfSources, { validValues: [ 1, 2 ] } ); In both cases, it seems appropriate to validate the validation options themselves, such as making sure the user didn't pass a non-array like
Sure, but
Thanks, I'll rename that. |
Here's a patch that accomplishes that. Once a set of options has passed validation, it is marked as approved. Options marked as approved aren't checked again. However, this has the side effect that it mutates options (and hence kind of appears in the API anyways). Or if options are mutated and reused it could have an incorrect approval, etc. etc.
|
This issue overlaps somewhat with phetsims/wave-interference#275 (comment) |
From today's dev meeting: Conversation A: using Validator in Property, and in standalone and in Emitter CM: can NumberProperty use validator for
|
Previous list of "next step"
This change in phetioInherit looks good. Right now we aren't using
I feel like it is pretty safe to differentiate these 2 based on checking
Out for review as part of #182
see #202 Next steps for this issue:
@samreid can you think of anything else to do here that won't be covered by follow-up issues? |
Sounds reasonable, I'll remove the corresponding TODO from the code.
I moved that to #205
I'll create a new issue for that too.
I'll create a focused issue regarding the questions about |
@zepumph said:
@samreid said:
If I understand correctly, the proposal is to make |
Not just a proposal, that is how Property validation has been since it was added in February 2018 in 866c63d I agree those are unsuitable for |
very good thanks! Good to note that #195 will be worked on more, but this feels like things have wrapped up well. I'm going to close, and new issues can be created from here. Thanks all! |
While talking to @samreid about #182, we discussed ways of trying to (a) have the best validation code possible for Emitter and Property as well as (b) have them both share as much api/code as is reasonable.
We came up with a strategy that would allow us to remove
isValidValue
andvalidValues
, and instead inline everything intovalueType
The goal would be to support all types of
valueType
in the same parameter. Here are the pieces we want to support:typeof value
to get the valueTypevalue instanceof X
to get the valueTypeProperty.valueType currently supports the first two, but to support the difference between the second two, @samreid and I have done some brainstorming.
name
property. For example:Anonymous functions don't have a name, so by checking on a name, we could cover many cases, for example:
If there was a case where you wanted a predicate to have a name, then we could make a convention that that function then needs a reserved property that we can check on:
The validation would be pretty simple, and not that different than the current form of
AXON/assertValueType
:On top of this (sorry for the long issue), having this reserved predicate marker could be really nice for factoring some of these out.
We could have a
Validators
class where we keep some simple validators likeValidators.greaterThanZero
Validators.numberOrNull
etc. . .
Each of the above static functions would have the
isPredicate
prop to support the validation as a named function.We will need to have something like this for each emitter arg as well, so it could be nice to factor it out into a central place
Marking for dev meeting.
The text was updated successfully, but these errors were encountered: