verifier
verifier copied to clipboard
Evaluate all predicates and return all errors
Imagine a user is filling out a web form with 20 fields, all of which have validation. The user doesn't want to fix validation errors one by one. They want to be presented with a list of all validation errors and fix them in a single pass.
Currently this is difficult to do with this library, as only one error is tracked, and predicates are not evaluated after the first error has occurred.
I think there's room for an enhancement to store a slice of errors in Verify instead without breaking API compatibility.
-
func (v *Verify) GetError() error
returns the first error, to maintain existing behaviour -
func (v *Verify) GetErrors() []error
method that returns all errors
The only implication I can see is that you'll be forced to do a nil check before evaluating further predicates, which is currently the case anyway.
func NewXYZ(transfer *Transfer) []error {
verify := verifier.New()
verify.That(transfer != nil, "transfer can't be nil")
if err := verify.GetError(); err != nil {
return []error(err)
}
verify.That(transfer.Amount > 0, "transfer amount should be greater than zero")
verify.That(transfer.Destination != "", "transfer destination can't be empty")
if errs := verify.GetErrors(); len(errs) > 0 {
return errs // now we can get both!
}
}
Hi Ben, I think this is a great idea and I'll implement it. The only thing I'm worried about is that method Predicate will change it's behaviour, so this change is not fully backwards compatible. But it shouldn't be a problem, because I can release it as 2.0.0 version.
As alternative we can create separate method that will accumulate errors:
func NewXYZ(transfer *Transfer) []error {
verify := verifier.New()
verify.That(transfer != nil, "transfer can't be nil")
if err := verify.GetError(); err != nil {
return []error(err)
}
verify.ThatAlso(transfer.Amount > 0, "transfer amount should be greater than zero")
verify.ThatAlso(transfer.Destination != "", "transfer destination can't be empty")
if errs := verify.GetErrors(); len(errs) > 0 {
return errs // now we can get both!
}
}
Can't figure out good name for it 😞 Maybe you can suggest some?
And other idea would be a separate mode for verifier:
func NewXYZ(transfer *Transfer) []error {
verify := verifier.Accumulative()
verify.That(transfer != nil, "transfer can't be nil")
if err := verify.GetError(); err != nil {
return []error(err)
}
verify.That(transfer.Amount > 0, "transfer amount should be greater than zero")
verify.That(transfer.Destination != "", "transfer destination can't be empty")
if errs := verify.GetErrors(); len(errs) > 0 {
return errs // now we can get both!
}
}
If you have any other thoughts or suggestions I'd be happy to hear 😃
I'd create a separate type that implements the same "interface." There is no reason to use the same verifier for those distinct styles.
Verify does what its called. It is a tool for expression assertions. Validate could use the same functions, but always aggregate errors and never short-circuit further processing.
P.S. Names are hard and really don't matter all that much as long as they're not misleading.