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.

Yet Another Community Expert

Adobe Community Expert

I’m a little late to the party but I got word yesterday that I was selected as an Adobe Community Expert for ColdFusion. I’m a little humbled by the company in just this last round of Community Experts, let alone the whole group.

I’m sure it will be a bit before my information is up on the site, but I just couldn’t contain my excitement.

Once I get the hang of this whole “being a dad thing” I’ll be posting ColdFusion content regularly again.

Thanks for letting me in, Adobe.

Simple IT Success

Avish Parashar, a friend of mine, is starting a new business venture. It’s a consulting and training company which is directed at teaching technical people non-technical skills. You know, those elusive “soft skills” you hear about from time to time.

I recommend Avish and his training in the strongest terms possible. I’ve worked with him in this capacity for eight years getting guidance on courage, creativity, communication, and influence along the way. I have definitely enjoyed the fruits of applying his philosophy and techniques to my regular working life.

Anyway, check out his site, simpleITSuccess.com, and if you are even considering it, drop him a line. You won’t regret it.

cf.Objective Progress

Less than a year ago, I went to cf.Objective for the first time, and came back with a list of items that I wanted to see myself do, because I was introduced to them at the conference. I thought I would do a quick public coming clean about my progress.

To recap, my list was:

  • Start using Coldspring
  • Start using an ORM
  • Start using a real (UI) framework
  • Stop thinking about objects in terms of data
  • Start doing development on my local machine
  • Stop spreading rumors that the man saying he is Sean Corfield having the real Sean Corfield tied up in his hotel room.

My progress:

I started using ColdSpring for dependency injection in a few of my projects. I haven’t reached by goal of using it for Aspect Oriented Programming yet. So that will go back on the list.

I refined Squidhead to work against multiple DBMS’s and to understand foreign keys; making is a real solution for at least me.

I failed to start using a real UI framework. I would still like to, but I’ve been lazy. I need to be more disciplined. I really want to start using either Fusebox or ModelGlue.

I think I’ve switching from thinking about objects as objects first, and then going into the database to represent them, not the other way around. Could I do better? Sure. But I am much further ahead of myself a year ago.

I switched to local development solely. No more remote servers. Feels great, I never want to go back. Thank you, Mark Drew, your “car with a spike on the steering wheel” analogy changed my professional life.

I don’t spread rumors about Sean’s identity anymore. In part, Sean finally updated his picture. In part because I heard if you make any sort of fun of him, he will track you down, and shave a half dollar sized bald spot onto your head. That man is dedicated! And a Philadelphia winter is much, much colder with a mini-tonsure. Trust me.

So that’s it. I’ll hold off on making a new list until after cf.Objective 2008.

And if you aren’t going, don’t worry, every ColdFusion blog will be full of stories of how awesome it is. So, you know, that will be just like being there.

ColdFusion – Market Share vs. Profitability

There is a very interesting article over at Knowledge@Wharton about Market Share vs Profitability.

I skimmed it a few months back when it came out but never thought about it in terms of the ColdFusion community until I saw this link at Daring Fireball applying this phenomenon to Apple.

Basically the gist I get from it is that profitability is more conducive to long term health of a company than market share. It’s not proven, but if it is true it puts the ColdFusion market into a particular light. If what is true for companies is true for products, it might not matter to ColdFusion’s long term health if it steals market share from ASP.NET or PHP. ColdFusion’s long term health might be in its profitability, which according to Adobe has been very good.

Market share is still important to us, as it helps determines availability of work. But this phenomenon might a good explanation for why what we see Adobe doing with ColdFusion doesn’t always match up with what the community wishes it would do.