Unless there is an error. The only issue I have with returning an error
collection is that then you have to find the data the user entered either by
looking at the form/url scope or by passing both the Order and the Error and
merging them if you want to display error messages next to any invalid
fields. That¹s why a part of me is tempted just to load any errors into the
order object and maybe do something like:

If Order.isValid()
  Order.save()
  location(listscreen)
Else
  view(formscreen) 

The nice thing about this is that I only have to pass the order object to
the form screen if there is an error to display the form, the initially
entered data and any errors that were found, so it¹s nicely encapsulated. I
could even be really smart and allow my Order.field(FieldName) to display
both the field and any errors for the field (using a project specific custom
view decorator for the order object to handle the display stuff) making any
forms with a standard layout as simple as:

<cfloop list=²#Order.metaGet(³FieldNameList²)#² index=²FieldName²>
#Order.title(FieldName)#<br />
#Order.field(FieldName)#<br /><br />
</cfloop>

Which would display both the title (which could also look internally and
make itself red, let¹s say,  if there was an error for that fieldname) and
the field along with any error text . . .

Still pondering and trying different things though . . .

Best Wishes,
Peter



On 1/15/08 4:00 PM, "Brian Kotek" <[EMAIL PROTECTED]> wrote:

> Well typically in an HTML application you would perform a redirect so that the
> data doesn't get saved twice if the user hits reload. Which means the next
> request would grab the user.
> 
> On Jan 15, 2008 3:59 PM, Paul Marcotte < [EMAIL PROTECTED]> wrote:
>> ack!  hit send before completing that thought!
>> 
>> 
>> user = getTransfer.new("user.User");
>> variables.beaner.populate(user,userData);
>> result = createResult();
>> result.setErrors(user.validate("save))  // validate() returns an error
>> collection struct
>> 
>> If (result.getSuccess()) { // returns true is StructCount(errors) eq 0
>>   getTransfer.save(user);
>>   result.setPayload(getUser(someUniqueIdentifier))
>> }
>> 
>> return result;
>> 
>> Client code would be
>> 
>> result = UserService.save(userData);
>> 
>> If (result.getSuccess) {
>>  // do somethings with user
>> } else {
>>  //do something with error collection
>> }
>> 
>> 
>> It would be preferable to me to not have to query the UserService for the
>> user I just saved.
>> 
>> 
>> 
>> On Jan 15, 2008 12:53 PM, Paul Marcotte <[EMAIL PROTECTED]> wrote:
>>> Baz, you're my brother from another mother.
>>> 
>>> I want to implement a Result object as well, but I'd like it to have a
>>> "Payload", or some other implementation that reduces an operation to a
>>> single service call.  Here's an example of how the save() method would roll
>>> in my UserService (using transfer).
>>> 
>>> user = getTransfer.new("user.User");
>>> variables.beaner.populate(user,userData);
>>> result = createResult();
>>> result.setErrors(user.validate("save))  // validate() returns an error
>>> collection struct
>>> 
>>> if (result.getSuccess()) { // returns true is StructCount(errors) eq
>>> 0getTransfer.save(user);
>>> 
>>> }
>>> else {
>>> result.addErrorMessages (user.getErrorMessages());
>>> result.setOriginalData(userData);
>>> }
>>> return result;
>>> 
>>> On Jan 15, 2008 12:16 PM, Baz < [EMAIL PROTECTED]
>>> <mailto:[EMAIL PROTECTED]> > wrote:
>>>> This is exactly where I wanted the conversation to go!
>>>> 
>>>> So Peter - if you did have a flex app, and you wanted to save a user what
>>>> would you do? At minimum you would have to pass in a struct of user values
>>>> to some webservice - but then what? Would you validate in that method? Or
>>>> would you have your flex controller first call a validate() webservice
>>>> method, then depending on the results the save() webservice method?
>>>> 
>>>> Brian I see you handle the inherent problem by having a custom RESULT
>>>> structure that you return - I understand why you do this - cuz I do it too
>>>> - but doesn't it kinda suck? When do you stop using it? At one point I was
>>>> thinking that I should use it as a return for any service function. The
>>>> object would have properties like: Status, MessageCode, Payload. This would
>>>> let me handle almost any cases and keep a standard interface to interact
>>>> with. 
>>>> 
>>>> Baz
>>>> 
>>>> 
>>>> 
>>>> On Jan 15, 2008 11:15 AM, Peter Bell <[EMAIL PROTECTED]
>>>> <mailto:[EMAIL PROTECTED]> > wrote:
>>>>> Hi Brian,
>>>>> 
>>>>> I'll disagree with you here. The calling code has to know three things:
>>>>> * How to pass information to the service in the format it wants
>>>>> * How to tell whether the save succeeded
>>>>> * How to pass any error messages in a way the display will want to see
>>>>> them (actually, it'll probably just be a conduit for the information, so
>>>>> it is more likely the view will have to know this).
>>>>> 
>>>>> It needs to know how to pass well formed data to the service otherwise the
>>>>> save won't work. It needs to tell whether the save succeeded as otherwise
>>>>> it won't be able to make the controller decision to say whether to
>>>>> cflocation to another screen or to redisplay the form (or whatever
>>>>> approach you're using), and it needs to pass the errors along in a way the
>>>>> view can understand as otherwise the view won't be able to display the
>>>>> correct error messages.
>>>>> 
>>>>> So, whether you make it:
>>>>> If UserService.isValid()
>>>>>     UserService.save();
>>>>>     location("UserList");
>>>>> Else
>>>>>     Display Form
>>>>> 
>>>>> OR
>>>>> 
>>>>> Success = UserService.Save()
>>>>> If Success 
>>>>>   location("UserList")
>>>>> Else
>>>>>     DisplayForm
>>>>> 
>>>>> (o rmore likely, a variant where "Success" is really ErrorCollection and
>>>>> you test whether ErrorCollection has any members, or is ErrorBean and test
>>>>> whether ErrorBean.hasErrors())
>>>>> 
>>>>> In any of these cases you are performing both a command and a query. The
>>>>> command is to save the data and the query is whether it was saved
>>>>> successfully. Nothing wrong with turning that into a single mixed method
>>>>> call (some purists might say you should keep commands and queries
>>>>> separated, but I'm not that picky), but it isn't reducing the amount of
>>>>> information required or the knowledge of the API. You're just doing the
>>>>> command and the query in a single line so it isn't making the controller
>>>>> any dumber ­ just more concise.
>>>>> 
>>>>> Best Wishes,
>>>>> Peter
>>>>> 
>>>>> 
>>>>> 
>>>>> On 1/15/08 12:56 PM, "Brian Kotek" <[EMAIL PROTECTED]> wrote:
>>>>> 
>>>>>> 
>>>>>> 
>>>>>> On Jan 15, 2008 11:57 AM, Adam Haskell <[EMAIL PROTECTED]> wrote:
>>>>>>> I'm much more comfortable with doing 2 calls in my service,
>>>>>>> model.validate(); model.save(), instead of Model.save() and have the
>>>>>>> save do the validation. Doing model.save makes my service not much more
>>>>>>> a facade which isn't what I want. Additionally in our environment we
>>>>>>> have multiple validaters, some of which should not, in my opinion, be
>>>>>>> part of the domain's concern. An example of this would be Enterprise vs
>>>>>>> domain specific validation. Something like name is 35 characters and
>>>>>>> does not have cross sit scripting is Enterprise concerns and part of the
>>>>>>> validation across all applications irregardless of domain. Where as
>>>>>>> address must be in the US is domain specific to Contest entries. The
>>>>>>> converse is true too though if you put too much in the service layer
>>>>>>> your domain model becomes anemic.
>>>>>> 
>>>>>> See, I disagree here. I don't think it should be the job of the calling
>>>>>> code to know that this is a two step process. I would call
>>>>>> myService.save(someData) and the validation would happen inside the
>>>>>> model. If you have some higher-level validation that would take place
>>>>>> outside of the actual business object, I would still do that in the
>>>>>> service; that is its job. I would do that validation inside the service,
>>>>>> or more probably I would build it into the Validators, which means the
>>>>>> Validator might internally be leveraging several specific Validators to
>>>>>> do it's job. So I might do
>>>>>> 
>>>>>> myService.save(userData);
>>>>>> 
>>>>>> and inside the service I might do:
>>>>>> 
>>>>>> user = createUser(userData);
>>>>>> result = createResult();
>>>>>> if (user.isValid()) {
>>>>>> result.setSuccess(true);
>>>>>> }
>>>>>> else {
>>>>>> result.addErrorMessages (user.getErrorMessages());
>>>>>> result.setOriginalData(userData);
>>>>>> }
>>>>>> return result;
>>>>>> 
>>>>>> 
>>>>>>  
>>>>>>> 
>>>>>>> Adam Haskell
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> On Jan 15, 2008 8:31 AM, Alan Livie < [EMAIL PROTECTED]>
>>>>>>> wrote:

Good anecdote but I am confused!

You said 'in this case the
Service should be earning it's keep and making sure the documents are
valid
and ready for it's client, the model. '

Are you sure about this? Shouldn't the model be responsible for making
sure things are valid - ie look after itself.

I see the service more as a smart api that delegates to the model for
all the business logic and also can provide 'application-specific'
functionality like logging, email notifications etc

But maybe I'm misunderstanding it or taking the anecdote too
seriously! It's more accurate than the MVC song at least :-)

Alan

On Jan 15, 12:47 pm, "Adam Haskell" <[EMAIL PROTECTED]> wrote:
> I've used this anecdote before, and I think it is amusing so I'll use it
> again.  The way I think about it is The model and View are going through a
> divorce and the controller and service are the lawyers. Now thinking about
> it in these terms, would it make sense for the Controller (the View's
> lawyer) to be taking care of the Model's Affairs, in this case validating
> documents for the model? That doesn't make much sense, in this case the
> Service should be earning it's keep and making sure the documents are valid
> and ready for it's client, the model. Sure the Controller might throw in
> some JS for the View to do some preliminary checking so the always bitchy,
> soon-to-be ex, spouse won't complain but it really is the spouses lawyer's
> duty to inform the spouse that the documents are valid, or  return the
> documents to some one telling them to try again, no deal. That being said
> Brian's earlier statement about calling something from Flex really has
> helped me clear up what should go where. Anecdotes provide a means to
> getting over the hump but once you are over the hump real life programming
> drives the point home and Brian's example/thought process is spot on.
>
> Adam Haskell
>
> On Jan 14, 2008 11:53 PM, Brian Kotek <[EMAIL PROTECTED]> wrote:
>
> > It depends on what you mean by "appropriate methods", but if you're
> > talking about something similar to what Peter used an an example:
>
> > If (Order.isValid())
> > {
> >    Order.save();
> > }
> > Else
> > {
> >   Screen = OrderForm;
> >   Data = Order;
> > };
>
> > No, I wouldn't be doing that in the Controller (and I think we might be
> > getting some miscommunication here because I'm pretty sure Peter and Sean
> > wouldn't either). My Controllers are very dumb. The only thing they do is
> > ask the Model to perform some business logic (via the service layer), and
> > then invoke the appropriate views or execute a redirect. That covers 99% of
> > what my Controllers do.
>
> > The problem with doing something like the above in the Controller means
> > that the model is no longer neutral and self-contained. I can't call the
> > service layer from Flex now, because the logic that checks validity and does
> > saving is executed by the Controller, not the Model. I would have a method
> > in my service named something like " orderService.saveOrder(orderData)",
> > and internally that service layer method might create an Order, validate it,
> > save it, and return a success or failure result that the Controller can then
> > use to determine how to proceed (cflocation or redisplay form with errors,
> > for example). I'm pretty sure that this is what Sean and Peter are also
> > talking about.
>
> > On Jan 14, 2008 9:11 PM, Baz <[EMAIL PROTECTED]> wrote:
>
> > > Sean, Brian, it seems you are both on board with getting a newUserBean()
> > > from the service in the controller then calling the appropriate methods on
> > > that UserBean later on in the controller. Do you also handle queries or
> > > multiple objects in the same way that Peter does? That is, do you code
> > > gateway-type methods into your service that interact with a DAO/Gateway to
> > > return multiple instances of your object?
>
> > > Baz
>
> > > On Jan 14, 2008 4:40 PM, Brian Kotek < [EMAIL PROTECTED]
<mailto:[EMAIL PROTECTED]>   > wrote:
>
> > > > Absolutely, I didn't mean to imply that the service actually does
> > > > everything itself.
>
> > > > On Jan 14, 2008 7:35 PM, Sean Corfield < [EMAIL PROTECTED] >
> > > > wrote:
>
> > > > > On Jan 14, 2008 1:19 PM, Brian Kotek < [EMAIL PROTECTED]> wrote:
> > > > > > I think he is saying that his controllers only interact with
> > > > > services. The
> > > > > > easy rule of thumb for me is: if this was called by Flex instead
> > > > > of my HTML
> > > > > > controller, would it still work? The answer should be "yes". Which
> > > > > means all
> > > > > > logic of any consequence (beyond doing something like a
> > > > > cflocation, which is
> > > > > > specific to the HTML view anyway) should be handled in the model.
>
> > > > > Right, but that can still be in the domain object rather than the
> > > > > service. You just need to expose the API via the service for remote
> > > > > interaction. It doesn't mean all the business logic is in the
> > > > > *service* which is at the heart of Baz's question, I believe.
> > > > > --
> > > > > Sean A Corfield -- (904) 302-SEAN
> > > > > An Architect's View --http://corfield.org/
>
> > > > > "If you're not annoying somebody, you're not really alive."
> > > > > -- Margaret Atwood

>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>> 
>>>>> 
>>>>> 
>>>> 
>>>> 
>>>> 
>>> 
>>> 



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