<?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; Technology</title>
	<atom:link href="http://shouldhavepaidmemore.com/category/technology/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>The Utilization Report, Part Two</title>
		<link>http://shouldhavepaidmemore.com/2009/the-utilization-report-part-two/</link>
		<comments>http://shouldhavepaidmemore.com/2009/the-utilization-report-part-two/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 14:00:20 +0000</pubDate>
		<dc:creator>spork</dc:creator>
				<category><![CDATA[Users]]></category>
		<category><![CDATA[inefficiency]]></category>
		<category><![CDATA[utilization]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=165</guid>
		<description><![CDATA["How does the utilization report arrive at its numbers?"

It seemed like a simple, straightforward and innocuous question at the time. Unfortunately, it opened an institution-sized metallic food storage container of blind, soil-ingesting invertebrates.]]></description>
			<content:encoded><![CDATA[<p><em>Note: You may wish to read </em><a title="The Utilization Report, Part One" href="http://shouldhavepaidmemore.com/2009/the-utilization-report/"><em>The Utilization Report</em></a><em> to gain context.</em></p>
<p>&#8220;How does the utilization report arrive at its numbers?&#8221;</p>
<p>It seemed like a simple, straightforward and innocuous question at the time. Unfortunately, it opened an institution-sized metallic food storage container of blind, soil-ingesting invertebrates.</p>
<p>You see, the person who&#8217;d commissioned the development of the utilization report didn&#8217;t really understand what he was building. He had vague amorphous ideas about what he wanted &#8211; perhaps he&#8217;d seen a report at some other company that was used to determine how well the employees were being utilized and decided it was a good idea. Based on second-hand knowledge and investigation into the reports themselves, here&#8217;s how I picture the utilization report&#8217;s progression in my head:<span id="more-165"></span></p>
<p><strong>Project Requester</strong>: &#8220;I want a report that tells me if there&#8217;s enough work for my employees.&#8221; <em>&#8211;note: He&#8217;s saying &#8220;show number of hours worked divided by number of hours that could have been worked&#8221;</em><br />
<em>&#8211; time passes &#8211;</em><br />
<strong>Programme</strong>r: &#8220;OK, here it is.&#8221;<br />
<strong>Project Requester</strong>: &#8220;It&#8217;s wrong. It needs to take holidays into account.&#8221;<br />
<em>&#8211; time passes &#8211;</em><br />
<strong>Programmer</strong>: &#8220;OK, here it is.&#8221;<br />
<strong>Project Requester</strong>: &#8220;It&#8217;s wrong. It needs to take PTO into account.&#8221;<br />
<em>&#8211; time passes &#8211;</em><br />
<strong>Programmer</strong>: &#8220;OK, here it is.&#8221;<br />
<strong>Project Requester</strong>: &#8220;It&#8217;s wrong. It  should use the number of hours the employee has been <em>scheduled</em> to work instead of the hours actually worked.&#8221;<br />
<strong>Programmer</strong>: &#8220;What?&#8221;<br />
<strong>Project Requester</strong>: &#8220;It has to.&#8221;<br />
<em><em>&#8211; time passes &#8211;<br />
</em><span style="font-style: normal;"><strong>Programmer</strong>: &#8220;OK, here it is.&#8221;<br />
</span><span style="font-style: normal;"><strong>Project Requester</strong>: &#8220;It&#8217;s wrong. If an employee had a job that ran late the night before, the Scheduling department schedules an employee for a block of time the next day in order to keep him from having to work. The report has to take that into account when it happens.&#8221;<br />
</span>&#8211; time passes &#8211;<br />
<strong><span style="font-style: normal;">Programmer</span></strong><span style="font-style: normal;">: &#8220;OK, here it is.&#8221;<br />
</span><strong><span style="font-style: normal;">Project Requester</span></strong><span style="font-style: normal;">: &#8220;It&#8217;s wrong. It needs to show that an employee worked the whole weekend if he was scheduled for a Saturday.&#8221;<br />
&#8211; time passes &#8211;<br />
<em><strong><span style="font-style: normal;">Programmer</span></strong><span style="font-style: normal;">: &#8220;OK, here it is.&#8221;<br />
<em><strong><span style="font-style: normal;">Project Requester</span></strong><span style="font-style: normal;">: &#8220;It&#8217;s wrong. It needs to assume every employee spent two hours to get to the job site and two hours to get home.&#8221;<br />
<em>&#8211; time passes &#8211;</em></span></em></span></em></span></em><br />
<strong>Programmer</strong>: &#8220;OK, here it is.&#8221;<br />
<strong>Project Requester</strong>: &#8220;It&#8217;s wrong.&#8221;<br />
<strong>Programmer</strong>: &#8220;How is it wrong?&#8221;<br />
<strong>Project Requester</strong>: &#8220;The numbers can&#8217;t possibly be that low. The report is wrong.&#8221; <em>&#8211;note: It showed an average of 64% utilization (i.e. employees jacked off 36% of the time for which they were paid). It was later found that actual utilization was 52% if they were afforded every possible benefit of the doubt.</em></p>
<p>The utilization report was used to determine year-end monetary bonuses for managers. However, every time the utilization numbers were too low to allow the maximum bonus, the managers would say &#8220;The report&#8217;s always been inaccurate. The numbers are really much higher.&#8221; And the bonus would be awarded.</p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/the-utilization-report-part-two/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Utilization Report</title>
		<link>http://shouldhavepaidmemore.com/2009/the-utilization-report/</link>
		<comments>http://shouldhavepaidmemore.com/2009/the-utilization-report/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 18:03:00 +0000</pubDate>
		<dc:creator>spork</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[inefficiency]]></category>
		<category><![CDATA[MS Access]]></category>
		<category><![CDATA[utilization]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=161</guid>
		<description><![CDATA[A utilization report is essentially a view of hours worked vs hours paid &#8211; simple, right? You can determine appropriate staffing levels by understanding how much work they&#8217;re performing and how much work needs to be performed.
It turned out &#8220;the utilization report&#8221; at my company actually meant six distinct reports. Here&#8217;s how the system worked:

At [...]]]></description>
			<content:encoded><![CDATA[<p>A utilization report is essentially a view of hours worked vs hours paid &#8211; simple, right? You can determine appropriate staffing levels by understanding how much work they&#8217;re performing and how much work needs to be performed.</p>
<p>It turned out &#8220;the utilization report&#8221; at my company actually meant six distinct reports. Here&#8217;s how the system worked:</p>
<ul>
<li>At the beginning of every month, a user would submit an IT ticket as a reminder to &#8220;run&#8221; the report on the 15th of the next month</li>
<li>Somewhere near the 15th of the month, a specific developer would navigate to a directory on his machine and double-click an Access database</li>
<li>The developer would then locate each of the six reports in the Access database and run them all in turn, exporting them as RTF files when they finished</li>
<li>Each report was extremely resource-intensive and completely took over the IT guy&#8217;s computer, rendering him useless for hours &#8211; and even longer if the Access database crashed</li>
<li>When all reports had been exported, they were attached to an email and sent to the user from Step 1</li>
</ul>
<p><span id="more-161"></span></p>
<p>This process was repeated every month and caused much frustration for the user (because they couldn&#8217;t get the report immediately) and the developer (because it consumed his computer and he couldn&#8217;t get anything done). After hearing the developer curse and complain about the utilization report a few times, I set to work on the Access database. The process was changed to:</p>
<ul>
<li>On the 15th of every month, Windows Task Scheduler opens the Access database, triggering a VBA subroutine</li>
<li>Each report is exported to RTF</li>
<li>All exported reports are programmatically attached to an email message and sent to the user</li>
</ul>
<p>The new process is entirely automated and takes about three minutes to complete. It turns out Access was running all of the report queries (a bunch of UNION ALLs in a number of views) twice &#8211; once to display the report to the developer, and again to export the data to RTF. In addition, the formatting process required to display the report inside Access took an enormous amount of time, whereas the formatting of the RTF to be displayed in an external viewer was far quicker.</p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/the-utilization-report/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Do Not Click Button</title>
		<link>http://shouldhavepaidmemore.com/2009/the-do-not-click-button/</link>
		<comments>http://shouldhavepaidmemore.com/2009/the-do-not-click-button/#comments</comments>
		<pubDate>Sun, 08 Nov 2009 19:15:03 +0000</pubDate>
		<dc:creator>spork</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Users]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=151</guid>
		<description><![CDATA[It seemed only fitting to provide them with the one thing they couldn't screw up: the Do Not Click button.]]></description>
			<content:encoded><![CDATA[<p>Everyone&#8217;s seen at least one enormous red button with a label like &#8220;GLOBAL THERMONUCLEAR WAR INITIATOR VALVE &#8211; DO NOT PUSH!&#8221;, oui? Of course there&#8217;s always a villain around to press the button and ostensibly end the world, but the general concept prevails.</p>
<p>Given the tendency of Plus users to do the most illogical things possible while refusing to read or apply any kind of instructions given and then blame the software for behaving &#8220;unexpectedly&#8221;, it seemed only fitting to provide them with the one thing they couldn&#8217;t screw up: the Do Not Click button.<span id="more-151"></span></p>
<p>A lot of thought went into the Do Not Click button. Its placement was particularly important &#8211; it had to be accessible yet unobtrusive enough to go unnoticed for a while. The button itself had to be recognizable as capable of performing an action, yet simple enough to be overlooked by a casual glance. It had to display enough of a warning to be clear that clicking was ill-advised, yet low-key enough to beckon seductively. The final product is thus:</p>
<p><a rel="attachment wp-att-152" href="http://shouldhavepaidmemore.com/2009/the-do-not-click-button/donotclick/"><img class="aligncenter size-full wp-image-152" title="The Do Not Click Button" src="http://shouldhavepaidmemore.com/wp-content/uploads/2009/11/donotclick.png" alt="The Do Not Click Button" width="123" height="33" /></a>Fetching, no? It was placed at the very bottom of the About dialog, which I doubt anyone ever accesses unless by accident. If any one of the 150 users happens upon it, however, he&#8217;s all but guaranteed to email the other 149 to tell them about it. And <em>that&#8217;s</em> when the fun starts.</p>
<p>&#8220;What happens when the Do Not Click button is clicked?&#8221; one might ask curiously. Let me give you the most likely scenario:</p>
<blockquote><p><strong>User</strong>: &#8220;What&#8217;s this thing that looks like a stop sign with a white X in it? That looks weird. Wait, there are some hieroglyphs beside it&#8230;they say &#8216;d&#8217;&#8230;no, &#8216;D&#8217;&#8230;I&#8217;ve got it! It says &#8216;Do&#8217;! Phew, that was hard work. I&#8217;d better take a break so as not to strain myself.&#8221;</p>
<p>&lt;- four hours later -&gt;</p>
<p><strong>User</strong>: &#8220;Why is there a window that says &#8216;About&#8217; open? This stupid software, always doing things I don&#8217;t tell it to! I&#8217;m going to create a helpdesk ticket for IT to fix it! No, I should compose a poison-filled email about how crappy Plus is and how it&#8217;s always broken and send it to all of the other field technicians so they can join me in my uninformed griping!&#8221;</p>
<p>&lt;- two hours later -&gt;</p>
<p><strong>User</strong>: &#8220;All that typing made me hungry. I&#8217;m going to go to the expensive steakhouse down the road and charge a hefty three-course to my company credit card and then take a nap.&#8221;</p>
<p>&lt;- the next day -&gt;</p>
<p><strong>User</strong>: &#8220;Hmm, what&#8217;s this window that says &#8216;About&#8217;? There&#8217;s a button that has a stop sign with a white X in it. It doesn&#8217;t say what it does&#8230;&lt;click&gt; Nothing happened. &lt;click&gt; &lt;click&gt; &lt;CLICK&gt; Stupid Plus! How can I be expected to perform any work if this trashy program won&#8217;t do anything? Those idiots in IT are just trying to keep me from doing my job!&#8221;</p></blockquote>
<p>Sadly, this is probably a realistic depiction of events. However, the Do Not Click button <em>does</em> do something &#8211; it records the number of times it&#8217;s been clicked. Yes, that&#8217;s right &#8211; there&#8217;s a persisted click count. When the user submits work (which is supposed to happen once every few days), the cumulative click count is stored to a server-side database along with the user&#8217;s username. There it waits until an intranet-accessible web page is requested, wherein it&#8217;s included in a report showing the users clicking the Do Not Click button the most.</p>
<p>And here&#8217;s the best part: Any &#8220;bug&#8221; report about the Do Not Click button being broken can be closed with &#8220;The button works as intended. Do not click the Do Not Click button.&#8221; When the question of why the button exists comes up, the answer is &#8220;The button is there to keep an issue from occurring. When the button is clicked, the issue occurs. If the button is not clicked, the issue does not occur. This is why it says &#8216;Do Not Click&#8217; on the button.&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/the-do-not-click-button/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>Double Take</title>
		<link>http://shouldhavepaidmemore.com/2009/double-take/</link>
		<comments>http://shouldhavepaidmemore.com/2009/double-take/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 14:28:01 +0000</pubDate>
		<dc:creator>benson</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=102</guid>
		<description><![CDATA[Sure enough as I debugged the code it was always zero.  So it was completely useless.]]></description>
			<content:encoded><![CDATA[<p>Below you will see some code I ran into a couple days ago.  It is one of those things that took me back to 3rd grade math and made me second guess myself.  If you look there is a new integer declared and it is set to zero.  Then a loop starts in reverse order to iterate through some tabs which are always going to be a quantity of 5.  What is interesting is that the integer is multiplied by -1.  At first glance it made sense, multiply 1 times -1 you get -1, 2 times -1 = -2.  But the value of intTabCounter was never being set inside the loop.  So it appears that it was always zero.  And sure enough as I debugged the code it was always zero.  So it was completely useless.</p>
<p><code>Dim intTabCounter As Integer = 0</code></p>
<p><code> </code></p>
<p><code>For intTabIndex As Integer = tcNewsDayTabs.Tabs.Count - 1 To 0 Step -1<br />
tabDate = Date.Today.AddDays((intTabCounter * -1))<br />
tabDate = NewsUtil.FindBusinessDayDate(tabDate.AddDays(1), ldTabPanelDates)<br />
ldTabPanelDates.Add(intTabIndex, tabDate)<br />
Next intTabIndex<br />
</code></p>
<p>This is an example of a time something looks good on the surface but has no functional value once you look a little deeper.  In a bad economy like we have these days I look at this as job security.</p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/double-take/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>The New World</title>
		<link>http://shouldhavepaidmemore.com/2009/the-new-world/</link>
		<comments>http://shouldhavepaidmemore.com/2009/the-new-world/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 19:56:15 +0000</pubDate>
		<dc:creator>benson</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=75</guid>
		<description><![CDATA[I realized that the man who developed this portal was sent from satan to destroy my hopes and dreams]]></description>
			<content:encoded><![CDATA[<p>So I had worked in a company that specialized in maintenance and service.  During my time at this organization I started a career as a software developer.  I dare say that it came naturally to me, being the lazy person that I am.  At this organization there were 2 developers that were primarily Java developers.  At the time, I was using .Net.  Oddly enough, I learned most of what I know from those 2 developers in spite of writing in different languages and for this I am eternally grateful.</p>
<p>So one day I decided that I may have better opportunities somewhere else.  So I got a new job at an insurance company and was now exposed to a very pure .Net atmosphere.  The main role I would have would be developing and maintaining the portal that they used for their agents.  Seems relatively simple.  Certainly there would be some quirkiness to this portal but the whole thing would be able to reuse a few abstract patterns right?</p>
<p><span id="more-75"></span></p>
<p>No not right.  The author of this application wouldn&#8217;t recognize a pattern even if it hit him in the jaw.  Oddly enough he was a consultant making multiple hundreds of dollars per hour.  What I learned about the .Net world is they encourage database heavy applications.  You&#8217;re probably thinking, oh they must have had ten or twenty stored procedures in their database if that were the case.  No, not 10 or 20, not even 100 or 200.  This database had 551 stored procedures in it.  In addition there are 172 tables and 104 functions.  Now at the time I had used some SPs for some complex needs and what not but I hadn&#8217;t seen anything like this.  I wondered if I was in over my head and wouldn&#8217;t understand the deep complexities of all of this data and perhaps I made a big mistake coming to this company.  After working on this for 2 years I realized that the man who developed this portal was sent from satan to destroy my hopes and dreams.  I will give you an example to help illustrate of 2 tables.  One called DO_DOCUMENT and another called FS_DOCUMENTS:</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>DO_DOCUMENT</p>
<ol>
<li>do_id</li>
<li>data</li>
<li>type_id</li>
<li>title</li>
<li>publish_date</li>
<li>expiration_date</li>
<li>revision_date</li>
<li>create_date</li>
<li>contenttype</li>
<li>lastmodified_date</li>
<li>lastmodified_loginid</li>
<li>do_status</li>
<li>do_formnumber</li>
<li>do_link</li>
</ol>
</td>
<td>FS_DOCUMENTS</p>
<ol>
<li>fd_id</li>
<li>fd_data</li>
<li>fd_typeid</li>
<li>fd_title</li>
<li>fd_publishdate</li>
<li>fd_expirationdate</li>
<li>fd_revisiondate</li>
<li>fd_createdate</li>
<li>fd_contenttype</li>
<li>fd_lastupdated</li>
<li>fd_modifiedby</li>
<li>fd_status</li>
<li>fd_formnumber</li>
<li>fd_link</li>
</ol>
</td>
</tr>
</tbody>
</table>
<p>Look familiar?  Well isn&#8217;t that special?  Why use one table when you can use 2 that are almost identical?  This must be some methodology that I am not familiar with.  Maybe the were using one table to store inactive data to increase performance.  Not likely, both tables had different types of documents in them based on business type.  I looked in the table on one contained 20,000 rows the other 50.  Seems like an opportunity for re-use to me.  This is one of many scenarios where logic or data was duplicated.  What is odd that in this dark place there were some point of brilliance.  But the .Net world was a bit different than the Java world.  The developers that I knew that were working in Java didn&#8217;t want anything in the database except data.  So this gave me an opportunity to discover the pros and cons of both.</p>
<p>The truth is we all write bad code at some time or another.  Somewhere out there someone is writing a message just like this about my code.  But one thing I will say about myself is I work as hard as I can to write as little code as I can.  Mainly because it is less work and more stable.  But stored procedures seem like extra work to me and that isn&#8217;t what I am all about.</p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/the-new-world/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Insurolink Part I</title>
		<link>http://shouldhavepaidmemore.com/2009/insurolinki/</link>
		<comments>http://shouldhavepaidmemore.com/2009/insurolinki/#comments</comments>
		<pubDate>Wed, 14 Oct 2009 19:39:45 +0000</pubDate>
		<dc:creator>rector</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://shouldhavepaidmemore.com/?p=79</guid>
		<description><![CDATA[Every time new code was added and changes were made, it broke everyone's local copies, and all the developers would play around with the code until one of them got it to compile.]]></description>
			<content:encoded><![CDATA[<p>A few years ago I interviewed with a regional insurance company for a &#8220;Senior Software Developer&#8221; position.    The application I would be working on was described as an Online application that allowed the companies agents to quote and sign business.  It was a &#8216;robust and flexible&#8217; system that had been developed and enhanced over 9 years.  The application was primarily developed by consultants (Boy THAT should have been a red flag), but the division was recently acquired by the regional insurance company and the new management wanted to do development in house.  I was to be the first of a dozen new hires.  I took the job.</p>
<p><span id="more-79"></span></p>
<p>On the first day, one of the contractors, Alicia,  was assigned to train me.   I should have known something was up when Alicia checked the code out and could not get it to compile.  She needed to go find Shaun, because &#8216;He had the working version&#8221;.  I asked, &#8220;Doesn&#8217;t everyone have a working version?&#8221;.  She replied, &#8220;No, Shaun does.&#8221;  It appeared that every time new code was added and changes were made, it broke everyone&#8217;s local copies, and all the developers would play around with the code until one of them got it to compile.  Then everyone would get that person to &#8216;recreate&#8217; what he/she did on their computers.</p>
<blockquote><p>Doesn&#8217;t everyone have a working version?</p></blockquote>
<p>Boy THAT should have been a red flag. Apparently, Shaun was the only person who could compile and deploy the code.  This week. Eventually, with Shaun&#8217;s help, the application was checked out of source control and compiled on my computer.  But for the next week, I saw PPT presentations of the &#8217;system design&#8217;, and code snippets on screen without actually having any interaction with the code.  When I finally pressed the point that I wanted a &#8216;walk through&#8217;, Alicia reluctantly agreed.  The application, being a J2EE implementation, was launched and the login page displayed.  Alicia then logged in using a test account and walked through the application, which bombed every other screen because &#8220;it can&#8217;t hit the service, you need to change the settings to point to a test service.&#8221;  Well, let&#8217;s do that, then&#8230;.</p>
<p>Fast forward ANOTHER week.  The application can finally run on my local machine, but there have been a half-dozen configuration changes to the local server, MANY changes to the local code, which, I am instructed to never check in, and any attempt to run the application in &#8216;debug&#8217; mode causes my laptop to freeze and crash&#8230;</p>
<p>Oh, and I saved the best part for last.  At some point during my &#8216;training&#8217;, I actually did look at the code.  I found the start of execution.  It was a Servlet.  It had over 2000 LOC in the doPost method.  It used reflection to dynamically instantiate dozens of other servlets who&#8217;s names and methods were contained in a Database.  It was the slowest running application on the planet.</p>
<p>I lasted 1 year exactly.  In that time dozens of developers were hired. Most left before me.</p>
<p>They really should have paid me more&#8230;.</p>
<p>Next, a glimpse into how this was coded.</p>
]]></content:encoded>
			<wfw:commentRss>http://shouldhavepaidmemore.com/2009/insurolinki/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
