About Time – An Air and SQLite Application

I few days ago I came across this post at Signal vs. Noise. The first item is about a clock that tells you the approximate time – for example 11:59 is “Nearly Twelve”, 12:30 is Half Past Twelve, etc. etc. The idea is, “Do you really need to know it is 12:53?” This clock gives you the amount of precision that you actually need when dealing with time.

I thought it was kinda cool, but I would never buy one. However when I thought about it, I realized it would make a good AIR application.

After thinking about I decided to do it because:

  • It’s a simple thing to write
  • It could use a database
  • I have a Air and SQLite presentation to prepare

All of these things added up to me writing the thing in about a day. Here’s what I did:

  • Filled a SQLite database with times and descriptions
    • 1 = Just After
    • 15 = Exactly Quarter Past
    • 59 = Nearly (Next hour)
  • Used HTML, JavaScript, and an Image to build the UI
  • Got rid of the default Chrome
  • Used Air Methods to query the database.
  • Placed taskbar items that allow you to:
    • Close
    • Force app Always on Top

The amazing thing to me was how easy it was to do. The actual app worked relatively quickly, most of my time was spent getting the details like icons, and text placement correct.


Download About Time

So if you want to know about what time it is, download your copy of About Time.

Disclaimer: This totally is “an Air app that didn’t really need to be”. I get that. I figured someone else might like it, or at least want to look at the source.

Posting Form to Itself

I’m working on someone else’s code base, and found that they were posting forms to themselves. However they had hard coded the form template names into the code for the form. Like the following:


action=“index.cfm”
method=“post”>

This is a bit of a pet peeve of mine because it tends to make the code very un-portable. What happens if you rename the file “dosomethingelse.cfm.” Now you have to go back and change the file name and the reference.

It was a quick proof of concept application, so I don’t fault the author. But they just aren’t lazy enough.

I prefer doing it this way:


action=“#cgi.script_name#”
method=“post”>

It’s highly cut and paste-able, and you never have to worry when you rename your templates. If you aren’t using cfform, you can still do it, just wrap the form element in a .

Now, I imagine that I will get a comment that says something about not trusting cgi variables. It works with every flavor of IIS and Apache that I have ever worked with. Anybody see any gotcha’s doing that.

Using ColdFusion and SVN to Create Release Notes

I was talking last week about using XML to act as an intermediate step in building your documentation (Automating Documentation and Automating Documentation Part 2). It dawned on me that I could also share my technique for building release notes.

I use Subversion. I’ve gotten positively anal about commenting when I make changes. So if you were to take the history of my SVN commits, they make pretty decent release notes. The trick is to grab them and automatically turn them into documentation.

SVN makes this pretty easy. It takes one command to grab all of the changes. It takes one switch to make the change export as XML. Once that is done, manipulating the content in ColdFusion is a breeze. I do it using <cfexecute> and svn.exe, below is my code:

<cfset svn.wc = “[path to svn working copy]”
/>

<cfset svn.exe = “[path to svn executable]”
/>

<!— -v = verbose –xml outputs it as xml —>

<cfset svn.arg = “log #svn.wc# -v –xml”
/>

<!— get contents of SVN history —>

<cfexecute name=“#svn.exe#”

arguments=“#svn.arg#”

timeout=“30”

variable=“changes”
/>

<cfset changes = XMLParse(changes) />

<cfoutput>

<cfloop
index=“i”
from=“1”

to=“#arrayLen(changes.log.logEntry)#”>

<!— lxml = LoopLocalXML (shorted for display) —>

<cfset lXML = changes.log.logEntry[i] />

<dl>

<dt>#lXML.XmlAttributes.revision#</st>

<dd>

<ul>

<li>#lXML.author.XMLText#</li>

<li>#lXML.date.XMLText#</li>

<li>#ParagraphFormat(lXML.msg.XMLText)#</li>

</ul>

<p>Files Effected</p>

<ul>

<cfloop
index=“j”
from=“1”

to=“#arraylen(lXML.paths.path)#”>

<!— lPaths = LoopLocalpaths —>

<cfset lPaths = lXML.paths.path[j] />

<li>

#lPaths.xmltext#

(#lPaths.xmlattributes.action#)

</li>

</cfloop>

</ul>

</dd>

</dl>

</cfloop>

</cfoutput>

In my build process, I use <cfsavecontent> and <cffile> to write the content to a file, and then use ANT to call the CFML page that creates the release notes – voila, release notes are now part of every build, with no extra work on my part.

Shortcut Key for Commit in Subclipse

This had been driving me nuts for a little while. Maybe I can save someone else the hassle too.

To set a shortcut key for Subclipse commit:

  • Go to Windows → Preferences
  • Go to General → Keys
  • Check the box “Include unbound Commands”
  • Then in the “type filter text” box, type commit
  • Then assign it to whatever key combination you want

If you go through this, and commit and other SVN methods don’t show up.

  • Go to Help → Software updates → Find and Install
  • Choose “Search for updates of currently installed features.”
  • Go through the choices and update Subclipse.

ColdFusion and ODBC Agent

This sent a co-worker down a wrong path yesterday, so I thought I would blog it in case it tripped anyone else up.

There was a problem with one of our SQL servers yesterday. (It was down a long time during a routine patch and reboot due to extra stuff in a Microsoft Tuesday patch.) In trying to troubleshoot the issue, one of the administrators saw errors in the event logs coming from the ColdFusion ODBC Agent.

We are using default driver for Microsoft SQL Server in the drop down on the Data Sources page. Therefore, we were using JDBC driver and weren’t impacted by the ODBC error. The error message was a red herring. It took focus away from the real problem, namely that the database server hadn’t come back online yet.

Going further, as far as I can tell all of the defaults on that page are JDBC drivers, with the exceptions of “ODBC Socket” and “Microsoft Access”. According to this Damon’s comment on this blog post, the “Microsoft Access with Unicode” doesn’t even need the ODBC driver. So I would say, unless you are doing coding against Access databases, or a known ODBC only product, you probably don’t need to install the ODBC services; especially since you can always install them if you need them.

I’d be interested to know if anyone violently disagrees, or if this has been said authoritatively somewhere, and I just not up on my Google-Fu.

Automating Documentation Part 2

This is a follow up to the post Automating Documentation. Jim Priest wanted to see example code, and I’m happy to oblige.

For this example, I am sharing the code for documenting “steps” in Squidhead. Steps are operations that do one thing, like generate stored procs, or ant scripts, or email developers. They are powered by cfm templates in a specific folder. Once there they can be referenced through in the project’s config file. The documentation for them is included in the download for Squidhead, and can be viewed online (Squdihead – Steps).

So after the jump, here is the code for creating this documentation.

So first thing I do is setup a few parameters.

<cfset stepsXMLfile = “#expandPath(‘.’)#/stepsXML.xml”
/>
<cfset
outputfile=“w:inetpubwwwrootsquidhead2docssteps.cfm”
/>

<cfdirectory
action=“list”
recurse=“false”
directory=“#expandPath(‘../../steps’)#”
name=“steps”
type=“file”
/>

Then I conditionally build the file in case I deleted it.

<h2>Building XML</h2>
<cfif

not
FileExists(stepsXMLfile)>

<p>Transforming Steps to XML.</p>

<cfxml
variable=“XMLOutput”>
<steps>
<cfoutput
query=“steps”>
<#ListFirst(name, ‘.’)#>
<documentation />
<requires />
</#ListFirst(name, ‘.’)#>
</cfoutput
</steps>
</cfxml>

<p>Writing to Disk.</p>

<cffile
action=“write”
file=“#stepsXMLfile#”
output=“#XMLOutput#”>


<cfelse>

<p>Already Built.</p>

</cfif>

Then I go through and check to see if each file has a documentation node:

<h2>Checking XML</h2>

<cffile
action=“read”
file=“#stepsXMLfile#”
variable=“rawFile”
/>
<cfset
stepsXML = XMLParse(rawfile) />
<cfset
changed = FALSE
/>

<cfoutput>
<cfloop

query=“steps”>
<cfset stepName = ListFirst(name, ‘.’)/>

<cfif
not
structKeyExists(stepsXML.steps, stepName)>

<p>Adding #stepName#</p>
<cfset changed = TRUE
/>

<cfset stepsXML.steps[stepName] = XmlElemNew(stepsXML,stepName) />
<cfset stepsXML.steps[stepName][‘documentation’] = XmlElemNew(stepsXML,“documentation”) />
<cfset stepsXML.steps[stepName][‘requires’] = XmlElemNew(stepsXML,“requires”) />

</cfif>

</cfloop>

</cfoutput>

<cfif changed>
    <cffile
action=“write”
file=“#stepsXMLfile#”
output=“#stepsXML#”
/>
</cfif>

Next I go through and mark any documentation that is not filled in as a problem and through a 500 error. This will cause ANT to stop running.

<cfset incomplete = FALSE
/>
<cfset
stepArray = StructKeyArray(stepsXML[‘steps’]) />

<h2>Checking Documentation</h2>

<cfoutput>
<cfloop

index=“i”
from=“1”
to=“#ArrayLen(stepArray)#”>

<cfif
StructKeyExists(stepsXML[‘steps’][stepArray[i]], “documentation”) AND

len(stepsXML[‘steps’][stepArray[i]][‘documentation’][‘XMLText’]) lt
1>


<p>Documentation for step #stepArray[i]# is not filled in. </p>


<cfset incomplete = TRUE
/>


</cfif>


</cfloop>
</cfoutput>

<cfif incomplete>

<cfheader
statuscode=“500”
/>

</cfif>

I finish by writing the XML back out to disk as HTML. I’m sure this can be done through XSLT, but I don’t bother.

<h2>Building HTML Reference.</h2>

<cfsaveContent
variable=“stepReference”>

<h2>Step Reference</h2>

<cfinclude
template=“stepsDocs.cfm”
/>
<cfset
stepArray = StructKeyArray(stepsXML[‘steps’]) />
<cfset

ArraySort(stepArray,‘textNoCase’ )>

<h2>Step Details</h2>

<cfoutput>
<dl>

<cfloop
index=“i”
from=“1”
to=“#ArrayLen(stepArray)#”>

<dt>#stepArray[i]#</dt>
<dd>#stepXML[‘steps’][stepArray[i]][‘documentation’][‘XMLText’]#</dd>
<cfif
len(stepXML[‘steps’][stepArray[i]][‘documentation’][‘XMLText’]) gt
0>

<dd
class=“requires”>Requires: #stepXML[‘steps’][stepArray[i]][‘requires’][‘XMLText’]#</dd>

</cfif>


</cfloop>

</cfoutput>

</dl>

</cfsavecontent>

<cffile
action=“write”
file=“#outputfile#”
output=“#stepReference#”
/>

Then to call through ANT, I just add this line to a task in my ANT build file:

<get
src=“${project.url}/tools/stepDocumenter/”
dest=“${project.logPath}/tools/stepDocumenter.html”
/>

I then include these dynamic steps in a static document that includes some background on what steps are and what not.


Automating Documentation

One of the things that I’ve been doing lately is writing reference documentation for my projects. Squidhead has an extensive set of configuration options, and an internal project has a custom XML format. I thought I would share the method I’ve come up with to make it much easier for me to do.

The problem with this type of documentation is that is really easy to do once and then not keep up to date. When coming up with a solution, it had to be repeatable and additive. You could just read in all that information and recreate dynamically from scratch, but that means you can’t manually alter the documentation. I was looking for something that would basically just remind/force me to document new options or files. With that in mind here is what I do:

  • Assume that I am documenting a set of configuration files
  • Create an XML file where each file to be documented is a node
  • Do a directory list of the files to be documented
  • Grab the name of each file
  • Check to see if a node currently exists in the XML for each file.
  • If not I add a node named after the file
  • Create blank sub nodes for “documentation,” “notes,” or “required” or whatever

When that pass is done:

  • I scan the XML
  • I check for blank sub nodes.
  • If any exit I throw an error

I then add this process to my ANT build for the project. Now every time I go to build the project, the documentation gets scanned, added to if needed, and I am prevented from moving forward until I document new changes.

This turned documentation for me from an incomplete mess of a task that takes two hours or so every few weeks to 5 minute maintenance step every time I build.

Basecamp API Update

First of all thanks to all of the people who have either promoted or contacted me about BasecampCFC. I am really excited about all of the interest. As of now it’s been mentioned at:

I have to admit, getting it on 37Signals’ radar was pretty cool.

Now on to the meat of this post, the latest update…

I’ve fixed a number of issues with both the basecamp.cfc and the demo app that goes along with it.

Basecamp.cfc

  • I added a debug setting to the init method. It adds extra information to the ColdFusion debugging output.
  • I added an authentication method. It allows you to tell the difference between
    • Authentication failure
    • API not being enabled
    • Basecamp project not existing
  • I made steps to ensure that all get methods would return consistent column lists for queries.

Demo application

  • Now tells you if you haven’t enabled the API
  • Now gives directions on enabling API.
  • It’s a bit more robust in handling blank records

Finally, if anyone is interested I added the unit tests to the SVN repository, if anyone wants to see how I’m testing the whole thing.

How to convince yourself to Unit Test

I was talking with someone recently about unit testing. His dilemma boiled down to the idea that he knew unit testing was one of those mythical “Good Things” but he couldn’t bring himself to do it; it seemed like such a large commitment in time. I’ve been thinking more and more about this, and I have come to the conclusion that the time factor in unit testing is actually a myth. Here’s why I think so.

Do you write code, and declare it finished when you are done editing it? I hope not. No, you go to your application and test the page you just changed through your browser. If you’re working on a CFC, maybe you go to a page named test.cfm, on which you have a few CFC calls and a CFDump. You then looked to see if the results you got conform to the results you expected. Did you do that? Then you just unit tested! The only difference between that and a formal unit test is that you throw away the test after you were done writing that piece of code.

I propose you formally unit test instead. Instead of throwing away that test code, put it in a formal testing framework. You’ll probably have to change it a bit to get it to work with one of those frameworks, but the learning cost for doing it this way is much, much cheaper that TDD. Once you do that, you’ll never have to worry about breaking code again because you hold on to every test you’ve ever written. Well, okay, you’ll still worry, but you know as soon as you do it what code you’ve broken, which is a much better place to be at.

I think a big part of the underlying misconception comes from the fact that most discussions of unit testing include a description of Test-Driven Development (TDD). That is the system were you figure out how exactly your code should behave, write tests to check for that behavior, then write code that behaves in a way to pass all of your tests. That is going to change the amount of time you spend on development (at least up front, where we tend to myopically be focused.) More than just a hit in terms of development time, it’s a hit when it comes to spending the time learning it. Mind you, I’m not saying that TDD is bad; it’s just a paradigm shift, and a big one at that.

BUT that doesn’t mean that unit testing IS Test-Driven Development; TDD relies on unit tests, not the other way around. Go ahead, write your unit tests after the fact. No one will know. In fact, many unit tests get written in response to bugs, even when you are doing TDD.

Another misconception is that you have to test everything you do. Some things work better with formal unit testing than others. Yes, with mock objects and development databases you can unit test anything, but that makes the learning curve even steeper. Screw that; don’t make it harder for yourself. Small components with a limited range of functions are the easiest to start to work with. Examples usually include some sort of calculator, or other such item that I never use in actual code. So here are my recommendations for low hanging unit testing fruit.

  • Authentication code, specifically that which test usernames and passwords (as opposed to session management)
  • Utility code, like a phone number formatter, or custom date converter
  • Parsing code, like code that takes a custom XML format and converts it to a usable format
  • Problematic code, code that breaks every time you do an update.

So start moving your informal tests to a formal unit tester. Start with the small stuff and don’t worry about testing everything. And for god’s sake don’t think you have to reach for TDD to be successful with unit testing. Somewhere between where you are and where you are heading is a much better place.

In case you want to know more about unit testing and ColdFusion, check out the ColdFusion unit testing frameworks:

Update: Someone pointed out to me that I had misspelled “TDD” as “TTD.” Sorry. I’m dumb sometimes.