MVC and separation of concerns question

Hi,

When discusssing frameworks with Coldfusion programmers with a fusebox
background I often find they put a lot of business logic in the
controller, using the model exclusively for CRUD operations. From the
description of MVC on this site however I understand the controller
should not contain any business logic at all. But I find it is very
easy to put business logic in the controller because:

the more business logic is put off the controller in another layer,
the more logic has to be created to communicate results back to the
controller which has to decide on setting a view depending on those
results. A simple example is a login scenario where the model is
called for authenticating credentials and conditional business logic -
injecting the request scope with appropriate error mesages, injecting
user data in the sessionscope, log messages and decide what view to
display in response to authentication results - is put in the
controller.

And more important, putting all this code in one location (the
controller) makes it easy to grasp an application's logic (like a
fusebox circuit).

That's why I found that even though I start out trying to keep the
controller devoid of busines logic over time I find my controllers
quickly abundant with code that is concerned with business logic (the
'how' of my application flow).

I wonder how much of application business logic should go in to the
controller and how much should go in the model?
And if the controller should not contain business logic at all (as I
conceive), is there a separation between business logic and
persistence (data access) so that there is a 4th layer next to M,V and
C that is confined to persistence? Is this where a service layer comes
in?

I am curious to learn more approaches than the one I outlined above

Marc

I am of the view that the controller should be as minimal as possible, a bit
of logic and if it can be re-used then it goes into a model/Service.

Regards,
Andrew Scott
http://www.andyscott.id.au/

From: coldbox@googlegroups.com [mailto:coldbox@googlegroups.com] On
Behalf Of marc
Sent: Friday, 10 September 2010 7:06 PM
To: ColdBox Platform
Subject: [coldbox:5689] MVC and separation of concerns question

Hi,

When discusssing frameworks with Coldfusion programmers with a fusebox
background I often find they put a lot of business logic in the

controller, using

the model exclusively for CRUD operations. From the description of MVC on
this site however I understand the controller should not contain any

business

logic at all. But I find it is very easy to put business logic in the

controller

because:

the more business logic is put off the controller in another layer, the

more

logic has to be created to communicate results back to the controller

which

has to decide on setting a view depending on those results. A simple
example is a login scenario where the model is called for authenticating
credentials and conditional business logic - injecting the request scope

with

appropriate error mesages, injecting user data in the sessionscope, log
messages and decide what view to display in response to authentication
results - is put in the controller.

And more important, putting all this code in one location (the
controller) makes it easy to grasp an application's logic (like a fusebox

circuit).

That's why I found that even though I start out trying to keep the

controller

devoid of busines logic over time I find my controllers quickly abundant

with

code that is concerned with business logic (the 'how' of my application

flow).

I wonder how much of application business logic should go in to the
controller and how much should go in the model?
And if the controller should not contain business logic at all (as I

conceive), is

there a separation between business logic and persistence (data access) so
that there is a 4th layer next to M,V and C that is confined to

persistence? Is

Good question and something I struggled with.

The model does hold the business logic, the persistence layer is contained within the model. This page in the wiki explains it well:
http://wiki.coldbox.org/wiki/Models.cfm

The controller should be responsible for the flow of your application. I once heard it described as a traffic cop, which I think makes sense.

So in the case of you login the controller would look something like (taken from the Models wiki page):

**<cffunction** name="doLogin" output="false" returntype="void">
		**<cfargument** name="event" type="any">
		**<cfscript>**
			//Authenticate
			if( instance.UserService.authenticate(event.getValue("username",""),event.getValue("password","")) ){
				setNextEvent('user.home');
			}
			else{
				getPlugin("messagebox").setMessage("warning","Username and password not valid. Please try again");
				setNextEvent('user.login');
			}
		**</cfscript>**	
	**</cffunction>**

If you are marrying ColdBox you can pass the event object directly to your model an set/get any value you need. That’s the easiest way to begin separating logic from flow-control.

It is better to pass in arguments as John illustrated, but, when I’ve helped people transition to OO/MVC we usually start by passing the event object to help grasp the separation of concerns.

Aaron Greenlee

http://aarongreenlee.com/
Twitter: aarongreenlee

(Brand brand new to ColdBox, apologies for blatant ignorance etc...)

I've been thinking about some closely related issues, default values
for form fields, and processing of those values.

For instance, say there's a calendar with a custom date range, form
fields named srchStartDate and srchEndDate. Seems to me it's the
model, not the controller, that should know the default values for
those fields, and probably the standard format we use for them.

To put it differently, services (models) shouldn't know about rc etc,
they look only at the arguments passed into them, and return values to
the calling controller. It's the controller's job to sequence service
calls correctly, and put applicable values into rc for use by the
view. For example, the form fields are srchStartDate and srchEndDate,
but the arguments to CalendarService.getEvents are startDate and
endDate.

That leads to controller code like this, replicated for end date:
  if(not StructKeyExists(rc, 'srchStartDate'))
    rc.srchStartDate =
variables.CalendarService.getDefaultStartDate();
  else
    rc.srchStartDate =
variables.CalendarService.stdDateFormat(rc.srchStartDate);

This seems kind of awkward and verbose, but so far I'm unable to talk
myself out of it. Any thoughts?

Thanks,
Dave

(Brand brand new to ColdBox, apologies for blatant ignorance etc...)

I've been thinking about some closely related issues, default values
for form fields, and processing of those values.

For instance, say there's a calendar with a custom date range, form
fields named srchStartDate and srchEndDate. Seems to me it's the
model, not the controller, that should know the default values for
those fields, and probably the standard format we use for them.

To put it differently, services (models) shouldn't know about rc etc,
they look only at the arguments passed into them, and return values to
the calling controller. It's the controller's job to sequence service
calls correctly, and put applicable values into rc for use by the
view. For example, the form fields are srchStartDate and srchEndDate,
but the arguments to CalendarService.getEvents are startDate and
endDate.

That leads to controller code like this, replicated for end date:
  if(not StructKeyExists(rc, 'srchStartDate'))
    rc.srchStartDate =
variables.CalendarService.getDefaultStartDate();
  else
    rc.srchStartDate =
variables.CalendarService.stdDateFormat(rc.srchStartDate);

This seems kind of awkward and verbose, but so far I'm unable to talk
myself out of it. Any thoughts?

Thanks,
Dave

Dave,

One quick thought is that I think your controller example could be cleaned up a little bit using the event.getValue(keyname, defaultValue) like so:

var startDate = event.getValue(“srchStartDate”,variables.CalendarService.getDefaultStartDate());
var endDate = event.getValue(“srchEndDate”,variables.CalendarService.getDefaultEndDate());

event.setValue(“srchStartDate”,variables.CalendarService.stdDateFormat(startDate));
event.setValue(“srchEndDate”,variables.CalendarService.stdDateFormat(endDate));

Regards,
Adam

I might be mis-understanding, but with forms I usually populate them from an object, so the first time through I’d do something like this in my handler:

rc.meeting = CalendarService.newMeeting();

then in my form I’d have:

If I wanted to have a default start date for my new meeting then I’d do this in the CalendarService. Something like:

any function newMeeting()
{
var meeting = new Meeting();
meeting.setStartDate( Now() );
return meeting;
}

Does that help?

+1 for John’s last post.

Hmmm, you're right, encapsulating these various form fields as a
CalendarSettings object, with defaults and clean-up behaviors that get
invoked on populate, that's a much cleaner approach. I wasn't thinking
about the settings for this screen as an object, since it's not
something that's a persisted object, but it could still get populated
like this, and the cleaned up version put into rc as an object that
the form reads from. The controller ends up just mapping form field
names to CalendarSettings field names, and the form itself maps them
back.

As long as I've been doing this, I've never thought of treating form
settings themselves as an object when they didn't represent some sort
of (usually persisted) domain object. There's a part of me that feels
like I don't have OO in my soul, still, even though I write CFCs for
nearly everything, and this feels like a symptom.

Thanks, I'll think on this.

Dave

Don’t think too much! Sounds like you got it!

I don't think that John was really creating a CalendarSettings object,
rather, he was adding behavior to his model in the CalendarService.

The basic idea (unless I'm completely misstating things which does
happen) is that you've got your Meeting. The Meeting has a number of
properties including StartDate and EndDate with getters and setters
and such. Then you have your CalendarService. This service is going
to add behavior to your object like creating a new instance, updating,
saving, etc. John is suggesting that you add some intelligence to your
CalendarService so that when you create a new Meeting object through
it, it also sets defaults for StartDate and EndDate (that would
qualify as a business rule in the lingo, I'd say).

So then in your handler you'd have logic to see whether it is a brand
new request or an update like so:

//Look to see if there is an existing meeting being updated or a new
one being created
if( event.ValueExists('meetingId') && rc.meetingId != 0 ){
  //hidden form field says that this isn't an existing meeting
rc.meeting = CalendarService.newMeeting();
} else {
//this is an existing meeting, populate from db, populate overwrite with form
var oMeeting = CalendarService.getMeeting(rc.meetingId);
populateBean(oMeeting );

//Do your validation
if (CalendarService.Validate(oMeeting ) == false){
//put the object back into RC to display to the form along with errors
rc.meeting = oMeeting;
} else {
  //save it and move on to your next event
}
}

At least that's what I generally do. I add in behavior to my service
objects to do automatic annotation of things like when the object was
created, who created it, last updated, last update by, etc and then do
defaults on new object instances and what not.

Hope this helps,
Judah

@John and Judah:

I think there's been a misunderstanding about my example. There is no
meeting involved here, or to the extent that there's anything like
that, it's not what I was referring to that has a startDate and
endDate. It's a calendar with user-selectable start and end dates, and
other fields that filter the events being displayed on the calendar.

The revelation for me was that it may well make sense to encapsulate
the state of those form fields as a bean, even though they _don't_
represent an actual business object like a meeting or a person, just
UI state. I've never considered that possibility before, but it neatly
handles both default values and custom formatting or other behaviors
of those fields, and also provides a single collection that can be
passed to a search form renderer. I've actually done something kind of
similar in js now that I think about it, but not on the server side.
I'm pretty comfortable with this, at least as far as the ideas behind
it; I'll see how I feel when I actually get time to code it up.

So here's my next level question: When the user submits the calendar
form, the controller will pass the appropriate rc fields into the
service's getCalendarSettings method, and the returned bean will
contain formatted versions of any fields that require processing. So
far so good. However, you first access the calendar, those form fields
aren't in rc, so the controller will blow up if it tries to access
them to pass them to the service. It either has to detect that no form
was submitted and pass nothing to the service (check for a hidden
formWasSubmitted field maybe), or individually test for the existence
of each field it might pass, and only access and pass it if it exists
in rc, pretty awkward.

I don't like either of those choices, and besides, (a) doesn't cover
checkboxes or radio buttons, which might not exist in form/rc even if
the form was submitted. It seems like the only real-world options are
a) Pass rc into the service as a whole, so it can default any missing
values, or b) Have the controller default the whole set of fields at
least to empty string, so it can reference them safely.

(a) is unappealing because the service/model layer shouldn't know
anything about the request cycle, form fields, or rc, and because it
should be dealing with object field names, not form field names. That
last distinction gets very relevant if you have, say, a person record
with any number of phone numbers, additional fields for which get
added via js. On the form, the fields might be phoneName_1,
phoneNumber_1, phoneName_2, etc, but at the service/model level, that
should already have been translated into an array of PhoneNumber
beans. The numeric suffixes, the maxPhoneCount field, and other
artifacts of the html form are completely gone.

Which leaves it up to the controller to be aware of form fields, at
least to the extent of defaulting all fields so it can pass them into
the service whether they're present in a submitted form or not. It's
also probably what must un-flatten those suffixed phone number fields
into an array of objects, even though it doesn't know anything about
the actual business rules for PhoneNumber beans.

In a larger sense, it's actually the view that should deal with form
fields, but that can't work unless some method of the view gets called
*before* the controller runs. I don't hear anyone suggesting that, and
anyway, as I understand it, views are cfms in ColdBox, not cfcs, so
they don't have any methods at all. (Never got why that was so. I've
been building views in cfcs for a while now. It makes tons of sense to
me that they inherit standard methods to render sets of html select
options, radio buttons, etc, as well as domain-specific widget
rendering methods, say renderUserPicker. Don't mean to be critical,
but view helpers seem like a baggier way of accomplishing the same
thing. Off track...)

Am I making sense here? Any other thoughts? I really resist getting
the controller involved with form field details, but I can't see any
other way to approach it. You could use an interceptor or setupRequest
method for the same purpose I think, but those still live in
controller-land, not that much different.

Thanks for any feedback,

Dave

Dave, it sounds like you are trying to over complicate things some.

I am using the methodology where I create a bean and this becomes my model,
and this is extremely easy in ColdFusion 9 with the accessors annotation. So
to make it very clear I personally would be looking at either passing the
event into the service, or using the DI to get the RC. From here you can the
pull up your model (bean) and apply the validation using hyrule for your
form.

That has got to be the simplest approach.

As for radio buttons, if you follow the rule when retrieving this
information and use event.getValue('myRadioButton','') then this will make
it default to empty or whatever you want in the second argument.

Is this along the lines that you are thinking?

Regards,
Andrew Scott
http://www.andyscott.id.au/

From: coldbox@googlegroups.com [mailto:coldbox@googlegroups.com] On
Behalf Of Dave Merrill
Sent: Saturday, 11 September 2010 2:06 PM
To: ColdBox Platform
Subject: [coldbox:5746] Re: MVC and separation of concerns question

@John and Judah:

I think there's been a misunderstanding about my example. There is no
meeting involved here, or to the extent that there's anything like that,

it's

not what I was referring to that has a startDate and endDate. It's a

calendar

with user-selectable start and end dates, and other fields that filter the
events being displayed on the calendar.

The revelation for me was that it may well make sense to encapsulate the
state of those form fields as a bean, even though they _don't_ represent

an

actual business object like a meeting or a person, just UI state. I've

never

considered that possibility before, but it neatly handles both default

values

and custom formatting or other behaviors of those fields, and also

provides a

single collection that can be passed to a search form renderer. I've

actually

done something kind of similar in js now that I think about it, but not on

the

server side.
I'm pretty comfortable with this, at least as far as the ideas behind it;

I'll see

how I feel when I actually get time to code it up.

So here's my next level question: When the user submits the calendar form,
the controller will pass the appropriate rc fields into the service's
getCalendarSettings method, and the returned bean will contain formatted
versions of any fields that require processing. So far so good. However,

you

first access the calendar, those form fields aren't in rc, so the

controller will

blow up if it tries to access them to pass them to the service. It either

has to

detect that no form was submitted and pass nothing to the service (check

for

a hidden formWasSubmitted field maybe), or individually test for the
existence of each field it might pass, and only access and pass it if it

exists in

rc, pretty awkward.

I don't like either of those choices, and besides, (a) doesn't cover

checkboxes

or radio buttons, which might not exist in form/rc even if the form was
submitted. It seems like the only real-world options are
a) Pass rc into the service as a whole, so it can default any missing

values, or

b) Have the controller default the whole set of fields at least to empty

string,

so it can reference them safely.

(a) is unappealing because the service/model layer shouldn't know anything
about the request cycle, form fields, or rc, and because it should be

dealing

with object field names, not form field names. That last distinction gets

very

relevant if you have, say, a person record with any number of phone
numbers, additional fields for which get added via js. On the form, the

fields

might be phoneName_1, phoneNumber_1, phoneName_2, etc, but at the
service/model level, that should already have been translated into an

array

of PhoneNumber beans. The numeric suffixes, the maxPhoneCount field,
and other artifacts of the html form are completely gone.

Which leaves it up to the controller to be aware of form fields, at least

to the

extent of defaulting all fields so it can pass them into the service

whether

they're present in a submitted form or not. It's also probably what must

un-

flatten those suffixed phone number fields into an array of objects, even
though it doesn't know anything about the actual business rules for
PhoneNumber beans.

In a larger sense, it's actually the view that should deal with form

fields, but

that can't work unless some method of the view gets called
*before* the controller runs. I don't hear anyone suggesting that, and
anyway, as I understand it, views are cfms in ColdBox, not cfcs, so they

don't

have any methods at all. (Never got why that was so. I've been building
views in cfcs for a while now. It makes tons of sense to me that they

inherit

standard methods to render sets of html select options, radio buttons,

etc,

as well as domain-specific widget rendering methods, say renderUserPicker.
Don't mean to be critical, but view helpers seem like a baggier way of
accomplishing the same thing. Off track...)

Am I making sense here? Any other thoughts? I really resist getting the
controller involved with form field details, but I can't see any other way

to

approach it. You could use an interceptor or setupRequest method for the
same purpose I think, but those still live in controller-land, not that

much

Probably I am overthinking. This sort of thing is only an issue if
you're trying to really separate the layers of the app, but I thought
that was a goal.

So, I thought services should be completely decoupled from the request
cycle, form fields, and Event, dealing only with defined arguments,
and returning values with no other side effects. Passing the event
into a service for it to modify goes against that, or so I thought.

If I were to go that way, what would you say the name of the service
method that defaults and processes search form fields would be? Maybe
getSearchFormSettings, and instead of modifying the event, have it
return a SearchFormSettings bean to the controller, which it puts into
the event itself?

I very much appreciate folks working through these basic architecture
questions with me.

Dave

No it's all good, I love a good conversation like this because it doesn't
happen very often.

As for passing the event, if you do DI you can always get the RC, in fact I
think this is automatically inject as the controller into models/services
that are stored in the model mappings.

You maybe don't need to pass the entire event, I think it is handy even if
you are not going to use everything. Because you can always use the
event.getValue() to search for variable and if not found return a default
string back.

As for a naming convention this is actually a good question, right now I
personally have a model for each type of form processing I want/need to do.
This is not very pretty as far as I am concerned, and there might be a
better way, but I like this way because with ColdFusion 9 and ORM and Beans
I can then use the hyrule validation on these.

There might be another way to do this in a more generic way, and I would
love to hear how others might be doing this as well.

Regards,
Andrew Scott
http://www.andyscott.id.au/

From: coldbox@googlegroups.com [mailto:coldbox@googlegroups.com] On
Behalf Of Dave Merrill
Sent: Saturday, 11 September 2010 8:59 PM
To: ColdBox Platform
Subject: [coldbox:5750] Re: MVC and separation of concerns question

Probably I am overthinking. This sort of thing is only an issue if you're

trying

to really separate the layers of the app, but I thought that was a goal.

So, I thought services should be completely decoupled from the request
cycle, form fields, and Event, dealing only with defined arguments, and
returning values with no other side effects. Passing the event into a

service

for it to modify goes against that, or so I thought.

If I were to go that way, what would you say the name of the service

method

that defaults and processes search form fields would be? Maybe
getSearchFormSettings, and instead of modifying the event, have it return

a

@Andrew: So you do have beans for UI-only form processing then, and
service calls to access them?

@All: Let me give an example of why I think form field names and
processing are more the business of the controller than the service.
Keep in mind that I'm talking about form fields that belong to a
search screen or other UI state, only, not ones that correspond to
fields in an actual business object. Interesting; that seems to be
where I'm headed.

Suppose there's a form with two calendars, each with user-settable
start and end dates. On the form, those fields are startDate1,
endDate1, startDate2, and endDate2, but at the service level, there's
just one getCalendarEvents(startDate, endDate) method. Clearly, the
controller should call that method twice, passing values from the "1"
fields the first time and values from the "2" fields the second. The
service shouldn't know or care about any of that; it just gets called
twice with the arguments it requires.

IMO, that scenario makes it clear that at least in some cases, the
controller *must* know which form fields are needed and what they're
called. If that's so, then something like this seems right for the
controller code:

// make sure these fields are defined in rc
StructAppend(rc, {startDate1: '', endDate1: '', startDate2: '',
endDate2: ''}, false);
// ask the service to process them as required and compose them into
an object, then put that result in rc as its own collection
rc.formSettings = service.getFormSettings(startDate1=rc.startDate1,
endDate1=rc.endDate1, startDate2=rc.startDate2, endDate2=rc.endDate2);

Inside getFormSettings, a FormSettings bean gets created, with
whatever defaults it defines, then it gets populated with any passed
form field values that aren't blank, and returned. The form itself
renders from rc.formSettings.

The controller knows which fields to pass to the service method, and
makes sure they're defined so it can reference them. The service
populates the bean from argumentCollection, without knowing what it
contains. Neither the controller nor the service knows about defaults
or processing for the form settings fields; that's the business of the
FormSettings bean.

Make sense? Is there a ColdBox shortcut for the StructAppend line?
Since it doesn't appear that anything like this is what people are
thinking, how are you handling defaults and processing for UI-only
form fields?

Thanks for any thoughts,
Dave

I have but in rare cases, I would use the bean and or Domain Class to do
validation only. In your example it makes sense to do something like that,
whether you do it at the service level or controller is really personal /
application preference.

As for a short cut.

<cfscript>
  rc['startdate'] = event.getValue('startDate'.'');
</cfscript>

Will work, you will also need to do the event.getValue() before passing it
in as args because it will throw a variable endefined otherwsie.

Regards,
Andrew Scott
http://www.andyscott.id.au/

From: coldbox@googlegroups.com [mailto:coldbox@googlegroups.com] On
Behalf Of Dave Merrill
Sent: Sunday, 12 September 2010 9:47 PM
To: ColdBox Platform
Subject: [coldbox:5753] Re: MVC and separation of concerns question

@Andrew: So you do have beans for UI-only form processing then, and
service calls to access them?

@All: Let me give an example of why I think form field names and

processing

are more the business of the controller than the service.
Keep in mind that I'm talking about form fields that belong to a search

screen

or other UI state, only, not ones that correspond to fields in an actual
business object. Interesting; that seems to be where I'm headed.

Suppose there's a form with two calendars, each with user-settable start

and

end dates. On the form, those fields are startDate1, endDate1,

startDate2,

and endDate2, but at the service level, there's just one
getCalendarEvents(startDate, endDate) method. Clearly, the controller
should call that method twice, passing values from the "1"
fields the first time and values from the "2" fields the second. The

service

shouldn't know or care about any of that; it just gets called twice with

the

arguments it requires.

IMO, that scenario makes it clear that at least in some cases, the

controller

*must* know which form fields are needed and what they're called. If

that's

so, then something like this seems right for the controller code:

// make sure these fields are defined in rc StructAppend(rc, {startDate1:

'',

endDate1: '', startDate2: '',
endDate2: ''}, false);
// ask the service to process them as required and compose them into an
object, then put that result in rc as its own collection rc.formSettings =
service.getFormSettings(startDate1=rc.startDate1,
endDate1=rc.endDate1, startDate2=rc.startDate2, endDate2=rc.endDate2);

Inside getFormSettings, a FormSettings bean gets created, with whatever
defaults it defines, then it gets populated with any passed form field

values

that aren't blank, and returned. The form itself renders from

rc.formSettings.

The controller knows which fields to pass to the service method, and makes
sure they're defined so it can reference them. The service populates the
bean from argumentCollection, without knowing what it contains. Neither
the controller nor the service knows about defaults or processing for the
form settings fields; that's the business of the FormSettings bean.

Make sense? Is there a ColdBox shortcut for the StructAppend line?
Since it doesn't appear that anything like this is what people are

thinking,

how are you handling defaults and processing for UI-only form fields?

Thanks for any thoughts,
Dave

> No it's all good, I love a good conversation like this because it
> doesn't happen very often.
>
> As for passing the event, if you do DI you can always get the RC, in
> fact I think this is automatically inject as the controller into
> models/services that are stored in the model mappings.
>
> You maybe don't need to pass the entire event, I think it is handy
> even if you are not going to use everything. Because you can always
> use the
> event.getValue() to search for variable and if not found return a
> default string back.
>
> As for a naming convention this is actually a good question, right now
> I personally have a model for each type of form processing I want/need

to

do.
> This is not very pretty as far as I am concerned, and there might be a
> better way, but I like this way because with ColdFusion 9 and ORM and
> Beans I can then use the hyrule validation on these.
>
> There might be another way to do this in a more generic way, and I
> would love to hear how others might be doing this as well.
>
> Regards,
> Andrew Scotthttp://www.andyscott.id.au/
>
>
>
> > From: coldbox@googlegroups.com [mailto:coldbox@googlegroups.com]
On
> > Behalf Of Dave Merrill
> > Sent: Saturday, 11 September 2010 8:59 PM
> > To: ColdBox Platform
> > Subject: [coldbox:5750] Re: MVC and separation of concerns question
>
> > Probably I am overthinking. This sort of thing is only an issue if
> > you're
> trying
> > to really separate the layers of the app, but I thought that was a

goal.