Re: Object validation

From: Fabricio Voznika (fabricio.voznik..artmouth.EDU)
Date: Tue Sep 09 2003 - 10:25:35 EDT

  • Next message: Mike Kienenberger: "Re: CVS"

    Andrus Adamchik wrote:

    > Hi Fabricio,
    >
    > On Monday, September 8, 2003, at 12:27 PM, Fabricio Voznika wrote:
    >
    >> There is a problem with the 3 methods solution. Pretty close to
    >> 99% of the times, exactly the same validation will be performed when
    >> the object is created and updated. Having 3 method will create the
    >> need to add another method with common validation and call it from
    >> validateForInsert and validateForUpdate (or make one call the other).
    >> There could be 2 methods (validateForInsertAndUpdate and
    >> validateForDelete), but I don't like it because it mixes both solutions.
    >
    >
    > As I see it, the exception should not be thrown till the end of all
    > validation to avoid unneeded try/catch everywhere in the code...So we
    > need some API for easy chaining of validation info... Here is how I
    > see it work (with a common method in addition to the 3 state-specific
    > methods).
    >
    > DataObject API:
    > public void validateForSave(ValidationResult); // common validation
    > public void validateForInsert(ValidationResult); // noop, for
    > subclassing only
    > public void validateForUpdate(ValidationResult); // noop, for
    > subclassing only
    > public void validateForDelete(ValidationResult); // noop, for
    > subclassing only

    I'm still for only 1 method to avoid bloating the interface too much.
    But anyway... :-)

    >
    >
    > flow of events in DataContext on commit:
    >
    > ValidationResult validation = new ValidationResult();
    > while('has more objects") {
    > nextDataObject. validateForSave(validation);
    >
    > // check persistence state and call appropriate method
    > nextDataObject. validateForXXX(validation);
    > }
    >
    > // if validation failed
    > throw new ValidationException(validation);
    >
    >
    > Notes on the API above:
    >
    > 1. validateForXXX all take a shared ValidationResult and throw no
    > exceptions by themselves
    > 2. All methods but validateForSave do nothing and exist for
    > subclassing only

    Yeap, that's what I had in mind. What would
    CayenneDataObject.validateForSave do?

    >
    >> * The error message:
    >> Usually a String with the error message will do it. Is there a need
    >> for more complicated messages, with formatting (like font properties,
    >> etc)? One could say it's the presentation layer problem, but the
    >> presentation layer might not have enough information to show an
    >> important word in bold. This is very implementation dependent
    >
    >
    > I can't think of any extra info to capture. You got it all. Though I'd
    > say such things like formatting shouldn't be a part of this package
    > (also since we have failure codes, a caller can always redefine
    > messages). Things like localization might be a nice addition (we may
    > ignore it initially I guess, since the rest of the exceptions are not
    > localized either).
    >
    > Few notes on the naming:
    >
    >> Error : Interface
    >
    >
    > I suggest something other than Error for the interface name (say
    > ValidationFailure). Error is to close to "java.lang.Error" (
    > especially bad since "java.lang" is imported by default).

    Agreed.

    >
    >
    >> ----
    >> getErrorString() : String // Shows error in a nice string format
    >
    >
    > How about "getDescription"? We can make it localizable at some
    > point......

    Agreed.

    >
    >
    >> getError() : Object // Error object. Usually a String but it could
    >> be anything
    >
    >
    > Maybe we can call it something like "getCode()" and define a few codes
    > for known errors (NULL_NOT_ALLOWED, MAX_LENGTH_EXCEEDED, etc.). Users
    > can define their own as well.

    I got a bit confused here. My idea was to create ValidationFailure
    interface with a method getDescription to be used in log messages and
    where strings are perfectly fine. The provided implementation
    FooValidationFailure would have an 'error' which is a string and just
    display it when getDescription is called. If somebody else needs
    something more complicated, they could create a
    ComplicatedValidationFailure where 'error' is a key for a resource
    bundle and getDescription would make a look up. If somebody else needed
    a FancyValidationFailure, 'error' could be a FancyError object that
    would do a bunch of fancy things :-) and getDescription would be used
    for logging and debug only. And it could also be a code, but we're not
    restricting it.

    >
    >
    >> ValidationResult : Class
    >> ----
    >> addError(Error)
    >> addError(Object, String, Object) // Create default error and call
    >> addError(Error)
    >> getErrors() : List
    >> getErrorsFor(Object) : List
    >> getErrorsFor(Object, Property) : List
    >> hasErrors() : boolean
    >> hasErrorsFor(Object) : boolean
    >> hasErrorsFor(Object, Property) : boolean
    >
    >
    > s/Error/Failure/g - to be consistent with the interface above.

    Agreed.

    >
    >
    >
    >
    >> ValidationException : Exception
    >> ----
    >> getValidationResult() : ValidationResult
    >
    >
    > If the call to validation is plugged in to commitChanges (I assume it
    > will be), then I suggest extending a RuntimeException, so that we do
    > not have to change the existing DataContext paradigms.

    Cool! I've got most of it already implemented in my application. I'll
    just move it to Cayenne and make a few adjustments.

    >
    >
    > Andrus
    >



    This archive was generated by hypermail 2.0.0 : Tue Sep 09 2003 - 10:24:49 EDT