Note: You may wish to read Part I and Part II of this series to gain context.
I enjoy using tables. They clearly demarcate the boundaries between datum, creating an easily-understood convention for interpreting information while retaining amazing flexibilities. They’re dead straight simple to program – an HTML layout table be created using as little as six tags with very logical names, a JSPWiki table simplistically requires only a few pipes, and Microsoft created an entire program designed around tables. They call it Excel.
According to Joel Spolsky, Microsoft initially developed Excel as an accounting tool until some user interaction testing for v5.0 demonstrated how people gravitated toward its clean tabular interface in order to format data lists! In my workplace everyone seems to have a dominant Excel fetish. Requirements meetings for report development requests usually have “I want it to be exported to Excel so I can work with the results” (and also, “This can be emailed to me automatically as an attachment, right?” and sometimes “Unless there are pink dragons on every line except those in which the total number of characters multiplied by the fractional representation of the current lunar phase is prime, this report will be useless”) in there somewhere. One request from May 09 specified that the Excel document produced by a Crystal Reports report must contain a dynamic number of inverted columns based on arbitrary, inconsistent numbers in a database! People think Excel is better than Batman, the Time Lords, and Bill Watterson rolled into one powerful little green package because it has such great tables!
However, not every table implementation is done well. Fortunately for us programmers, the necessity of tables is ubiquitous enough to inspire table support in most GUI libraries. The Java Swing libraries, for example, include a number of interfaces and concrete and abstract classes for creating tables, displaying data in implementation-specific ways, handling user input, validating data, refreshing data, sorting by column, handling events, etc. Much of the table functionality is automatic and requires zero additional coding. Simple tables are quick ‘n’ easy to generate and they can get as complex as the programmer needs. JTables were built with user interface best practices in mind, and there’s an entire industry of highly-educated professionals determining what those should be.
Some of the data entry forms in Jim’s Plus application needed to display tabular data with well-known constraints (known max number of columns – 21 – and common datatypes, known maximum row count of 240) and handle user input. Any high school student with an Introduction to Java course under his belt would immediately think “JTable!” when faced with this requirement, but Jim’s first thought was more like “I can write better table code than those highly-educated nerds at Sun!” (this was a common theme with him; a future story will elaborate on how Jim rolled his own Tomcat server).
So Jim thought for a bit and came up with a grand idea. “I’ll put 5040 total textboxes (21 columns * 240 rows) into 21 separate arrays and just display them as if they were part of a table!” At first glance, his finished JTextField array-based table implementation didn’t seem so bad. It had row numbering down the left side, you could enter data, and the textboxes creatd a decent approximation of a tabular format.
Unfortunately for the life-span of Jim’s “tables”, there were problems. Users saw an Excel-like interface and assumed Jim had rewritten Excel just for them. They complained that the arrow keys didn’t let them jump between fields and they had to use Tab instead. They complained that there weren’t averages at the bottom for numerical fields. They complained that there wasn’t any real-time input validation. They complained that the forms were excessively slow and difficult to work with. They complained that the fields were way to big and only eight rows fit on the screen at one time. They complained that the tab order went left-to-right when it should really hop betwixt the first two columns until the last row, and then it should revert back to “normal” left-to-right order for the rest of the columns (sadly, that is not hyperbole).
My personal favorite was when they complained that the cells didn’t turn yellow when their value was more than 20% away from the column’s overall average value.
Jim listened to all of these complaints about his pseudo-JTable. He bared his teeth in a pseudo-smile, like a Mafia don feigning benevolence, and started slinging code like a mentally unstable bull with diarrhea spreads fertilizer. Adding to the abysmal performance of his pseudo-JTable, Jim wrote a background thread to run every 30 seconds and calculate the overall average of numerical columns. He threw up another that iterated over every textbox and changed its background color to yellow if it was 20% away from its column average. He spurted out a FocusTraversalPolicy implementation to meet the wacky tab order requirements.
The user’s would have rejoiced if they weren’t such losers. “It’s just like Excel!” they would have cheered, then linked arms and skipped off toward a black hole.
Oops, ignore that last part. Somehow my daydream got mixed in.
Anyway, most of the users’ complaints about the fake JTable were addressed, but there were still issues. The weird 20% background color thread would falsely Crayola™* a field if it ran before the average-calculation thread did. The averages themselves were frequently incorrect. The textboxes were still enormous and took up far too much space, both vertically and horizontally. Jim had used BoxLayouts that automatically determined the appropriate size for GUI components, and there wasn’t any great way to reduce their size across the board (all of Jim’s form layouts sucked horribly and used up far too many resources, but I digress). The complaints about the table’s performance (now even worse) trailed off, but only because no one was willing to address them.
Then one day a new complaint came in. “I entered 240 rows of data and only 80 were saved!” sniveled the user. An investigation found that a very specific sequence of events could indeed cause the pseudo-JTable to display 240 rows for data entry but only save some of them. An outcry was launched, fingers were pointed, blame assigned, and demands made. The forms had to be revamped, and immediately.
So yours truly analyzed the problem, determined that a GUI table is not core business functionality, and took Joel Spolsky’s advice. The basic pseudo-table interface had to be followed, of course, but Swing’s great JTable support was harnessed to quickly create an efficient, componentized table that addressed the users’ requirements and still performed like a greased gecko on methamphetamines.
Since it implemented the JTable components as intended by The Maker (Sun), the new table even added some features. Each column had a specific datatype and prevented inappropriate entries, and user input was validated in real-time. A cell’s border turned red when it contained an unacceptable value. Its background turned yellow (sigh) when the value was more than 20% away from the column average. The column average itself was recalculated when one of the column’s cells was changed. The columns were sortable, and users could use the arrow keys to navigate to any cell they desired.
It was a nice change. So nice, in fact, that another form was changed from yet another array-based pseudo-tabular GUI to use the more appropriate JTable (it’s going to take some time to get them to understand in-place edits for that one). When I first got to this form, none of the controls lined up or sized appropriately. The buttons on the right would randomly disappear, making it impossible to enter data. The labels had misspellings. Like the other tabular form, this one held all of its controls (an astonishing 4500 of them) in arrays and made each row visible as the user finished with the previous one. The JTable-based form eliminated the label repetition, corrected the spelling, appropriately sized the input fields, and introduced sorting. The buttons stay put as well.
So what did the users’ representative say when he saw the much-improved JTable-based forms? “The tab order’s wrong”.
* You know how annoying people say a word has been “verbed” if it was previously used only as a subject but they’ve incorrectly wedged it into a sentence where the verb should have been? Has anyone addressed the infinite recursive loop that comes from the act of “verbing” “verb”, considering “verb” is a subject until used incorrectly as a verb? Dare I utter it more clearly, lest a the loop creates a black hole? I do! Those are verbed verbs (and spelling errors)!



Comments