Table normalization verses long-term data storage

I'm currently working on an application that involves long-term storage of assessment data. Users submit records of their activities and assess their performance, and then reviewers look over those assessments and denote whether they agree or disagree with them. Each assessment database record is related to a reviewer through the unique reviewer id that is part of the assessment record, and I can use that relationship to retrieve the reviewer's name whenever I display the assessment record.

It's a standard example of table normalization. If the reviewer's name was stored within the assessment record itself, and the reviewer changed their name for some reason (marriage, divorce, mid-life crisis, etc.), the application would have to update the name in both the reviewer's record AND the assessment record. But by using the reviewer's id in the assessment record to establish a relationship between the assessment record and the reviewer record, the reviewer's name only needs to be recorded or updated once.

However, this project will entail keeping the assessment data for an undetermined number of years. With the data arrangement I just described, that means I would have to store the assessment records and all of the related reviewer records if I want to be able to keep showing the name of the reviewer when looking at older assessment records. That could result in keeping a lot of extra data about reviewers (addresses, e-mail addresses, logins, passwords, etc.) who are no longer associated with the program simply because we need to keep their name tied to the assessments.

I think this is one of those situations where it makes sense to repeat a little data. Recording the reviewer's name in the assessment records allows me to let the administrative users of the application delete reviewer user accounts without impacting historical data. It means a bit more work in keeping the reviewer's name the same in both records, but in the long run I think it's worth the effort.

Some updates on reordering items with jQuery

If you follow my blog at all, you know I have a keen interest in being able to reorder items in a list and then record that change in order in a database using JavaScript, specifically with the jQuery UI Sortables component. Here's some things I've learned recently regarding the topic:

Reordering Nested Lists

In my last project, I created a tool that allowed my clients to rearrange nested lists of articles and article categories using the jQuery UI Sortables component and the techniques I demonstrated in an earlier blog post.

My clients were very excited about the tool when they saw it in the prototype, but they ran into some difficulty when they tried to use it themselves during the final testing. They found it hard to place an item at either end of a list block because there were no visual cues outlining the borders of the list.

It was also nearly impossible for them to move an item around in the top-most list: if they tried to place it in between sibling items or at the end of the list, the item would almost always get dropped at the end of whatever sublist came at the end of the sibling item above.

Finally, the scrollable <div> element containing the nested lists would not scroll to match the drag movement of the cursor, so if they needed to move an item from one end of the nested lists to the other, the item would have to moved in steps.

I solved all of these problems by abandoning the drag-and-drop technique and replacing it with a version of my "click-to-click move" technique. So now when they need to move an item, they click on an icon associated with each item (hidden until needed), and target <div>s are created above and below each item:

Image of move targets in my last project

They then just click on the target for the place they want the item moved to, and the item is "moved" and the targets are removed (technically, the item is cloned, the clone is put in the new position, and the original item is deleted).

They like the "click-to-click move" version a lot better, so perhaps that's a better means of reordering items when using nested lists. But I recently discovered jTree, a brand-new jQuery plugin someone wrote specifically for sorting nested lists using drag-and-drop. I tried out the demo for it, and it has visual cues to help you position items in the right list, but it does flicker a bit at times. Still, I might play with it the next time I have to deal with nested lists again.

Reordering Table Rows

Lists are nice, but they don't cut it when each item is really a collection of separate items: that's when you need a table. In my current project, I needed a way to reorder the rows in my table as a means of letting the user reorder the data records. The jQuery UI Sortables component, however, does not work on table rows.

I tried to create a pseudo-table by using <div>s within each <li> item to evenly space the data fields in each row. I got it working and looking slightly less than ugly in FireFox, but it didn't fare so well in IE.

I then went browsing through the jQuery UI discussion board on Google Groups and found a post that mentioned a plugin for sorting/rearranging table rows.

It's called TableDnD, and it's a slightly different approach to the challenge. When you click on a row and drag it, there is no drag outline and no gradual movement: if you move up far enough, the content of the row you're dragging and the row above it quickly switch places, and vice-versa if you move downward. It highlights the moving row as you move it so you can keep track of what's happening. The movement is very smooth and you can go as fast as you like.

The only drawbacks I'm aware of so far is that the dragging action will not trigger the scroll bar if you're trying to drag the row beyond the visual limit of the window or scrollable container (much like my original nested list tool), and someone pointed out to me that if you fill all of the cells in a row with other DOM elements such that you cannot click on any of the cells themselves, you won't be able to grab the row and move it. That's not a problem your table cells just contain text, but it's something to keep in mind if you plan on formatting the text with <span> tags or providing input boxes for the user to edtit the cell data.

Flex adoption leads to thousands of new ColdFusion developers?

One of the sessions I attended at cf.Objective() was Maxim Porges' presentation on developing in Flex without using a Flex framework. I visited his blog this morning because I wanted to find his e-mail address and send him a question.

In doing so, I stumbled upon a post he wrote while at the conference about a conversation he had with several people following the Birds-of-a-Feather discussion between the Adobe folks and the community about the next version of ColdFusion 9.

Apparently some very interesting things were revealed in that conversation, one of them being that many folks who are starting to learn Flex have also gained an interest in learning and using ColdFusion. How many? The number cited was 75,000.

I'm not sure how Adobe determined that correlation between the uptake in Flex and the uptake in ColdFusion, but even if the real number is half that amount, that's still pretty impressive in my book.

Other items were discussion, including a mention of Adobe's current view regarding open source and ColdFusion. I encourage folks to go read the blog entry for themselves:

http://maximporges.blogspot.com/2008/05/future-of-cf-part-ii.html

Reflections on cf.Objective()

Like I said in my comment on his blog post, I don't think I can top Ben Nadel's description of the experience of being at cf.Objective().

Still, there are a few things I want to say for myself. First of all, a big thank-you to everyone involved in the planning and execution of the conference. You all did a remarkable job. Same goes for the speakers. I think everyone learned a lot at the conference.

But what really made this conference special to me were the conversations I had outside of the presentations. I've been to CFUnited and even to MAX before, and while I learned a great deal at both, I tended to feel a bit lost, being a solo developer amongst a large crowd of folks who knew each other already or came with colleagues. cf.Objective() was different: it never took more than a minute or two to get involved in a conversation with folks from the blogosphere or even developers I knew nothing about. I always felt like I was part of what was going on. It was truly the most enjoyable conference I've ever attended.

Like I alluded to in my earlier post, I'd been feeling down and negative about, well, a number of things in the weeks leading up to the conference. I feel now like I'm back on track, ready to take what I got from this experience and run with it. So stay tuned.

P.S. A big thanks to Adobe for bring MXNA back to life, better than ever!

Off To cf.Objective()

...And not a moment too soon! I've been in a bit of a rut lately, so I'm hoping the conference and my fellow conference-goers will help re-energize my enthusiasm a bit.

I doubt I'll be blogging much from the conference: I tend to write slowly and with the MXNA blog aggregator still down for the most part, I'm not sure that anyone would "hear" me anyway. So if you want to keep track of what's going on at the conference, tune in to the bloggers covered by one of the other aggregators like FullAsAGoog, Feed-Squirrel, or ColdFusionBloggers

Finish the sentence: "I know I'm in a coding zone/groove when..."

"...I correctly write a recursive algorithm involving nested arrays on the first try."

What about you? When do you know you're in a coding groove such that it feels like you're coding by feel/intuition?

ColdFusion Weekly Podcast 3.07: Flex Frameworks

Matt and Peter discuss the various Flex application frameworks out there with several guests.

As always, you can get it by either subscribing to the podcast via ITunes or by downloading it from the ColdFusion Weekly web site.

BlogCFC was created by Raymond Camden. This blog is running version 5.1.004.