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.

On Jan 14, 2008 4:08 PM, Baz <[EMAIL PROTECTED]> wrote:

> Pretty neat tricks you got up your sleeve. A lot of people go by the rule
> of thumb that controllers should only interface with services and the
> services in turn play with the objects. But your way does solve a lot of the
> issues that arise from that.
>
> Pleasure picking your brain as usual...
>
> Baz
>
> On Jan 14, 2008 1:01 PM, Peter Bell <[EMAIL PROTECTED]> wrote:
>
> >  I use services:
> >
> >    - As remote API – can't send smart beans over the wire, so I have
> >    methods like UserService.save(). Of course, all they do is user =
> >    THIS.new(), user.load() and user.save(), so they delegate to the
> >    bean, but they provide the remote API.
> >    - To handle aggregates – I find it more intuitive to UserList =
> >    UserService.getByFilter("Subscribed = 1") rather than asking a
> >    User for a list of users. Also, ColdFusion doesn't support class 
> > methods, so
> >    I'd have to create a Singleton User which just doesn't seem to be the 
> > best
> >    approach in CF.
> >    - As a factory – user = UserService.new() returns a user with any
> >    dependencies injected. It's really just a one line call to LightWire 
> > which
> >    does the DI, but it gives me a place to add more intelligence to my 
> > factory
> >    if I want to override new() for a given business object.
> >
> >
> > I don't currently have the use case for different validations, but I've
> > had it in the past (although back then I just solved it procedurally). I'd
> > be tempted to EITHER have different isValid() methods, or more likely to
> > have a OrderState control which would allow me to set the state (and hence
> > validations and the like) for different states, so I might do:
> >
> > Order.set("State", "Situation1");
> > If (Order.isValid())
> >  . . .
> >
> > Although I'd have to play with it to see if it worked out.
> >
> > Best Wishes,
> > Peter
> >
> >
> > On 1/14/08 3:51 PM, "Baz" <[EMAIL PROTECTED]> wrote:
> >
> > Peter I like what you are saying.
> >
> > When do you use a service by the way? You seem to be interacting
> > directly with beans a lot.
> >
> > Second, if you had varying levels of validation complexity for orders
> > such as:
> >
> >
> >    - Situation 1: Validate Order, User, Billing, Statistics (the
> >    previous example)
> >    - Situation 2: Validate Order, Shipping
> >    - Situation 3: Validation Order
> >
> > Would you then have different aggregate validations? I.e.
> > Order.isValidSituation1(), Order.isValidSituation2 (),
> > Order.isValidSituation3()
> >
> > Cheers,
> > Baz
> >
> >
> > On Jan 14, 2008 12:34 PM, Peter Bell < [EMAIL PROTECTED]
> > <mailto:[EMAIL PROTECTED]> <[EMAIL PROTECTED]> > wrote:
> >
> > 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]> <[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
-~----------~----~----~----~------~----~------~--~---

Reply via email to