Categories
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

<< July, 2007 >>
SMTWTFS
1234567
891011121314
15161718192021
22232425262728
293031
Search Blog

Recent Comments
Re: Disappearing IE Popup Window During Save/Open Dialog (by LZ at 4/20 7:58 AM)
Re: Create Dynamic WHERE Clauses in PHP (by pooja at 3/20 7:29 AM)
Re: Just What IS a 'Service Layer', Anyway? (by EugenK at 3/07 7:56 PM)
Re: Using Google as your CF Mail Server (by 5starwebteam.com at 2/25 1:27 AM)
Re: Why Provide for Service layer objects in CFWheels? (by Steven Benjamin at 1/25 11:43 AM)
Re: What is an 'Advanced' Coldfusion Developer? (by ColdFusion Developer at 12/24 5:14 AM)
Re: Equivalent of SQL "TOP X" in Oracle (by Ashenafi Desalegn at 12/06 5:29 AM)
Re: PHP Export to Excel Snippet (by serene at 12/05 1:44 AM)
Re: Just What Is 'Application Logic', Anyway? (by Arif at 11/13 8:06 AM)
Re: Hosts File Changes Not Acknowledged on Vista 64 (by Aaron at 10/22 2:31 PM)
Re: PHP Export to Excel Snippet (by Jafar Shah at 10/10 4:28 AM)
Re: Viewing Option Text (in IE7) that's Wider than the Select List (by Chenelle S at 10/04 12:53 PM)
Re: PHP Export to Excel Snippet (by Kilo at 9/26 5:20 PM)
Re: Porting Coldfusion Code to Mura (by tariq at 9/03 9:51 AM)
Re: Just What IS a 'Service Layer', Anyway? (by James at 8/27 4:06 PM)
Re: Calculating Business Hours (by helen at 8/14 2:54 AM)
Re: What IS 'Business Logic', Anyway? (by dougboude at 8/06 11:30 AM)
Re: What IS 'Business Logic', Anyway? (by Adrianne at 8/06 10:29 AM)
Re: Family Law: The Weapon of Choice for Woman Scorned (by dougboude at 8/04 4:39 PM)
Re: Family Law: The Weapon of Choice for Woman Scorned (by Lola LB at 8/04 7:43 AM)
Archives
Photo Albums
Funnies (5)
Family (3)
RSS

Powered by
BlogCFM v1.11

31 July 2007
Coder Funnies (well, I think they are!)
This is a photo blog, click here to view all thumbnails. or click here to view the text of this entry.

A while back my sense of self-entertainment took the form of cartooning and over the course of a week I drew up a few that I thought were funny. Of course, everybody has a different sense of humor, so what makes my diaphragm spasm may not affect you at all. If not, well, I can only speculate that there's something terribly handicapped about your sense of humor, and I sincerely hope at some point  that a Lourdes-level miracle occurs (for some, that's what it takes!) and you suddenly find it healed. Just kidding. I'm man enough to accept that I may be somewhat more warped than the average gnurd bird. Anywho, without further adieux, click the pic links at the top if you wanna see into my 'maginations....
Posted by dougboude at 12:26 AM | PRINT THIS POST! | Link | 1 comment



27 July 2007
Model Glue Views Demystified
At first, getting a grasp on how to "think" about rendered views in Model Glue may appear to be challenging; but I tell you, that you already know exactly how to think about them. If you have EVER included a template using <CFINCLUDE>, then you have a two minute learning curve to working with views in Model Glue.

Breaking your page up into individual pieces, and then including those pieces later on as needed is not a new thing for most of us. That is precisely what Model Glue allows us to do as well. Is it ever required that we divide our code into individual templates? Nay, and neither does Model Glue require it. It is, however, a very good idea in most instances, and MG gives us a very easy way to do this.

Picture if you will, a template.

We have dsp_main.cfm that will act as our layout, containing only DIV tags with appropriate IDs. Dsp_main.cfm also includes our external style sheet to provide appropriate positioning and look and feel to whatever content we put into those DIVs. Before Model Glue, we'd do it like this:

<html>
<head>
    <title>My Composite Template</title>
    <link rel="stylesheet" type="text/css" href="css/styles.css" media="screen" />
</head>

<body>

<div id="header"><cfinclude template="dsp_header.cfm"></div>
<div id="nav"><cfinclude template="dsp_nav.cfm"></div>
<div id="body"><cfinclude template="dsp_body.cfm"></div>
<div id="footer"><cfinclude template="dsp_footer.cfm"></div>

</body>
</html>


Nothing new there, right? With Model Glue, the same dsp_main.cfm looks like this:

<!--- grab my rendered views out of the viewcollection... --->
<cfset header = viewCollection.getView("header") />
<cfset footer = viewCollection.getView("footer") />
<cfset body = viewCollection.getView("body") />
<cfset nav = viewCollection.getView("nav") />

<html>
<head>
    <title>MG View Demo</title>
    <link rel="stylesheet" type="text/css" href="css/styles.css" media="screen" />
</head>

<body>

<div id="header"><cfoutput>#header#</cfoutput></div>
<div id="nav"><cfoutput>#nav#</cfoutput></div>
<div id="body"><cfoutput>#body#</cfoutput></div>
<div id="footer"><cfoutput>#footer#</cfoutput></div>

</body>
</html>


With Model Glue, rather than include those templates within the page itself, the templates were pre-rendered (almost exactly like using a CFSAVECONTENT), the rendered html stuffed into what's called the ViewCollection, and then we simply grab that rendered HTML out of the ViewCollection and output it in a very familiar fashion.

Now, how were those individual templates included? We told Model Glue to do it within the Modelglue.XML file that defines our individual events. For instance, let's say the event we called was 'main.landing' (http://www.mysite.com/index.cfm?event=main.landing). The relevant XML looks like this:

<event-handler name="main.landing">
    <broadcasts />
    <results />
    <views>
        <include name="body" template="dsp_content.cfm" /><!-- available in the viewcollection as 'body' -->
        <include name="nav" template="dsp_nav.cfm" /><!-- available in the viewcollection as 'nav' -->
        <include name="footer" template="dsp_footer.cfm" /><!-- available in the viewcollection as 'footer' -->
        <include name="header" template="dsp_header.cfm" /><!-- available in the viewcollection as 'header' -->
        <include name="main" template="dsp_main.cfm" /><!-- container template to layout individual parts -->
    </views>
</event-handler>


Using the 'include' tag within the 'views' tag, we told Modelglue which templates to render. Of note is the fact that the order in which they are rendered is completely irrelevant, WITH ONE EXCEPTION: the template that acts as the layout container MUST BE RENDERED LAST.

Also of note is the fact that each of your view templates should act independently of one another. For example, let's say that a Model Glue variable is needed in the dsp_nav.cfm and that same variable is also used somewhere in the dsp_content.cfm template. It would be bad practice for you to retrieve that variable within dsp_nav.cfm and then attempt to access the retrieved instance from dsp_content.cfm; each template should be retrieving it for themselves.

That's it, boys and girls. Nothing to it, and very little difference from the way you've been using <CFINCLUDE> all along!
Posted by dougboude at 12:01 PM | PRINT THIS POST! | Link | 4 comments
23 July 2007
Anti-Spam snippet
When I first began blogging, I was naive enough to think that porn bots (or whatever they're properly called) wouldn't find me. Wrong. So, I enabled the Captcha that comes built in to BlogCFM (yep, not CFC...I'm a rebel). That immediately thwarted their attempts at decorating my blog posts with colorful solicitations. Then a month or two later, I got a sudden influx of the same spam! So, I swapped out my captcha with something that would require some real thought: a math problem. That stopped them for another couple of months, then lo and behold it happened again. I really have no idea how the spam hackers do it, but it has resulted in yet another evolution in my efforts to stop the spam. So far it's worked solidly, so I thought I'd share it in case anybody else might find it useful.

It consists of a function that generates a question that must be answered, and the answer to that question. It will ask the commenter to figure out what letter is exactly X number of places before or after a randomly selected letter in the alphabet, then directs them to type their answer exactly Y number of times in the answer box. Upon page load the correct answer is saved to a persistent variable, then when the comment is submitted the answer typed (form.answer) is compared to the stored answer (session.answer).  Simple enough I think, but with enough randomness to make it something that can't be automatically breached without some real effort.

Here's the code for the function:

<cffunction access="public" name="genQuestion" output="false" returntype="struct" description="I generate a random question to use as an antispam key">
    <cfset var stReturn = structnew() />
    <cfset var firstnum = randrange(1,4) />
    <cfset var secondnum = randrange(1,4) />
    <cfset var letter = randrange(5,20) />
    <cfset var where = randrange(1,2) />
    <cfset var answer = "" />
    <cfset var i = "" />
    <cfset variables.numbers = "one,two,three,four" />
    <cfset variables.letters = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z" />
    <cfset variables.beforeafter = "before,after" />   
    <CFSET stReturn.times = randrange(1,4) />
    <cfset stReturn.question = "What letter comes " & listgetat(variables.numbers,firstnum) & " places " & listgetat(variables.beforeafter,where) & " the letter " & listgetat(variables.letters,letter) & "?<br>Type your answer exactly " & listgetat(variables.numbers,secondnum) & " times in the box below." />
    <cfif where eq 1>
        <cfset letter = letter - firstnum />
    <cfelse>
        <cfset letter = letter + firstnum />
    </cfif>
    <cfloop index="i" from="1" to="#secondnum#" >
        <cfset answer = answer & listgetat(variables.letters,letter)/>
    </cfloop>
    <cfset stReturn.answer = answer />
    <cfreturn stReturn />
</cffunction>

(the function returns a structure containing the keys "question" and "answer")

Here's some starter code for utilizing it:

Code to evaluate saving a comment...
<cfif isDefined("saveComment")>
    <cfif form.answer neq session.answer>
        <cfset errorMessage = errorMessage & "<li>Invalid anti-spam key.  Please try again.</li>#Chr(10)#">
    <cfelse>
        <!--- perform comment saving here --->
    </cfif>
</cfif>


Code for displaying question and capturing answer:
<cfset variables.spamquestion = genQuestion()>

<h3>Please answer the following question:</h3>

<CFOUTPUT><STRONG>#variables.spamquestion.question#</STRONG></CFOUTPUT><br>
Type in the answer to the question you see above:
<input type="text" name="answer" size="6" maxlength="6" required="Yes" Message="You must complete the anti-spam field.">

<!--- save the answer to session for evaluation after the form is submitted... --->
<cfset session.answer = variables.spamquestion.answer>


Hope it helps!   :)
Posted by dougboude at 2:17 AM | PRINT THIS POST! | Link | 6 comments
17 July 2007
EgoSurf™ Formette Snippet
EgoSurf...I'm not really sure what to make of it, but it's an interesting use of asynchronous processing, to say the least. Anyway if you haven't heard of it, it's a site that will do deep searches of various search engines for you and your associated web site, then score you based on the results. I thought it was interesting enough to put a formette in my side nav, so thought I'd share the code in case anybody else was interested in doing something similar. It took a little time to dig through and find the hidden fields and what values are expected, etc., so hopefully this will save someone some time. Without further adieux, here it is in all its splendor:

<form action="http://www.egosurf.org/search.php" method="get" target="_blank" name="egosurf">
    <TABLE CELLPADDING="1" CELLSPACING="1">
        <tr>
            <td align="right" valign="bottom">You:</td><td><input type="text" name="search" size="17" /></td>
        </tr>
        <tr>
            <td align="right" valign="bottom">Your Web Site:</td><td valign="bottom"><input type="text" name="resource" size="17" /></td>
        </tr>
        <tr>
            <td colspan="2" align="center"><input type="submit" name="fj" value="Find Your EgoSurf&trade; Score!" /></td>
        </tr>
    </table>
    <input type="hidden" name="ds" value="1" />
    <input type="hidden" name="e-g" value="1" />
    <input type="hidden" name="c-g" value=".com" />
    <input type="hidden" name="c-y" value=".com" />
    <input type="hidden" name="c-m" value=".com" />
   
</form>
Posted by dougboude at 6:36 PM | PRINT THIS POST! | Link | 0 comments
10 July 2007
Promoting Family Unity
How to Build a Patio

We just moved into a new house. Fairly large, 2,500 square foot, two story house nestled (very tightly!) in a new subdivision in north San Antonio. The back porch is extra large and shaded by its own roof from the cruelly hot south Texas sun. This provides an absolutely lovely place to set up the hammock and relax on a breezy evening with a cold glass of white merlot and some tuneage; but, for fear of scorching the underside of the porch roof, it provides us no place to put the grill!

Anybody who knows anything about Texans, especially south Texans, knows the absolute imperativeness of BBQ at least once a week. Grilled skirt steak (fajitas), corn on the cob, asparagus dowsed in olive oil and lemon pepper, brauts, and all the other fixins that accompany such a cornucopia are as much a requirement for us as the thick humid air that keeps our terrestrial gills in working order. Now, you may wonder why we wouldn’t just put the grill right out there in the yard somewhere like people in places such as Missouri or Michigan do. What are we afraid of? That we might perspire if we have to stand in the sun? Do we have a phobia of grass? Nay, my foreign brethren (everybody NOT from Texas is a foreigner); The thing that deters us from spending too much time standing in one spot in our yards down here is a little thing I like to call Fire Ants. If you go to any house in San Antonio, step into the yard and stand still for more than a couple of minutes, a Fire Ant WILL climb onto you, find a bare piece of skin, and with great purpose, sting you repeatedly until you put it out of your misery. Though we South Texans have learned to live side by side with them to a degree, it has only been by accepting that the grass, any and all grass, is their territory. Hence our family’s need for a place to put the grill. The solution we came up with was to build a patio.

HOW TO BUILD A PATIO

Items Needed

  • One Long-Handled Flat Blade Spade
  • Two each 40 pound bags of course sand
  • One each 40 pound bag of crushed (or decayed) granite
  • Thirty three bricks
  • Your spousal unit, if applicable, and all the kids you got

Directions

1) Gather your family together and discuss the idea of making a patio for your BBQ or outdoor fireplace. If you don’t own a BBQ or outdoor fireplace, discuss getting one. As the father, husband, and guide of your household, ensure that the conversation ends up as all in favor of the project by using your experience, wisdom, and skills in gentle persuasion.

2) Set goals for the project. Procurement of the items can be a separate task from the actual building of the patio if need-be, due to time constraints.

3) Take all or as many as possible of the family on the outing to procure the needed items. Make sure to include the kids in on the process of deciding which sand, spade, and granite to purchase. Also, make sure you ask them if they can think of anything else you might need for the project (suggest gloves, bottled water, and other such amenities if no one else thinks of them  ).

4) Upon arriving home, enlist the aid of the family to transport the items to the construction site. Be sure to feed everyone’s anticipation and excitement of the final product.

5) Upon undertaking the actual construction, assign tasks. You will need:
  • A waterboy/girl and general purpose gopher or two;
  • Someone to provide and maintain the background music;
  • Mud puppies (kiddos to help remove mud/dirt from the hole and to dig through clods already removed to find worms and grubs to study);
  • A surveyor (someone to help you measure and layout the patio boundaries)
 Set all assigned personnel to accomplishing their tasks as needed

 6) Using stakes (or screwdrivers, or any other item you can hammer into the ground), mark the corners of your patio. Once marked, re-measure to ensure that each side is 40 inches long.

7) Using the spade, dig the entire border of the patio’s foundation. Remove all dirt/clay to a depth of about 4 inches. Be sure to keep the entire hole’s bottom level so that as few dips or humps are present as possible. If need be, task the Mud puppies with putting some dirt back into low areas to even it out.

8) Once the hole is prepared, pour in both bags of sand and level out.
 Place bricks into the hole, ensuring that each brick placed is level with the ones adjacent to it. More than one person can perform the brick placement simultaneously, and in fact, this is recommended in order to lend a greater sense of accomplishment and participation to the group. Here is the pattern for the bricks:


9) When all bricks are in place, pour a large pile of the crushed granite at each opposite corner of the patio. Have all available hands rub and roll granite around on top of the patio until all crevices appear to have been filled. Save the remaining crushed granite for another time when the fill will have settled, revealing the need for another round of “filling the gaps”.

10) Instruct the waterboys/girls to bring refreshments to the other workers and themselves. Make sure the radio station selected is one that the majority enjoy, and break out the chilled blush for you and the spousal unit.

11) Chillax for a half hour, making sure that everybody gets praise for a job well done. Talk about how the patio will be used, imagining scenarios out loud and even planning as a group your first usage of it. Also, plant the thought of coming up with a next family project.

CONCLUSION

Few things promote such sincere togetherness and family unity as do joint projects, and this was no exception. So many good things came from this task...the cooperation, the sense of accomplishment, the planning and procurement skills, the practicing of the mindset to not be afraid of hard work, the sweat equity that everybody contributed and thus a stake in seeing it succeed, the exercising of love and patience, the overall feeling of ‘togetherness’ that was promoted; And more than that, the hope that this patio represents: the future memories we’ll all make out here BBQing as a family.

Posted by dougboude at 5:34 PM | PRINT THIS POST! | Link | 2 comments
05 July 2007
DEMYSTIFYING JSON (for myself)
I'm doing this post because the term 'JSON' has continued to appear here and there within blog posts, conference sessions, articles, and emails that I consume as part of my professional growth regimen. Despite the fact that the term is so very often mentioned casually as if everybody has known about it since Kindergarten, the greater part of my understanding of JSON is barren except for the few clues I have managed to glean through context. So, I decided to take the time to get to know JSON a little more intimately, and learned some interesting things.

WHAT I THOUGHT IT WAS
Based solely on the info I managed to gather from "between the lines", I knew that JSON stood for JavaScript Object Notation, and that it was an alternative to XML when dealing with the results of Ajax calls. Knowing that much, I could deduce that it was basically "data in a string". But what it looked like, how to handle it, and why I would want to do it were still questions in my mind.

WHAT I FOUND IT TO BE
JSON is indeed a string representation of simple or complex data, just as is XML, only without the tags AND without the need to treat that string as a document type in order to transverse it elegantly. JSON contains two indicators: curly braces to indicate that a structure follows, and square brackets to indicate an array. Here's a structure written in JSON: {key1:"val1",key2:"val2",key3:"val3"} and a one dimensional array: ["val1","val2","val3"]. You can nest these types within one another, too; for example, the value of a structure key could be an array, and would be written as this: {key1:["val1","val2","val3"],key2:"val2"}. Pretty cool, eh?

Now, how to get data back and forth between JSON and raw CF types. It's a no-brainer using a tag made available as an open source project on RIA Forge by Andrew Powell: CFJSON . I downloaded it and was using it in less than two minutes on a test template. Very simple, very easy.

All of this good information led me to pose more questions, which I went on to get answers to.

  • Were there any performance advantages of using JSON over XML?
  • Was there significant differences in the length of the string produced by a JSON conversion as opposed to an XML conversion (significant in the realm of web services where that string will have to be sent over the wire)?
  • Were there any compelling reasons to adopt JSON in leiu of XML or WDDX?

Following are the results of me finding out the answers to those questions.

THE EXPERIMENT
Working with a 500 row recordset, each row containing 52 fields of mixed data types, including some sql text, convert it to both JSON and XML and record the results of the time it took and the resulting string length. Do this in both a local template/cfc environment AND over the wire via a web service. I used CFJSON as the JSON converter, and Ray Camden's XML.cfc as the XML converter.

THE RESULTS
LOCAL TESTS
1
JSONXML
String Size 539906 1250561
Time (ms) 36374 2046
2
JSONXML
String Size 539906 1250561
Time (ms) 36156 2640
3
JSONXML
String Size 539906 1250561
Time (ms) 37103 2156

WEB SERVICE TESTS
1
JSONXML
String Size 539906 1250561
Time (ms) 36581 2390
2
JSONXML
String Size 539906 1250561
Time (ms) 37832 2496
3
JSONXML
String Size 539906 1250561
Time (ms) 37644 2406

The string size was consistent, as expected. JSON produced a string that was 57% smaller than the same data represented as XML. Even so, the actual difference in the time it takes to send the larger string doesn't even come close to compensating for the additional time it took to produce the shorter JSON string. It took 1,370% LONGER to produce the JSON string than it did the XML string. Wow, at this point it's almost a no-brainer that I would NOT want to use JSON for much if anything. But this huge difference got me to thinking: What was so vastly different about the way the XML was being produced and the way the JSON was being produced? So I dug into the CFCs to find out.

THE DIFFERENCE
Both CFC methods make use of lots and lots of looping and string concatenation. The only glaring difference was in the way this was done. XML.CFC leverages the Java.lang.stringbuffer object and CFJSON uses straight CF string manipulation. So, I altered the portion of the method in CFJSON.CFC that converts queries to utilize the java.lang.stringbuffer object as well. The results were VERY favorable! check out these time tests after I made the switch:

CFJSON.CFC TESTS AFTER STRINGBUFFER CONVERSION
TESTLOCAL TIME(ms)WEB SERVICE TIME(ms)
1 2156 4437
2 2125 3843
3 2031 4022

Wow. The conversion to JSON now runs neck in neck with the XML conversion, simply by leveraging the stringbuffer object. Sweeeeet.

Okay, now that I know that JSON data strings are significantly smaller, just as fast to create, how about manipulation? How painful is that? To find out I decided I was going to use my JSON data in a javascript function. I scaled down the size of the data set to only five records and a handful of fields for this test. Check out how simple it was to 'dump' my data into javascript and to access it afterwards:
<script>
    function showMeSomeJSON(){
        var objQuery = <CFOUTPUT>#jsondata#</CFOUTPUT>;
        var i = 0;
        for(i=0;i<objQuery.recordcount;++i){
            alert(objQuery.data.due_date[i]);
        }
    }
</script>


CONCLUSION
I have come to no solid conclusion as of yet, but I must say that I'm leaning heavily towards JSON in lieu of XML. It's got a smaller footprint all the way around, has the ability to capture complex nesting, and is really straightforward to navigate using Javascript. Additionally, the same way CFJSON can encode complex data, it also DECODES it on the receiving end, turning it back into something that CF recognizes.

Oh, and I think I'm going to email the CFJSON guys and let them know about the significant performance improvement I got when switching to stringbuffer. They may have already experimented in this arena, but just in case, I'll let them know.

That's it for my personal "JSON Demystification". :)

Doug out.

P.S. If you would like to see an actual JSON representation of my five record query, here it is:

{"recordcount":5,"columnlist":"complete,date_desired,dept,details,developer,due_date,est_hours","data":{"complete":["100%","100%","0%","100%","0%"],"date_desired":["Less Than 2 weeks","Less Than 1 week","More Than 2 weeks","Less Than 1 week","Less Than 1 week"],"dept":["Eligibility","Marketing","Benplan_com","Repricing","EDI"],"details":["1. For rehires, if a rehire date is present on the file and the rehire date is greater than the date of hire, then I need to use it.\r\n\r\n2. Cobra reason - make sure the term reason for a benefit is being put on the AE2 file. This is tied in with Scott\'s work.\r\n\r\n3. Some dependents have termed benefits but no effective dates, also no effective date for the employee. I need to find out where these are coming from.\r\n\r\n4. Terms need to be removed from the file 60 days after the employment term date. This will actually be added to the TSS AE2 file as well.","Dave Lawson, SWI, would like for us to send him the annual report we created for him that gives him EE and Dependent data for Group #s 90947 and 90947P.","- We will send?? or receive daily RX claims\/deductible file updates to one or two PBM\'s--Innoviant for sure and maybe Catalyst.\r\n"," 1) Show correct network for each group. 2) Change elapsed days to start counting on the day the claim was sent out. ","Correct the SSN validation on inbound EDI returned repriced claims. "],"developer":["Dan Crouch","Kelly Young","Gemma Anthony","Kelly Billen","Kelly Billen"],"due_date":["09\/09\/2004","8\/19\/04","NA","08\/30\/2004","08\/13\/2004"],"est_hours":["",1,400,1,1 ]}}

Posted by dougboude at 5:50 PM | PRINT THIS POST! | Link | 4 comments
04 July 2007
Getting Your Deposit Back
Any other renters out there? If you've EVER rented before, you know the incredible disadvantage you can be at as a tenant when it comes time to get your deposit back. Out of all the places I've rented in my life...and that's actually quite a few...I can't remember EVER getting my deposit back, and that's not because I tore up every house I lived in, either. In fact, I've been a very GOOD tenant and have done my own repairs, upgrades, and even minimal remodeling. I didn't get my deposit back because the people I rented from summarily judged me and, using the advantage they have legally, managed to embellish enough to consume all of the funds. Not wanting to deal with the hassle of fighting it, I've always just walked away. Not this time.

I recently moved from the house I had been renting for two years to a larger one, and of course had to go through the whole "return of deposit" routine. As has been my experience, it went sour near the very end. While at first the landlady was amicable and friendly (by all appearances), when it came time to discuss the deposit she suddenly returned to me a laundry list of items that she said justified her keeping it all. Most of the items were normal wear and tear, which legally the tenant is not liable for covering financially, such as walls needing fresh paint, carpet getting worn, etc. One of the items on her list was, and I quote, "aquarium pebbles on the lawn". It got ridiculous, to say the least. So this time I decided to push the issue and formally request that she and the true owner (my landlady is a proxy) reconsider their position for several good reasons. I did this via a letter sent certified mail.

Since it took me several hours to draft and perfect this letter, I thought I'd share it here with you all in case anybody else is ever looking for a good "return of deposit dispute" letter template. Do with it what you will, and good luck getting your deposit back!

P.S. IF the lessor decides NOT to reconsider, and you feel that you have a very good case as to why you SHOULD receive some or all of your deposit back, the next step to take is to document everything that occurred (conversations, dates, times, etc.), go down to your county courthouse, and file a small claims suit naming your lessor as the defendant. I'll see in ten business days from now if that's what I need to do or not.

THE LETTER

Doug Boude

[my new address]

July 3, 2007

 

[insert ignorant landlady's name here]

[insert ignorant landlady's address here]

 

 
Dear Miss Ignorant Landlady:

 
I received what I can only assume is your handwritten letter postmarked June 29, 2007 which cited a lease agreement signed by myself on July 2, 2005 and stated that due to failure to provide thirty days written notice, all security deposits had been forfeited. This letter appeared to be a copy of a faxed document, and was signed by a person unknown to me and claiming to be co-owner of the property at [my old address].

 

I respectfully request that you and the true home owner, [true homeowner's name], reconsider your decision to withhold the entire amount of my nine hundred forty dollar deposit, paid by check on July 2, 2005 for the following reasons:

 

1. As of July 2, 2006, the lease agreement I signed on July 2, 2005 and all terms therein expired; no other lease agreement was ever signed. The supposed reason for withholding my deposit cited, vaguely, an expired agreement.

 

2. I was a very good tenant at all times, caring for the property as if it were my own and always with the mindset that if the homeowner were to show up at any time, she would not be disappointed with the state of the property. I paid the full amount of my rent every month, and only deviated from the acceptable window of payment when previous arrangements were made with you; hence the fact that there is no back rent due at this time. In addition, I performed countless hours of maintenance and repairs (approximately valued at $1,195), many at my own expense for supplies and all with my own time, in order to maintain the property in good working order. AC filters were bought and changed regularly; lawn maintenance was above par (mowed and edged, yard fertilized, trees fed/spiked, flowers planted, shrubbery trimmed, grass watered and kept green – I even contracted with a lawn care company for a time in order to keep the lawn healthy), lawn equipment (which came with the house) was maintained exquisitely (mower blade changed, cracked fuel tank replaced, synthetic oil used in the motor), toilet internal parts were replaced, loose towel racks repaired, shower fixtures repaired or replaced, incandescent light bulbs replaced with low wattage energy saving fluorescent (all of which I left with the house), exterminator called as needed, garbage disposal repaired, clogged toilets and sinks unclogged…and any other thing that needed attention: I took care of it all, and willingly so.

 

3. I am uncertain as to who is actually making the decisions and judgments that are affecting the return of my good faith deposit. Since I was given no contact information for the home owner (who I understand to be in the military) and was directed to deal with you, her proxy, I could not contact the owner directly to discuss the terms of the return of my deposit. I then requested of you, in writing, to be put in communication with the actual home owner on June 14, 2007 and received no response whatsoever to date, effectively and purposefully preventing me from contacting her. Even the handwritten letter I received on July 1 omitted any return address nor did the letter itself contain any contact information (though the postmark shows it was sent from San Antonio). In addition, according to the Bexar County Appraisal district records, [my old address] only has one owner, [homeowner's name], and that at 100% ownership, making the claim of someone else touting themselves as “co-owner” very much suspect.

 

4. My failure to give a full thirty days notice was not done maliciously nor was it premeditated. The circumstances surrounding it were strictly financial, wherein a plan that would have allowed me to meet my financial needs was suddenly and unexpectedly disrupted. As soon as I was aware that I would not be able to pay the rent for the following month of June, I contacted you in writing to let you know and even went so far as to put the “for rent” sign out into the yard for you and repair it when the wind had knocked it down. I also answered inquiries from passers-by who were interested in the house and took them on tours of it in order to assist you in finding subsequent tenants. I acted with my, yours, and the homeowners best interest in mind and with fidelity at all times, as my deeds do attest.

 

5. I did everything in my power to leave the house in as good or better condition than I received it, with the one exception of repainting three or four walls back to the original color. The repainting issue was discussed with you, I informed you that I would not be able to do that, and so there was no miscommunication on that matter. Everything else, however, I did do. I cleaned the house in its entirety, including kitchen, floors, and refrigerator. I disposed of all trash in the bins and even came back after I had moved out to ensure that the bins were set on the curb to be emptied. I’m sure that there was yet more cleaning that could have been done in order to pass the white glove test, but due to my grandfather having a stroke on May 27th and me being the only family he has locally, my cleaning efforts were delayed. I informed you of that situation in writing on May 31st. The hole in the garage which you brought to my attention as not being pre-existing, I purchased the supplies for and performed the repair of. The process of repairing such a hole is two step, and since the second step of sanding and painting had to be performed after my move-out date, I informed you of that need as well and offered to return to complete it. Once I had received from you a rough list of items that you deemed as deductible from my deposit (including items deemed by the attorney general as ‘normal wear and tear’), I offered to return and take care of any of them that you wanted me to. I received no response in the affirmative or negative…there was no communication from you. Again, as with the general care of the property while living there, my intentions and mindset regarding the state of the property at the time of my departure were completely upright and with the owner’s and my best interest in mind, even informing you that I was making myself available after my departure if it was desirable for me to return and take care of any outstanding matters.

 

For the reasons stated above, it is my contention that withholding of the full deposit amount is absolutely unfounded, morally wrong, and is not a just reciprocation for the very good tenant I have been for the past two years. If there were legal precedent that enabled a landlord to withhold the entire amount of a tenant’s good faith deposit when no valid lease agreement is in place due solely to the lack of a full thirty day written notice to vacate, that does NOT justify the doing of it when all other factors cast the tenant in so favorable a light.

 

My desire at this time is to be in communication directly with the home owner herself and not her proxy, in order to come to an amicable, fair, and just agreement regarding this matter as soon as possible.

 

I respectfully request that this letter be immediately forwarded to [homeowner] and that she contact me at the address in this letter’s header section within ten business days, in writing, regarding a fair and equitable agreement as to what portion of the deposit should be returned to me.

 

 Sincerely,

 

 DOUG BOUDE

PREVIOUS TENANT, [my old address]

(JULY 2005 – MAY 2007)

Posted by dougboude at 1:50 PM | PRINT THIS POST! | Link | 2 comments
02 July 2007
Basic Event Security in Model-Glue Applications
To anyone who has not yet breached the subject of model-glue event security, it can potentially be confusing at first, so I thought I'd share my approach to it in case it helps save someone a little time.

Understanding and being able to visualize the life-cycle of a Model-Glue event is a prerequisite to really grasping event security, so let me share my take on what a brief overview of that life-cycle is.

  1. A request is made, notifying model-glue to execute a specific event (eg; http://www.somesite.com/?event=fireinthehole )
  2. MG looks in its modelglue.xml file to find out what messages to broadcast to listening controllers ( <broadcast><message name="blowitup" /></broadcast> ) for the 'fireinthehole' event
  3. controllers listening for the "blowitup" message execute their corresponding functions ( <controller name="bombController" type="controller.eodGuy"><message-listener message="blowitup" function="BlowInPlace" /></controller> )
  4. MG executes any relevant result actions (acts as an 'if' statement almost) if they exist
  5. MG renders any views that are defined for this event
  6. The event lifecycle is over.

So, now that we know the flow of a named event within Model-Glue, it's time to add in a security check to make sure the current user has permission to execute that event. In my scenarios typically I have private and public events (those that can be executed without being logged in (such as the 'login' event itself), and those that require previous authentication (such as 'manageAccount')) and events requiring a specific role (such as viewing billing reports).
What we will effectively do is slide in some functionality between the event request and the execution of the event itself by leveraging OnRequestStart. This functionality will either allow the named event to pass on through OR redirect the user to the event we want them to arrive at. For instance, if they attempt to access an event that requires login and we intercept that event, we'll redirect them to the login page.

Here's the process for putting the named event check functionality in place:

1.Create a function that checks the current event name against a given list of event names;
2.Register that function to be called at 'onRequestStart';
3.In the Modelglue.xml file, create an event called "modelglue.OnRequestStart";
4.Within the modelglue.OnRequestStart event, register named results and provide appropriate redirection values;

What's going to happen then during the event life-cycle is that, before the actual named event executes, any controllers listening for the 'onRequestStart' message will execute their functions. One of those functions will have the sole job of verifying that the event being requested is allowed to be called in the current session state (logged in, not logged in, is an admin, etc.) If the event is good to go, the function is finished. If the event should NOT be allowed to execute, the function will set a model-glue named result. Next, since we defined an event called modelglue.OnRequestStart, that event is evaluated before any named events. The only thing we have defined for it to do is to look for specific named results and if one of them is found, perform the appropriate redirection. If none of the results being watched for are present, the named event executes normally.

I know at this point there must be a lot of questions on how to actually implement what I've been describing at a high level, so here are the same steps with snippets you can use:

1.Create a function that checks the current event name against a given list of event names;
In our scenario, let's assume two things: that we have events we want to require security, and events that we want to require that the person logged in also be an administrator.
<CFFUNCTION name="checkEvent" access="public" returntype="void" output="false">
    <CFARGUMENT name="event" type="any">
    <CFSET var eventname = arguments.event.getValue(arguments.event.getValue("eventValue")) />
    <CFSET var user = arguments.event.getValue("currentUserObject") />
    <CFIF not user.getUserID() and not listFindNoCase("login,signup,forgotpassword,sendpassword", eventname)>
        <!--- if we aren't logged in AND the event we're calling is NOT a public event... --->
        <CFSET arguments.event.addResult("LoginNeeded") />
    <cfelse><!--- we are logged in. If this event is in our list of events requiring admin login, check to see our user is an admin. if not, redirect them to home. --->
        <cfif listFindNoCase("admin.home,admin.billing,admin.creditAccount", eventname)
                and not user.getRole("Admin")>
                <CFSET arguments.event.addResult("AdminNeeded") />
        </cfif>
    </CFIF>
</CFFUNCTION>


2.Register that function to be called at 'onRequestStart';
<controller name="MyController" type="controller.Controller">
    <message-listener message="OnRequestStart" function="checkEvent" />
</controller>

3.In the Modelglue.xml file, create an event called "modelglue.OnRequestStart";
and
4.Within the modelglue.OnRequestStart event, register named results and provide appropriate redirection values;
<event-handler name="modelglue.OnRequestStart">
    <results>
        <result name="LoginNeeded" do="login" redirect="true" />
        <result name="AdminNeeded" do="home" redirect="true" />
    </results>
</event-handler>

As with anything Model-Glue or OO, there's always greater levels of detail to be expounded upon, but these snippets are more for illustrative purposes than actual 'out of the box' code, so I'm leaving a lot of the details to you. Such as where you should really store your lists of named events, or how your user object is always present, empty or populated, regardless of whether or not the user is authenticated, etc.

Anyway, hope this helps get somebody over the hump!
Posted by dougboude at 3:27 PM | PRINT THIS POST! | Link | 2 comments
01 July 2007
The Key to True Conflict Resolution
A Design Pattern in Life
A design pattern is a recurring concept, arrangement of things, and/or repeated process. Life is composed entirely of such patterns. From the patterns found in the genetic blueprints of even the simplest form of life to the consistent and measurable rising and setting of the sun: life is a beautiful matrix of overlaid and interacting patterns. Ah, but more than simply random patterns, these are patterns in the very design of how everything works, including human behavoir. I want to expound upon one such pattern in particular, and that is the pattern that exists between two people who are at odds with one another and what I have observed the pattern to be that leads to resolution in almost every case.

I was once conducted through a phone interview for a technical job and, as interviews will go, I was presented several questions which were nothing more than scenarios, with my response to be the approach I would take in resolving them. One question in particular involved the situation where I was project lead and had two separate groups between which I was liaison. The two groups had opposing opinions as to what decision should be made on a particular aspect of the project. The question posed to me: "How would I resolve it"? It didn't take me long to come up with an answer, because what I imagined in the scenario looked exactly like other scenarios I had encountered in life, and I recognized the pattern: that of two (or more) people who had opposing viewpoints, with each refusing to budge from their position and yet both having the need for agreement. My answer: to make sure that both sides were heard by the opposing side.

It may seem by all outward appearances that conflicts of viewpoint are all about whose viewpoint is better, and that resolution can only be had by compromise or relinquishment of one or both views. This is not true. In scenarios between my children where I have played diplomat and in scenarios between myself and my significant other (where I WISH I had a diplomat!), I have seen the same recurring pattern, and it was never one side managing to out muscle the other side that resulted in peace and accord. The true answer in mending discord lies in something so much more simple: fulfilling the need to be heard.

I type those words slowly, I say them in my mind slowly and with reverence as I read them, because they are so fundamentally important. Hours, days, years even of stubborn silence can be avoided if the parties involved would just recognize what the true need of the opposite side is and fulfill it. The other side really only wants to "have the floor", if you will, long enough to have expressed their opinion fully and, (this is the MOST important part, O Best Beloved) to KNOW that they were truly heard. Once a person has been given opportunity to speak uninterrupted and they are made to know that their side had truly fallen on open ears and an open mind, the fire amazingly just fizzles out. They still have their opinion, of course; but the ire that drove them and their inability to see beyond their own cause just melts away, because the true root need has been satiated. Ah, and the doors to communication that are immediately opened in a nearly miraculous way! Suddenly, whereas this individual was seemingly incapable of hearing a word the other side had to say, now they can hear with clarity and attention, and truly consider their opponent's viewpoint.

Simple enough, right? Just be quiet while the other side talks! Not so, O Best Beloved. A simple stay of the tongue does not a truly hearing opponent make. You see, once one side does agree to give the other the floor and hold their tongue while the other speaks, the speaker now will be examining every minute detail of everything that is occuring while he or she is laying things out. When I say 'everything', I mean absolutely EVERYTHING. It likely won't be done consciously, but without a DOUBT they will be noting every twitch of the listener's facial expressions, the movement of their eyes, their body posture, movements, shifting of body weight, and most of all where their attention is at all times. What they are doing is looking for the one thing they need, evidence that they have been truly heard. Now, although how a person listens is vital, even more vital and necessary to this process is how the listener then responds. The very next thing that comes out of their mouth will either make the exercise a success or total failure. Remember, it isn't agreement that fulfills this pattern in human behavior, it's listening, so it isn't required that one's response be to the effect that they agree. Anything along the lines of "I can see your point", or "I hadn't looked at it like that" can suffice. Be warned though: truly listening is an impossible thing to fake. I can't tell you the innumerable times I've been involved in this scenario and the other side, though seeming to have listened and even responding with something like "I see your point", IMMEDIATELY blew the whole thing out of the water by adding on the word "but". Look at this: "I really do see your point, BUT...." What just happened there? The speaker's viewpoint was instantly invalidated and minimized. What follows the 'but' is irrelevant, and the other person isn't going to be able to hear it anyway, because that 'but' told them that their honest outpour had fallen on ears that never intended to hear them in the first place. Back to square one for everybody.

Learn to recognize the human conflict pattern. It comes in many forms and has varying degrees of intensity, but it's always the same. When you DO recognize the pattern, just remember that the true key to resolution lies in you making sure that you give your opponent the opportunity to fully express himself, you truly open your ears and mind and hear him out, and above all cause him to know that you heard him. Do NOT allow yourself to let the word 'BUT' be part of anything you respond with, or you will have exposed yourself as someone who pretended to hear but really had no interest at all, leaving your opponent's one true need yet unfulfilled. There really is something to the phrase we've heard throughout our life, that 'communication is as much listening as talking'. Practice your listening skills, thus fulfilling your opponent's true need, and you'll find yourself spending a lot less time immersed in life's daily dose of human conflicts.

Doug out.
Posted by dougboude at 6:23 AM | PRINT THIS POST! | Link | 0 comments