[ColdBox 3.8.1] "polluting" rc, prc

I was going to leave this alone but it’s bugging me.

I saw a reference somewhere (I believe in one of the answers here in Google Groups) to “polluting prc/rc” but it read like a personal preference. Didn’t really see any explanation but rather came across as “just one of those things…”

Then I saw the same language here - http://wiki.coldbox.org/wiki/EventHandlers.cfm (see below)

View Args

Data can be passed from your handler to the view via the rc or prc (request collection and private request collection). If you want to pass data to a view without polluting rc and prc, can pass it directly in as the args parameter.

var viewData = {
  data1 = service.getData1(),
  data2 = service.getData2()
};

event.setView( view='myView', args=viewData );

Access the data in the view like so:

**<cfoutput>**
  Data 1: #args.data1#**<br>**
  Data 2: #args.data2# 

So now it’s bugging me. I’ve been thinking that results from model logic that need to go to the view should be placed in prc structure. I’m wondering - does “prc” get additional processing somewhere that “args” in the above example does not? If so then I suppose I’ll switch to the above method of moving data to the views. If not then I don’t get the point of “polluting” the prc. Does this make sense to anyone?

Thank you!

Yes, it’s a better practice, especially with ORM objects with many relationships, to pass those as args. I found that out the hard way, myself. The prc/rc is so convenient that it’s easy to just throw things in there, but objects in there persist all the way through to the end of the request. By passing them as args, the objects are unloaded once the view content is rendered. In some cases, it can make a noticeable difference in your request times. Either way, it’s a better practice to explicitly pass your args as a structure and keep your rc/prc for globals or template variables created outside of the controller method being fired.

Jon

This is personal preference as you suspect, but I feel there’s a very good reason for our recommendation. In short, is all boils down to one word:

Encapsulation

Do you know those little lockers at the pool where you pay a quarter to store your personal belongings while you swim? imagine for a moment, if everyone paid a quarter to dump their shoes, towels, and flip flops into one giant, shared, bin. Now, this might work out pretty well if you were the only person at the pool. You might also get away with it if your hot pink sunglasses were so completely unique that they could never be confused with someone elses. What about if there were several large families all sharing that same locker with you? What if they use the same set of towels as you? Can you trust them not to steal your wallet? Wouldn’t be harder to identify lost items that no one was using? A personal locker seems like a good idea all of a sudden, doesn’t it?

Imagine for a moment, the following hypothetical page where each bullet is a separate event/view or layout:

  • Your sites home page
    • layouts.main
      • layouts.mainNav
        - layouts.productsMenu
        - layouts.specialOffersMenu
        - layouts.yourAccountMenu
      • layouts.breadcrumbs
      • mysite.home view
        - view.mainContent
        - view.dynamicFeaturedArticle
        - view.dynamicFeaturedArticle
        - view.dynamicFeaturedArticle
        - view.messageFromCEO
        - view.recentPurchases
        - view.pollOfTheWeek
        - view.emailSubscribePod
        - view.sidebarSocial
        - view.footerInfo

It’s a busy day at the pool, isn’t it? :slight_smile: This example isn’t too far of a stretch either and is pretty close to some sites I’ve worked with. Breaking apart a busy, or very dynamic CMS-driven page into separate events/views is very common. The issue is, most of those events/views have their own data that only they care about. What about the dynamic featured article? We used that view three times and it expects the same variable name every time. How do we keep all the variables separate and prevent accidental overwriting? How do it we mitigate debugging nightmares? The answer is, we encapsulate by writing self-contained bits of code that don’t “bleed” their state into unrelated parts of your site. This is a basic OO principle and it still works great in MVC. This is also a good idea for the same reason you should have never just put all your variables in the “variables” or “request” scopes.

So, if you’re already looking into reusable “viewlets” to break up large pages, then I would totally recommend encapsulating all the data they need to keep your sanity. However, if you’re building incredibly simple apps that just run a single event and render a single view inside a single layout, then there’s probably not much point to all this. Just stick the data in the prc and be done with it. At the end of the day, it’s your code so it needs to be easy for you to manage.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Obviously I’m still not getting the difference between args and prc. How are the two below different?

/// using args ////

var viewData = {
data1 = service.getData1(),
data2 = service.getData2()
};

event.setView( view=‘myView’, args=viewData );

Data 1: #args.data1#
Data 2: #args.data2#

OR

/// using prc ////

prc.data1 = service.getData1();
prc.data2 = service.getData2();

event.setView( view=‘myView’)

Data 1: #prc.data1#
Data 2: #prc.data2#

??

Thanks!

Perhaps i’ll try explaining it with code this time. Consider these two cfm templates that achieve the same end result but with different levels of encapsulation:

good.cfm

function doSomething( myArg ) {
// use arguments.myArg
}

function doSomethingElse( myOtherArg ) {
// use arguments.myOtherArg
}

doSomething( ‘private value only seen by this function’ );
doSomethingElse( ‘Another private value’ );

pollution.cfm

request.globalVar = ‘I am visible to any code in this request’;
request.anotherGlobalVar = ‘I am also visible to any code in this request’;

function doSomething() {
// use request.globalVar
}

function doSomethingElse() {
// use request.anotherGlobalVar
}

doSomething();
doSomethingElse();

Note how in good.cfm, the data used by the functions are passed right in and ONLY available to that function and nothing else. This is good encapsulation and I can call 1,000 functions, but my request scope will remain nice and clean.

If you look at pollution.cfm, you’ll see that the data used inside the functions are just place in the request scope and then pulled back out. While the code in this file will still run, it is poor encapsulation and harder to debug and write tests for. Calling a large number of methods this way would end up with dozens of variables all floating around the request scope-- some of the names possibly colliding.

If you can understand this, then just transfer that to the difference between args and prc (or rc for that matter). prc/rc are just request-scoped buckets where can put data. They work well, but in a large app, sloppy coding can lead to hundreds of variables in rc and prc. Args are passed straight into the event and are ONLY available to that even which needs them. This is cleaner and more encapsulated. it also allows you to call the same event over and over with different inputs with no worry of variable collision.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Ok, thank you for that. It seems I’ve got rc and prc variables wrong in my head. At the handler level I’m viewing rc vars as stuff coming in. I’m then passing those IN to the model to do stuff. They certainly go in as arguments there. The stuff I get back OUT from the model I was setting as prc vars and then sending on to view. In my head rc vars are coming in from view and prc are going back out to view. If rather arg vars are for going back to view what is prc for?

Thank you!

In their most basic form, rc and prc are really just two structs in the request scope that you can put stuff in. They are available to ALL views, handlers, and layouts. The only real functional difference is that rc is pre-populated with the contents of your form and URL scope. If you enable event caching, the cache key is based on the contents of your rc as well.

The idea in your head of stuff going ‘in’ and ‘out’ sounds about right.

If rather arg vars are for going back to view what is prc for?

It’s also for going back to the view :slight_smile: But it doesn’t have to just be that. Remember, not all apps are just a single event, rendering by a single view wrapped in a single layout. Events can call other events, render multiple views, and even nest multiple layouts. The stuff you put in rc and prc are available to EVERYTHING downstream. Event args are ONLY available to the specific event you pass them into which is why they’re ideal for viewlets (self-contained view).

Think of the prc as the “easy” way to get stuff from a handler to a view in a simple app, and think of event args as a more advanced technique in a more complex app to help encapsulate all your data. Honestly, if event args are this difficult to understand, just ignore them for now. It sounds like your app is simple enough that you don’t really need to bother. If at some point in the future you find yourself with an app that’s grown in complexity and size and you realize you’ve got a giant pot of variables all swimming around in prc and colliding, then you’ll be ready for event args :slight_smile:

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Thank you. I think the difference between prc and event args is clearer. Chaining events together is still a little fuzzy so I may be back in a few days. I appreciate the help. For several years I’ve used a different framework where things are chained together via XML. Some of these things get repeated a lot and in Coldbox I was looking at using interceptors. I just need to figure out when best to use interceptors vs. runEvent. I’ll get there.

Honestly I hadn’t thought of the args values going anywhere but back to a view. I was wondering “Why is this guy explaining function arguments to me?” : ) The “flow” in Coldbox is getting clearer. Sorry to be so dense.

Thanks again!

Irv

As Brad alluded, I think if you read up on “viewlets” and then imagine multiple viewlets on a page, then the reason for choosing args over prc will become more clear. It’s understandable to question the reason for the difference when you’re looking at a rather simple, Coldbox 101 type of app.

Think of interceptors as being a part of AOP, the idea is that you allow points in your application, to extend manipulate further work flow, rather than providing it as core functionality.

Rather than try to explain it.

http://en.wikipedia.org/wiki/Aspect-oriented_programming

A rather basic introduction would be, to say retrieve data from a webservice, then depending on who wants to listen to the response the data can be manipulated to any format for that function. It is very similar to C# Delegate to a degree, that you provide a mechanism that can be called to anyone who wishes to listen.

For example ContentBox, uses interceptors to extend the core features, by allowing authors of modules, to do things that ContentBox doesn’t do natively.

For example

When saving content / post / entry or whatever the content is, there maybe images that get attached uploaded, this would be handled by the file manager a separate module that can work on its own. The core of this is just that, very core features. But as an author, I can say when an image is saved I will intercept that call and make sure the images are of a certain size, then create the desired thumbnails. But as this is something that is maybe used in one or two situations, it is best to run with AOP / Interceptors.

But yeah, if you look at C# delegates or similar in Java, then you would have a fair understanding of how it fits into the picture.

Another example, would be to take the ContentBox entry, intercept it prior to displaying it and you can either have one feature strip anything like fonts or images or whatever, then another feature could be to turn code or snippets and format it differently. Now you get to keep the same functionality, but you get to extend it by listening and manipulating what is required.

Very good examples would be SaaS Applications, where customers require different features above and beyond core, that might be only for them. The list is endless when it comes to practicality.