[bv-dev] Method Validation: Why Example 4.11 should be allowed

Matt Benson mbenson at apache.org
Mon Jul 23 10:16:37 EDT 2012


Discovered this unsent draft, which I had intended to send:

On Thu, Jul 19, 2012 at 2:54 PM, Gunnar Morling <gunnar at hibernate.org> wrote:
> Hi Matt,
>
> 2012/7/19 Matt Benson <mbenson at apache.org>:
>> On Thu, Jul 19, 2012 at 2:02 AM, Gunnar Morling <gunnar at hibernate.org> wrote:
>>>
>>> Am 18.07.2012 18:51 schrieb "Paul Benedict" <pbenedict at apache.org>:
>>>
>>>
>>>>
>>>> Gunnar, thank you for writing back!
>>>>
>>>> On Tue, Jul 17, 2012 at 4:12 PM, Gunnar Morling wrote:
>>>> > Hi Paul,
>>>> >
>>>> > thanks for your feedback, that's much appreciated.
>>>> >
>>>> > The reason for the restriction basically is that a client of an API
>>>> > doesn't necessarily know its implementation. Let's for instance assume
>>>> > a client receives an implementation of the OrderService interface via
>>>> > dependency injection:
>>>> >
>>>> > public class Shop {
>>>> >
>>>> >     @Inject
>>>> >     private OrderService orderService;
>>>> >
>>>> >     ...
>>>> > }
>>>> >
>>>> > Here, the programmer of the Shop class doesn't know which
>>>> > implementation will be injected, maybe it's SimpleOrderService, maybe
>>>> > it's an implementation type not even known to the Shop programmer at
>>>> > all. If it would be legal to add parameter constraints to the
>>>> > OrderService implementation, there is no way to find out for the
>>>> > caller what parameter values for placeOrder() are valid.
>>>>
>>>> I see your viewpoint. However, I am not sure BeanValidation needs to
>>>> be this smart.
>>>
>>> This is not specific to BV. OO design in general has the notion that any
>>> sub-type can be used where its super-types can be used. This principle is
>>> violated if parameter constraints could be added to sub-types, putting more
>>> constraints in place to be obeyed by the caller.
>>>
>>
>> Gunnar, this argument makes perfect sense.  Yet, consider the fact
>> that the v1.0 BV validation routine evaluates "all getter level
>> validations (including the ones expressed on interfaces and
>> superclasses)".  This seems to establish a bit of a precedent IMO.
>
> The discussed rule only forbids a strengthening of preconditions (as
> represented by parameter constraints), it doesn't apply to
> post-conditions (as represented by return value constraints), which on
> the contrary may be strengthened but not weakened by sub-types.
>
> The 1.1 spec draft says [1]:
>
> "In sub types (be it sub classes/interfaces or interface
> implementations) return value constraints may be declared on
> overridden or implemented methods and the return value may be marked
> for cascaded validation. Upon validation, all return value constraints
> of the method in question are validated, wherever they are declared in
> the hierarchy (since this only poses possibly a strengthening but no
> weakening of the method's postconditions guaranteed to the caller)."
>
> So this is perfectly inline with the rules for BV 1.0 property-level
> constraints.
>

Okay, point taken.  Thanks for clarifying the distinction between
pre/post-conditions corresponding to method parameters vs. return
values here.  Still, consider the JDK itself:  the java.util.Deque
interface imposes no requirements on the parameter to its #push()
method, yet the java.util.ArrayDeque implementation forbids null
elements and is declared as throwing an NPE if the parameter to
#push() is null.  I can fully understand your assertion that this
violates DbC and even basic OO principles, but is it *necessary* that
BV deny users the option to work with such a design?  I'm not yet
convinced of the harm it would cause, beyond implementation complexity
(which IMO doesn't seem extensive), to permit a user to add decoupled
validation constraints per Paul's example, or to customize a given
implementation as in mine.  Nothing here would prevent the purist user
from operating per your recommendations.

br,
Matt

>> In
>> any event, it seems the requested functionality could be provided as a
>> parameter-driven, implementation-specific option.
>
> Maybe a BV provider could implement such sort of option, but I'd
> strongly recommend against it. Behavioral sub-typing is a fundamental
> principle which IMO shouldn't be allowed to be "turned off". I'm also
> not aware of any existing DbC library supporting such sort of option
> (but I'd be interested if someone has seen this in the wild).
>
>>
>> Matt
>
> [1] http://beanvalidation.org/1.1/spec/#d0e2429
>
> --Gunnar
>
>>
>>>>
>>>> Let's make up an example.
>>>> 1. OrderService is a popular interface in the public domain for several
>>>> years.
>>>> 2. OrderService was created years before BeanValidation exists.
>>>
>>> I don't see a difference depending on when an interface was written. Imagine
>>> it would be allowed to add parameter constraints in implementations of
>>> java.util.List. Such an implementation would potentially break all code
>>> written against the List interface which is not aware of the additional
>>> constraints.
>>>
>>>> 3. OrderService constraints are documented in the javadoc. A custom
>>>> Exception type is thrown.
>>>> 4. A new vendor wishes to implement SimpleOrderService using Bean
>>>> Validation. Their plan is to capture ConstraintViolationException and
>>>> marshall it to the custom Exception type.
>>>
>>> The idea behind BV method validation is that some integration layer (e.g.
>>> CDI, AOP,based etc.) performs the constraint validation. So any
>>> ConstraintViolationException would not be reachable from within
>>> SimpleOrderService, as the call flow wouldn't get there.
>>>
>>>>
>>>> The new vendor will not be able make such a design under the current
>>>> spec. This is where the rub lies: assuming the lack of BeanValidation
>>>> means the validation constraints are specified. Is this sensible?
>>>> Actually, in this case, no constraints assumes all data is
>>>> automatically valid.
>>>
>>> I'm not sure whether I can follow.
>>>
>>>>
>>>> I believe it should be the opposite -- constraints are undefined.
>>>> Because a plethora of popular interfaces exist without BeanValidation,
>>>> the spec should give leniency to the situation.
>>>>
>>>> Would you consider a new annotation that prevents the strengthening or
>>>> loosening of validation? Perhaps you need something like this:
>>>>
>>>> @ValidationConstraintsComplete
>>>> public interface OrderService {
>>>>     void placeOrder(String customerCode, Item item, int quantity);
>>>> }
>>>
>>> At the moment I don't see that this would help. If OrderService was written
>>> without BV in mind, the annotation can't be added there. If it was written
>>> with BV in mind, why not placing any parameter constraints on the interface?
>>>
>>>> Thanks!
>>>> Paul
>>>
>>> --Gunnar
>>>
>>>> _______________________________________________
>>>> beanvalidation-dev mailing list
>>>> beanvalidation-dev at lists.jboss.org
>>>> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
>>>
>>>
>>> _______________________________________________
>>> beanvalidation-dev mailing list
>>> beanvalidation-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
>>>
>> _______________________________________________
>> beanvalidation-dev mailing list
>> beanvalidation-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev
> _______________________________________________
> beanvalidation-dev mailing list
> beanvalidation-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/beanvalidation-dev


More information about the beanvalidation-dev mailing list