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 -~----------~----~----~----~------~----~------~--~---
