Some of My Questions about Object-Orient Programming with ColdFusion

Wow. Some days I feel like I am just barely treading water on this Object-Oriented Stuff. Today is one of those days. I go to do a simple search on some concept in OO and I end up spending an hour and a half reading posts from all of these frakking geniuses

that make me feel dumber than a bag of hair.

I want to ask questions, but three things stand in my way.

  1. I don't want to bombard one or two people with all of my questions
  2. If I email one or two people, I don't want them to feel obligated to answer me
  3. It's hard to ask a question when I don't know all the terminology and I need to provide a huge example of what I am doing

So, to solve these problems, I am going to ask my questions here. This way anyone that wants can answer my questions in any of the following ways:

  1. Answer a question in the comments
  2. Write a blog post about it and link it in the comments
  3. Link me to an existing blog post
  4. Ignore this post completely and go back to surfing for por... er answers to their own questions

Without further yammering:

Using Transfer/Rector with your Service Layer

I was reading Brian Rinaldi's post on this topic, and it was great! But one thing that I am not sure it answered, and I am kind of confused about it: Is it OK for my service to be aware of Transfer or Reactor?

In Brian Kotek's post he says "This way, your manager doesn't have to know anything about the Reactor factory...". So I am confused. Is it ok for a service layer object to call Transfer or Reactor from its variables scope?


<cffunction name="getList" output="false" returntype="string" access="public">
<cfreturn variables.Transfer.List('pages.page') />
</cffunction>

It seems to me that by doing this that the Service layer becomes aware, and dependent on the ORM framework. Is this one of those no-nos I keep hearing about? If so, how do I do it "correctly"?

Bean Construction

I think I have the general concept of beans and object inheritance and composition down; however, putting them into practice is quite a different story.

So let's say I have a simple bean that represents a page on a web site. And that page can contain links in a one to many relationship. So I want object composition between page beans and link beans. So my question is, when I call for a specific page bean in my controller/listener/handler/whatever from my pageService, what should I get back?


<cfset pageBean = pageService.getPage('18') />

Should this return a fully populated pageBean, including an Array (or struct) of all of its link objects? Or should it only return the page bean and then with a separate call from my controller to the linkService should I get all of the links for that page and then add them to the pageBean?


<cfset aLinks = linkService.getLinkArrayByPageId('18') />
<cfset pageBean.setLinkArray(aLinks) />

If it should be a fully populated pageBean, with the linkArray, where should that be created? Do the links get set into the pageBean in the service layer using code like what I have above? Or is it requested by the bean itself (I doubt it), or does ColdSpring or Transfer do this for me somehow?

Using Tranfer/Reactor instead of or in addition to a DAO and Gateway

So I think the H3 tag there sums up my question. I think I know the answer to this, but I will ask for clarification. I think that if all I need are CRUD (Create, Read, Update, Delete) methods and the List methods and other methods included with Transfer/Reactor that I do not need a DAO or Gateway in addition to the ORM. But, if I do need functionality beyond what an ORM offers, I can have a DAO and/or Gateway present and inject them into the service layer without interfering with the ORM. Is this correct?

Wrap up

These are big, ugly (and probably mis-worded) questions, and no doubt some of you will think them quite silly or simple. But to me, and I am sure to many others, the answers are not obvious. I think all too often, the expert developers to whom many of us look up will blog about a topic with the assumption of a more learned audience. And if that is the intended audience, that is fine. But I know, in my blog browsing experience, there is a very big gap in between the very basic posts and the super advanced Kotek-talking-to-Corfield posts.

A lot of times I will also see posts that talk about a neat "technique" for accomplishing "X", and the blogger will post a snippet of "Here is all you need to add to your ...", and then we are left to figure out the rest on our own. Maybe these types of posts are only intended for people that already know the rest, but for me, they are very frustrating, because I say to myself, "That is what I was looking for! Where is the rest of it?". I am not skilled enough yet to figure out the rest on my own.

I hope that I can get some of these questions answered. I also hope I am not making a fool of myself revealing how little I really know.

Comments
phill.nacelli's Gravatar Hey Jason,
This is my non ORM way of doing, I'm sure most folks now are using Transfer but I have yet to jump on that bandwagon (I'm still a control freak when it comes to my objects but that's just a personal issue, not in any way meant as a lash at the great work Mark is doing with Transfer).

Basically what I do is inject LinkService into PageService (using Coldspring off course!) so that when page service is assembling the page it has the tool it needs to add the links for example, in this example I have an Operator that has a set of Authorizations and Roles, the following methods are in Operator Service but keep in mind that it also contains OperatorDAO, AuthorizationService, and RoleService passed into it by ColdSpring, each one of these objects are accessible via their own respective getter method (getOperatorDAO() returns variables._operatorDAO property of OperatorService), I hope this makes sense if not please feel free to shoot me an email:

   <cffunction name="getOperator" access="public" returntype="Operator" output="false" hint="gets operator instance, if the id is valid instance is loaded from persistence">
      <cfargument name="operatorId" type="Numeric" required="false" default="0" />
      <cfscript>
         var operator = createObject("component","Operator").init();

         operator.setId(id:arguments.operatorId);

         // get operator dependencies
         operator.setAuthorizations(authorizations:getAuthorizationService().getAuthorizationCollection());

         if(operator.getId()){
            readOperator(operatorBean:operator);
         }

         return operator;
      </cfscript>
   </cffunction>

   <cffunction name="readOperator" access="public" returntype="Void" output="false" hint="gets operator info form persistence">
      <cfargument name="operatorBean" type="Operator" required="true" />
      <cfscript>
         var operator = arguments.operatorBean;

         // retrieve operator info from persistence
         getOperatorDAO().read(operatorBean:operator);

         // if operator exists, get dependencies
         if(operator.getId()){
            // get operator roles
            operator.setRoles(getRoleService().getRolesByOperator(operatorId:operator.getId()));
            // retrieve operator authorizations
            getAuthorizationService().readOperatorAuthorizations(
               authorizationCollection:operator.getAuthorizations(),
               operatorId:operator.getId()
            );
         }

         return;
      </cfscript>
   </cffunction>

PS: I'll be going on vacation tomorrow for 10 days, but will be happy to answer any question you have when I get back. Cheers..
# Posted By phill.nacelli | 7/3/08 7:25 AM
Jason Dean's Gravatar @phil - Thanks for the outstanding comment. That really helps to clarify some of this for me. I can better see how the Service Layer should be working. I was hoping that it worked this way, because this seemed like the way to do it, but I wasn't sure, and I did not know how how to go about it. I have been putting off a project, a bit, because I did not want to proceed until I got this right. I was afraid that if I did it wrong that it would bite me about 12 hours in. So again, Thanks! I appreciate you taking the time.

btw, your Design Patterns presentation at cf.Objective() was one of my favorites at the conference. I look forward to hearing more form you. You have an excellent way of presenting information that makes it really understandable.
# Posted By Jason Dean | 7/3/08 8:01 AM
Kurt Wiersma's Gravatar 1. Using an ORM in your service layer - I usually have my DAO's be the only ones calling the ORMs frameworks. That way if need be I can swap out Transfer/Reactor for a custom DAO if I need to. In reality I rarely do this but it doesn't seem to hurt me since I am setting up a separate DAO from my service anyway.

2. Bean construction - I agree with Phil's method.

3. Basically I would use the ORM when you can and revert to sql when you cannot use the ORM listing features which happens quiet frequently for me.

You can see an example how I set this up in AppBooster by visiting my blog www.wiersmablog.com.
# Posted By Kurt Wiersma | 7/3/08 9:20 AM
Tom Chiverton's Gravatar Hay, why not ask on cf-talk or cfcdev (@cfczone.org tends to have better signal-to-noise ratio than cf-talk) - that way not only well you get a nice wide variety of answers, but other can benefit from listening.
Don't be afraid to use new words or what have you - as long as you make clear your skill level some of the frakking geniuses should be able to answer at the right level.
# Posted By Tom Chiverton | 7/3/08 11:29 AM
Jason Dean's Gravatar @Kurt, Thanks. I will look at AppBoster.

@Tom - I have never looked at those services before. I will do so now. Thanks for the tip.
# Posted By Jason Dean | 7/3/08 11:42 AM
fuzie's Gravatar Blogging your questions & observations is not a bad way to get the answers you seek. Then you even have a reference to point ppl to that you're asking on IRC or in a group list. I am somewhat of an OO n00b myself and will be watching your blog with interest. I'm actually in the middle of setting up my own blog, partially for similar purposes... and hopefully to help those in my stead somewhat.

I find ppl to be incredibly helpful in most cases. In fact, sometimes you get so many opinions on a topic that you're overwhelmed at which way is "the right" way. I finally just jumped in and went for it with what seems right to me, and I'm going to get a private code review at various points from willing experts here and there. Then I might get daring and open up some code for random comment. :)
# Posted By fuzie | 7/3/08 9:02 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1. Contact Blog Owner