Re: [Figleaf-developer] Validation and PropertyDescriptor
Status: Alpha
Brought to you by:
steckman
|
From: <sam...@ma...> - 2004-07-08 12:45:10
|
> I think we need validation at two levels. First the individual
> properties, and second on the whole object.
Agreed (see later).
<snip>
> >You are now poluting property accesing methods with figleaf dependant code.
> >Developers now need to explicitly invoke validation for all their set
> methods,
> >and have to do so in a way that ties their object to figleaf. I prefer to
> deal
> >with validation at the point we describe the properties (or general
> 'action'
> >methods) to the figleaf system, that is in the PropertyDescriptor.
> >
> Polluting was intentional on my part, as I envision this as one primary
> way to write classes for the system if you don't care about portability.
> It is potentially the most straightforward and powerful way to write
> behaviorially complete objects: but they get contaminated with Figleaf
> APIs.
My approach (outlined below) moves the requirement for validation into methods
defined in Informative, rather than in the domain object's property methods -
the coupling is then only present in those areas that get invoked directly by
figleaf itself.
> >>Case B: The implementation you suggest:
> >>
> >>public class MyInformative implements Informative{
> >> public void setPropertyA(Object value){...}
> >> public Object getPropertyA(){...}
> >>
> >> PropertyDescriptor[] getPropertyDesctiptors(){
> >> PropertyDescriptor[] pds=new PropertyDescriptor[1];
> >> pds[0]=new MyInformativePropertyDescriptor(
> >>
> >>getMethod("getPropertyA", null).
> >>
> >>getMethod("setPropertyA", new Class[]{Object.class}),
> >>
> >>"Property A",
> >>
> >>"Description of Property A");
> >> return pds;
> >> }
<snip>
> >
> >I wouldn't call methods like that - I'd call them directly on the object to
> gain
> >compile-time checking and simpler looking code.
> >
> How would you implement a PropertyDescriptor to call the method directly
> without needing one PropertyDescriptor class for each individual property?
Well, either you do have one PropertyDescriptor per-object instance per-property
(which isn't a huge overhead), or you keep the PropertyDescriptor as being
per-class and have:
Object read(Object objectToReadFrom)
void write(Object objectToWriteTo, Object newVal)
> >>In the first case I used an object that's defined elsewhere so that
> >>makes the code look shorter but in reality it probably won't be. I
> >>prefer the listener approach of Case A because I think it has more
> >>flexibility and is a standard pattern so users will understand the API
> >>right away.
> >But users have to define validation logic and invoke it themselves - my
> approach
> >just has them define validation rules, and everything else is handled for
> them,
> >making thw system simpler for them to use.
> >
> I was thinking that we could proxy the property methods so the
> validation logic could be implemented elsewhere. I think the same
> results can be had with either approach.
But your example has the user defining validation in the getters/setters they
write. We might choose to create proxies and insert validation code there
(althought I don't think we need to - again see below), although I accept I may
of misunderstood your ealier example.
> >You then require that figleaf has to proxy method calls. You also expose
> >implementation detail. The UI then has to invoke the method itself, catch
> the
> >exceptions etc. What about remoting? What if invoking the property actually
> >invokes a webservices call? Now we have to create a fake Method which we
> can't
> >easily do (Method is a final class).
> Remoting is a whole can of worms. Any method should be taggable as
> "remote", which means it is executed on the server object, not on the
> remote side. Again it requires proxies. I don't see a way around that in
> any case. One advantage with using a Method, Figleaf itself can alter
> the method returned by the PropertyDescriptor to point to a Figleaf
> implemented interceptor.
However that is not an argument for exposing Method objects directly from a
PropertyDescriptor.
> >>I also prefer using the Methods because I
> >>think they are more flexible. They can reference any method in any class
> >>without having to implement an extra class just for redirection.
> >
> >I don't agree really - where would you need an object to expose the method
> of
> >another class?
> >
> If PropertyDescriptor is a separate class, then the Method it refers to
> is in a different object.
I accept that, but my approach still handles that and doesn't expose the method
>
> >>If a class doesn't implement Informative itself, then everything needs
> >>to be handled by the Proxy in either case.
> >
> >Which I already do - exposing the method is no simpler than directly
> invoking it
> >inside the property, I've had proxies working in both ways.
> >
>
> That's why I think we might be splitting hairs. Probably everything can
> be done either way. It's not even clear to me one implementation is
> better than the other at this point.
For me what it comes down to is this - I cannot see and advantage to exposing a
Method object from the PropertyDescriptor class (be it a class or instance
specific object), and can in fact see several disadvantages to it. I'd rather
resolve this now rather than later, as the longer we leave it the more work is
involved in changing it.
>
> >In reality validation at a property-by-property basis is simple from
> developer
> >terms, but is often not good enough, for example what if a customer bean has
> 3
> >telephone number fields, and one of them has to be non-null? Neither of our
> >approaches work, as we are still validating on a property-by-property basis
> -
> >even a final-mile validation check on the object as a whole happens to late,
> as
> >by then the object might be in an invalid state.
> >
> If the object is in an invalid state that is OK. The important thing is
> to not persist data that is invalid. If the object is deemed to be
> invalid, it can be reloaded.
>
> >I say lets rethink the problem. We need to not only validate a single
> property
> >change, but the validaity of a set of changes on an object. Lets add the
> >following method to Informative:
> >
> >boolean commitChanges(ChangeSet set)
> >
> >Lets keep your add and remove validation listeners on Informative. A
> ChangeSet
> >is a set of changes on an object, and now becomes the only mechanism by
> which
> >figleaf writes changes to an object - it consists of a series of property
> change
> >messages. I'll knock up a prototype in the next day or so and see if its a
> >workable idea.
> >
> This gets back to whether the object is persisted after each property
> set call, or only after a "save event" occurs (clicking a save button,
> for example). The latter is a simpler case to handle, because you can
> call all the property setters, and then before you want to save the
> object call a single validate() method. The object then validates
> itself. A proxy can intercept the call to validate() and redirect it to
> another object that has the validation logic if required.
>
> I don't see a problem with the object transiently becoming invalid. As
> long as it's not saved or used for anything while it's invalid. It is
> essentially a data holder for input forms.
If we edit an object using a changeSet which transparently handles validation,
an object will never become invalid. It also lets us handle validation of a
group of properties, and still supports the user just defining simple validation
rules if required. If this is the only way for figleaf to change properties, we
also do not need to worry about proxying the properties. A ChangeSet can also be
easily sent over the wire if required. My example using ChangeSets is coming on
nicely - hopefully once I can show it working it will better show the advantages
of the approach.
sam
http://www.magpiebrain.com/
|