<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Architecting FB4.1</title>
	<atom:link href="http://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/</link>
	<description>Thoughts, rants, and even some code from the mind of Barney Boisvert.</description>
	<lastBuildDate>Thu, 11 Sep 2014 09:58:12 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: Barney</title>
		<link>https://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/comment-page-1/#comment-51</link>
		<dc:creator>Barney</dc:creator>
		<pubDate>Sat, 30 Jul 2005 18:56:41 +0000</pubDate>
		<guid isPermaLink="false">http://barneyb.com/barneyblog/?p=69#comment-51</guid>
		<description>Richard,

Yeah, you&#039;ve misunderstood a little.  Action pages are like &quot;process this form submission&quot;, while display pages are like &quot;display this page&quot;.  Each page may required multiple fuses (and fuseactions, in FB4.x), quite possibly even some of the same ones.  But the two things should be separate requests.

For example, say I click an &#039;add to cart&#039; button for a product.  The overall result of the click should be to add the product, and display the cart for the user.  The click will first call an action page that&#039;ll add the item to the cart.  Then the fusebox should redirect to another (display) page that renders the shopping cart.  The two shouldn&#039;t happen in the same request.

The end result is that the user experience hasn&#039;t changed (aside from perhaps a short extra delay for the redirect), but the user is protected from adverse consequences of hitting the refresh button.  It also makes the code simpler, because each request is only doing a single thing.  Simpler code is easier to maintain code, and that&#039;s always a good thing.
</description>
		<content:encoded><![CDATA[<p>Richard,</p>
<p>Yeah, you've misunderstood a little.  Action pages are like "process this form submission", while display pages are like "display this page".  Each page may required multiple fuses (and fuseactions, in FB4.x), quite possibly even some of the same ones.  But the two things should be separate requests.</p>
<p>For example, say I click an 'add to cart' button for a product.  The overall result of the click should be to add the product, and display the cart for the user.  The click will first call an action page that'll add the item to the cart.  Then the fusebox should redirect to another (display) page that renders the shopping cart.  The two shouldn't happen in the same request.</p>
<p>The end result is that the user experience hasn't changed (aside from perhaps a short extra delay for the redirect), but the user is protected from adverse consequences of hitting the refresh button.  It also makes the code simpler, because each request is only doing a single thing.  Simpler code is easier to maintain code, and that's always a good thing.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Richard</title>
		<link>https://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/comment-page-1/#comment-50</link>
		<dc:creator>Richard</dc:creator>
		<pubDate>Fri, 29 Jul 2005 09:06:28 +0000</pubDate>
		<guid isPermaLink="false">http://barneyb.com/barneyblog/?p=69#comment-50</guid>
		<description>I may be a little late to this discussion but I though I&#039;d add my tuppence worth anyway.

Its regarding point #1 - split action and display pages, so that an action page has to redirect to a result page.  I may have misunderstood so correct me if i&#039;m wrong, but isn&#039;t this what fuses are designed for?  You can still have one page request, ie fuseaction, but split it into separate action and display fuses? Each fuse is still independent and reusable, and this way you have one less fuseaction to worry about.

It seems a bit of overkill to have a different fuseaction for each individual fuse.</description>
		<content:encoded><![CDATA[<p>I may be a little late to this discussion but I though I'd add my tuppence worth anyway.</p>
<p>Its regarding point #1 &#8211; split action and display pages, so that an action page has to redirect to a result page.  I may have misunderstood so correct me if i'm wrong, but isn't this what fuses are designed for?  You can still have one page request, ie fuseaction, but split it into separate action and display fuses? Each fuse is still independent and reusable, and this way you have one less fuseaction to worry about.</p>
<p>It seems a bit of overkill to have a different fuseaction for each individual fuse.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ulf</title>
		<link>https://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/comment-page-1/#comment-49</link>
		<dc:creator>Ulf</dc:creator>
		<pubDate>Thu, 16 Dec 2004 17:13:21 +0000</pubDate>
		<guid isPermaLink="false">http://barneyb.com/barneyblog/?p=69#comment-49</guid>
		<description>Hi Barney,

Many thanks. You helped to come forth.

Ulf</description>
		<content:encoded><![CDATA[<p>Hi Barney,</p>
<p>Many thanks. You helped to come forth.</p>
<p>Ulf</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Barney</title>
		<link>https://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/comment-page-1/#comment-48</link>
		<dc:creator>Barney</dc:creator>
		<pubDate>Thu, 16 Dec 2004 17:07:58 +0000</pubDate>
		<guid isPermaLink="false">http://barneyb.com/barneyblog/?p=69#comment-48</guid>
		<description>Ulf,

You got it.  I usually set variables.my.lockkey to a UUID in the init() method and use that as my lock name.  If I need multiple lock names, then I&#039;ll obviously have multiple keys.  That helps avoid typos in your lock names, which can lead to amazingly subtle (and difficult to quash) bugs when your app starts running under load.

Don&#039;t try to do too much with your service component regarding locking.  Just as it encapsulates the locking behaviour from it&#039;s calling code, your other objects should encapsulate their locking behaviour from the service object.  If you&#039;re allowing multiple service method calls to access a single object, then yes, the service needs to lock that.  But if your business object has an internal race condition, the BO should do the locking, not the service, because the service can&#039;t know that race condition exists without knowing how the BO is implemented (and thereby breaking encapsulation).</description>
		<content:encoded><![CDATA[<p>Ulf,</p>
<p>You got it.  I usually set variables.my.lockkey to a UUID in the init() method and use that as my lock name.  If I need multiple lock names, then I'll obviously have multiple keys.  That helps avoid typos in your lock names, which can lead to amazingly subtle (and difficult to quash) bugs when your app starts running under load.</p>
<p>Don't try to do too much with your service component regarding locking.  Just as it encapsulates the locking behaviour from it's calling code, your other objects should encapsulate their locking behaviour from the service object.  If you're allowing multiple service method calls to access a single object, then yes, the service needs to lock that.  But if your business object has an internal race condition, the BO should do the locking, not the service, because the service can't know that race condition exists without knowing how the BO is implemented (and thereby breaking encapsulation).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ulf</title>
		<link>https://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/comment-page-1/#comment-47</link>
		<dc:creator>Ulf</dc:creator>
		<pubDate>Thu, 16 Dec 2004 16:59:41 +0000</pubDate>
		<guid isPermaLink="false">http://barneyb.com/barneyblog/?p=69#comment-47</guid>
		<description>Hi Barney,

just to get it right. If I need locking, I&#039;ll have to do it in this service component (which is in application scope). 

So I don&#039;t lock access to the service component (and use cflock scope=&quot;application&quot;). I&#039;ll have to use named cflocks in a called method if I use business objects where race conditions can occur. Is that right?

Ulf</description>
		<content:encoded><![CDATA[<p>Hi Barney,</p>
<p>just to get it right. If I need locking, I'll have to do it in this service component (which is in application scope). </p>
<p>So I don't lock access to the service component (and use cflock scope="application"). I'll have to use named cflocks in a called method if I use business objects where race conditions can occur. Is that right?</p>
<p>Ulf</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Barney</title>
		<link>https://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/comment-page-1/#comment-46</link>
		<dc:creator>Barney</dc:creator>
		<pubDate>Thu, 16 Dec 2004 16:24:36 +0000</pubDate>
		<guid isPermaLink="false">http://barneyb.com/barneyblog/?p=69#comment-46</guid>
		<description>Ed,

Redirect after post is pretty simple.  Any time a request is a form submissions, don&#039;t display a page, use CFLOCATION (or an equivalent) to go to another page for the display.  Take the example of an &quot;edit user&quot; operation.  First page is the form.  It submits to a second page which runs an UPDATE query.  Then, instead of displaying a &quot;update complete&quot; message, it uses CFLOCATION to forward to a third page, and that third page displays the &quot;update complete&quot; message.

The only exception is errors in server-side validation.  In that case, it&#039;s okay for the action page to detect the validation error, and then regenerate the form with the error message(s) at the top.

For the independant UI and model, DAOs aren&#039;t going to get it for you.  Those are an implementation detail of the model (a specific way of implementing persistance operations), and if your FB app knows about the DAOs, then it&#039;s not encapsulated.  The service object provides an adapter between FB and your model.  If you use DAOs, your service will deal with them.  If you use inline SQL, your service will do it.  The FB app doesn&#039;t know and doesn&#039;t care, as long as the service method does what it&#039;s supposed to do (addUser, getUserList, etc.).

Breaking down your persistance code into DAOs that are then leveraged by your business logic is a good plan, but they are for separating business and persistance logic, not business and presentation logic.  Both are desirable, but your business and persistance logic are usually much more tightly coupled (just the nature of the beast), so the benefits aren&#039;t as great as between business and presentation logic.

I don&#039;t really have any good samples to share, unfortunately.  The code from my presentation at the conference has an example of how service objects are used.  Any book on application design should also talk about these principles, no matter the platform (CF, J2EE, .NET, FORTRAN).</description>
		<content:encoded><![CDATA[<p>Ed,</p>
<p>Redirect after post is pretty simple.  Any time a request is a form submissions, don't display a page, use CFLOCATION (or an equivalent) to go to another page for the display.  Take the example of an "edit user" operation.  First page is the form.  It submits to a second page which runs an UPDATE query.  Then, instead of displaying a "update complete" message, it uses CFLOCATION to forward to a third page, and that third page displays the "update complete" message.</p>
<p>The only exception is errors in server-side validation.  In that case, it's okay for the action page to detect the validation error, and then regenerate the form with the error message(s) at the top.</p>
<p>For the independant UI and model, DAOs aren't going to get it for you.  Those are an implementation detail of the model (a specific way of implementing persistance operations), and if your FB app knows about the DAOs, then it's not encapsulated.  The service object provides an adapter between FB and your model.  If you use DAOs, your service will deal with them.  If you use inline SQL, your service will do it.  The FB app doesn't know and doesn't care, as long as the service method does what it's supposed to do (addUser, getUserList, etc.).</p>
<p>Breaking down your persistance code into DAOs that are then leveraged by your business logic is a good plan, but they are for separating business and persistance logic, not business and presentation logic.  Both are desirable, but your business and persistance logic are usually much more tightly coupled (just the nature of the beast), so the benefits aren't as great as between business and presentation logic.</p>
<p>I don't really have any good samples to share, unfortunately.  The code from my presentation at the conference has an example of how service objects are used.  Any book on application design should also talk about these principles, no matter the platform (CF, J2EE, .NET, FORTRAN).</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Barney</title>
		<link>https://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/comment-page-1/#comment-45</link>
		<dc:creator>Barney</dc:creator>
		<pubDate>Thu, 16 Dec 2004 16:10:04 +0000</pubDate>
		<guid isPermaLink="false">http://barneyb.com/barneyblog/?p=69#comment-45</guid>
		<description>Ulf,

No, not really.  Access to shared-scope CFCs does not require locking unless a race condition is created.  However, only the CFC should know if such a condition exists (because that&#039;s an implementation detail of the CFC), so only the CFC itself can know if locking is required.  Thus, any CFLOCKs that you need are internal to the service CFC, not external (in the calling code).

In this app, the service object happens to carry a single instance variable (the datasource name) and the SQL access is all transactional, so there are no race conditions to worry about.  That will undoubtedly change in the future, and at that point, I&#039;ll add CFLOCK calls as necessary.  Because they are internal, my FB app won&#039;t even know the change happened; it is 100% isolated from implementation details.</description>
		<content:encoded><![CDATA[<p>Ulf,</p>
<p>No, not really.  Access to shared-scope CFCs does not require locking unless a race condition is created.  However, only the CFC should know if such a condition exists (because that's an implementation detail of the CFC), so only the CFC itself can know if locking is required.  Thus, any CFLOCKs that you need are internal to the service CFC, not external (in the calling code).</p>
<p>In this app, the service object happens to carry a single instance variable (the datasource name) and the SQL access is all transactional, so there are no race conditions to worry about.  That will undoubtedly change in the future, and at that point, I'll add CFLOCK calls as necessary.  Because they are internal, my FB app won't even know the change happened; it is 100% isolated from implementation details.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ed.T</title>
		<link>https://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/comment-page-1/#comment-44</link>
		<dc:creator>Ed.T</dc:creator>
		<pubDate>Thu, 16 Dec 2004 14:39:55 +0000</pubDate>
		<guid isPermaLink="false">http://barneyb.com/barneyblog/?p=69#comment-44</guid>
		<description>Barney,

I saw your presentation at Fusebox 2004 and left with some ideas for improving my apps.  But I&#039;m still coming up short.  Can I get some training wheels?  I feel the need for two major improvements and you&#039;ve got them: re-direct after post, and model independent implementation.  I&#039;ve been trying to get more comfortable with DAO&#039;s expecting the model to be more flexible through their use.  Any materials or samples you can suggest to get these ideas through my thick skull?

Thanks,

Ed</description>
		<content:encoded><![CDATA[<p>Barney,</p>
<p>I saw your presentation at Fusebox 2004 and left with some ideas for improving my apps.  But I'm still coming up short.  Can I get some training wheels?  I feel the need for two major improvements and you've got them: re-direct after post, and model independent implementation.  I've been trying to get more comfortable with DAO's expecting the model to be more flexible through their use.  Any materials or samples you can suggest to get these ideas through my thick skull?</p>
<p>Thanks,</p>
<p>Ed</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ulf</title>
		<link>https://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/comment-page-1/#comment-43</link>
		<dc:creator>Ulf</dc:creator>
		<pubDate>Thu, 16 Dec 2004 08:13:01 +0000</pubDate>
		<guid isPermaLink="false">http://barneyb.com/barneyblog/?p=69#comment-43</guid>
		<description>Hi Barney,

Are there any problems to expect because the service factory is in application scope and calls to it can not be locked in circuit.xml?</description>
		<content:encoded><![CDATA[<p>Hi Barney,</p>
<p>Are there any problems to expect because the service factory is in application scope and calls to it can not be locked in circuit.xml?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: barneyb</title>
		<link>https://www.barneyb.com/barneyblog/2004/12/15/architecting-fb41/comment-page-1/#comment-42</link>
		<dc:creator>barneyb</dc:creator>
		<pubDate>Thu, 16 Dec 2004 02:47:21 +0000</pubDate>
		<guid isPermaLink="false">http://barneyb.com/barneyblog/?p=69#comment-42</guid>
		<description>The service is just a collection of methods that implement the business operations of the application, in a framework agnostic way.  That lets the backend (the real application) be independant of the UI being used, as well as support multiple concurrent UIs (such as an HTML version and a Flash version).

For example, I&#039;ve got a method for retrieving a comment, which is called like this:

[set name=&quot;comment&quot; value=&quot;#application.blogservice.getCommentById(attributes.id)#&quot; /]

Of particular import, note that the method doesn&#039;t know where the ID came from (attributes scope, in this case), nor the name of the variable it&#039;s return value is stored in (comments, in this case).  Because of that, I can call the method in a different way (from a CFC facade, for example) without the method caring.

That&#039;s one of my major gripes with &quot;standard&quot; FB4 MVC, because your fuse defines what the parameters and return variable must be named.  Well, the Fusedoc does, but the point is that they are locked at architect-time.  With a method call, I can pass it a value from a query, a page parameter, a hard coded value, or whatever, and I can also assign the result to a variable of my choosing.  No variable collisions, no fuse-centric variable assignments, just pure logic in a container that&#039;s not only reusable throughout the framework, but throughout the app as a whole.</description>
		<content:encoded><![CDATA[<p>The service is just a collection of methods that implement the business operations of the application, in a framework agnostic way.  That lets the backend (the real application) be independant of the UI being used, as well as support multiple concurrent UIs (such as an HTML version and a Flash version).</p>
<p>For example, I've got a method for retrieving a comment, which is called like this:</p>
<p>[set name="comment" value="#application.blogservice.getCommentById(attributes.id)#" /]</p>
<p>Of particular import, note that the method doesn't know where the ID came from (attributes scope, in this case), nor the name of the variable it's return value is stored in (comments, in this case).  Because of that, I can call the method in a different way (from a CFC facade, for example) without the method caring.</p>
<p>That's one of my major gripes with "standard" FB4 MVC, because your fuse defines what the parameters and return variable must be named.  Well, the Fusedoc does, but the point is that they are locked at architect-time.  With a method call, I can pass it a value from a query, a page parameter, a hard coded value, or whatever, and I can also assign the result to a variable of my choosing.  No variable collisions, no fuse-centric variable assignments, just pure logic in a container that's not only reusable throughout the framework, but throughout the app as a whole.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
