Sign Language

Heather and I have two kids: Lindsay who will be three in January, and Emery who turned one in August.  Around a year of age, we taught both of them a few bits of sign language for when they had the mental capacity to communicate, but not the vocal control to do it aurally.  Nothing much: "more", "please", "thank you", "all done", and a few others.  However, worth it's weight in gold, let me tell you.

Lindsay still uses it, and has become infatuated with Signing Time with Alex and Lia (forgive misspellings if there are any), which is a series of videos made by a hearing gal that had a deaf daughter (Lia).  Her vocabulary has grown quite a bit, perhaps 40-50 signs, and while not at all essential since she can speak well, has provided welcome reinforcement for saying please and thank you, along with helped Emery pick up some of those same habits, even before he can talk.

Tags in Subversion

A while back, I posted an entry about using Subversion and just got a comment on it a day or two ago with a question about tags.  Tags are absolutely essential in CVS, but in Subversion, they're a bit less required.  Still very useful, however.

In a nutshell, a tag is a named handle on a given set of files at a given set of revisions.  A tag lets you, at any future time, extract that set of files in one fell swoop.  The typical scenario is doing releases.  When you get ready for a release, you create a tag for the source that is being released.  Then if you ever need to look at the source for that release again, you can easily pull it back out.

With Subversion (unlike CVS),  there isn't a difference between a tag and a branch. A tag is simply a branch that has never been committed to.  A very typical use case is to create a tag when you do a release, and then when you need to make a fix to that release (independant of the main trunk of development), you create a branch at the release tag.  You make your fixes on that branch, and then merge them back into the trunk for inclusion in future releases of the product.

In my previous post, I'd alluded to using a tag and an externals definition together to ensure that inter-project dependancies were managed via Subversion rather than manually.  In that particular case, you create a tag on the dependancy for the version you want to use, and then set up an svn:externals definition in the parent project that points at the tag.  Then everyone that checks out the parent project will be assured of having the same version of the project's dependancies.  Even better, changing the location of the tag in the future will automatically update everyone's working copies next time then run svn update, which makes dependancy upgrades a snap.

And keep in mind, Subversion can handle binary files as well as text files, so I'd highly recommnd storing EVERYTHING in your repository, be it your development tools (Eclipse), external libraries (any JARs or DLLs your app might need), server configuration files (web server, DB server), bootstrap scripts, etc.  Aside from hardware and system software, creating a new environment to run your application shouldn't require anything that's not stored in version control.

Now only Mostly Human

For the first time in my life, I'm now only mostly human.  Yesterday I had hernia surgery and got a plastic mesh implant to help strengthen the hole in my abdominal wall where the plumbing for my testicles passes through.  In a nutshell, the hole is supposed to be tight (only enough to let the plumbing through), but can weaken and the intestines try to push out.  This is a Bad Thing, and about 2% of men end up having surgery to correct it.  It's also what hte "turn your head and cough" routine during a physical is checking for.

Fairly minor procedure, but definitely no longer the same.  Will see as time goes on, but it's quite obvious that there's something not natural in there; something that doesn't stretch and move the way flesh is supposed to.

On the plus side, I get a day or two of vicodin-induced haze, during which I don't have to do any hard-core coding.  Probably will work on a couple littler personal projects that don't have any great emphasis on working perfectly the first time, since I'm not sure what kind of "interesting" design characteristics might come out of my inability to concentrate.

The doc said 2-4 days to be mostly recovered, and six weeks to totally healed with as much strength to the reinforcement as there will be.  I've been pleasantly surprised at smoothly everything has gone to this point.  Only major discomfort was getting out of bed this morning, because I think the patch had partially pulled away from the abdominal lining and was poking something or other.  But that was quickly fixed with some wiggling around to get everything back in the right position.

To Closure Or Not To Closure

Sean, programmer extrordinaire, released a closures library for CF and it's generated a lot of interest.  Unfortunately, a lot of the interest has been of the "what are closures and what are they good for" type.  So I thought I'd contribute my thoughts.

Closures, at a most basic level, are functions defined inside a scope of some sort.  You can then pass the function around and call it whenever, and the function continues to execute as if it were still inside the scope it's defined in.  Closures (and their close derivatives) are often found in multithreaded environments as callback functions.  Every JS Remoting library that I've played with, (along with Flash Remoting) uses callbacks for responding to request completion.  What you may not have been aware of is that the callback functions are closures, not just simple functions.

I'm going to avoid using Sean's library, because it makes the issue a bit more confusing than it needs to be because of the syntax it entails.  Instead, I'm going to use Javascript, since that should be pretty familiar to everyone who reads this.  Here's a JS Remoting invocation using a non-existant Remote library:

function getSomethingById(id) {
  Remote.invoke("http://domain.com/neat_service/" + id, function(response) {
    recordSomethingById(id, response);
  });
}

What's going to happen is that when the request finishes, the server's response  is going to be passed as an argument to the callback function.  What's not quite so obvious is that the callback function is going to be invoked LONG after this bit of code actually runs to completion (because the remoting request is asynchronous).  What's amazingly useful is that the callback function can use variables that are defined outside the callback, but inside the outer function (e.g. the id parameter), even though the outer function has long since returned.

This is the essence of closures.  Not only are they a discrete block of functionality that can be passed around (i.e. a function), but they carry with them the scope they were defined in, and can reference back any time they are executed.  In this case, the use is pretty bland, simply as an adapter for the recordSomethingById method because the raw callback's signature doesn't match.  They can be used for much more interesting things, however.

Imagine, if you will, a collection of "things".  You need to sort those things, but the code in charge of building the collection (e.g. hitting the DB) is not the same as the code in charge of specifying the sort criteria.  One approach would be to force the sorting code to specify the sort order to the collection building code (for use in an ORDER BY).  Often nonviable because the sorting code doesn't call the building code, it just gets handed a collection.  Another would be for the sorting code to get the unsorted collection and manually sort it with some sort of sorting algorithm for the specific type of "thing" that the collection is made of.  Less coupling, which is good, but you can imagine if you have five (or 500) different types of things to sort; lots of sorting algorithms that are all basically the same, and only differ in the comparison bits.  Finally, the "right" solution: a generic sorting algorithm that doesn't understand how to compare objects, just sort them.  You pass it a collection and a closure that can do a comparison between any two "things" in the collection.  So now you can use the same sorting agorithm regardless of collection type, as long as you can provide a closure for comparison.  Here it is in code (again JavaScript):

 


function sort(collection, comparator) {
  var n = collection.length;
  for (var i=0; i < n - 1; i++) {
    for (var j=0; j < n - i - 1; j++)
      if (comparator(a[j+1], a[j])) {
        swap(collection, j, j + 1);
      }
    }
  }
}
c = [
  {name: "barney", height: 195, weight: 80},
  {name: "heather", height: 182, weight: undefined},
  {name: "jerry", height: 185, weight: 81}
]c_by_height = sort(c, function(a, b) {
  return a.height < b.height;
});
c_by_name_reverse = sort(c, function(a, b) {
  return a.name > b.name;
});

 

Notice that the sort function is totally generic, and that sorting an arbitrary collection of arbitrary elements is as simple as writing a comparison function.  In this case I've opted for a bubble sort, but imagine the freedom you have; at any point in the future you could reimplement the sort method with a mergesort and magically all your sort operations would be updated.

How about a more practical issue.  I don't know about anyone else, but transaction management is one of the more frustrating aspects of CF to me.  In particular, there's simply no good way to say "if i'm not in a transaction start one, otherwise just use the one I'm already in".  A solution (that does not work on BlueDragon, by the way, because of different connection pooling models) is to implement a transaction management CFC that manages transactions directly with the database instead of using CFTRANSACTION.  There are definite downsides, like the horrific mess you can get into if you don't trap exceptions properly, but the upsides are very nice (not having to worry about transaction nesting).  The problem is that you end up with boilerplate code all over the place:

...
<cfset variables.transactionManager.enterTransactionalBlock() />
<cfquery ...>
...
</cfquery>
<cfset variables.transactionManager.exitTransactionalBlock() />
...

Not a big deal, but if you leave it out, or only put half of it, you can get some weird issues.  Now if we were to have a "good" language-supported closure implementation, we could do this:

<cffunction name="callback">
  <cfquery ...>
  ...
  </cfquery>
</cffunction>
<cfset variables.transactionManager.doInTransaction(callback) />

Not hugely different, I'll admit, but notice that the doInTransaction method totally encapsulates all the transaction related stuff, be it a CFTRANSACTION tag or some custom mumbo-jumbo.  As such, you can transparently switch back and forth as needed, and because closures carry the scope they are defined in, that CFQUERY tag in there can reference variables local to where it's define even though it's executing inside the doInTransaction method of some other CFC.  This is a ludicrously powerful concept, though one that, if applied to the wrong tasks, can lead to very nasty code. 

One last note, for those familiar with Java.  Java doesn't have real closures because it doesn't have functions, but anonymous inner classes share most of the same traits, and usually the same purpose.  Not a syntactically elegant, but having multiple methods on an object rather than a single function can be quite useful in some scenarios.  Java also forces you to  mark as final all local variables (including method parameters) that your anonymous inner class will reference, which is an aid to performance as well as helping demark what external references have a closure dependancy.

Charlie's Stalking

Charlie Arehart is stalking bloggers, and wants the bloggers to help.  Just kidding, of course, but he makes a good point about the anonymity of a lot of blogs.  I can't say I'm all over the personal sharing, but I've at least got my name and a contact form available.  People can build enormous personal brand by blogging, but if the brand isn't obviously attached to you the blogger, it's of little benefit to you when you go for a job interview or the like.  So get your name on you blog, and make sure that if you participate on mailing lists, you use the SAME name, furthering both the branding and the brand relevance.

Google Screwed Up?

Part of the application I spend most of my time working on is consumption and aggregation of XML feeds, and when the month of October turned, and interesting thing happened: processing a significant number of feeds suddenly started erroring.  We don't do it manually, instead using the very capable rssatom.cfc from Roger Benningfield, so the errors seemed doubly odd.

Futher investigation, however, indicated that Google News was misformatting their dates.  They seemed to be prepending a zero to months to make them two digit, without bothering to check whether the month was already two digit.  This yielded dates like this: 2006-010-03T15:40:02+00:00, which is obviously invalid.  Adding this line above like 1014 in rssatom 2.08 seems to have resolved the issue:

<cfset mydatebites.main = REReplace(mydatebites.main, "([0-9]{4}-)0([0-9]{2}-)", "\1\2", "one") />

New App – Purchase Tracker

I've been using GnuCash for my money management for a long while, and quite like it.  But certain transactions cause problems.  In particular, when Heather goes to the store and buys apples and laundry detergent, the transaction needs to be split between groceries and household expenses.  You can imagine that when there are 30 different line items, that split gets cumbersome.

I've also oft wondered what the price of different things is over time.  For example, how much has the price of milk fluctuated over the past 12 months.  Being the good programmer I am, I built a very simple purchase tracking app, and make the 0.1 release available for download.  Installation is simple: unzip somewhere, and ensure you've got a MySQL DSN set up that matches the name in act_setappvars.cfm, and that CF has the ability to create/edit tables within.  Note that I've only tested on CFMX 7 and MySQL 4.1.  It should work on any Java-based CFML runtime with CFC support and on MySQL 4.1 or newer, but I haven't tested that.

Basically, it's a place to record the individual line items for a purchase, and the software will track the price of the items as well as split up the total purchase into different product categories.  Everything's dynamic, of course, and it works pretty well.

It's got a couple neat extra features as well:

  • Database auto-upgrade.  Check the database.cfc file for an automated upgrade script.  If/when you upgrade the code, that file will transparently ensure your schema is up to date as well.
  • Externalized strings.  All strings are externalized in standard Java properties files (and loaded through Java's PropertyResourceBundle class).  Note that locale support is NOT enabled, as I didn't want to introduce classpath dependancies, but it would be simple to add it manually.
  • Multiple configurations.  Built on top of the externalized strings is the ability to run the same code in multiple configurations.  In act_setappvars.cfm, you'll see an 'invoices' configuration that is commented out.  Uncomment it and you'll get a second copy of the database (with a different table prefix), and different strings throughout the UI so the same code can be used as a simple invoicing application.  The number of configurations is limitless.
  • Mollio for the UI.  Nothing particularly special here, but saved lots of time and still provides a professional look and feel.
  • Scriptaculous/Prototype for JS remoting.  A lot of the UI is centered around Scriptaculous's Ajax.InPlaceEditor, which saves a lot of page loads, and a lot of UI work.  A good example of how an HTML UI can be made a lot more usable with just a few simple additions.

Notably lacking is ColdSpring and Reactor support.  I greatly dispise their required server-level (ed. or at least webroot-level, per Kurt's comment below) configuration.  CF apps that are distributed as a pile of CFML should be neutral.  If you're distributing a WAR, no such qualms, of course.  If CF allowed for per-application (i.e. request-configured) mappings, that'd fix the issue.

Mollio

I've used Mollio on two projects now, and I have to say I'm really impressed.  The guys down at Daemon have done a great service to web developers at large by releasing Mollio as they have.  I can't say I particularly care for the red/black theme, but it's consistent, attractive, and unless you've got branding considerations, is perfectly acceptable.

It's also really easy to work with, as it's pretty unobtrusive in your markup.  Sure, there's some things you have to do a certain way (like the way you assemble forms or use THEAD), but nothing terribly bizarre.  I just took a little 15-page app that didn't have HTML tags or a stylesheet and Mollio-ized in about an hour, including some futzing with my layouts to not use (gasp!) tables.  In my defense, I assmbled the app in about 3 hours last night between midnight at 3am (and FB5, by the way, rules).

My next task with it will be to rebrand it a bit.  Starting with changing the color scheme and some of the L&F images, of course, and I'm hoping that'll be enough.  Their CSS is pretty well written, so I think I'll be able to get all I need with just that.  I'll also be extending the CSS (the form formatting stuff, in particular) to do some extra stuff (like per-field validation errors).  More details as that process progresses.

Anyway, if you haven't taken a look, highly recommended.  And all you BlogCFC guys out there, I'd bet Mollio would provide a 2-hour route to get away from the default look and feel with pretty minimal fuss.  It's got decorated pod support built right in and everything.  And when you're done, open source it.  ;)

Get Firefox – Piss Off

After much griping about my Get Firefox banner, I've added a 'piss off' (read: opt-out) link to the banner that will set a cookie so you won't see it again for 30 days.  After that, it'll tell you you still need a better  browser, but you can, of course, opt out again, ad nauseam.

CSS and Get Firefox

Everyone knows that browser compatibility is the bane of web developers.  If it's not a CSS bug or some DOM incompatibility, it's a plugin version issue (what's that, you say?  I'm thinking of something that starts with 'F' and ends with 'lex'….).  So help people put their best foot forward with a neat little CSS trick.  Drop this HTML into your page, just before the closing body tag:

<div id="betterBrowser" title="get firefox">
Get a better browser.<br />
<a href="http://www.getfirefox.com/">
<img src="static/get_firefox.gif" alt="Get Firefox" /></a>
</div>

And then this CSS in your stylesheet:

#betterBrowser {
position: absolute;
top: 0px;
right: 0px;
margin: 5px;
padding: 5px;
border: 1px solid #999;
background-color: #eee;
text-align: center;
display: block;
}
#betterBrowser[title="get firefox"] {
display: none;
}

Last step is to download the get_firefox.gif file and save it in the appropriate place (updating the HTML as needed). 

Voila!  Any browser that doesn't support CSS attribute selectors (cough … IE … cough) gets a nice little prompt to get a better browser.  No user agent sniffing, just a direct check for broken implementation.

Note that I'm running a slightly tweaked (though equally functional) version on this blog, so don't copy the code from my source.