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