Skip to main content
Inspiring
March 20, 2013
Answered

A 'Best Practices' Question on Components

  • March 20, 2013
  • 2 replies
  • 1881 views

LET'S SAY I HAVE 2 FOLDERS...

Framework Components - Holds components that are used across multiple web applications which are setup to use the framework.

Application Components - Holds components designed for specific web applications (not global in it's functions)

In short, think of owning a Pizza store and a Burger store.  A method called "OrderIngredients" would exist in the "Framework Components" folder, because both stores (web apps) would utilize it.  However, the function "MakePizzaSlices" would be in the "Application Components" folder of the Pizza web app only, since there's no need for it to be in other web apps (that don't make pizza)

So here's the thing.  The FW COMS folder has about 12 coms, totaling about 542KB of code.  The APP COMS folder (for this particular app) has 4 files totaling 88KB.

SO HERE'S MY QUESTION...

Performance-wise, have you found it better to just instantiate everything into the APPLICATION scope onApplicationStart so that code can reference this whenever it wants without having to check for whether it has been instantiated yet?  Or do you prefer instantiating the components on an 'as-needed' basis?

For the former, any REQUEST-based component, such as template generation, could be instantiated off the component in the APPLICATION scope and exist for just the duration of the REQUEST.  I'm just looking for what isn't going to overload the server.  Hopefully holding <1MB of data in memory for the duration of the Application's timespan is OK.

    This topic has been closed for replies.
    Correct answer Adam Cameron.

    So I should instead reference it like

    <cfset REQUEST.template = APPLICATION.coms.template.init() />

    The init() method would return THIS, and then the REQUEST.template can operate independent of the template component that I instantiated into the APPLICATION scope. Is that the right line of thinking?


    No, just go request.template = new Template().

    You need a Template instance each request, so just instantiate it each request. There's no point in having it in the application scope too.

    --

    Adam

    2 replies

    Inspiring
    March 20, 2013

    I'd not optimise your code until you need to. And the size of components you are talking about are not big anyhow.

    So I'd design your application the way it is logically supposed to come together, and deal with optimisations when you identify a need (and a resolution) for them.

    So if you have a component that should be a singleton: implement it that way; if you have a component that should be transient: implement it that way.

    --

    Adam

    Inspiring
    March 20, 2013

    Hey Adam, thanks for the input!

    So you're saying "Just code in a way where the application assumes all components are instantiated" (and use try/catch blocks in the event the component is not. Right?  I have to look up what "singleton" and "transient" components are.  If that's literal

    Inspiring
    March 21, 2013

    So you're saying "Just code in a way where the application assumes all components are instantiated" (and use try/catch blocks in the event the component is not. Right?  I have to look up what "singleton" and "transient" components are.  If that's literal

    I more meant that just instantiate the thing when you need it, eg:

    theObjectYouNeed = new TheComponent();

    theResult = theObjectYouNeed.someMethod();

    etc.

    It doesn't sound like you have enough components to worry about doing this, but you might want to look at ColdSpring (or something of its ilk) to manage the components/objects for you. It does make life easier if you need to scale up, although it will perhaps had a slight overhead to start with, it won't be such that it matters.

    --

    Adam

    Participating Frequently
    March 20, 2013

    1MB of memory is not a very large amount of data to cache things in.

    However, one would make the argument of whether you needed to cache them

    at all. If you have a low traffic site, and your components don't take a

    long time to set up, I might avoid the caching of the components because

    it isn't needed.

    If you do need to cache the components, you'll need a way to kick over

    the cache when you make updates. This is often done by a URL parameter

    and using the Application.onRequestStart() method to see if the

    components need reinitialization.

    If you are going down this route, I'd say it might be a good idea to

    start looking at a factory object to handle the creation of the

    components and to manage the state for you. You can look at LightWire or

    DI/1 for something simple, or Wirebox or Coldspring for something more

    robust. It'll help you later on when your design may require one

    component to make another one of your components.

    DW

    Inspiring
    March 20, 2013

    Thanks for your input Dan!

    I haven't done the metrics, and I might just be picking nits when it comes to the performance difference between doing it one way vs. the other.

    I know that when I do instantiate the applications into the APPLCIATION scope, making subsequent changes (without restarting the application) is ganked simply because the server is holding onto the old code for the duration of the app's lifespan.  Generally, my remote environment, which is controlled by my host, is restrictive only to the point where they forcibly cache template requests, so if I update page code and upload it to them via FTP, often times I have to login into the CP and use their "clear template cache" function.  A pain in the butt, but it seems that's how they "optimize" their shared hosting Coldfusion plans.

    I guess I can just store everything into the app, and maybe even reduce the application timespan from 4 hours to something smaller like 2 hours.  The application startup can take a moment longer to server up the first request, but at least I wouldn't have to code tons of logic on "Is this component instantiated?" and instead, just write code as if it DOES exist (but of course, using TRY blocks to capture in the event it isn't)