The naming in the bootstrap API was lacking some consistency and was a
bit obscure at time
I went back tot he drawing board and came with something that is I
think more natural and thus easier to use:
- to build ValidatorFactory
- to build Validator
Each set of proposal change is followed by the old and new syntax.
Feedback welcome.
To Build a ValidatorFactory
Here are the proposed changes
ValidatorFactoryBuilder => Configuration (should it be
ValidatorFactoryConfiguration)
Validation.builderType(Class<T>) to Validation.byProvider(Class<T>)
Validation.defineBootstrapState() to Validation.byDefaultProvider()
GenericBuilderFactory.getBuilder() to
GenericConfigurationFactory.configure()
SpecializedBuilderFactory.getBuilder() to
SpecializedConfigurationFactory.configure()
ValidatorFactoryBuilder.build() to
Configuration.getValidatorFactory() (should it be
buildValidatorFactory()?)
ValidatorFactoryBuilder.configure() to
Configuration.customConfiguration()
Also I am considering:
- removing Validation.getBuilder() (which would have been
Validation.configure() )
- adding Validation.getDefaultValidatorFactory() (which correspond
to the default bootstrap strategy used by JPA and JSF unless overridden)
Here are various bootstraps with the old naming followed by the new
naming. You will see that we gain in consistency and expressivity:
- byProvider(Class<?>) vs byDefaultProvider()
- the object type retrieved and its purpose is more obvious
(configure(), getValidatorFactory())
- the builder is a configuration object retrieving state to build
ValidatorFactory
//simple bootstrap
ValidatorFactoryBuilder<?> builder = Validation.getBuilder();
=> no equivalent but replaced by
Configuration<?> configuration =
Validation.byDefaultProvider().configure();
Validation.getBuilder().build();
=>
ValidatorFactory factory = Validation.getDefaultValidatorFactory();
//use generic provider with specific resolver strategy
ValidatorFactoryBuilder<?> factoryBuilder =
Validation.defineBootstrapState()
.providerResolver(...) //optional step
.getBuilder();
=>
Configuration<?> configuration =
Validation.byDefaultProvider()
.providerResolver(...) //optional step
.configure();
//use a specific provider with specific resolver strategy
ValidatorFactoryBuilder<?> factoryBuilder =
Validation.builderType(ACMEValidatorFactoryBuilder.class)
.providerResolver(...) //optional step
.getBuilder();
=>
Configuration<?> configuration =
Validation.byProvider(ACMEValidatorConfiguration.class)
.providerResolver(...) //optional step
.configure();
I am also wondering if we should rename the methods on the
Configuration object (former ValidatorFactoryBuilder):
- messageResolver => useMessageResolver
- providerResolver => useProviderResolver
- traversableResolver => useTraversableResolver
- customConfiguration => useCustomConfiguration
- constraintFactory => useConstraintFactory
This makes them a bit more "fluent" but also more verbose.
To Build a Validator
rename ValidatorFactory.defineValidatorState() to
ValidatorFactory.usingContext()
rename ValidatorBuilder to ValidatorContext
Here are various bootstraps with the old naming followed by the new
naming. We gain consistency with the VF creation as well
//simple validator creation
Validator validator = validatorFactory.getValidator();
=>
Validator validator = validatorFactory.getValidator(); //unchanged
//with overriding context
Validator validator =
validatorFactory.defineValidatorState()
.traversableResolver(...)
.messageResolver(...)
.getValidator();
=>
Validator validator =
validatorFactory.usingContext()
.traversableResolver(...)
.messageResolver(...)
.getValidator();
What do you think?
There are three layers of changes:
- having a consistent naming between VF and V creations and using
more meaningful name for the build method (ie getValidator /
getValidatorFactory
- having a consistent path and naming wether you use the default
provider or a specific one
- rename the builder classes with meaningful definitions