NO MORE CAREER
POLITICIANS!
Get Out Of Our House: Replacing congress with TRUE citizens!
Contact Doug!
Learn About Doug!
View Doug Boude's online resume
updated 11/18/2009

View Doug Boude's profile on LinkedIn
Link to me!

Follow Doug Boude on Twitter
Follow me!

Be Doug's friend on Facebook
Befriend me!
(I promise not to follow you home)
OO Lexicon
Chat with Doug!
Recent Entries
You may also be interested in...
Web Hosting

best web hosting - top web hosting sites, thetop10bestwebhosting.com

Czech your Page Rank!
Check Page Rank of any web site pages instantly:
This free page rank checking tool is powered by Page Rank Checker service
Surf's Up!
Visit Egosurf.org and massage YOUR web ego!
My Score: 9,001
Doug's Books

Read (and recommend)

  • Men are from Mars, Women are from Venus
  • The Wisdom of Crowds: Why the Many Are Smarter Than the Few and How Collective Wisdom Shapes Business, Economies, Societies and Nations
  • Blink: The Power of Thinking Without Thinking
  • Head First Design Patterns
  • Transact-SQL Programming
  • What's So Amazing About Grace?
  • Just So Stories (Rudyard Kipling collection)

Reading

  • Prayer: Does it Make Any Difference?
  • Data Mining (Practical Machine Learning Tools and Techniques)
<< June, 2007 >>
SMTWTFS
12
3456789
10111213141516
17181920212223
24252627282930
Search Blog

Recent Comments
Re: Railo 3.1 on Windows Server 2008 and IIS7 - Part 3 of 3 (by Jon at 8/27 2:04 PM)
Re: Hosts File Changes Not Acknowledged on Vista 64 (by Spacy at 8/24 3:46 PM)
Re: THE DAY CFUNITED DIED (by ComboFusion at 8/23 10:50 AM)
Re: My Grandpa (by Tasha at 8/10 4:29 PM)
Re: Just What IS a 'Service Layer', Anyway? (by dougboude at 8/02 10:10 AM)
Re: Just What IS a 'Service Layer', Anyway? (by Isaac at 8/02 2:25 AM)
Re: PayPal IPN Coldfusion CFC (by Soyestudiambre at 7/25 6:12 PM)
Re: PHP vs COLDFUSION (by Tony Garcia at 7/17 11:24 AM)
Re: PHP vs COLDFUSION (by dougboude at 7/14 8:45 AM)
Re: PHP vs COLDFUSION (by Lola LB at 7/14 5:51 AM)
Categories
Archives
Photo Albums
Funnies (5)
Family (3)
RSS

Powered by
BlogCFM v1.11

27 June 2007
American Airlines, YOU SUCK!
American Airlines, if you were a gas, you would be malodiferous and noxious; if you were a teenage girl, you would be gangly and plain, nobody would ever ask you to the prom, and you would die a virgin.

This particular day, I've found myself with you, American Airlines, in an intimate setting, and all of the assumptions I had about you based on hearsay and things gleaned from between the lines over the years have turned out to be completely confirmed: you're absolutely hideous when it comes to everything you tout yourself to be good at.

Okay, I can understand that you can't do anything about the weather and that a major storm front between Dallas and DC is a good reason to keep the plane grounded on the tarmac while you calculate an alternate route. But THREE FREAKING HOURS to come to the conclusion that you're gonna have to go AROUND it? That amazing feat of absurdity is head-wagging in and of itself. Oh yes, you were "courteous" enough to give us updates every half hour, your likely under-paid captain reassuring the passengers that you were still working on coming up with an alternate route and that until somebody figured one out, we were "grounded indefinitely" (yes, he continued to use the word even three hours later...real good for morale, Einstein). But while we all sat there with nothing to do but cat nap and study the moles on our neighbors' necks, it took you two hours to even consider offering us a drink of water. Meanwhile, the "first class" passengers were being wined, dined, and doted upon continuously. By this time during the nightmare I'm noticing every little defect you have, American Airlines; the way you are sooo careful to ensure that you lay the little napkins face up...not to give me a nice map of the U.S. to look at like your MUCH more attractive competitor Southwest Airlines, but rather to shove your cheesy sleezy advertising in my face for Citi financial and their efforts to help me dig myself further into debt. I resent it, American Airlines, and say again: YOU SUCK!

THREE hours of letting gravity bring my coccyx and the metal frame of your undersized seat closer and closer to one another; three hours of my empty stomach attempting to implode upon itself, the anticipation of my obligatory snack growing more and more intense; wondering why, if you thought to bring me a drink (eventually), you didn't also think to offer me some peanuts or pretzels so I could satiate my hunger. Three hours later, when captain Smiley finally gave us the good news that the unseen geniuses who work with you had cleverly devised a solution to our dilemma and drew a line going AROUND the storm, I found out why you hadn't thought to offer me peanuts: YOU DON'T GIVE YOUR PASSENGERS PEANUTS! Ah, but you did lovingly offer to rape me by selling me a cookie for THREE DOLLARS! A 59 cent cookie, if that, for three bucks?!?!?

You truly do suck, American Airlines, without a doubt and unequivocably. You're a cheap, slutty, miserly, cruel, ugly thing who makes no secret of how little you truly care about your customer. The only thing about you that is remotely attractive (until one actually makes your acquaintance) is how CHEAP you are. You draw in the unsuspecting and unwary and milk them for all you can, then cast them out on the street, leaving them feeling quite used and abused. You hope that we'll go away thinking that "this is just the way flying is". Well, THIS traveler knows better, and can speak from experience when he says "YOU SUCK, AMERICAN AIRLINES!"

Ah, and the paradox of all paradoxes, the audacity you have when you speak lovingly to us over the intercome, "We know you have a choice when you fly, and thanks for choosing us
! We hope you'll come back!". More empty, absurd words could never be spoken, and if you, American Airlines, are naive enough to think that you are offering anything at all to the general public that is the LEAST bit attractive (besides being one of the cheapest ho's in town), you're sadly mistaken. I'm sure you adopted the line "we know you have a choice" from you more successful competitors and just thought you should say it, too; but you really shouldn't bother saying those words at all because it only makes you look even LESS business-savvy than you are.

If you ever want to have a hope of real success, of truly satisfying customers and making them WANT to return, American Airlines, then lay it to heart when I say, as a real world customer who currently loathes your very existence, "YOU SUCK!", and do something about that.

Doug out.
Posted by dougboude at 12:00 AM | PRINT THIS POST! | Link | 46 comments



23 June 2007
American Sign Language as a Second Language
Why I'm Learning Sign
On every Tuesday and Thursday evening in the month of June, I have been taking a sign language class. Of course the first question that tends to come to mind is "why?", so let me address that first. If you've ever read Kipling's 'The Elephant's Child', then you've caught a glimpse into the mind that drives one who is plagued with "insatiable curiosity"; they do odd things, like travel to the great, grey, green greasy Limpopo River to ask questions that to others seem unworthy of being uttered. I am plagued with a similarly insatiable curiosity (although I DO know what the Crocodile has for supper, O Best Beloved), and in particular am insatiably curious about languages. How one idea can be thoroughly communicated in so many different ways fascinates me, and so at any given point in my life since about the age of 16, I have been in the process of exploring some new language. Some stuck rather well, like Spanish, French, Albanian, and Hindi; Others linger in the form of a few words or expressions, like Mandarin, Hebrew, and Russian. American Sign Language is a language in its own right, with its own syntax and word form, so it too fell into my sights. I first learned a portion of it several years ago when I desired to do a Bible study with a deaf couple I had met. I spent several hours creating a list of all the potential vocabulary words I might need, then went to the library and looked up each one, drawing myself little pictures of how to form the word. I spent many hours practicing the same, and finally did have that Bible study. Presently, I'm in love with a woman who happens to have two profoundly deaf sisters and a deaf brother in law. Last month we went and visited her family in Chicago, and I felt myself to be quite handicapped when it came to communicating with them. Fortunately, they all read lips well and even speak, so their skill set made up for what I consider to be MY handicap in not knowing Sign Language; but I did resolve within myself that the next time we meet they wouldn't have to carry so much of the burden of communication. And so, I'm making Sign Language a part of my daily regimen!

Last night, as part of our class, I attended a performance of "Annie" put on by the San Antonio Deaf Dance Company. It was mandatory, as our instructor had made it part of the curriculum. I took my fiancee and five of my seven children. We arrived early and got into our seats amidst several of the kids' grumblings about how boring this was going to be. But an hour and a half later, after all was said and done, none of us had a single shred of regret that we had come, not even the kids! Everything was done in sign language, with interpreters for the hearing provided, but even though I know very little sign and my kids know even less, we all learned something about human communication, that there is so much more than words to it all, and of the incredible amount of information that can be transferred accurately by a simple raise of an eyebrow or a facial expression. So what appears to be at first glance a language that would severely impair one's ability to communicate deep thoughts or detailed feelings is actually probably more robust and alive than any spoken language ever could be.

The performance itself was amazing. As you know, "Annie" is a musical, so there were several songs, both solo and with chorus, as well as several dance numbers that required coordination among the dancers themselves. Most of the time, music did accompany those numbers, though once or twice they were done completely in silence. It was mesmerizing when, without song or music, the troupe performed flawlessly and in beautiful synchronicity. For those of us who are hearing and who are able to realize a different perspective on the challenge that such a thing can present, it was inspiring and impressive beyond words. I'm extremely glad that I took my kids, and I'm very happy at the final reactions that came from them. Whereas at first they thought it was funny...not the people's handicap, but the way signing appeared...by the end they were impressed, themselves, and had even managed to learn some signs just by watching the audience interact during intermissions.

Don't know any Sign Language yourself? I highly recommend that, the next time your local school district offers adult education classes that you sign yourself up and partake of the benefits that come by delving a little bit into the world that our non-hearing brethren live in. Empower yourself a little, become capable of doing your part to bridge the communication gap the next time you encounter someone whose primary language is visual. You won't regret it. ;)

Doug out.
Posted by dougboude at 10:03 AM | PRINT THIS POST! | Link | 5 comments
22 June 2007
Human-Protist Symbiotic Experiment
The man who could digest wood!
We all have one, don't we? A favorite protist. One protozoa out of them all that just stands out in our minds as THE protozoa, the one that captures our imagination and intrigues us to no end. Well, I must say that personally I have a list of about five protozoa that are at the top, but one has just recently topped them all: Triconympha. Oh yes, Paramecium with his 'oral groove' and cilia-covered body is amazing to behold as he swims about sucking his smaller cousins into his gullet; and Euglena...wow, a pioneer in the protista kingdom, blurring the line between plant and animal in a very politically incorrect manner. But Triconympha is my all time favorite as of late because, through MUCH experimentation, I have finally succeeded in breeding a strain that can survive in the stomach of a human being! Namely, me. You may be thinking "gross", or "wtf?!?", but allow me to elucidate. Triconympha has been a long time symbiotic partner of our little-loved friend the termite. He lives in his stomach and does Mr. Termite the favor of digesting the wood that termite eats. I learned this in sixth grade, and from that moment onward it has been a constant source of meditatory food for me as I marveled at how perfect their relationship was. I also longed to have that same kind of relationship with Triconympha. But alas! My gastric crib was quite inhospitable to the little guy! Every time I munched a sunflower seed (and ate the hulls, as is my habit), I longed to be able to receive not only the benefit of the huge amount of roughage the hulls provided me, but also the nutritional sustenance that I KNEW was locked in their, too! The only way I could do this would be by having my own personal colony of Triconympha living, breeding, and dying within me. Hence the experimentation that has led to my success!

I'm no gene splicer myself, so I relied on the gene splicing that's built into every living thing: reproduction. Since these little guys are single celled, they don't actually exchange genetic material during reproduction, but simply divide in half, producing two from one. So what I had to do was find individual specimens that exhibited unusually high tolerance to travel through my gut and intestinal tract. Once I had found several such specimens, I would give them time to multiply into yet another thriving colony, then perform another iteration of the "gut travel" procedure, until finally I had a thriving colony that were perfectly at home inside of ME! The entire process took about five years. At the rate that Triconympha reproduces, that actually equates to about four thousand years of evolution in human terms. I acting as the "natural selection" mechanism managed to guide them into exactly what I wanted them to be. Following are a few details of the experiment as it progressed, for your entertainment value.

Step one: Establish a thriving colony.
Where does one find a starter colony of Triconympha? Inside the stomachs of termites, of course! That is their natural habitat, and so that is where I went. Several days of searching the uninhabited lands around my subdivision resulted in the collection of thousands of donor termites. Now, how to extract the Triconympha...hmmm. Well, the first obvious approach was to just grind a bunch of termites to mush and hope the Triconympha could find their own way out. Microscopic examination revealed that, although the Triconympha were indeed emancipated from their gastric domains, they didn't do so well on the outside. What I needed then was some way of emulating a termite's stomach environment, only on a larger scale than the termite itself. Something maintainable, and preferably non-decaying. So, I determined the PH of the termite's stomach content and through a combination of white distilled vinegar, non-iodized salt, and distilled water, produced a solution with an equivalent PH; I produced what looked to be an approximate substitute for decaying wood chewed and swallowed by a termite by combining sawdust from sawing old wood with a diluted solution of off-the-shelf hydrochloric acid and my own saliva. Yep, that is gross, BUT it was precisely what the doctor ordered. I didn't know it at the time, but it was ALSO the first step in producing Triconympha that were acclimatized to the human body as a host. As a matrix in which to combine the "stomach juices" and "food", I used a sterile, non-lubricated or powdered surgical glove. A small piece of new sponge was sealed up in the opening of the glove so that  a free exchange of gases could take place. I know, I know, the danger of microbial invasion existed at that point due to the fact that the sponges pores are monstrous compared to the tiny openings that serve to exchange gases and nutrition within the mucous membranes of a termite, but it never seemed to be a factor in my experiments. I got lucky on that one.  Now, with the glove prepared, I tossed in a pre-measured amount of freshly ground termites and let the process begin. After three days I did a microscopic examination of the contents and found that the Triconympha were doing absolutely marvelous. I measured the PH again and found that adding the termite bodies had lowered it a bit, so I created a new matrix that had a slightly higher PH prior to the addition of the termites. That one, after three days, had a colony of Triconympha that were multiplying like crazy. I had found the magic balance and was ready now to set up the endurance test.

Step two: Endurance testing.
Now, how to find out which of these little buggers would be most prone to live in MY gut? I decided to gradually alter the environment of the matrices towards the environment of my own gullet. But what was that environment? I could look it up online, the PH of my stomach...but to be even more accurate, I had to measure it myself. I won't go into the gory details, but I did measure the PH of my OWN stomach and found it to be about actually a bit higher than the averages: I'm a 3.5. This actually made it a little easier for me since the PH of a termite's stomach is around 4.3. I set up ten test matrices, and decreased each of their PH by .1 every four days. Just prior to decreasing the PH, I would do a culture exam to see who was thriving and who wasn't. As soon as I saw a decrease of between 10 and 15% of active Triconympha, I would cease the PH adjustment schedule, remove a small sample of Triconympha from that matrix, and place them into a matrix that was .2 PH higher than what they had just come from. That culture would be allowed to grow for two weeks, after which the PH decrease regimen would begin again. Eventually, I had seven colonies of Triconympha who were living, breeding, and thriving in a PH of 3.5, which put me at the precipice of the final step in my experiment.

Final Step: Introducing The Colony to Doug Boude.
While I left the seven colonies to thrive, I now proceeded to do some preliminary wood digestion experiments on myself with which to compare results after introduction of the protozoa to my gut. Since sunflower seed hulls had been the catalyst for the experiment in the first place, I used them. Again, I won't go into the gory details, but suffice it to say that the process involved eating a pre-measured amount of sunflower seeds on an empty stomach, then closely monitoring and collecting appropriate stool samples for examination. As you may have envisioned (he he he he he), without Triconympha present, all I got was a neatly packaged lump of chewed sunflower seed hulls, with a slightly malodiferous disposition. I then introduced Triconympha into my stomach. It was an early Sunday morning. I filled three sterile gelatin capsules with samples from three of the matrices, and swallowed them down with a distilled water chaser. I then quickly ate a pre-measured amount of sunflower seeds, and waited. Although I thought I could imagine feeling the little guys working in my stomach, all I really felt was a bit hungry. Hours passed. I believe this was the first time ever I was actually giddy with anticipation at taking a poo. Finally, late that night, nature called. The results were astounding! The amount of fibrous hull present in my stool was a mere 5% of what it had been prior to Triconympha's introduction! The remainder of the mass more closely resembled what you might consider a "normal" poo consistency and texture, and with the same essence about it. Microscopic examination of the stool sample revealed some dead trace representation of Triconympha, but not nearly enough to indicate a complete evacuation of the critters. As a final test to conclude that they guys had indeed taken up residence within me, I forced myself to vomit. You guessed it: There under the microscope, within my own vomit, were living, swimming, happy Triconympha. SUCCESS!

So now I do believe that I'm the only living human being who has the benefit of being able to receive sustenance from the consumption of wood. Pretty cool, eh?

Doug out.
Posted by dougboude at 10:47 AM | PRINT THIS POST! | Link | 2 comments
20 June 2007
Circular Dependency Experiment
Circular Dependency is a phrase used to describe two objects who both use one another internally. That's simple enough. But...how the heck do those two OBJs get inside each other? And how do they behave once they're in there? These were some of the questions I needed answers to, and so I'd like to share with you my experiment and some of the things it taught me about circular object dependency.

I basically had the following questions I wanted to answer:

  1. How can I successfully get instantiated objects inside one another?
  2. Once instantiated, does object 2's manipulation of its internal copy of object 1 affect object 1's state, and vica versa?

Getting Objects Inside One Another
Okay, so how do we get an object inside another object? We inject it (embrace the phrase, you're gonna hear it a lot in the OO world!). With Coldfusion CFCs, this can be done one of two ways that I'm aware of: using "Setter Injection", or "Constructor Argument Injection". The Coldspring framework does that very thing for us when we leverage it in our apps, BUT I wanted to know what the raw, manual process of doing so looked like, so I created two sets of rudimentary CFCs, each of which has circular dependencies within them.

The first set (CFC1 and CFC2) have dependencies which utilize setter injection; The second set (CFCA and CFCB) use constructor arguments to get inside each other. CFC1 and CFC2 are identical, code-wise, as are CFCA and CFCB. Here is what they look like:
CFC1 and 2:
<cfcomponent displayname="CFC1 and CFC2">
    <cffunction name="init" access="public" returntype="any">
        <cfreturn this>
    </cffunction>
    <cffunction name="getMyName" access="public" returntype="string">
        <cfreturn variables._myname />
    </cffunction>
    <cffunction name="setMyName" access="public" returntype="void">
        <cfargument name="newname" type="string" required="true" />
        <cfset variables._myname = arguments.newname />
    </cffunction>   
    <cffunction name="getObj2" access="public" returntype="any">
        <cfreturn variables._obj2 />
    </cffunction>
    <cffunction name="setObj2" access="public" returntype="void">
        <cfargument name="obj2" type="any" required="true" />
        <cfset variables._obj2 = arguments.obj2 />
    </cffunction>
</cfcomponent>

(The Setter Injection method, as seen in CFC1, simply utilizes a "setObj2" method to set an internal variables-scoped variable to hold an instantiated copy of CFC2)


CFCA and B:
<cfcomponent displayname="CFCA and CFCB">
    <cffunction name="init" access="public" returntype="any">
        <cfargument name="obj2" type="any" required="true" />
        <cfargument name="myName" type="string" required="true" />
        <cfset variables._myName = arguments.myName />
        <cfset variables._obj2 = arguments.obj2 />
        <cfreturn this>
    </cffunction>
    <cffunction name="getMyName" access="public" returntype="string">
        <cfreturn variables._myname />
    </cffunction>
    <cffunction name="setMyName" access="public" returntype="void">
        <cfargument name="newname" type="string" required="true" />
        <cfset variables._myname = arguments.newname />
    </cffunction>   
    <cffunction name="getObj2" access="public" returntype="any">
        <cfreturn variables._obj2 />
    </cffunction>
    <cffunction name="setObj2" access="public" returntype="void">
        <cfargument name="obj2" type="any" required="true" />
        <cfset variables._obj2 = arguments.obj2 />
    </cffunction>
</cfcomponent>

(Notice that I still do have setters and getters for obj2; I didn't really have to have a setter, but the getter is needed so I can retrieve obj2 and call its methods)

Here is the code I used to instantiate CFC1 and CFC2 using the Setter Injection method:
<cfscript>
    //circular dependency using setter injection...
    obj1 = createobject("component","CFC1").init();
    obj2 = createobject("component","CFC2").init();
    obj1.setMyName(newname="Object 1");
    obj1.setObj2(obj2);
    obj2.setMyName(newname="Object 2");
    obj2.setObj2(obj1);
</cfscript>

Here is the code I used to instantiate CFCA and CFCB using the constructor argument method:
<cfscript>
    //circular dependency using constructor argument injection
    objA = createobject("component","CFCA");
    objB = createobject("component","CFCB");
    objA.init(obj2 = objB.init(obj2 = objA,myName="object B"),myName="object A");
</cfscript>

Okay, everything instantiated without any errors! Cool, and I have answered my first question. Now for question 2...

Object Behavior
How do these objects behave when set up in this fashion? To find out, I conducted interviews with each of the objects. Following are some exerpts and code snippets from those interviews (full interview can be seen here):

Interviewing obj1...

Q: What is your name?
A: My name is Object 1!
My name is #obj1.getMyName()#!
Q: What is your dependent object's name?
A: My dependent object's name is Object 2!
My dependent object's name is #obj1.getObj2().getMyName()#!

Interviewing obj2...

Q: What is your name?
A: My name is Object 2!
My name is #obj2.getMyName()#!

Q: What is your dependent object's name?
A: My dependent object's name is Object 1!
My dependent object's name is #obj2.getObj2().getMyName()#!

Q: Can you change your dependent object's name?
A: I don't know...let's give it a try, shall we?
(lots of grunting and straining sounds can be heard...)
<cfscript>
    obj2.getObj2().setMyName(newname="Eduardo");
</cfscript>

I think I did it! My dependent object's name is NOW Eduardo!
I think I did it! My dependent object's name is NOW #obj2.getObj2().getMyName()#!

Interviewing obj1 again...

Q: What is your name NOW, obj1?
A: My name is Eduardo!
My name is #obj1.getMyName()#!

Q: Why don't you go ahead and try to change YOUR dependent object's name...
A: Sure thing! My dependent object's new name is Florence. He he he he he.
<cfscript>
    obj1.getObj2().setMyName(newname="Florence");
</cfscript>
My dependent object's new name is #obj1.getObj2().getMyName()#. He he he he he.

Interviewing obj2 again...

Q: Obj2, is that really your new name?
A: Lemme check... Florence...yep!
Lemme check...#obj2.getMyName()#...yep!

I conducted the same interview with objA and objB, and the answers were identical.

My Conclusion
Circular dependencies, in my experiment, are nothing more than providing each object with a proper internal reference to the instance of the other object, in a reciprocal fashion. The fact that I could change the value of a variables-scoped variable in an injected instance of obj2, and that change be visible by obj2 itself from outside of obj1 proves that point unequivocably. Just for fun, I asked one final question of Obj1:

One Final Deep Question for obj1...

Q: Obj1, what is the name of your dependent object's dependent object's dependent object's dependent object?
A: It's name is Florence
It's name is #obj1.getObj2().getObj2().getObj2().getMyName()#


Cool stuff. Remember though, Coldspring is there for you to manage all of this so that you don't HAVE to do it manually. Coldspring can perform even deeper work, too, like injecting individual METHODS into objects on the fly! That's a little thing I like to call Aspect Oriented Programming, or AOP. You should take the time to investigate it.

Doug out.
Posted by dougboude at 2:26 PM | PRINT THIS POST! | Link | 3 comments
Just What IS Circular Dependency?
Circular dependency.

Initially, the phrase invokes visions of things that we naturally know to steer clear of, like infinite loops. If we've come to OO from a procedural world, we've probably been groomed to fear circular dependency in coding, reinforced by having encountered errors that demeaningly declared "Can't resolve circular dependencies, Idiot!". Circular dependency...it just sounds dangerous, doesn't it? Unstable, unpredictable, uncontrollable; without an end and without a beginning, as in the proverbial question of the chicken and the egg. In OO though, circular dependency needn't be a taboo phrase at all.

When you take a look at the natural world (of which Object Oriented methodologies are a rough emulation of), circular dependencies are common occurrences, and actually viewed as good things. I need my job and my job needs me. That's circular. I need my spousal unit and my spousal unit needs me. That's got a roundness to it, too (pun intended).  But, even deeper than the "we need each other" view, circular dependency implies that each of the two are within one another. Kinda like the ol' Frampton song, "I'm in you....you're in meEEeeeee....". A circular dependency in code is exactly the same thing: two objects who depend on one another for something and exist within each other. My user service needs my address service, and my address service needs my user service. We shouldn't be looking for ways to break these guys up! Rather, let us look at their relationship with admiration, because it is a perfectly natural one.

Now, some architects (we're ALL architects to some degree) might hold fast to a rule of "No Circular Dependencies", and rather than have two objects dependent upon one another directly, they'll create a third object to act as the broker between them. Instead of the two objects being injected into one another, those same two objects are instead injected into the third object, who orchestrates how they work together. I wouldn't say this is a bad thing, and in fact probably makes perfect sense to do so in many situations. Bottom line, though, is that we don't have to avoid circular dependency relationships when they do make sense.

All this talk about circular dependencies got me to wondering just how it all works under the covers. For instance, if I instantiate a CFC that needs another CFC internally, how can I do that without having first instantiating the OTHER CFC (who itself needs an instance of the first CFC I haven't instantiated yet!)? And if I DO manage to get instances injected into one another, will they be by ref or by val? In other words, will object 1 have a copy of object 2 inside of it, and my object 2 have a copy of object 1 inside of it? Or, will they both actually be seeing one another real time? Time for an experiment in object dependency! I'll share the results very soon.

Doug out.

P.S. Here is the link to my circular dependency experiment. (http://www.dougboude.com/blog/1/2007/06/Circular-Dependency-Experiment.cfm).  It REALLY helped clear some things up regarding how to "think about" this topic.
Posted by dougboude at 1:33 PM | PRINT THIS POST! | Link | 1 comment
10 June 2007
Global Configuration Settings in Model-Glue:Unity
Some Suggestions
When making the transition from procedural CF to OO, sometimes what was SO simple before can become a challenge (at least the first time). For instance, the way we used to pass around our app's DSN value was probably something along the lines of setting an application variable in our application.cfm or cfc, thus making it accessible throughout our app while consolidating the value to a single location for ease of change later. But now that we've decided to force ourselves to learn to do things in an OO fashion, where on earth is the "correct" place, or what is the "correct" way to perform this same action?

In our procedural apps, common sense told us to "find a place within the execution path that always gets called, no matter what, and check for and set your global value there...". Let's use that same line of thinking for our OO app, too, and find an appropriate spot in which to set our global variable.

Even in an OO approach, CF still respects application.cfc/cfm, so setting the value there could be an option. However, one of the chief tenets of OO is encapsulation, meaning that we try to make each aspect of the application as non-dependent as possible on the rest of the application. Setting our DSN in application.cfc/cfm then means that likely our urge would be to stuff it into the application scope:

<cfset application.dsn = "Horton" />

If I want to use that value within any of my model CFCs then, SOMEWHERE I'd have to write a line of code that talks to the application scope; not a best practice, and indeed immediately makes my CFC dependent on the existence of some value outside of itself. No bueno.

How 'bout instead we utilize a configuration bean...a tiny object whose sole purpose in life is to pack around global values I might need here and there, and to make itself available anywhere within my app? Now that makes my common sense tingle with delight. Utilizing Model-Glue:Unity, let me share a couple of ways I have done this very thing.

At this juncture, if you aren't familiar with the member of the Model-Glue: Unity trinity called Coldspring, it's time you two met. Coldspring is an expert bean handler, and is quite a versatile fellow when it comes to creating beans and making them available wherever you'll be needing them. Coldspring does all of what it does based on the content of its XML configuration file (Coldspring.XML), so it is within that file where we will 'instruct' it regarding our configuration values.

At this point you're probably thinking to yourself, "okay self, all I need to do then is create a CFC that handles configuration values for my app. I'll make a getter and setter method for my DSN, one for my images directory path, one for....". Hey, that is definitely a good way of thinking. HOWEVER, Coldspring has a surprise for you, O Best Beloved. Coldspring can automagically create that configuration bean for you, and all you gotta do is tell it what you want it to contain via the Coldspring.XML file! Allow me to
elucidate.

In order to auto-create one of these configuration beans, let's define it within Coldspring.XML, like so:
  <bean id="AppConfiguration" class="ModelGlue.Bean.CommonBeans.SimpleConfig">
    <property name="Config">
      <map>
    <!-- this is the DSN used throughout the app... -->
        <entry key="DSN"><value>Horton</value></entry>
    <!--  path the CSS directory -->
        <entry key="CSSPath"><value>/appCSS/</value></entry>
      </map>     
    </property>
  </bean>
(Note: Notice the class of our configuration bean...we're leveraging a built-in class of model-glue)

Now that we've defined it, from this moment onward we'll maintain our app settings RIGHT THERE. If the DSN changes, I'll change the value of the DSN entry key.

Making this configuration bean available throughout the app is a purposeful endeavor, meaning that you have to explicity tell Coldspring to make it available to a specific CFC. We do this by "injecting" it into other CFCs that we've told Coldspring about. Looky here:

  <bean id="EmailService" class="model.EmailService">
    <constructor-arg name="AppConfiguration">
      <ref bean="AppConfiguration" />
    </constructor-arg>
  </bean>

I've told Coldspring "I have an EmailService.CFC, and it is expecting an argument value named 'AppConfiguration', so when you instantiate EmailService for me, please go ahead and pass in an instance of my AppConfiguration bean as that value. Thanks man."

Okay, the only other thing you have to do in order for this to work smoothly is to ensure that the object you're wanting to inject the configuration bean into is prepared to receive it. With the approach we're taking, the proper way to do this is to make sure your CFC has an init method, and within that init method create a required argument named exactly the same as your constructor-arg name. Like so:

<cffunction name="init" returntype="EmailService" output="false" hint="Constructor">
    <cfargument name="AppConfiguration" required="true" />
    <cfset variables._config = arguments.AppConfiguration />
    <cfreturn this />
</cffunction>

Okay, so now we have our Coldspring simple config object injected. Pay attention, this is important: for every value we defined for this config object, you will access it via the following method: getConfigSetting([value name]). For instance, if within our EmailService object we have a method that needs the DSN value, we'll grab it with
<cfset myDSN = variables._config.getConfigSetting("DSN") />

Alternatively (and this is what I did), you can create a generic "GetConfigSetting" method within your recipient object, like so:

<cffunction name="GetConfigSetting" access="private" returntype="string" output="false">
    <cfargument name="name" required="true" type="string" />
    <cfreturn variables._config.getConfigSetting(arguments.name) />
</cffunction>

With that method present in your recipient object, you would access the DSN like this:

<cfset myDSN = GetConfigSetting("DSN") />


It's a little cleaner, I suppose.

Now, you could be thinking that since your config object contains values that may also be needed within a view, such as a CSS path, or an images directory path, that you'll need a way to make it available there, too. Let me toss out a suggestion based on the way I have done it.

Everytime a MG:U event is called, you can have listeners that execute beforehand based on the fact that they're listening for a call to "OnRequestStart", as in this snippet from my modelglue.XML file:


<controller name="MyController" type="controller.Controller">
   <message-listener message="OnRequestStart" function="loadConfiguration" />
</controller>

You can, within the method being referenced in onRequestStart, stuff the configuration bean into the event object, thus making it available to every other object referencing that event, INCLUDING your views! Let's look at the controller object mentioned in this example:

<cfcomponent displayname="Controller" extends="ModelGlue.unity.controller.Controller" output="false">
    <!--- Autowire / private getter --->
    <cffunction name="setAppConfiguration" access="public" returntype="void" output="false">
        <cfargument name="AppConfiguration" required="true" type="any" />
        <cfset variables._config = arguments.AppConfiguration />
    </cffunction>
    <cffunction name="getAppConfiguration" access="private" returntype="any" output="false">
        <cfreturn variables._config />
    </cffunction>


    <!--- Place the configuration bean into the viewstate --->
    <cffunction name="loadConfiguration" access="public" returnType="void" output="false">
      <cfargument name="event" type="any">
      <cfset arguments.event.setValue("appConfiguration", getAppConfiguration()) />
    </cffunction>
</cfcomponent>

A few things to point out here:
1. Because this object is a controller object, Coldspring gives us the privilege of autowiring in beans that it knows about by simply providing it with a "get" and "set" method named according to the bean we want to inject. In this instance, Coldspring already had created for us a bean called AppConfiguration, so by virtue of the fact that Coldspring saw our controller object had a method named "getAppConfiguration" and "setAppConfiguration", it assumed we wanted it to inject an instance of the AppConfiguration bean. Coool.
2. On request start, Model-Glue is calling our "loadConfiguration" method, which is taking the injected configuration bean and placing it into the Event bucket (some like to call it the event 'bus', but thinking of it as a bucket makes more sense to me). This automatically means that the configuration bean will be available in our viewstate as well, and from within any view can be referenced like


<cfset appConfig = viewstate.getValue("appConfiguration") />

<link rel="stylesheet" type="text/css" href="<cfoutput>#appConfig.getConfigSetting("CSSPath")#</cfoutput>styles.css" media="screen" />

Now, having shared all of that, I will tell you that if you're using Reactor within your app, you were already defining the DSN within the Coldspring Reactor Bean, and may not want to define the DSN twice, but rather would like to use Reactor's DSN value throughout your app. This can be done just as easily, only you'll be injecting not your appConfiguration bean into the CFCs that need the DSN value, but the "reactorConfiguration" bean instead (already exists within your Coldspring.xml file). Once injected, you'll get at your DSN value with a method called "getDSN()".

Here's something else to chew on that may be helpful to you (as it was for me): Besides just a global application config bean, you can also define configuration beans for different services that your app has. For instance, my app performs image manipulation, so within my Coldspring.xml file I defined a configuration bean called "ImageServiceConfig" that contains settings for thumbnail dimensions, large image dimensions, naming conventions, pathing information, etc., then I inject that bean into my ImageService.cfc. I do the same thing for my EmailService.cfc. This allows me to truly consolidate all of my application settings within my Coldspring.xml, simplifying maintenance in that regard.

That, Boys and Girls, is injection at its finest, and it allows me to maintain my app's global values in one place, just like I used to do with application.cfc/cfm.

Doug out.
Posted by dougboude at 9:58 AM | PRINT THIS POST! | Link | 8 comments