Hi Baz,

 > First, there is a kind of awkward coupling between the validate()  
and save() functions. You will never want to save invalid data, so  
these functions will almost always be called in sequence

I don't think so - that's where "tell, don't ask" comes in.

If I want to save an article, I just call Results = article.save();  
It's the save method that knows to call the validate method first,  
encapsulating that. I guess you could be more expressive by renaming  
save() as validatethenSave(), but I don't find it a problem personally.

 > Consider a slightly more complex example where you had different  
degrees of saves(), like savePersonalDataOnly(), and therefore  
different degrees of validation()

Right, that is where the concept of roles or states comes in. Often  
you'll have role or state specific validation methods. You can either  
call the appropriate save method - e.g. saveBasicUserDetails() vs.  
saveFullUserProfile() both of which know to use their corresponding  
validation methods, or you use some kind of state within the object so  
that when you ask it to save() it's smart enough to know what state it  
is in and therefore what save and validate methods to call.

 > Another potential problem is the case of interacting with multiple  
BO's in one service function. What if saveUser() also needs to  
validate or save a second BO that the UserBO is not composed of?
 > There is no real solution to that except for more controller logic  
- which is bad.

If it's composed, just call User.save() in the controller and your ORM  
(in house or community) will take care of the composed validations/ 
transactions/etc - it's not that hard to come up with a set of  
patterns to implement this in a fairly useful general way.

 > Finally let's consider flex. The validation logic that you have in  
the controller will need to be duplicated.

Maybe we're misunderstanding each other. The validation logic is  
within the business objects (probably implemented using a composed  
validator). The same logic can be used for remote calls, just going  
through some kind of remote proxy to return the appropriate structure  
for the Results of the save() call.

Best Wishes,
Peter



On Jul 17, 2008, at 5:21 PM, Baz wrote:

> Mark and Peter, I use the exact same technique very often in my  
> applications because I find it very clean and simple, but it has  
> some serious drawbacks.
>
> First, there is a kind of awkward coupling between the validate()  
> and save() functions. You will never want to save invalid data, so  
> these functions will almost always be called in sequence. This  
> sequence, or relationship has to be known, documented and  
> remembered, which will only cause problems down the road. Consider a  
> slightly more complex example where you had different degrees of  
> saves(), like savePersonalDataOnly(), and therefore different  
> degrees of validation(). You will have to either know which  
> validate() functions to match to which saves() or look into the  
> internal workings of the save() to know which columns to validate()  
> in your generic validate() method - the first solution increases  
> coding complexity and is prone to errors, and the second violates  
> encapsulation. Your team will have to be heavily trained and up to  
> speed on which functions are related to which and therefore mistakes  
> will happen. Now on the flip-side, if you use the result object  
> technique, you can provide simple service functions such as  
> saveUser() and savePersonalData() that perform the appropriate  
> validation for you and return a nice neat result object with  
> everything that you need.
>
> Another potential problem is the case of interacting with multiple  
> BO's in one service function. What if saveUser() also needs to  
> validate or save a second BO that the UserBO is not composed of?  
> There is no real solution to that except for more controller logic -  
> which is bad.
>
> Another problem is what if your validation is slightly more complex  
> than pass/fail - for example let's say that in a certain case of  
> saving(), you want to default one of the invalid values to some  
> other value, rather than error out the save(). Your options would be  
> to add more controller logic, or make to make yet another coupled  
> special validation() function that also changes the values of your  
> BO - awkward.
>
> Finally let's consider flex. The validation logic that you have in  
> the controller will need to be duplicated. So rather than simply  
> invoking saveUser() and getting back a structure that has the  
> validation errors and the business object, you will have to send  
> two, separate, nearly identical and potentially heavy requests to  
> your service to first validate() then save(). What happens if your  
> consumer forgets to validate? Basically there is no real choice but  
> to combine the validate() and save() into one neat function and that  
> requires a result object. Amazon, google and yahoo work like that.
>
> Just some thoughts,
> Baz
>
>
> On Thu, Jul 17, 2008 at 6:10 AM, Peter Bell <[EMAIL PROTECTED]>  
> wrote:
>
> Ahh, makes perfect sense. Sounds like we do things pretty similarly.
>
> On Jul 17, 2008, at 8:58 AM, Mark Mandel wrote:
>
> >
> > No, I wouldn't throw an exception for a validation error.  That  
> wasn't
> > the point I was making.
> >
> > The point I was making was that it reminded me of days in which  
> error
> > handling was done by returning error codes.  It was cumbersome, and
> > fragile to handle. The better way to handle major errors is through
> > exceptions, which is what they were built for, rather than having to
> > remember error code 19223.2, you can catch a meaningful exception.
> >
> > In this sort of instance, if something goes horribly wrong, yes, I
> > would throw an exception - that is what it is there fore.  I feel  
> like
> > returning a result object for something like that goes against  
> common
> > development practices, and returns us to error codes.
> >
> > For validation type erroring, I have no issue with some sort of
> > validation error collection, be it an object or a struct being  
> coupled
> > to the BO's validation, and the view, I feel funny about that  
> coupling
> > being extended to the service as well.
> >
> > I would ask the BO if it is valid in the controller, because if it  
> is
> > valid, is part of the controller logic.  If it is valid, it will
> > probably go to one view, and if it isn't, it would go to another.  I
> > feel like this shouldn't be moved to the service to handle.
> >
> > Brian, you have talked about having 'dumb' service objects.  Isn't
> > moving this validation logic into your service a move away from  
> that?
> >
> > Mark
> >
> > On Thu, Jul 17, 2008 at 5:40 PM, Alan Livie
> > <[EMAIL PROTECTED]> wrote:
> >>
> >> Mark, I have my validation in BO's too. Say in your User BO in
> >> validate() method you find username is less than 6 chars (which it
> >> shouldn't be as a business rule dictates).
> >>
> >> Are you saying you'll throw an exception rather than return the
> >> info in some sort of error struct / object so your form can handle
> >> it?
> >>
> >> Alan
> >> ________________________________________
> >> From: [email protected] [EMAIL PROTECTED] On Behalf
> >> Of Mark Mandel [EMAIL PROTECTED]
> >> Sent: 17 July 2008 05:22
> >> To: [email protected]
> >> Subject: [CFCDEV] Re: Service Layer X OO Architecture
> >>
> >> Honestly, the result object approach feels a little funny to me...
> >> but
> >> I do see where the reasoning comes from.
> >>
> >> Maybe because it reminds me too much of returning error codes  
> (1234),
> >> rather than throwing exceptions.
> >>
> >> And maybe because it couples your entire model to this result  
> object.
> >>
> >> I don't have validation coming from my service save() methods, I  
> have
> >> it coming from my BO's.  I don't think that its the Service's
> >> responsibility to handle validation.  Maybe that's just me tho.
> >>
> >> Mark
> >>
> >> On Thu, Jul 17, 2008 at 1:32 PM, Alan Livie
> >> <[EMAIL PROTECTED]> wrote:
> >>>
> >>> Thanks for this Brian.
> >>>
> >>> I'm just returning an array of structs with properties that map to
> >>> form fields, message, error type etc. Makes a lot of sense to wrap
> >>> this in a nice Result object.
> >>>
> >>> I'm just about to refactor the bean validation code so this was a
> >>> timely discussion :-)
> >>>
> >>>
> >>> Alan
> >>>
> >>> ________________________________________
> >>> From: [email protected] [EMAIL PROTECTED] On Behalf
> >>> Of Brian Kotek [EMAIL PROTECTED]
> >>> Sent: 16 July 2008 21:32
> >>> To: [email protected]
> >>> Subject: [CFCDEV] Re: Service Layer X OO Architecture
> >>>
> >>> Yep that's pretty much it....things like isSuccess(),
> >>> setSuccess(), hasErrors(), getErrors(), etc.
> >>>
> >>> On Wed, Jul 16, 2008 at 4:17 PM, Baz <[EMAIL PROTECTED]<mailto:[EMAIL 
> >>> PROTECTED]
> >>> >> wrote:
> >>> I think Brian's result object is a generic one that can be re-used
> >>> with any change operation. Something along the lines of:
> >>>
> >>> *   Status (i.e. Success/Fail)
> >>> *   StatusCode (i.e. User.Validation.Error)
> >>> *   Message (i.e. There were some validation errors in the user
> >>> object)
> >>> *   Payload (i.e. contains a structure of validation errors, or a
> >>> proper business object - depending on the whether the operation
> >>> was success or fail)
> >>>
> >>> The view would check the status of the result object to see how to
> >>> handle the payload.
> >>>
> >>> Correct me if I am wrong Brian...
> >>>
> >>> Baz
> >>>
> >>>
> >>>
> >>> On Wed, Jul 16, 2008 at 1:09 PM, Ronan Lucio  
> <[EMAIL PROTECTED]<mailto:[EMAIL PROTECTED]
> >>> >> wrote:
> >>>
> >>> Brian,
> >>>
> >>> Brian Kotek escreveu:
> >>>> No Result is only returned during change operations, i.e.  
> saving a
> >>>> User. For list operations I just return the query, because there
> >>>> can
> >>>> be no validation failures for simply *getting* something.  
> Hopefully
> >>>> that makes sense.
> >>>
> >>> Yeap. That's clear.
> >>>
> >>> Thank you once again,
> >>> Ronan
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>
> >>>>
> >>>
> >>
> >>
> >>
> >> --
> >> E: [EMAIL PROTECTED]
> >> W: www.compoundtheory.com
> >>
> >>
> >>
> >>>
> >>
> >
> >
> >
> > --
> > E: [EMAIL PROTECTED]
> > W: www.compoundtheory.com
> >
> > >
>
>
>
>
>
> >


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"CFCDev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/cfcdev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to