11 Replies Latest reply: Mar 24, 2013 3:51 PM by Aegis Kleais RSS

    A 'Best Practices' Question on Components

    Aegis Kleais Community Member

      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.

        • 1. Re: A 'Best Practices' Question on Components
          DanWilson_ MeganK

          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

          • 2. Re: A 'Best Practices' Question on Components
            Adam Cameron. Community Member

            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

            • 3. Re: A 'Best Practices' Question on Components
              Aegis Kleais Community Member

              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)

              • 4. Re: A 'Best Practices' Question on Components
                Aegis Kleais Community Member

                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

                • 5. Re: A 'Best Practices' Question on Components
                  Aegis Kleais Community Member

                  Ah, found a good readup on Singleton and Transients.  >> http://www.fancybread.com/blog/post.cfm/a-coldfusion-transient-factory-example

                   

                  Interesting read.

                  • 6. Re: A 'Best Practices' Question on Components
                    Adam Cameron. Community Member

                    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

                    • 7. Re: A 'Best Practices' Question on Components
                      Aegis Kleais Community Member

                      So would it be fine then for, in the onApplicationStart() to just loop through all components in the 'coms' folder and store them into a structure, say, 'APPLICATION.coms'.  So if I had, say 3 coms called 'data.cfc', 'templates.cfc' and 'error.cfc', then there would be a:

                       

                      APPLICATION.coms.data

                      APPLICATION.coms.error

                      APPLICATION.coms.template

                       

                      And in th event that I needed to create an instance off one (like template, since it handles per-user template generation needs rather than data which handles calls made to datasources), I could do something like:

                       

                      REQUEST.myTemplateObj = new APPLICATION.coms.template().

                       

                      And, being in the REQUEST scope, it will die automatically at the end of the request, right?

                      • 8. Re: A 'Best Practices' Question on Components
                        Adam Cameron. Community Member

                        No. You need to understand the difference between a component and an object.

                         

                        When you go

                         

                        application.coms.template = new Template();

                         

                        That's creating an object (application.coms.template) instance of the component (Template). So on the RHS of that statement, you need to use a component name.

                         

                        If in your code you need a tansient Template object, just create one. only put non transients into the application scope.

                         

                        --

                        Adam

                        • 9. Re: A 'Best Practices' Question on Components
                          Aegis Kleais Community Member

                          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?

                          • 10. Re: A 'Best Practices' Question on Components
                            Adam Cameron. Community Member

                            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