How about:
If (Order.isValid())
{
Order.save();
}
Else
{
Screen = OrderForm;
Data = Order;
};
First method could both return a boolean as to whether the order is valid
(which would only be true if all of the composed objects were also valid)
and would also set all of the necessary error messages within the Order (and
the composed beans) so you could just pass the error (containing both the
data and the associated error messages) back to (say) a form for displaying
the issues.
I think it¹d be straightforward to have a generalizable solution to this
which would use relationship metadata and introspection to get the order to
automatically ask all composed beans and properties whether they were valid.
I see something along the lines of:
Valid = 1
For each property:
If NOT THIS.isValid(PropertyName)
Valid = 0
And the isValid() method would call the appropriate type of validation
depending on the data type of the property. If the property was a composed
bean, it¹d just call that beans general isValid() method. Then you just need
a errorMessage(PropertyName) method which would display the error message
for each property (it¹d be null unless the property was invalid). Details
beyond that would depend on relationship between validations and properties
and whether you just look for one error per property or catch them all (i.e.
could a single property have multiple error messages at any one time).
I don¹t see any need for either service or controller to do anything here
that seems a little procedural to me.
Best Wishes,
Peter
On 1/14/08 3:21 PM, "Baz" <[EMAIL PROTECTED]> wrote:
> Hey Peter, so you are doing the equivalent of a separate validate() and save()
> right on the bean itself, which, in this example, doesn't make too big a
> difference. But some problems can arise if we look at a more complex yet
> realistic use-case.
>
> Let's say a user submits an order and we need to:
> * partially update the user (perhaps they changed a communication preference
> during the order process)
> * create an order
> * create a billing address
> *
> * update an independent statistics table that executive management uses
> There are several objects involved here - possible composed, possibly not, it
> doesn't really matter - and each would probably have a layer of validation.
> One way of performing the save is to have one main function saveOrder()
> (located in some service) that goes about creating, validating and saving each
> object then aggregating the error messages into one final ErrorCollection.
> This provides a nice, clean, simple interface for a complex process. But then
> what do you return from that function - just the ErrorCollection? What about
> the objects at hand, such as the newly created billing address, how do we get
> references to those? Perhaps we can reload everything on a subsequent
> broadcast, but using which OrderID?
>
> On the flip side we can break apart the jumbo method and start calling smaller
> methods independently each of them returning appropriate data that we need
> back to the controller. But of course, the more you do that, the smarter your
> controller is getting and the less re-usable your code.
>
> So the tighter and cleaner you make your service functions, the more awkward
> or problematic the returntypes. And the more flexible or atomic you make the
> service the more intelligence your controller has to hold. In the
> aformentioned case it seems that there is no level of real cleanliness.
>
> Thoughts?
> Baz
>
>
>
>
> On Jan 13, 2008 6:20 PM, Peter Bell <[EMAIL PROTECTED]> wrote:
>> Hi Baz,
>>
>> I can't think of a case where I'd be saving 10 independent objects. In my
>> experience, I'm either saving one object, I'm saving a collection of objects
>> of the same type (e.g. To update the price on 8 different products using a
>> single form or grid) or I'm saving an object which may have composed or
>> associated objects that also require saving.
>>
>> My real code assumes a collection of n-objects of the same type, and a single
>> object is just a special case where n=1, so imagine the code I sent you
>> within a cfloop and you'll get the idea. For composed objects I let my ORM do
>> the lifting. If I really had a use case where I had to save multiple
>> completely independent objects (that don't have any association or
>> composition relationships) , I'd probably create an appropriate service class
>> for handling that and would write a method within it that would orchestrate
>> the independent method calls to the various object services. To date that use
>> case has never arisen in the projects I've built.
>>
>> As for returning errors, I've been playing with a number of different
>> approaches since obviously you want both the bean data and the error
>> messages. I'm moving towards something like:
>>
>> If User.isValid()
>> User.save()
>> /If
>>
>> And with a User.getInvalidFieldList() and/or a User.isValid(PropertyName) and
>> User.errorMessage(PropertyName). Also, as this is an IBO, it can contain a
>> collection of users, so I can loop through them and store validation status
>> and error messages for each, making this equally easy to work with for one
>> object or for a collection of objects as the single is just the special case
>> of n-objects where n=1. With this approach, I just pass the bean around and
>> it contains both the data the user tried to enter and the associated errors.
>>
>> Right now I do something a little different each time I touch validation so I
>> can get a feel for the different approaches and decide what to standardize
>> on.
>>
>> Best Wishes,
>> Peter
>>
>>
>>
>> On 1/13/08 8:40 PM, "Baz" <[EMAIL PROTECTED]> wrote:
>>
>>> If the form submission was a lot more complex and required the saving of,
>>> say, 10 different objects. Would you still interact with each object
>>> individually in the controller, or move all of that to a service function
>>> that orchestrates the interactions? If you would choose the latter, and
>>> given that in the another post you said that you would handle the creation
>>> of objects in the service rather than the controller, you are then faced
>>> with the issue of how to return the bean(s) and/or errorcollection from the
>>> save() method...
>>>
>>> You know?
>>>
>>> Baz
>>>
>>>
>>> On Jan 13, 2008 5:15 PM, Baz <[EMAIL PROTECTED]> wrote:
>>>> Hey Peter,
>>>>
>>>> Looks very tidy! So I guess the validation occurs in the save() method.
>>>> What would that method return, True/False? And then later on you would
>>>> evaluate the result to see whether to retrieve the error collection?
>>>>
>>>> Cheers,
>>>> Baz
>>>>
>>>>
>>>> On Jan 13, 2008 5:08 PM, Peter Bell <[EMAIL PROTECTED]
>>>> <mailto:[EMAIL PROTECTED]> > wrote:
>>>>> Hi Baz,
>>>>>
>>>>> Why not just:
>>>>>
>>>>> var Result = ";
>>>>> var User = UserService.new(User);
>>>>> User.LoadStruct(form);
>>>>> Result = User.save();
>>>>> AddResult(Result);
>>>>>
>>>>> I have some generic code so I don't have to type this for every controller
>>>>> that handles a form, but this is generally what I do.
>>>>>
>>>>> Best Wishes,
>>>>> Peter
>>>>>
>>>>>
>>>>>
>>>>> On 1/13/08 8:00 PM, "Baz" <[EMAIL PROTECTED]> wrote:
>>>>>
>>>>>> Another design choice I see go both ways is whether to perform validation
>>>>>> in the save() method or to call each method separately. Example
>>>>>> controller functions could be (pseudo code):
>>>>>>
>>>>>> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
>>>>>> - - - - - - - -
>>>>>>
>>>>>> SEPARATE SAVE & VALIDATE
>>>>>> var UserService=getBean('UserService');
>>>>>> var FormVariables=getAllValues();
>>>>>>
>>>>>> var ValidationResult='';
>>>>>> var SaveResult='';
>>>>>>
>>>>>> set ValidationResult=UserService.validate(FormVariables); // returns an
>>>>>> error collection object
>>>>>>
>>>>>> if ValidationResult.hasErrors()
>>>>>> setValue('ReturnObject', ValidationResult);
>>>>>> addResult('Fail');
>>>>>> else
>>>>>> set SaveResult=UserService.save (FormVariables); // returns a
>>>>>> populated user bean object
>>>>>> setValue('ReturnObject', SaveResult);
>>>>>> addResult('Success');
>>>>>> end
>>>>>>
>>>>>> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
>>>>>> - - - - - - - -
>>>>>>
>>>>>> COMBINED SAVE & VALIDATE V1.0
>>>>>> var UserService=getBean('UserService');
>>>>>> var FormVariables=getAllValues();
>>>>>>
>>>>>> var UserBean=UserService.newUser();
>>>>>> var SaveResult='';
>>>>>>
>>>>>> set UserBean.setMemento(FormValues);
>>>>>> set SaveResult=UserService.save(UserBean); // returns true if saved
>>>>>> successfully, or false if validation errors exist (the error collection
>>>>>> would be saved in the bean itself for retrieval later)
>>>>>>
>>>>>> setValue('ReturnObject', UserBean);
>>>>>>
>>>>>> if SaveResult is True
>>>>>> addResult('Success');
>>>>>> else
>>>>>> addResult('Fail');
>>>>>> end
>>>>>>
>>>>>> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
>>>>>> - - - - - - - -
>>>>>>
>>>>>> COMBINED SAVE & VALIDATE V2.0
>>>>>> var UserService=getBean('UserService');
>>>>>> var FormVariables=getAllValues();
>>>>>>
>>>>>> var SaveResult=UserService.save(FormVariables); // returns a complex
>>>>>> result object with properties: STATUS ('Success', ValidationError') and
>>>>>> PAYLOAD (that contains either a UserBean or ErrorCollection depending on
>>>>>> the STATUS)
>>>>>>
>>>>>> setValue('ReturnObject ', SaveResult.getPayload() );
>>>>>>
>>>>>> if SaveResult.getStatus() is 'Success'
>>>>>> addResult('Success');
>>>>>>
>>>>>> else SaveResult.getStatus() is 'Validation'
>>>>>> addResult('Fail');
>>>>>> end
>>>>>>
>>>>>> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
>>>>>> - - - - - - - -
>>>>>>
>>>>>> CONS OF KEEPING THEM SEPARATE:
>>>>>> * Controller has to be smarter, which is bad, because there will be more
>>>>>> code duplication if you change the presentation layer to flex, for
>>>>>> example.
>>>>>> * Function coupling: Coders have to "remember" to always validate()
>>>>>> before saving() - an unnecessary additional complexity (unless, of
>>>>>> course, there are times in your app where you save() by defining all
>>>>>> values yourself (thereby knowing the values are correct) rather than from
>>>>>> user input)
>>>>>> CONS OF COMBINING THEM COMBINED
>>>>>> * Requires complex and unnatural result handling (either by affecting the
>>>>>> bean by reference, or using a special RESULT object)
>>>>>>
>>>>>> Cheers,
>>>>>> Baz
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>>>
>>>
>>
>>
>>
>
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---