Skip to content
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

Validation improvements #149

Merged
merged 11 commits into from
Feb 10, 2022
Merged

Validation improvements #149

merged 11 commits into from
Feb 10, 2022

Conversation

hadley
Copy link
Member

@hadley hadley commented Feb 8, 2022

  • Error when setting property that doesn't exist
  • validate() checks properties types, then recursively checks object
  • Property multi-assignment

@hadley
Copy link
Member Author

hadley commented Feb 8, 2022

@DavisVaughan can you please review? Probably easiest to start with the documentation improvements to validate() so you get a sense of what it's supposed to do.

R/property.R Outdated Show resolved Hide resolved
R/property.R Show resolved Hide resolved
Comment on lines 215 to +216
if (isTRUE(check) && !class_inherits(value, prop$class)) {
stop(sprintf("%s@%s must be of class %s, not %s",
obj_desc(object), name,
class_desc(prop$class),
obj_desc(value)
), call. = FALSE)
stop(prop_error_type(object, name, prop$class, value), call. = FALSE)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you extract out a validate_property() from validate_properties() and then use that here? Then if we add more validation checks we don't have to keep these in sync

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about that too. It's just pretty marginal since it's only used in two places and the logic is v simple.

R/valid.R Outdated
#' automatically when creating new objects (at the end of [new_object]) and
#' when setting any property.
#' @description
#' `validate()` calls the validator of an R7 object. This is done automatically
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My first two thoughts were:

  • What is the job of a validator? Like what exactly is the scope of what it should be validating
  • Where do I set a validator? (Looking into the examples you learn that you set this in new_class(validator=) but it might be nice to mention that here somehow)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've expanded the validator docs in new_class() and linked to them from here.

R/valid.R Outdated Show resolved Hide resolved
#' r
#' }
#' rightwards(r, 20)
validate <- function(object, properties = TRUE) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I were designing this function, this is where I'd put ... to force named arguments, because validate(x, FALSE) is essentially meaningless to me without the argument name.

Plus this feels like a function which has a decent chance that we will add more arguments to it, and that would free us from caring about argument order.

Not sure how we feel about this principle for R7 though, since it will be tied closely to base R

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, agreed with both points. But since this is going in base R (which doesn't use that pattern), and properties is mostly their for internal use, I'll leave as is.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding an unneeded ... to the argument list also comes with a price. I would never want to pay that just to force users..

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explicit formal arguments also improve code clarity. Users are free to follow whatever calling convention they like.

if (is.null(validator)) {
return(invisible(object))
# First, check property types - if these are incorrect, the validator
# is likely to return spurious errors
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the errors in the object validator are likely to be spurious, should we just go ahead and error immediately if any properties are invalid? Maybe it could have a header of Invalid <obj> properties:?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see you've tried to do something like this by avoiding the object validator with the length(errors) == 0 branch. Hmm, I think I still prefer an immediate error - but only because I would mention in the header that it was the properties that were invalid (I don't feel strongly about this if you want to keep it as is)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good idea.

R/property.R Show resolved Hide resolved
R/valid.R Show resolved Hide resolved
tests/testthat/test-valid.R Show resolved Hide resolved
@hadley hadley merged commit 7adda89 into master Feb 10, 2022
#'
#' The job of a validator is to determine whether the object is valid,
#' i.e. if the current property values form an allowed combination. The
#' types of the properties are always automatically validator so the job of
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

always automatically validator

typo here, validator->valid

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, thanks.

@hadley hadley deleted the validation-improvements branch February 10, 2022 21:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants