<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Should Have Paid Me More &#187; coworkers</title>
	<atom:link href="http://shouldhavepaidmemore.com/tag/coworkers/feed/" rel="self" type="application/rss+xml" />
	<link>http://shouldhavepaidmemore.com</link>
	<description>Tales from the underpaid</description>
	<lastBuildDate>Sun, 29 Nov 2009 14:00:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Change It Back!</title>
		<link>http://shouldhavepaidmemore.com/2009/change-it-back/</link>
		<comments>http://shouldhavepaidmemore.com/2009/change-it-back/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 18:13:14 +0000</pubDate>
		<dc:creator>spork</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Users]]></category>
		<category><![CDATA[coworkers]]></category>
		<category><![CDATA[plus]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=142</guid>
		<description><![CDATA[He blamed me for "making changes without [his] knowledge".]]></description>
			<content:encoded><![CDATA[<p>Code comment written less than a month ago:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * Added 10/7/2009 by specific request of sjohnson. Of course there's no HD
 * ticket or other documentation for the request because everyone knows
 * normal rules don't apply to the field staff.
 */</span></pre></div></div>

<p>Code comment written today:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * Removed 11/5/2009 by specific request of sjohnson. Of course there's no HD ticket
 * or other documentation for the request because everyone knows normal rules don't apply
 * to the field staff. sjohnson swears this is a showstopper and must be removed because
 * now that he actually has to work in Plus on a daily basis he understands how
 * ridiculously foolish it is to clear out the time entry fields after every entry is
 * added to the table.
 */</span></pre></div></div>

<p><span id="more-142"></span>Mere days before a version of Plus was to be released, the manager in question demanded that the functionality be changed as it was &#8220;not the way the staff work&#8221;. He was made aware of the reason the product functioned the way it did and warned of the problems that would occur should his demand be met, but these logical beseechings fell upon deaf ears. He was given an opportunity (two full weeks) to test this change and he signed off on the final product. Almost exactly a month later, the manager had to take on the role of a field technician. As part of that, he had to use Plus, and blamed me for &#8220;making changes without [his] knowledge&#8221;.</p>
<p>This manager demanded that this and a second change be immediately coded and pushed into production as an &#8220;emergency&#8221; release&#8230;without any testing. He was warned of the expected problems of the second change and how testing helps ensure quality, but again he exhibited Deaf Man&#8217;s Vendetta. We&#8217;ll see how that turns out.</p>
<p><strong>Update</strong>: A week later (11/13/2009) the same manager went into another panic and demanded the functionality be reverted again, emailing &#8220;can you please verify and correct this issue immediately? This is the same issue we had in October!&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/change-it-back/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jim&#8217;s Keys</title>
		<link>http://shouldhavepaidmemore.com/2009/jims-keys/</link>
		<comments>http://shouldhavepaidmemore.com/2009/jims-keys/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 18:49:09 +0000</pubDate>
		<dc:creator>spork</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Users]]></category>
		<category><![CDATA[coworkers]]></category>
		<category><![CDATA[plus]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=106</guid>
		<description><![CDATA[He saw a set of blank data entry forms assigned to the new schedule instead of all the data he'd already entered under the old schedule.]]></description>
			<content:encoded><![CDATA[<p>Note: You may wish to read <a title="Jim's Comments" href="http://shouldhavepaidmemore.com/2009/10/02/jims-comments">Part I</a>, <a title="Jim's Themes and Dancing Monkeys" href="http://shouldhavepaidmemore.com/2009/10/08/jims-themes-and-dancing-monkeys">Part II</a>, <a title="Jim's Tables" href="http://shouldhavepaidmemore.com/2009/10/10/jims-tables/">Part III</a>, <a title="Jim's Tomcat Server" href="http://shouldhavepaidmemore.com/2009/10/17/jims-tomcat-server/">Part IV</a>, and <a title="Jim's Opus" href="http://shouldhavepaidmemore.com/2009/jims-opus/">Part V</a> of this series to gain context.</p>
<p>As relayed in previous posts in this series, the Plus application was meant to facilitate the transmission of data from field technicians to the home office. However, at some point it was decided that Plus should <em>also</em> be responsible for transmitting and displaying data from the home office to the field technicians. This information ended up being things like equipment-specific metadata, customer contact numbers, location of each piece of equipment, a directory of everyone employed at the company that developed Plus (no, I&#8217;m not kidding), and schedule data. All of this came from a poorly-standardized, non-normalized database used by the company&#8217;s CRM application, <a title="Clearview" href="http://www.nexterna.com/clearview" target="_blank">Nexterna Clearview</a>, which uses a batch-and-post system. <span id="more-106"></span></p>
<p>The schedule data was an important piece because it gave the field technicians a way to see scheduled work without having to use any brainpower. After adding this information to the Plus application the powers that be decided Plus should use it to automatically determine and display the appropriate data forms for the technician to fill out for each site visit. It was further decided that the forms themselves should dynamically change based on the equipment information from the CRM application.</p>
<p>Eventually this was all made ready and deployed to the field technicians. As usual, there were exclamations of &#8220;Wow, this is great!&#8221; and &#8220;This will make us so much more efficient!&#8221; at first. But soon the users started reporting problems. They&#8217;d enter data into a form and it would disappear the next time they downloaded schedule updates from the home office. It turned out Jim built Plus and the <a title="Jim's Tomcat Server" href="http://shouldhavepaidmemore.com/2009/jims-tomcat-server/" target="_blank">Plus server</a> to use auto-generated database record IDs as unique identifiers for schedule data. When a field technician entered form data, it was tied to the schedule&#8217;s database record ID. When the form data was sent to the home office, the Plus server displayed it to home office users by establishing a link between the schedule&#8217;s database record ID and the record ID in the returned data. In a normal world, this wouldn&#8217;t be a problem &#8211; using database keys guaranteed to be unique is good practice, right?</p>
<p>The issue came into play when one of the schedulers at the home office altered a schedule after a field technician had already used Plus to enter form data. The scheduler, called a &#8216;CSAM&#8217;, would change the schedule&#8217;s location, equipment, date, assigned technician, and even go so far as to delete the schedule altogether and create a new one in its stead. The next time the field technician used Plus, he saw a set of blank data entry forms assigned to the new schedule instead of all the data he&#8217;d already entered under the old schedule. In essence, data entered into Plus was &#8220;lost&#8221; due to the normal day-to-day operation of the CSAMs.</p>
<p>Later I found that there had been many a heated argument betwixt Jim and <a title="benson's profile" href="http://shouldhavepaidmemore.com/author/benson/" target="_blank">benson</a> about the use of auto-generated database record IDs as data keys. &#8220;That&#8217;s not how the users work!&#8221; benson would exclaim. &#8220;It&#8217;s the right way to do things!&#8221; Jim would shoot back. The end result was always the same &#8211; Jim would simply continue the way he wanted.</p>
<p>For quite some time people just blamed Plus for everything. &#8220;This stupid tool loses my data!&#8221; they&#8217;d gripe. &#8220;It eats my work!&#8221; Eventually I was able to show that a very small change to the existing CSAM scheduling process could avoid the majority of these situations, and the complaints changed to&#8230;well, they didn&#8217;t change at all. Everyone still made Plus the scapegoat, and the CSAM group refused to believe they could possibly have anything to do with the issues. Their leader wasn&#8217;t willing to even admit it was a possibility.</p>
<p>Finally I rewrote enormous chunks of the Plus application to use less volatile keys that mapped more directly to the way the users worked (vindication for you, <a title="benson's profile" href="http://shouldhavepaidmemore.com/author/benson/" target="_blank">benson</a>). Of course, at the same time the CSAM group finally conceded to make that one tiny change (it took the head of the company to get even that), and they&#8217;re taking credit for reducing the number of issues with Plus data. Oh well, only 11 more days&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/jims-keys/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jim&#8217;s Opus</title>
		<link>http://shouldhavepaidmemore.com/2009/jims-opus/</link>
		<comments>http://shouldhavepaidmemore.com/2009/jims-opus/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 13:59:46 +0000</pubDate>
		<dc:creator>spork</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[coworkers]]></category>
		<category><![CDATA[plus]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=99</guid>
		<description><![CDATA[Note: You may wish to read Part I, Part II, Part III, and Part IV of this series to gain context.
As demonstrated in Part I, Part II, Part III, and Part IV of this series, the Plus application was a mess. It never really worked and when the desired functionality was simulated, it caused other issues. To be fair, the [...]]]></description>
			<content:encoded><![CDATA[<p>Note: You may wish to read <a title="Jim's Comments" href="http://shouldhavepaidmemore.com/2009/10/02/jims-comments">Part I</a>, <a title="Jim's Themes and Dancing Monkeys" href="http://shouldhavepaidmemore.com/2009/10/08/jims-themes-and-dancing-monkeys">Part II</a>, <a title="Jim's Tables" href="http://shouldhavepaidmemore.com/2009/10/10/jims-tables/">Part III</a>, and <a title="Jim's Tomcat Server" href="http://shouldhavepaidmemore.com/2009/10/17/jims-tomcat-server/">Part IV</a> of this series to gain context.</p>
<p>As demonstrated in <a title="Jim's Comments" href="http://shouldhavepaidmemore.com/2009/10/02/jims-comments">Part I</a>, <a title="Jim's Themes and Dancing Monkeys" href="http://shouldhavepaidmemore.com/2009/10/08/jims-themes-and-dancing-monkeys">Part II</a>, <a title="Jim's Tables" href="http://shouldhavepaidmemore.com/2009/10/10/jims-tables/">Part III</a>, and <a title="Jim's Tomcat Server" href="http://shouldhavepaidmemore.com/2009/10/17/jims-tomcat-server/">Part IV</a> of this series, the Plus application was a mess. It never really worked and when the desired functionality was simulated, it caused other issues. To be fair, the department that requested Plus in the first place was also a mess &#8211; its manager not only couldn&#8217;t manage the department&#8217;s 150 employees, but further had no understanding of what they did or what they were supposed to be doing (and those two things were definitely not the same). As a result, change requests for the Plus application had no order, logic, or sanity, and often contradicted <em>other</em> change requests made by the same department slightly earlier. It was a constant cycle of &#8220;Make this change&#8221; &#8220;Why did you change that? Change it back!&#8221; &#8220;Make this change&#8221;.<span id="more-99"></span></p>
<p>Culpability of the project requester aside, the Plus application was awfully, horribly coded. When eight new complex Swing forms are cached in memory every time the mouse is clicked, you know there are some performance optimization opportunities ripe for consumption. The code&#8217;s terribleness was truly stunning in the same way a 450-pound person is &#8211; you&#8217;re disgusted and feel sorry for their plight but oddly intrigued at the same time because you wonder how they can possibly perform even the most basic of daily tasks.</p>
<p>As noted in previous parts of this series, after being charged with managing communication about the Plus application&#8217;s bugs I could hold back any longer &#8211; I had to dive in and fix some of the problems. It was like coming home every day to a towering stack of food-encrusted dishes &#8211; eventually you just have to clean them up. I fixed a few of the smaller bugs in the codebase, tested the fixes, and checked the changes in to the Subversion repository.</p>
<p>Later that week I sat down to lunch with the rest of the IT squad. The boss was there as usual and had some interesting news. &#8220;I talked to Jim last night,&#8221; he led off (Jim and the boss worked at the same company for years &#8211; when the boss was hired at our company, he brought Jim with him from their old employer). &#8220;He was furious that you changed the Plus code.&#8221;</p>
<p>&#8220;What&#8217;s the problem?&#8221; I asked warily.<br />
&#8220;He was extremely upset because you changed his code,&#8221; the boss said.<br />
&#8220;&#8230;but I <em>fixed</em> it&#8230;&#8221;<br />
&#8220;Yes, I know. But Jim and I talked for a long time tonight. He sees the changes you made as an intrusion. He acted very protective of his code.&#8221;<br />
&#8220;&#8230;but I <em>fixed</em> it&#8230;&#8221;<br />
&#8220;Jim said it was like defacing a masterpiece. He called Plus his opus.&#8221;<br />
&#8220;His <em>opus</em>? That&#8217;s normally used to describe an <em>accomplishment</em>. He considers <em>Plus</em> his greatest achievement?! Those saps who hired him are in for a surprise!&#8221;</p>
<p>Ahh, they definitely should have paid me more to put up with this.</p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/jims-opus/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Jim&#8217;s Tomcat Server</title>
		<link>http://shouldhavepaidmemore.com/2009/jims-tomcat-server/</link>
		<comments>http://shouldhavepaidmemore.com/2009/jims-tomcat-server/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 05:59:31 +0000</pubDate>
		<dc:creator>spork</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[coworkers]]></category>
		<category><![CDATA[plus]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=92</guid>
		<description><![CDATA[The application just zipped the schedule data into a temp directory and sent the file path back to the client.]]></description>
			<content:encoded><![CDATA[<p>Note: You may wish to read <a title="Jim's Comments" href="http://shouldhavepaidmemore.com/2009/10/02/jims-comments">Part I</a>, <a title="Jim's Themes and Dancing Monkeys" href="http://shouldhavepaidmemore.com/2009/10/08/jims-themes-and-dancing-monkeys">Part II</a>, and <a title="Jim's Tables" href="http://shouldhavepaidmemore.com/2009/10/10/jims-tables/">Part III</a> of this series to gain context.</p>
<p>One of the prevailing requirements for <a href="http://shouldhavepaidmemore.com/2009/10/02/jims-comments/">the Plus application</a> was that it allow field staff to enter data offline and &#8220;sync&#8221; it over the Interwebs at their leisure. In addition, the application had to get updated schedule information and previously-synced data and show it to the user while offline. As you know, the most logical design that meets this requirement is a disconnected client-server model. Therefore, a server had to be built to accept connections from the client, process incoming data, and send back schedule  information and previously-synced data.<span id="more-92"></span></p>
<p>This by itself isn&#8217;t such a big deal, right? <a title="Tomcat" href="http://tomcat.apache.org/">Apache Tomcat</a> exists <em>just</em> for tasks of this nature. It&#8217;s an entire server container that&#8217;s mature, been heavily tested, well-maintained, and trusted by enormous companies that could easily afford to choose any server product on Earth. It includes all sorts of advanced configuration options, logging facilities, exception handling, and standards adherence. There&#8217;s even a Windows installer package available! Installation, configuration, and basic Java implementation is fast and easy.</p>
<p>But since this was Jim&#8217;s project, it wasn&#8217;t fast, easy, simple, logical, standards-based, or maintainable. Jim rolled his own Tomcat server instead. Yes, that&#8217;s right &#8211; he ignored the ready-built server software available and wrote his own software to do the same thing. However, his version didn&#8217;t have the benefit of testing&#8230;or configuration options&#8230;or exception handling&#8230;or standards compliance&#8230;or maintainability&#8230;or &#8211; well, you get the idea. As a result, Jim&#8217;s Tomcat didn&#8217;t really work.</p>
<blockquote><p>As anyone might imagine, the directory quickly grew and eventually consumed all disk space on the server, crashing it.</p></blockquote>
<p>Jim split the server implementation into two completely separate areas of the server itself. The actual application itself was only responsible for receiving client requests for schedule information &#8211; but not for sending the data itself back to the client. Instead, the application just zipped the schedule data into a temp directory and <strong>sent the file path</strong> back to the client. The client then connected to an SFTP server and downloaded the specified file. When the client needed to download previously-submitted data files, it connected to the same SFTP server, navigated to a hard-coded directory, and downloaded everything in it. Yes, that&#8217;s right &#8211; <strong>each user ended up downloading all data ever submitted by any of the 150 users every time the client updated</strong>. As anyone might imagine, the directory quickly grew and eventually consumed all disk space on the server, crashing it.</p>
<p>The <em>submission </em>of data, however, was handled by the client. The client connected to that same SFTP server, navigated to a hard-coded directory, and uploaded individual files to it. Then a cron job ran every 60 seconds, swept the directory, determined the type of each data file by matching the beginning of its filename, loaded the data into a database, and moved the files to the &#8220;submitted data&#8221; folder that every client downloaded. If a file couldn&#8217;t be read, the cron job died and any file not already loaded was left in the folder. The next time the cron job ran the same problem would occur&#8230;without any notification to anyone.</p>
<p>I inherited all of this when I was stuck with the Plus project. Had I known what I was getting into, I would&#8217;ve said &#8220;You&#8217;ve gotta pay me more.&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/jims-tomcat-server/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Jim&#8217;s Tables</title>
		<link>http://shouldhavepaidmemore.com/2009/jims-tables/</link>
		<comments>http://shouldhavepaidmemore.com/2009/jims-tables/#comments</comments>
		<pubDate>Sat, 10 Oct 2009 22:58:10 +0000</pubDate>
		<dc:creator>spork</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[coworkers]]></category>
		<category><![CDATA[plus]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=53</guid>
		<description><![CDATA[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.]]></description>
			<content:encoded><![CDATA[<p>Note: You may wish to read <a title="Jim's Comments" href="2009/10/02/jims-comments">Part I</a> and <a title="Jim's Themes and Dancing Monkeys" href="2009/10/08/jims-themes-and-dancing-monkeys">Part II</a> of this series to gain context.</p>
<p>I enjoy using tables. They clearly demarcate the boundaries between datum, creating an easily-understood convention for interpreting information while retaining amazing flexibilities. They&#8217;re dead straight simple to program &#8211; an HTML layout table be created using <a title="W3 Schools HTML Table Tutorial" href="http://www.w3schools.com/html/html_tables.asp" target="_blank">as little as six tags</a> with very logical names, a JSPWiki table simplistically requires <a title="JSPWiki Table Syntax" href="http://www.jspwiki.org/wiki/TextFormattingRules#section-TextFormattingRules-Tables" target="_blank">only a few pipes</a>, and Microsoft created an entire program designed around tables. They call it Excel. <span id="more-53"></span></p>
<p>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 <a href="http://www.joelonsoftware.com/uibook/chapters/fog0000000065.html" target="_blank">in order to format data lists</a>! In my workplace everyone seems to have a dominant Excel fetish. Requirements meetings for  report development requests usually have &#8220;I want it to be exported to Excel so I can work with the results&#8221; (and also, &#8220;This can be emailed to me automatically as an attachment, right?&#8221; and sometimes &#8220;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&#8221;)  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 <a title="Doctor Who Official Site" href="http://en.wikipedia.org/wiki/Doctor_Who" target="_blank">Time Lords</a>, and <a title="Bill Watterson Wikipedia Entry" href="http://www.google.com/url?q=http://en.wikipedia.org/wiki/Bill_Watterson&amp;ei=qu3QSt2dKo3UMuHrlYgJ&amp;sa=X&amp;oi=spellmeleon_result&amp;resnum=1&amp;ct=result&amp;ved=0CAcQhgIwAA&amp;usg=AFQjCNFZKwNq5K821JrV4ej97KGDjFTTMQ" target="_blank">Bill Watterson</a> rolled into one powerful little green package because it has such great tables!</p>
<p>However, <a href="http://thedailywtf.com/Articles/Best_of_2006_0x3a__Web_0_0x2e_1.aspx" target="_blank">not every table implementation is done well</a>. 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 &#8216;n&#8217; 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&#8217;s an <a href="http://www.joelonsoftware.com/printerFriendly/uibook/fog0000000249.html">entire industry of highly-educated professionals</a> determining what those should be.</p>
<p>Some of the data entry forms in Jim&#8217;s Plus application needed to display tabular data with well-known constraints (known max number of columns &#8211; 21 &#8211; 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 &#8220;JTable!&#8221; when faced with this requirement, but Jim&#8217;s first thought was more like &#8220;I can write better table code than those highly-educated nerds at Sun!&#8221; (this was a common theme with him; a future story will elaborate on how Jim rolled his own <a title="Apache Tomcat" href="http://tomcat.apache.org/" target="_blank">Tomcat</a> server).</p>
<div id="attachment_54" class="wp-caption alignright" style="width: 130px"><a rel="attachment wp-att-54" href="http://shouldhavepaidmemore.com/2009/10/10/jims-tables/floodedjarsformold/"><img class="size-thumbnail wp-image-54   " title="*shudder* It looks so...placid...not nearly as evil as it turned out to be" src="http://shouldhavepaidmemore.com/wp-content/uploads/2009/10/FloodedJarsFormOld-150x144.png" alt="*shudder* It looks so...placid...not nearly as evil as it turned out to be" width="120" height="115" /></a><p class="wp-caption-text">Jim&#39;s array-based table implementation</p></div>
<p>So Jim thought for a bit and came up with a grand idea. &#8220;I&#8217;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!&#8221; At first glance, his finished JTextField array-based table implementation  didn&#8217;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.</p>
<p>Unfortunately for the life-span of Jim&#8217;s &#8220;tables&#8221;, 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&#8217;t let them jump between fields and they had to use Tab instead. They complained that there weren&#8217;t averages at the bottom for numerical fields. They complained that there wasn&#8217;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 &#8220;normal&#8221; left-to-right order for the rest of the columns (sadly, that is <em>not</em> hyperbole).</p>
<p>My personal favorite was when they complained that the cells didn&#8217;t turn yellow when their value was more than 20% away from the column&#8217;s overall average value.</p>
<p>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 <a title="FocusTraversalPolicy Documentation" href="http://java.sun.com/j2se/1.5.0/docs/api/java/awt/FocusTraversalPolicy.html" target="_blank">FocusTraversalPolicy</a> implementation to meet the wacky tab order requirements.</p>
<p>The user&#8217;s would have rejoiced if they weren&#8217;t such losers. &#8220;It&#8217;s just like Excel!&#8221; they would have cheered, then linked arms and skipped off toward a black hole.</p>
<p>Oops, ignore that last part. Somehow my daydream got mixed in.</p>
<p>Anyway, most of the users&#8217; 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&#8217;t any great way to reduce their size across the board (all of Jim&#8217;s form layouts sucked horribly and used up far too many resources, but I digress). The complaints about the table&#8217;s performance (now even worse) trailed off, but only because no one was willing to address them.</p>
<p>Then one day a new complaint came in. &#8220;I entered 240 rows of data and only 80 were saved!&#8221; 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.</p>
<div id="attachment_59" class="wp-caption alignleft" style="width: 190px"><a rel="attachment wp-att-59" href="http://shouldhavepaidmemore.com/2009/10/10/jims-tables/sealedjarsformnew/"><img class="size-medium wp-image-59  " title="Much faster, much cleaner, much cooler tabular data presentation and input handler" src="http://shouldhavepaidmemore.com/wp-content/uploads/2009/10/SealedJarsFormNew-300x186.png" alt="JTable-based form" width="180" height="112" /></a><p class="wp-caption-text">New and improved: The JTable-based form</p></div>
<p>So yours truly analyzed the problem, determined that a GUI table is not core business functionality, and took <a title="If it's a core business function, do it yourself, no matter what" href="http://www.joelonsoftware.com/articles/fog0000000007.html" target="_blank">Joel Spolsky&#8217;s advice</a>. The basic pseudo-table interface had to be followed, of course, but Swing&#8217;s great JTable support was harnessed to quickly create an efficient, componentized table that addressed the users&#8217; requirements and still performed like a greased gecko on methamphetamines.</p>
<p>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&#8217;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&#8217;s cells was changed. The columns were sortable, and users could use the arrow keys to navigate to any cell they desired.</p>
<p>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&#8217;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.</p>
<div id="attachment_60" class="wp-caption aligncenter" style="width: 250px"><a rel="attachment wp-att-60" href="http://shouldhavepaidmemore.com/2009/10/10/jims-tables/partsusedformold/"><img class="size-full wp-image-60 " title="A horrific mess this one was. When I got to it none of the controls lined up and some of them would randomly disappear." src="http://shouldhavepaidmemore.com/wp-content/uploads/2009/10/PartsUsedFormOld.png" alt="The old array-based form" width="240" height="39" /></a><p class="wp-caption-text">The old array-based form after a bit of sprucing up</p></div>
<div id="attachment_61" class="wp-caption aligncenter" style="width: 250px"><a rel="attachment wp-att-61" href="http://shouldhavepaidmemore.com/2009/10/10/jims-tables/partsusedformnew/"><img class="size-full wp-image-61 " title="Now we're talking. Input validation and a JTable-based format." src="http://shouldhavepaidmemore.com/wp-content/uploads/2009/10/PartsUsedFormNew.png" alt="New and improved:" width="240" height="138" /></a><p class="wp-caption-text">New and improved: The JTable-based form</p></div>
<p>So what did the users&#8217; representative say when he saw the much-improved JTable-based forms? &#8220;The tab order&#8217;s wrong&#8221;.</p>
<blockquote><p>* You know how annoying people say a word has been &#8220;verbed&#8221; if it was previously used only as a subject but they&#8217;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 &#8220;verbing&#8221; &#8220;verb&#8221;, considering &#8220;verb&#8221; 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)!</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/jims-tables/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jim&#8217;s Themes and Dancing Monkeys</title>
		<link>http://shouldhavepaidmemore.com/2009/jims-themes-and-dancing-monkeys/</link>
		<comments>http://shouldhavepaidmemore.com/2009/jims-themes-and-dancing-monkeys/#comments</comments>
		<pubDate>Fri, 09 Oct 2009 02:49:39 +0000</pubDate>
		<dc:creator>spork</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[coworkers]]></category>
		<category><![CDATA[plus]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=36</guid>
		<description><![CDATA[I discovered that Jim had used a portion of his 9-month development time to add themes. Yes, that's right - the Plus application was failing all sorts of tests for critical functionality, but it had themes.]]></description>
			<content:encoded><![CDATA[<p><em>Note: You may wish to read </em><a title="Part I" href="http://shouldhavepaidmemore.com/2009/10/02/jims-comments/" target="_self"><em>Part I</em></a><em> of this series to gain context.</em></p>
<p>When first assigned to the Plus project I was told to play the role of &#8220;bug manager&#8221;. &#8220;Jim (see <a href="http://shouldhavepaidmemore.com/2009/10/02/jims-comments/">Part I</a>) wants to do the right thing,&#8221; the boss remarked. &#8220;so he&#8217;s informed his new company that he&#8217;ll be providing bugfixes and support on the Plus project during his first month. We can contact him about bugs at any time during work hours and he&#8217;ll try to have a fix coded and checked into SVN before the next day.&#8221;</p>
<p>Given Jim&#8217;s apparent charity, my role in the project was simply to aggregate bug reports from the 150 users, de-duplicate and prioritize them, and ship the result off to Jim. This seemed decently straightforward; after all, I didn&#8217;t know anything about the 500-class codebase or the difference between intended functionality and broken features, and there wasn&#8217;t any requirements document, project documentation, or decent in-code documentation available. As the voluminous bug reports crashed in like a tidal wave in monsoon season during an earthquake, I went to work. <span id="more-36"></span></p>
<p>This system worked out okay for a couple of days, which is about as long as it took to get the first response from Jim regarding the bug reports (which represented 49 serious issues over a period of five months). Problems like &#8220;Application memory usage climbs in direct relation to the duration it is open&#8221; got solutions like &#8220;Upgrade RAM for all users&#8221;. Problems like &#8220;Autosave creates 500+ MB of identical files &#8211; runs continuously&#8221; resulted in (I&#8217;m <em>not</em> joking) &#8220;coded&#8221; (it wasn&#8217;t). And the rest, like &#8220;Data form randomly saves blank files and won&#8217;t allow user to enter data&#8221; (complete with concrete evidence and steps to reproduce), didn&#8217;t receive any response at all.</p>
<p>During this period I was the sole point of contact for the angry users of this product. Finally I became so frustrated that I started investigating the Plus codebase. <a href="http://shouldhavepaidmemore.com/2009/10/02/jims-comments/">Part I</a> chronicles some of the unhelpful comments found there, but more interestingly I discovered that Jim had used a portion of his 9-month development time to add themes. Yes, that&#8217;s right &#8211; the Plus application was failing all sorts of tests for critical functionality, but it had <em>themes</em>.</p>
<p>More than <em>twenty</em> of them.</p>
<p>In addition, it had a feature that created a preview of each tab as the user hovered the cursor over the tab name. Also, the application&#8217;s splash screen was a 6MB animated GIF of a weird-looking spinning globe (almost-kind of-sort of like the company&#8217;s logo, except horribly distorted and using non-company colors). As if that weren&#8217;t enough, easter eggs littered the code landscape, activated by lucky keystroke combinations. Ctrl-Alt-F7 launched a Tetris mini-game complete with a high-score board. Alt-Shift-T popped something called &#8220;Tea Timer&#8221;, which turned out to be a dialog that allowed the user to choose between tea, hot chocolate, and coffee and see Jim&#8217;s estimated preparation time (no, I&#8217;m not joking). This appeared to be Jim&#8217;s introduction to Java Swing components, his experimental form in which to try those weird GUI things like listening for user-initiated events and laying out form controls. I hope this is so &#8211; the alternative is that Jim&#8217;s knowledge of Swing programming was around the average high schooler&#8217;s level in 2000.</p>
<p>As soon as the option came I ripped out every one of these &#8220;features&#8221;, giggling with glee and smiling devilishly. What bastard puts a Tetris game in a productivity application designed for people who were stereotyped as lazy, unmotivated, dishonest, unsupervised fools? What non-managerial sniveling turd decides pretty GUI themes is more important than core functionality? What lying coward assures everyone he will stand behind his work, is given the support to do so, runs away and <em>then</em> has the nerve to complain loudly because someone else has touched his sacrosanct code (to be explained in a future story)? And let&#8217;s face it, what loser thinks a Swing form acceptable as a first-week assignment for an Introduction to Programming course is anywhere nearly as cool as an easter egg is meant to be?</p>
<p>I ask these probing questions because after systematically exterminating every ridiculous non-essential programming perversion Jim wedged in, I added dancing monkeys for <a title="rector's author profile" href="/author/rector">rector</a> to find after I&#8217;ve been fired and he&#8217;s forced to take over the codebase <img src='http://shouldhavepaidmemore.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/jims-themes-and-dancing-monkeys/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Jim&#8217;s Comments</title>
		<link>http://shouldhavepaidmemore.com/2009/jims-comments/</link>
		<comments>http://shouldhavepaidmemore.com/2009/jims-comments/#comments</comments>
		<pubDate>Sat, 03 Oct 2009 02:29:56 +0000</pubDate>
		<dc:creator>spork</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[coworkers]]></category>
		<category><![CDATA[plus]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=8</guid>
		<description><![CDATA[And that's when I found out what "you could be a god here" really means. When people are happy with a god people have sort of a vague "yeah, he's cool, no smiting lately" attitude" when you bring him up. But when they're pissed about something, anything , all you hear is blasphemy and threats of atheism.]]></description>
			<content:encoded><![CDATA[<p>When I interviewed for a programmer/analyst job at one company I was impressed by the high-class technology and excited by the opportunities it represented (&#8220;You could be a <em>god</em> here&#8221; was mentioned several times). Shortly after starting work another member of the company&#8217;s four-person development team took off for greener pastures with a year of employment under his belt. This programmer, whom we&#8217;ll call &#8220;Jim&#8221;, had been the sole developer on a revolutionary project we&#8217;ll call &#8220;Plus&#8221;.</p>
<p>Plus was intended to be a company-changing desktop application giving remote field technicians the ability to record site visit information offline and later &#8220;sync&#8221; it with the company&#8217;s servers. The product was released straight from Jim&#8217;s development machine to production on 150 technician laptops just two weeks before Jim&#8217;s last day at the company. Being the only available developer, I was assigned to the project in his stead.<span id="more-8"></span></p>
<p>&#8220;Jim used to be at IBM,&#8221; the boss said. &#8220;I worked with him at my last job and brought him over when I was hired here. He&#8217;s a top-notch programmer. You shouldn&#8217;t have any problems with his code.&#8221;</p>
<p>And that&#8217;s when I found out what &#8220;you could be a <em>god</em> here&#8221; really means. When people are happy with a god people have sort of a vague &#8220;yeah, he&#8217;s cool, no smiting lately&#8221; attitude&#8221; when you bring him up. But when they&#8217;re <em>pissed </em>about something, anything , all you hear is blasphemy and threats of atheism.</p>
<p>On one hand, I did get a god status. On the other hand, there weren&#8217;t any bonus points for lack of smiting. As the bug reports and shouts of anger began pouring in, I started looking at the Plus code and found more and more reasons for god-to-god smiting action. Following are some of Jim&#8217;s code comments verbatim:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">/* ---------------------------------------------------------------
 @author [Jim's real name here], [his side company's name here] LLC
 Date: 2008-4-18
 Project: Departed Friend
 --------------------------------------------------------------- */</span></pre></div></div>

<p>Hmmm&#8230;seems like a bit of egomania here. The project&#8217;s name was definitely not &#8220;Departed Friend&#8221;. And&#8230;putting your one-man &#8220;consulting&#8221; company down as the author? Chintzy.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Give it some time to complete the save.... This is just a guess</span>
<span style="color: #666666; font-style: italic;">// and is not good code, but owell when you read this I'm sure I</span>
<span style="color: #666666; font-style: italic;">// wont be working here anyway</span></pre></div></div>

<p>This one really toasted my tootsies. At the time I was naive and thought good programmers felt a responsibility to write maintainable code. Boy, was I dumb. The code below this comment added a five-second delay to the application&#8217;s closing to prevent an exception in case the autosave mechanism happened to be running. The delay had no actual relationship to the autosave mechanism &#8211; it could have kicked off at the last second and still caused the exception, so the it was absolutely  pointless.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">int</span> n <span style="color: #339933;">=</span> <span style="color: #003399;">JOptionPane</span>.<span style="color: #006633;">showConfirmDialog</span><span style="color: #009900;">&#40;</span>god, <span style="color: #0000ff;">&quot;Are you sure you want to cleanup files older then 40 days that we have a more recient copy of?  Why I ask is that this step will tie up your computer for some time, so is a great item to run when you have a coffee break or before you go to bed.&quot;</span>, <span style="color: #0000ff;">&quot;Are you sure you want to cleanup old useless files? &quot;</span>, <span style="color: #003399;">JOptionPane</span>.<span style="color: #006633;">YES_NO_OPTION</span>, <span style="color: #003399;">JOptionPane</span>.<span style="color: #006633;">WARNING_MESSAGE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Holy <a href="http://www.merriam-webster.com/dictionary/piquant">piquant</a> pineapples, Batman! Definitely one of the longer (and more ridiculous) modal pop-up dialog messages I&#8217;ve encountered in an internal product&#8217;s code. <a href="http://www.thehindu.com/2009/05/30/stories/2009053055392200.htm">Kavya Shivashankar</a> (world spelling bee champion), you can rest easy.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//  Yeah this is the cheap mans way to use a lot of memory for something that most likely will not be visible.</span></pre></div></div>

<p>This gem was above some code that instantiated up to <strong>5040</strong> <code>JTextField</code>s and added them to a Swing container &#8211; and <strong>immediately made them invisible</strong>. Jim was trying to present tabular data to the user and, instead of using a <code>JTable</code>, used 7 <code>JTextField</code> arrays to represent 7 columns of data. Is anyone surprised that one of the loudest complaints about the application was its abysmal performance?</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Its not returning the number I thought it would so we will just</span>
<span style="color: #666666; font-style: italic;">// waste CPU time</span>
<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> <span style="color: #cc66cc;">2000</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Hurts&#8230;so bad&#8230;can&#8217;t&#8230;comment&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//TODO verify that this is all of them.  IF they added for more people then this is not good enouf but its 11:00 PM and im on #4 of the IPA here so this is as good as it gets for a friday night at a brewery. :-)</span></pre></div></div>

<p>Jim worked remotely from another state 668 miles away. He obviously did some of his work at the bar. This does not surprise me.</p>
<p>As I found, they should have paid me more.</p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/jims-comments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
