11 Replies Latest reply on Mar 1, 2009 4:36 AM by Mihai Baboi

    CFC best practices

    Mihai Baboi Level 1
      Hello. Please help me out with a little issue I have. I've recently started working with CFC's and there is something that I want to get clear. I have seen two different ways to write CFC's (although I'm sure that there are many others). Let me get to the point. The first method uses an init() function that acts as a constructor.
      The second way does not use the init() function. It just has the set and get methods and uses "This" to refer to them. I will attach both code snippets at the end. My question is. What is the best way (if there is any)? Are there advantages to one of the methods? if there is anything I left out that would make my question more clear please let me know. Thank you for your time.

        • 1. Re: CFC best practices
          Dan Bracuk Level 5
          I don't normally do that type of work so I don't write those types of cfc's. Looking at your example, I'd do neither.

          I'd use the property scope for the name, id, etc instead of the this scope. The property scope is available to all the functions, but not to the calling template. I would also have a single init function that sets all the values. It would return true, not this.

          But then again, it depends on what you intend to do with your object after you have created it.
          • 2. Re: CFC best practices
            Level 7
            > Hello. Please help me out with a little issue I have. I've recently started
            > working with CFC's and there is something that I want to get clear. I have seen
            > two different ways to write CFC's (although I'm sure that there are many
            > others). Let me get to the point. The first method uses an init() function that
            > acts as a constructor.

            Good question!


            > <cffunction name="init">
            > <cfscript>
            > variables.attributes = structNew();

            One thing you could do with your init() method is to have optional
            arguments for each of your object properties here too. This allows the
            calling code to init() the object and set some properties in one hit,
            rather than having to init() then set().


            > variables.attributes.cityId = 0;
            > </cfscript>
            > <cfreturn this>
            > </cffunction>

            Here's a question for you. I see a lot of people doing this, and I just
            don't get it. You've got this <cfscript> block, but you stick the return
            statement outside it. Why not do this:

            variables.attributes.cityId = 0;
            return this;
            </cfscript>
            </cffunction>

            It's a very trivial thing, but it piques my interest.


            > <cffunction access="public" name="getId" returntype="numeric">
            > <cfreturn This.id>
            > </cffunction>
            > </cfcomponent>

            I would say with properties exposed in the THIS scope, one would not
            necessarily bother with getters. The whole point of THIS-scoped variables
            is that they're accessible directly. Using your example code, one would
            just do personDTO.id in the calling code.

            That said, I would almost never store my object's properties in the THIS
            scope, I'd keep them safely locked away in the VARIABLES scope.

            --
            Adam
            • 3. Re: CFC best practices
              -==cfSearching==- Level 4
              > You've got this <cfscript> block, but you stick the return
              > statement outside it. Why not do this:

              > variables.attributes.cityId = 0;
              > return this;
              > </cfscript>
              > </cffunction>

              My preference is to put return statements outside of cfscript blocks. To me it emphasizes the exit point of a function and I am less likely to overlook it. But technically either option is valid. So I think it is more of a stylistic preference. I am sure some might find the reverse more readable.

              > Are there advantages to one of the methods?

              One difference I see is that option #1 sets default values for each of the components properties (id, name, etcetera). Whereas option #2 does not. So an error might occur if you were to call one of the getX() functions too soon, because the properties are not defined yet inside the component.

              <cfscript>
              personDTO = createObject("component", "PersonDTO");
              id = personDTO.getID();
              </cfscript>

              That said, I completely agree with Adam's comments about using the THIS scope. I rarely use it either.

              • 4. Re: CFC best practices
                Mihai Baboi Level 1
                Thank you for all your to the point answers. I come from php so "This.id" came more natural to me as it resembled very much "$this->id". I understand now that the variables scope is the way to go for what I'm trying to achieve here. As for the <cfreturn>, I didn't pay much attention to it. I guess, as -==cfSearching==- said, it's a matter of preference. Me, that's the way I found the code in the book that I'm using to learn and it suited me just fine.
                • 5. Re: CFC best practices
                  Dan Bracuk Level 5
                  quote:

                  Originally posted by: Mihai Baboi
                  Thank you for all your to the point answers. I come from php so "This.id" came more natural to me as it resembled very much "$this->id". I understand now that the variables scope is the way to go for what I'm trying to achieve here.

                  Maybe, maybe not. I'll have to try this myself on Monday when I get back to work.

                  <cfcomponent name="abc">
                  <cfset x = 2>
                  <cffunction name="xyx">
                  <cfreturn true>
                  </cffunction>
                  </cfcomponent>

                  calling template.
                  <cfset x = 1>
                  <cfinvoke component="abc" method = "xyz" returnvariable = "def">
                  <cfdump var="#x#>

                  If you see 2, you had better reconsider that variables scope.

                  I don't actually know. I've never tried it.
                  • 6. Re: CFC best practices
                    -==cfSearching==- Level 4
                    > If you see 2, you had better reconsider that variables scope.

                    No, using the variables scope is fine:

                    The Variables scope in a CFC is private to the CFC. It includes variables defined in the CFC body (initialization or constructor code) and in the CFC methods. When you set Variables scope variables in the CFC, they cannot be seen by pages that invoke the CFC
                    • 7. Re: CFC best practices
                      Mihai Baboi Level 1
                      quote:


                      If you see 2, you had better reconsider that variables scope.

                      I don't actually know. I've never tried it.



                      I don't think I'm gonna have this problem. That CFC is going to be used to map the columns of the tables in the database so I'm going to load it from a query. Most of the times I'm going to call the "get" methods from the CFC so I can manipulate and display the data.

                      The only time I'm going to use the set methods is when I want to update a table. Maybe this kind of approach may seem odd to some of you, but as I said I come from PHP and I like some of the methods there. The objective is to have these DTO's (Data Transfer Objects) that I can use as an interface between the business logic and the database. Here is an example of what I mean by using the set methods for an update:

                      1. Load the DTO with data from the query ( return a single row by ID )
                      2. Change only the fields that I'm interested in updating ( personDTO.name = "corrected name" )
                      3. Call the method that updates the database using the data in the DTO object
                      • 8. Re: CFC best practices
                        Level 7
                        > 1. Load the DTO with data from the query ( return a single row by ID )
                        > 2. Change only the fields that I'm interested in updating ( personDTO.name =
                        > "corrected name" )
                        > 3. Call the method that updates the database using the data in the DTO object

                        Before you reinvent too many wheels, have a look at Reactor
                        ( http://reactorframework.com/) or Transfer( http://www.transfer-orm.com/).

                        Whilst you're about it, also have a gander at Model-Glue
                        ( http://www.model-glue.com/) and ColdSpring
                        ( http://www.coldspringframework.org/).

                        A lot of the work you might be setting out to do could already have been
                        done for you.

                        --
                        Adam
                        • 9. Re: CFC best practices
                          Mihai Baboi Level 1
                          quote:

                          Originally posted by: Newsgroup User
                          Before you reinvent too many wheels, have a look at Reactor
                          ( http://reactorframework.com/) or Transfer( http://www.transfer-orm.com/).

                          Whilst you're about it, also have a gander at Model-Glue
                          ( http://www.model-glue.com/) and ColdSpring
                          ( http://www.coldspringframework.org/).
                          Adam



                          I've read about all of these. I was most interested in Transfer and Reactor because I prefer ORM to MVC. I will admit that at the time I only read about them as a curiosity and I didn't dig to much into the documentation. That being said, I will admit that I like working with my own objects, because I can build them to work for my style of coding in stead if writing code to work with the built in objects of a framework. I must also add the fact that right now, I'm not working with ColdFusion, so there's no deadline looming over me. I just started to learn ColdFusion because I like very much. I think it's one of the fastest ways to get from database to browser. So I thought that by making my own objects an a sort of framework I get to dig into it more and learn more stuff. If I start working on a real project I will probably use Transfer or Reactor because the goal is to use a reliable framework that speeds up the development process, not play around with experimental objects.
                          • 10. Re: CFC best practices
                            Level 7
                            > I've read about all of these. I was most interested in Transfer and Reactor
                            > because I prefer ORM to MVC. I will admit that at the time I only read about
                            > them as a curiosity and I didn't dig to much into the documentation. That being
                            > said, I will admit that I like working with my own objects, because I can build
                            > them to work for my style of coding in stead if writing code to work with the
                            > built in objects of a framework. I must also add the fact that right now, I'm
                            > not working with ColdFusion, so there's no deadline looming over me. I just
                            > started to learn ColdFusion because I like very much. I think it's one of the
                            > fastest ways to get from database to browser. So I thought that by making my
                            > own objects an a sort of framework I get to dig into it more and learn more
                            > stuff. If I start working on a real project I will probably use Transfer or
                            > Reactor because the goal is to use a reliable framework that speeds up the
                            > development process, not play around with experimental objects.

                            I think what you say here is almost the model answer to getting up to speed
                            with CF, and then transitioning into a production environment. I wish
                            other people (ha: including myself!) had this take on things.

                            Best of luck with your experimentation, and obviously post up any questions
                            that crop up.

                            --
                            Adam
                            • 11. Re: CFC best practices
                              Mihai Baboi Level 1
                              quote:

                              Originally posted by: Newsgroup User
                              Best of luck with your experimentation, and obviously post up any questions
                              that crop up.

                              --
                              Adam



                              I'm sure I'll be back pretty soon, as there are still a lot of things that I haven't gotten to grips with. Thanks for all your support.

                              Mihai