<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6179958794694518483</id><updated>2011-12-19T20:14:09.935-06:00</updated><category term='design'/><category term='.net'/><category term='hibernate'/><category term='travel'/><category term='business'/><category term='code'/><category term='capistrano'/><category term='software-cliffs-notes'/><category term='books'/><category term='rails'/><category term='nhibernate'/><title type='text'>Other Than Think</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Dan</name><uri>http://www.blogger.com/profile/03843459686471424463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-gwb56XFQQpU/TdmghI0uFJI/AAAAAAAAAAM/H1pTXd6Yhbk/s220/dan.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>41</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-1437431886360606002</id><published>2011-10-10T13:42:00.003-05:00</published><updated>2011-10-10T13:47:18.884-05:00</updated><title type='text'>Living in Crazy Town</title><content type='html'>&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: arial; font-size: small; "&gt;DATE: 10/10/2011&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: arial; font-size: small; "&gt;FROM: Dan&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: arial; font-size: small; "&gt;TO: Development Team Leads&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: arial; font-size: small; "&gt;SUBJECT: Idea for new tables going forward&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: arial; font-size: small; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: arial; font-size: small; "&gt;Hi guys,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: arial; font-size: small; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: arial; font-size: small; "&gt;I got the production DDL for the software we inherited to support from our vendor today, and am thoroughly impressed by the first two tables created in the script:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div&gt;CREATE TABLE [dbo].[YEARS](&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;[YEAR] [numeric](4, 0) NULL&lt;/div&gt;&lt;div&gt;) ON [PRIMARY]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;CREATE TABLE [dbo].[YEAR](&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre; "&gt; &lt;/span&gt;[YEAR] [numeric](4, 0) NULL&lt;/div&gt;&lt;div&gt;) ON [PRIMARY]&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I couldn't find any tables with year type columns in them that had a foreign key constraint to the year (or years) tables.  That may be due to the year column being nullable in both of the above tables.  But I think this is something we can learn from.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For all of our new databases going forward, I think we should have a primary key table for every kind of numeric value we'll be using in our domain.  That will allow us to not only maintain constraint integrity, but also reduce the amount of data we'll need to collect.  e.g. Instead of a birthdate column that is allowed to stand on its own without any constraints, I think we should create a birthdate table.  Then we'll populate it with all of the birthdates possible.  Given we'll have a lot of dates possible, I think we should be efficient with the data and only populate rows where a known birthday has occurred.  We could take the lazy route and populate every row with a birthdate, but if you're going to do a job, then you should it right.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Of course this also brings up some political and religious ramifications that our project management staff will need to be aware of.  If we base the beginning of human history based on current scientific theories, that would bring us back about 2 million years worth of birthdays.  Some would argue that 5,000 years worth of birthdates are sufficient.  Given that our field of computer science is relatively new, and hardly considered a true science by any stretch of the imagination, I think that 5,000 years is sufficient.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To increase efficiency even further, we could create an algorithm as part of the birthdate population application to heuristically estimate days when there weren't births on the earth. (Sorry, making assumptions that all births were on Earth so far...but hey, let's be Agile about this and iterate non-Earth births in future releases.)  That does mean this algorithm definitely needs to be part of the 1.0 release.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Whew - good stuff.  I've got a feeling about this project already!&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-1437431886360606002?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/1437431886360606002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=1437431886360606002' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1437431886360606002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1437431886360606002'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2011/10/living-in-crazy-town.html' title='Living in Crazy Town'/><author><name>Dan</name><uri>http://www.blogger.com/profile/03843459686471424463</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://2.bp.blogspot.com/-gwb56XFQQpU/TdmghI0uFJI/AAAAAAAAAAM/H1pTXd6Yhbk/s220/dan.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-2399240379405491142</id><published>2011-05-11T16:12:00.000-05:00</published><updated>2011-05-11T16:12:23.410-05:00</updated><title type='text'>who needs /etc/passwd?</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-aLHcoi7v1Mo/Tcr7eXBDR9I/AAAAAAAACVg/WjQTrqef_6Y/s1600/doh.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="293" src="http://3.bp.blogspot.com/-aLHcoi7v1Mo/Tcr7eXBDR9I/AAAAAAAACVg/WjQTrqef_6Y/s320/doh.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;&lt;span class="Apple-style-span" style="font-family: arial;"&gt;A funny thing happened to me today...&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;div style="font-family: arial;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: arial;"&gt;I had expanded a zipped file into our development server's /tmp directory, and accidentally littered that directory instead of expanding the files into their own subdirectory.&lt;/div&gt;&lt;div style="font-family: arial;"&gt;I wanted to clean those files up, so I started typing:&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo rm -rf &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: arial;"&gt;....but then I thought, maybe I should be safe about it and only remove my files.&lt;/div&gt;&lt;div style="font-family: arial;"&gt;I forgot the syntax for removing files owned by a specific user, so I googled it, came back, and pasted in the command to find a given user's UID:&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;cat /etc/passwd |grep dtanner&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: arial;"&gt;then I hit enter.&lt;/div&gt;&lt;div style="font-family: arial;"&gt;That command somehow strangely didn't work, but whatever. &amp;nbsp;I cleverly realized I didn't need to read /etc/passwd for my own UID, so I typed "id", got my uid, then did the find and piped my files into the rm command. &amp;nbsp;Problem solved.&lt;/div&gt;&lt;div style="font-family: arial;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: arial;"&gt;But...about five minutes later, one of our developers asked me why he couldn't sudo any more. &amp;nbsp;I thought that was a little odd, since he should've been able to.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: arial;"&gt;I tried it myself, and got the message "&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;user root does not exist&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: arial;"&gt;".&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: arial;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: arial;"&gt;*gulp*&lt;/div&gt;&lt;div style="font-family: arial;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: arial;"&gt;I figured I had to have been the one to cause this problem, so I did a quick check of my command history. &amp;nbsp;About 10 commands back, I found this brilliant gem:&lt;/div&gt;&lt;div style="font-family: arial;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;832 &amp;nbsp;sudo rm -rf cat /etc/passwd |grep dtanner&lt;/span&gt;&lt;/div&gt;&lt;div style="font-family: arial;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: arial;"&gt;*cough*. ohhhh fuuuuuuuuuuuu^*.&lt;/div&gt;&lt;div style="font-family: arial;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: arial;"&gt;It actually turned out to not be that severe of a problem. &amp;nbsp;I had a backup of the /etc/passwd because of the /etc/passwd- automatic backup file, and after booting to single-user mode and fixing file ownership of some files that lost their owners during my multi-tasking mayhem, the server was back up. &amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-2399240379405491142?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/2399240379405491142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=2399240379405491142' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2399240379405491142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2399240379405491142'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2011/05/who-needs-etcpasswd.html' title='who needs /etc/passwd?'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-aLHcoi7v1Mo/Tcr7eXBDR9I/AAAAAAAACVg/WjQTrqef_6Y/s72-c/doh.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-2938096083233019122</id><published>2010-12-29T21:58:00.000-06:00</published><updated>2010-12-29T21:58:08.369-06:00</updated><title type='text'>Choosing a Vendor</title><content type='html'>This is another short article on the &lt;a href="http://otherthanthink.blogspot.com/2010/07/cliffs-notes-of-software-development.html"&gt;Cliffs Notes of Software Development&lt;/a&gt; series. &amp;nbsp;In this post, I'll offer some tips on how to make a good choice for your custom software vendor. &amp;nbsp;This article doesn't discuss the decision of whether you should build or buy; it assumes you're already down the path of building something - whether it's a completely custom solution, or customizing packaged software.&lt;br /&gt;&lt;br /&gt;In no particular order, here are some things you can do that will keep you headed down the right path:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Get assistance from an experienced and trusted guide.&lt;/b&gt;&lt;br /&gt;If you don't speak the language and know the turf yourself, find someone that does. &amp;nbsp;For any project that matters, it's far cheaper to get good, unbiased advice up front. &amp;nbsp;Maybe one day you'll be able to rely on your vendor as that trusted advisor, but until they've proven themselves, use caution. &amp;nbsp;It doesn't have to be a long-term engagement; it can be a quick "am I headed down the right path?" few hour session at critical milestones.&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Ensure they can communicate technical concepts clearly.&lt;/b&gt;&lt;br /&gt;Don't trust a geek that can't clearly translate techno-babble. &amp;nbsp;Our tribe is notoriously bad at glomming onto the latest technical trends regardless of their merit to the business. &amp;nbsp;It's an extremely rare breed of technical advisor that has the experience and wisdom to know when something is a genuine improvement, and not just another revision of a failed idea that a vendor is relying on for their revenue (e.g. Portals, EJBs, ESBs)&lt;/li&gt;&lt;li&gt;&lt;b&gt;Identify and interview the implementation team.&lt;/b&gt;&lt;br /&gt;The software industry is still immature by trade standards, and the construction of most new projects requires a lot of experience and mindful improvisation. &amp;nbsp;i.e. The people building the software (not just designing it) can not be commoditized yet (if ever). &amp;nbsp;Most software vendors (especially the bigger ones) will have a mixed bag of staff. &amp;nbsp;You or your trusted guide should hand-pick the people on your project to make sure they're both technically qualified and a good cultural fit. &amp;nbsp;Be suspicious of any vendor that objects to this.&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Favor those that have done something like this before.&lt;/b&gt;&lt;br /&gt;Sometimes what you're trying to do is truly novel or revolutionary, in which case you should hire a company that specializes on making revolutionary software. &amp;nbsp;For the other 99% of the projects out there, it's already been done before, and those people that have already done it have learned from their mistakes. &amp;nbsp;It usually takes a few tries to build any software right, and if this is the first time your vendor is building something for you, be prepared for it to be wrong the first couple of times. &amp;nbsp;It's just a current fact of life - customers aren't able to specify exactly what it is they want the first time, and builders aren't able to build things exactly right the first time.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Good luck!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-2938096083233019122?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/2938096083233019122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=2938096083233019122' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2938096083233019122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2938096083233019122'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2010/12/choosing-vendor.html' title='Choosing a Vendor'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-2682083677760305533</id><published>2010-10-16T14:17:00.000-05:00</published><updated>2010-10-16T14:17:29.634-05:00</updated><title type='text'>Playhouse</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;A few months ago, I promised Maria that I would get her and Daniela a playhouse for their birthdays. &amp;nbsp;I was originally going to buy them a little Step2 playhouse, which would've been totally fine. &amp;nbsp;But my good friend Rob, a skilled woodworker, convinced me that building a playhouse was the way to go. &amp;nbsp;I was a little tentative about the idea, since I hadn't built a real structure before on my own, but he very generously offered to help (and with two kids of his own, meant that his wife Karen also very generously to help...we still can't thank them enough!)&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;So I found this &lt;a href="http://www.rockler.com/product.cfm?page=11275"&gt;plan&lt;/a&gt;, made a few modifications, and off we went:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Starting with a pile of boards...&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://4.bp.blogspot.com/_lWbr1k8gyZ8/TLnuMKWCy7I/AAAAAAAACPM/gcUjsXaB5A4/s1600/100828_IMG_3919.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/_lWbr1k8gyZ8/TLnuMKWCy7I/AAAAAAAACPM/gcUjsXaB5A4/s320/100828_IMG_3919.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;and a friend who know's what he's doing...&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://1.bp.blogspot.com/_lWbr1k8gyZ8/TLnuQRhiLgI/AAAAAAAACPQ/w7d0QJ32Vh4/s1600/100829_IMG_3929.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://1.bp.blogspot.com/_lWbr1k8gyZ8/TLnuQRhiLgI/AAAAAAAACPQ/w7d0QJ32Vh4/s320/100829_IMG_3929.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;things started to take shape, and a lot of space!&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnuate1LOI/AAAAAAAACPU/3_I62PcxU-Y/s1600/100829_IMG_3931.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnuate1LOI/AAAAAAAACPU/3_I62PcxU-Y/s320/100829_IMG_3931.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;We passed the initial kid inspection...&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnua7XPlxI/AAAAAAAACPY/C4VOJXVLnQc/s1600/100829_IMG_3933.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnua7XPlxI/AAAAAAAACPY/C4VOJXVLnQc/s320/100829_IMG_3933.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;and had lots of "help".&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://3.bp.blogspot.com/_lWbr1k8gyZ8/TLnugzMKjMI/AAAAAAAACPg/-qn13rhy610/s1600/100829_IMG_3937.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://3.bp.blogspot.com/_lWbr1k8gyZ8/TLnugzMKjMI/AAAAAAAACPg/-qn13rhy610/s320/100829_IMG_3937.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;The first wall goes up...&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://4.bp.blogspot.com/_lWbr1k8gyZ8/TLnuhuJ0MTI/AAAAAAAACPk/KqNpZii8vvM/s1600/100904_IMG_1129.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://4.bp.blogspot.com/_lWbr1k8gyZ8/TLnuhuJ0MTI/AAAAAAAACPk/KqNpZii8vvM/s320/100904_IMG_1129.JPG" width="239" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;And the playhouse is now fully operational.&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://1.bp.blogspot.com/_lWbr1k8gyZ8/TLnuiZcLaII/AAAAAAAACPo/an7qhFZebE8/s1600/100918_IMG_1257.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="239" src="http://1.bp.blogspot.com/_lWbr1k8gyZ8/TLnuiZcLaII/AAAAAAAACPo/an7qhFZebE8/s320/100918_IMG_1257.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;But we realized that it absolutely has to be red.&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://3.bp.blogspot.com/_lWbr1k8gyZ8/TLnujllodnI/AAAAAAAACPs/XV-avC0EMMg/s1600/100918_IMG_3944.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://3.bp.blogspot.com/_lWbr1k8gyZ8/TLnujllodnI/AAAAAAAACPs/XV-avC0EMMg/s320/100918_IMG_3944.JPG" width="240" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Much better color!&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnup85HypI/AAAAAAAACPw/5VbCg1AXxd8/s1600/100919_IMG_1305.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="239" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnup85HypI/AAAAAAAACPw/5VbCg1AXxd8/s320/100919_IMG_1305.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;I finished up the railing in the dark with a million mosquito friends.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://1.bp.blogspot.com/_lWbr1k8gyZ8/TLnuqpOpMiI/AAAAAAAACP0/j-t-c8YmM3M/s1600/100920_IMG_1307.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="239" src="http://1.bp.blogspot.com/_lWbr1k8gyZ8/TLnuqpOpMiI/AAAAAAAACP0/j-t-c8YmM3M/s320/100920_IMG_1307.JPG" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;One of the owner-operators.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnuq7m7G7I/AAAAAAAACP4/2oRZGl6CX6E/s1600/100929_DSC_4771.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnuq7m7G7I/AAAAAAAACP4/2oRZGl6CX6E/s320/100929_DSC_4771.jpg" width="212" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Of course it has to have a doorbell.&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://3.bp.blogspot.com/_lWbr1k8gyZ8/TLnurV0jsMI/AAAAAAAACP8/BrN0yl5Al2k/s1600/101003_IMG_1369.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://3.bp.blogspot.com/_lWbr1k8gyZ8/TLnurV0jsMI/AAAAAAAACP8/BrN0yl5Al2k/s320/101003_IMG_1369.jpg" width="239" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;and a &lt;a href="http://www.amazon.com/gp/product/B0013HPNRY"&gt;solar-powered light&lt;/a&gt; for late night parties.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnuxbKYTFI/AAAAAAAACQI/7OYOB5EqKv4/s1600/101016_DSC_4783.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnuxbKYTFI/AAAAAAAACQI/7OYOB5EqKv4/s320/101016_DSC_4783.jpg" width="212" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;And with the trim, it's pretty much done!&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnur2Wo9VI/AAAAAAAACQA/1XtBHgAwPyc/s1600/101016_DSC_4780.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="212" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/TLnur2Wo9VI/AAAAAAAACQA/1XtBHgAwPyc/s320/101016_DSC_4780.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://3.bp.blogspot.com/_lWbr1k8gyZ8/TLnutWBli3I/AAAAAAAACQE/aswF6coWgvA/s1600/101016_DSC_4782.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="212" src="http://3.bp.blogspot.com/_lWbr1k8gyZ8/TLnutWBli3I/AAAAAAAACQE/aswF6coWgvA/s320/101016_DSC_4782.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-2682083677760305533?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/2682083677760305533/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=2682083677760305533' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2682083677760305533'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2682083677760305533'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2010/10/playhouse.html' title='Playhouse'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_lWbr1k8gyZ8/TLnuMKWCy7I/AAAAAAAACPM/gcUjsXaB5A4/s72-c/100828_IMG_3919.JPG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-4097661429512054106</id><published>2010-10-10T23:46:00.110-05:00</published><updated>2010-10-11T00:32:37.785-05:00</updated><title type='text'>Generic Dev Team Recommendation</title><content type='html'>A few months back, a friend and I were hired to lead a development team that was to be built from the ground up, to serve as the development arm for an established company that was rebuilding its development group.  When we were originally hired, plan A of senior management was to staff the development leadership locally, and offshore the bulk of the implementation team.  However, our own experiences in the past gave us the opinion that for this particular situation, the company would be best served by having a single co-located development team.  &lt;br /&gt;&lt;br /&gt;To be clear, everyone's situations are different, and what I present may not apply to your situation.  I have a lot of extremely talented friends and colleagues in this business that live  many time zones away, and I've worked on a number of successful projects with them...despite us being widely distributed.&lt;br /&gt;&lt;br /&gt;But specifically, why is it so hard?  (We are programmers, and communication is often not our strongest skill.)  And how does being distributed impact the business?  The goal of this opinion paper was to answer those questions, viewing the situation from both a high level (annual operational costs) and low level (a single feature).&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;h1&gt;ABC Development Team Organization Recommendation&lt;/h1&gt;&lt;p&gt;We&amp;#39;re currently facing an important decision in determining the ABC development team structure and organization. The goal is to provide ABC with a long-term development capability that is &lt;b&gt;productive&lt;/b&gt;, &lt;b&gt;high quality&lt;/b&gt;, and &lt;b&gt;cost-efficient&lt;/b&gt;. We are currently considering from the following choices:&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li style="text-align:left"&gt;Create an offshore development center, either independently or in partnership with existing relationships. &lt;/li&gt;&lt;li&gt;Consolidate the development team in one location at the Minneapolis MN location.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;Based on the situation and our experience, we recommend a single location for the development team. At a high level, this is because the cost of communication issues associated with distributed teams usually outweigh their advantages.&lt;/p&gt;&lt;h3&gt;The Communication Issues Explained&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;It&amp;#39;s difficult to have quality design discussions with distributed teams.&lt;/b&gt; For example, ad-hoc whiteboarding is an essential process when communicating complex design concepts. In distributed teams, this is not feasible. Some workaround technologies exist, such as Microsoft LiveMeeting, but they are inadequate replacements because of their technical limitations. &lt;/li&gt;&lt;li&gt;&lt;b&gt;Limited non-verbal communication.&lt;/b&gt; Remote teams are restricted to the lowest quality forms of communication - written and voice. This leaves out much more effective styles of communication, such as gestures, body language, eye contact, touch, facial expressions, and posture. &lt;/li&gt;&lt;li&gt;&lt;b&gt;Limited window of communication.&lt;/b&gt; Speaking of India specifically in this case, the work day overlap is a couple hours. By regular work day standards (8-5), there is no overlap at all, but teams in this situation accomodate by adjusting their work schedules to work either early or late to get a small window where they can talk. &lt;/li&gt;&lt;li&gt;&lt;b&gt;Slow communication turnaround.&lt;/b&gt; Because of the limited window of communication, it takes additional time for issues and tasks to go through their feedback and approval cycle. A typical example is the following scenario: The project manager gives the developer a 2 hour task on a Monday morning, which is the end of that developer&amp;#39;s day. On Tuesday morning, the developer has her detailed design questions answered for the task. Wednesday morning, the technical lead is able to review the initial draft of the development and finds some feedback items. By Thursday, the team can mark the issue as resolved and move on to the next task. Contrast this common four-day flow with a co-located team, where the task is resolved in one day.&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;The Benefits of Co-location&lt;/h2&gt;&lt;h3&gt;Co-located teams make software faster and more efficiently&lt;/h3&gt;&lt;p&gt;Due to the differences in communication quality and efficiency, software with a moderate degree of complexity can be built faster and more efficiently when the team is co-located. It can be built faster due to the quicker feedback loop, as is discussed in the earlier slow communication turnaround scenario. In an ideal situation, developers working around the globe can create software more quickly. This scenario is rarely a reality though, because building anything but the simplest software requires signficant back and forth collaboration. The same communication turnaround scenario also explains how it can be built more efficiently when the teams are co-located. The following diagram illustrates how this happens in real life using a sample four-hour development task.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div id="w_x3" style="text-align:center"&gt;&lt;img src="http://docs.google.com/a/dantanner.com/File?id=dgpkjh2t_12gmm7zpdr_b" style="width:100%"&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;In the above example, the distributed team gets started on Tuesday morning at 8AM, and finishes Friday at 10:30AM - an elapsed time of &lt;b&gt;four &lt;/b&gt;calendar days.&amp;nbsp; The co-located team also gets started Tuesday at 8, but finishes on Wednesday at 4:30PM - an elapsed time of &lt;b&gt;two&lt;/b&gt; calendar days. &amp;nbsp; The amount of work is the same in both scenarios, with one small exception.&amp;nbsp; The co-located developer discusses questions she has with the business analyst in person rather than over email. &amp;nbsp;As will be discussed later, this illustrates how you can develop software more efficiently with co-located teams, without doing anything differently other than choose how you locate people. &amp;nbsp;In this example, almost all of the elapsed time differences happen because of the timezone challenge.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;As a result, the co-located team finishes this task in nearly half the time as that same time in a distributed situation.&amp;nbsp; In reality, people will have more than one task assigned at a time, so this inefficiency can be mitigated to a degree by multitasking (assigning more than one development task at a time).&amp;nbsp; But multitasking has its own challenges, as context-switching itself drops efficiency levels.&amp;nbsp; There are also times when a person simply has only one thing they can work on at a time, due to project priority or constraints.&lt;br /&gt;&lt;br /&gt;In a best case scenario for distributed development, people are always working on something and never waiting, and each task simply takes longer to complete compared to a co-located team.&amp;nbsp; In a worst case scenario, people spend 100% of their time on this task, and it costs the company four days of time and money to implement the feature as compared to two days. &lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;The Cost Factor&lt;/h2&gt;&lt;p&gt;There isn&amp;#39;t much debate in saying putting people together in a room produces higher quality software compared with separating them. So why do most companies choose a distributed model? Resource availability and cost are the two most common reasons. As resource availability isn&amp;#39;t a factor in this case, we&amp;#39;re left with the potential benefit of cost in leveraging an off-shore model. &lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Can we make software that meets the goals of ABC in a more cost-effective way by leveraging an off-shore distributed model? Calculating this is difficult if close to impossible. For example, we can&amp;#39;t do what-if scenarios for things like &amp;quot;how many customers will we lose if we build mediocre software?&amp;quot;, or &amp;quot;how much is the business impacted if we can&amp;#39;t accommodate change in the time required?&amp;quot;. However, we can compare most operating costs quite easily. We can also roughly compare development and maintenance staffing costs by making some assumptions about how much additional waste is incurred in the process due to the communication issues.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;For example, here are some predicted costs for a distributed team working in timezones with a differential greater than a working day where most development is done in one location and most leadership tasks done in the other.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div id="n-fx" style="text-align:left"&gt;&lt;img src="http://docs.google.com/a/dantanner.com/File?id=dgpkjh2t_16c3d3vrft_b" style="height:567.448px;width:648px"&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Contrasting the same task implemented by a distributed with a co-located team, what would be a 12-minute informal chat in a co-located team must be a one hour prepared call in a distributed team. Extra time is required to set up the means to communicate with remote collaborators. &amp;nbsp;For a verbal meeting, this means preparing an online voice or video session; for written correspondence, this means organizing questions or thoughts into complete and concise statements. &amp;nbsp;Hallway chats and quick brainstorming sessions are simply not feasible. &amp;nbsp;The closest tool we have for impromptu discussions when working remotely is instant messaging. &amp;nbsp;Again though, written communication is a weak method compared with other richer forms of communication, where things like body language, inflection, and eye contact can drastically affect the message.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;hr class="pb"&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;Cost differential at a higher level&lt;/h3&gt;&lt;p&gt;The earlier examples show the development process for a single typical task.&amp;nbsp; Another way to contrast costs between co-located and distributed teams is by their annual operational costs.&amp;nbsp; The following tables illustrate those cost differences:&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;table border="0" cellpadding="3" cellspacing="0" class="zeroBorder"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="height:20pt;vertical-align:bottom;width:283pt"&gt;&lt;/td&gt;&lt;td colspan="2" style="background-color:#c2d1f0;height:20pt;text-align:center;vertical-align:bottom;width:95pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;ABC-Controlled ODC&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td colspan="2" style="background-color:#c2d1f0;height:20pt;text-align:center;vertical-align:bottom;width:93pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Subcontract ODC Resources&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td colspan="2" style="background-color:#c2d1f0;height:20pt;text-align:center;vertical-align:bottom;width:89pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Local Resources&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:283pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Major Categories of Expense Differences&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:95pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Startup Cost&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:97pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Yearly Cost&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:93pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Startup Cost&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:104pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Yearly Cost&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:89pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Startup Cost&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:103pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Yearly Cost&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:283pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Variable Consulting Costs*&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:95pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:97pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;325,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:93pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:104pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;415,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:89pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:103pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;450,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:283pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Additional Building Lease&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:95pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:97pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;10,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:93pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:104pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:89pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:103pt"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:283pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Additional Office Equipment and Services&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:95pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;20,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:97pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;10,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:93pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:104pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:89pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:103pt"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:283pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Telecommunication&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:95pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;5,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:97pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;1,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:93pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:104pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:89pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:103pt"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:283pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Additional Administration&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:95pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:97pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;1,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:93pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:104pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:89pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:103pt"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:283pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Additional Server Hardware and Licenses&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:95pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;60,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:97pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;15,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:93pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;60,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:104pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;15,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:89pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:103pt"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;vertical-align:bottom;width:283pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:95pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;$85,000&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:97pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;$362,000&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:93pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;$60,000&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:104pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;$430,000&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:89pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:103pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;$450,000&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;vertical-align:bottom;width:283pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:95pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:97pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:93pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:104pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:89pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:103pt"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;vertical-align:bottom;width:283pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:95pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:97pt"&gt;&lt;font face="arial,sans,sans-serif" size="3"&gt;&lt;font color="#000000"&gt;&lt;b&gt;$447,000&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:93pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:104pt"&gt;&lt;font face="arial,sans,sans-serif" size="3"&gt;&lt;font color="#000000"&gt;&lt;b&gt;$490,000&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:89pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:103pt"&gt;&lt;font face="arial,sans,sans-serif" size="3"&gt;&lt;font color="#000000"&gt;&lt;b&gt;$450,000&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;i&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;&lt;b&gt;*&lt;/b&gt; The Variable Consulting Costs category only shows the yearly burn rate for development. It does not factor in software quality or the amount of features built in that timeframe, which will be higher in a co-located environment.&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/i&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The consulting cost for distributed offshore resources are lower than US-based resources.&amp;nbsp; In the example of using a ABC-controlled Offshore Development Center, the costs end up being slightly lower due to the additional equipment and maintenance.&amp;nbsp; When partnering for ODC resources, the additional equipment costs actually push the cost higher than operating with a single US-based team.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;hr class="pb"&gt;&lt;p&gt;&lt;/p&gt;The Variable Consulting Costs in this table are derived from the following information.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;table border="0" cellpadding="3" cellspacing="0" class="zeroBorder"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="height:20pt;vertical-align:bottom;width:138pt"&gt;&lt;/td&gt;&lt;td colspan="3" style="background-color:#9bbb59;height:20pt;text-align:center;vertical-align:bottom;width:165pt"&gt;&lt;b&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Annual Cost&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:138pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Resource/Role&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:center;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;ABC-Controlled ODC&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:center;vertical-align:bottom;width:178pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Subcontract ODC Resources&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:center;vertical-align:bottom;width:144pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;Local Resources&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:138pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Project Manager&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;40,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:178pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;60,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:144pt"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:138pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;India Admin&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;25,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:178pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:144pt"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:138pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;US Admin&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;50,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:178pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;vertical-align:bottom;width:144pt"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:138pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Developer&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;30,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:178pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;50,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:144pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;65,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:138pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Developer&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;30,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:178pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;50,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:144pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;65,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:138pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Developer&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;30,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:178pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;50,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:144pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;65,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:138pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Developer&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;30,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:178pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;50,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:144pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;65,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:138pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Developer&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;30,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:178pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;50,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:144pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;65,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:138pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Jr. QA&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;25,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:178pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;45,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:144pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;50,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;text-align:left;vertical-align:bottom;width:138pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;Jr. DBA&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;35,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:178pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;60,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:144pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;font size="2"&gt;75,000&lt;/font&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="height:20pt;vertical-align:bottom;width:138pt"&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:165pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;$325,000&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:178pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;$415,000&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;td style="height:20pt;text-align:right;vertical-align:bottom;width:144pt"&gt;&lt;font face="arial,sans,sans-serif"&gt;&lt;font color="#000000"&gt;&lt;b&gt;&lt;font size="2"&gt;$450,000&lt;/font&gt;&lt;/b&gt;&lt;/font&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;p&gt;The leadership roles are excluded from this table, as they are fixed in the sense that they would be necessary in any case.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h2&gt;&lt;font size="3"&gt;Co-located teams make higher quality software&lt;/font&gt;&lt;/h2&gt;&lt;p style="margin-left:0px;margin-right:0px"&gt;All other things equal, a software team in a single location will produce software that conforms more closely to the intended features, and has fewer defects. To quote Alistair Cockburn&amp;#39;s research on the subject:&lt;/p&gt;&lt;p style="margin-left:14px;margin-right:0px"&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/p&gt;&lt;p style="margin-left:14px;margin-right:0px"&gt;&lt;i&gt;Osmotic communication makes the cost of communications low and the feedback rate high, so that errors are corrected extremely quickly and knowledge is disseminated quickly. People learn the project priorities and who holds what information. They pick up new programming, design, testing, and tool handling tricks. They catch and correct small errors before they grow into larger ones.&lt;/i&gt;&lt;/p&gt;&lt;p style="margin-left:0px;margin-right:0px"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="margin-left:0px;margin-right:0px"&gt;By having a better understanding of the requirements, it can be inferred that the resulting software will also be more fault-tolerant and maintainable. More fault-tolerant because the well-known high risk areas can be engineered more defensively. More maintainable because fewer mistakes go into the design and construction. &amp;nbsp;Cheaper to maintain because business changes cost less to implement. &amp;nbsp;Attempts have been made to quantify the long-term effects of quality on a project, but these metrics are still too subjective and unreliable to be used as an argument in this discussion. &amp;nbsp;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h2&gt;&lt;font size="4"&gt;Summary&lt;/font&gt;&lt;/h2&gt;We&amp;#39;ve depicted how the reduced cost of a less expensive developer can be offset by inefficient communication. &amp;nbsp;We have also shown that it is likely to take considerably longer to complete a project when using a distributed team. &amp;nbsp;However these examples do not consider software quality, which has lasting effects on cost - from maintenance to scalability, and often with greater consequences than initial cost.&lt;br /&gt;&lt;br /&gt;Given our conclusion that the project will cost roughly the same with a co-located team, and have a higher productivity rate with increased quality, it is our recommendation to use a co-located team for this project.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-4097661429512054106?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/4097661429512054106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=4097661429512054106' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4097661429512054106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4097661429512054106'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2010/10/generic-dev-team-recommendation.html' title='Generic Dev Team Recommendation'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-4631398144881041646</id><published>2010-08-20T12:44:00.000-05:00</published><updated>2010-08-20T12:44:03.350-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software-cliffs-notes'/><title type='text'>Methodologies at a High Level</title><content type='html'>[Part of the &lt;a href="http://otherthanthink.blogspot.com/2010/07/cliffs-notes-of-software-development.html"&gt;Cliffs Notes of Software Development Series&lt;/a&gt;]&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Merriam-Webster's definition:  a body of methods, rules, and postulates employed by a discipline : a particular procedure or set of procedures&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;So it's how we do things in this industry.  Set aside the fact that our industry hasn't figured out a standardized set of methods and rules yet.  While other disciplines have had thousands of years to mature, ours isn't even a generation old yet.  Not for lack of trying though - we're cranking out new names of methodologies every few years.  Sometimes it's just slapping a different label on an old trick, and sometimes it's a genuinely new idea.  &lt;br /&gt;&lt;br /&gt;These are the most popular methodologies used over the last couple decades:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;90s&lt;/b&gt;: CMM (Capability Maturity Model), RUP (Rational Unified Process).  These were document-oriented techniques that valued heavyweight specifications and processes over human interaction.  Each cog in the wheel wrote down what they wanted in an isolated fashion and handed it off to the next party with the expectation that what came back was what they wanted. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;late 90s and early 00s&lt;/b&gt;: The inception of the Agile movement and its name brands Scrum, eXtreme Programming threw out a lot of the heavyweight process, with an emphasis on the human factor.  Their prescriptions are a much shorter list of project guidelines, with some or all of them marked as optional.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;mid 00s to today&lt;/b&gt;: The above flavors of Agile are the current mainstream choice, along with the somewhat recent additions of Lean and Kanban.  Lean and Kanban are direct translations of the auto-manufacturing process, where the goal is to not be wasteful and do what's needed just in time.  &lt;br /&gt;&lt;br /&gt;What I've said so far is mostly factual.  Now for some contextual and subjective quick answers...&lt;br /&gt;&lt;br /&gt;So these are the "formal" techniques for making software.  You might then wonder how much a particular methodology choice can influence the success (or failure) of a project.  &lt;b&gt;In my opinion, not much.&lt;/b&gt;  &lt;br /&gt;&lt;br /&gt;&lt;i&gt;What?  How could it not matter much?!!&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Before denouncing heresy or ignorance, remember that the software industry is still in an infantile state.  We're constantly reinventing the wheel as we arrogantly proclaim the code we just re-wrote to provide the same business function for the last 40 years is once again completely obsolete and needs to be re-written from scratch.    We're evolving, yes, and these methodology changes are improving our chances (usually).  But the single most notable trait of the recent methodologies is to emphasize the human aspect of the software development process.  To err is human.  In other words, we know we're a bunch of screw-ups, and the best idea we have so far is to fail as early as possible.  Not to scoff at that idea - it is an improvement...the trouble is that we're still failing when we get to the finish line far too often.  Don't blame the methodology though, blame the people that didn't do the project right.  To put it in kitschy terms: Methodologies don't screw up projects, people screw up projects.  More on that in the "It's All About The People" article.&lt;br /&gt;&lt;br /&gt;This opinion of methodology isn't anything new, although it's not the norm, especially among those that aren't master software builders, or have something to sell you.  I'm sure many professional methodologists would have a problem with what I just said as well.  But the funny thing is that the best ones wouldn't.&lt;br /&gt;&lt;br /&gt;As an example, what's going to be the next evolution of methodology?  &lt;a href="http://en.wikipedia.org/wiki/Jeet_Kune_Do"&gt;Jeet Kune Do&lt;/a&gt;!  "My style is no style." &lt;br /&gt;&lt;br /&gt;Just kidding!  Actually, I'm not.  Alistair Cockburn (one of the world's best software guides) is &lt;a href="http://alistair.cockburn.us/Vid+of+Alistair+describing+Shu+Ha+Ri"&gt;starting to teach Shuhari&lt;/a&gt;.  In layman's terms, when you're a master, you don't need the instruction manual.  His &lt;a href="http://alistair.cockburn.us/Oath+of+Non-Allegiance"&gt;Oath of Non-Allegiance&lt;/a&gt; request is another example that our trade doesn't yet have the maturity to define a standard on how to create software.&lt;br /&gt;&lt;br /&gt;In summary, my advice on methodologies is that you shouldn't worry about any particular name brand.  It doesn't really matter.  There are definitely some very helpful and specific activities you can do during the process, and for that consult your local (or bring in) experts for guidance.  I'll discuss how to find the right people in more detail in another article on this series.  Just remember, it's all about having the best &lt;strike&gt;resources&lt;/strike&gt; &lt;strike&gt;staff&lt;/strike&gt; people.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-4631398144881041646?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/4631398144881041646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=4631398144881041646' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4631398144881041646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4631398144881041646'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2010/08/methodologies-at-high-level.html' title='Methodologies at a High Level'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-4438857940413898528</id><published>2010-07-17T23:05:00.002-05:00</published><updated>2010-08-20T12:44:39.377-05:00</updated><title type='text'>Cliffs Notes of Software Development</title><content type='html'>Most of my articles on software development are targeted towards experienced software developers.  That world is a weird one though, filled with thousands of unfamiliar terms and concepts that are difficult to relate.  The best developers are also excellent communicators, but that's unfortunately a rarity in our breed. &lt;br /&gt;&lt;br /&gt;As a maker of custom software, I've seen it happen many times in the past where the buyer is frustrated with this communication divide of understanding, yet needs us to solve their problem and is forced to navigate the process on their own without a trusted guide.  &lt;br /&gt;&lt;br /&gt;In the small and medium business world, the most common situation is when a business first outgrows their spreadsheets and access forms, and needs a custom solution to better integrate their information.  In these situations, most business owners are quite comfortable admitting they know nothing about custom software; they just want someone to solve their problem.  Even in the "enterprise" world it's common for a manager to be responsible for a software solution, yet not have any experience in this dirty process of building software.  If they're lucky, they'll have a friend in information technology to whom they can ask their "stupid" questions.  Often times though there's no one; just them, a budget way bigger than their bonus, and some resources that were assigned to them from who-knows-where.  If they're lucky, not only are they all in the same building, but they're sitting within 30 feet of you.  Lucky?  Why?  Just how important is that?  Turns out it's really important.  But that's just one of topics that can make or break your project's success.  Hmmm...well, why doesn't that ever happen?  Turns out that a lot of the people making decisions like this are themselves just trying to keep afloat in the sea of change.&lt;br /&gt;&lt;br /&gt;So...this series of articles is my attempt to boil down some of these key questions and topics a person might have about this fast-moving and immature industry.  Consider it the cliffs notes of  software development.  Below is the list; each item will be a hyperlink to the details as it is written:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://otherthanthink.blogspot.com/2010/08/methodologies-at-high-level.html"&gt;Methodologies at a High Level&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Choosing a Vendor&lt;/li&gt;&lt;li&gt;Build vs. Buy&lt;/li&gt;&lt;li&gt;Choosing a Platform&lt;/li&gt;&lt;li&gt;Programming Religions&lt;/li&gt;&lt;li&gt;Costs&lt;/li&gt;&lt;li&gt;Biggest Weaknesses of the Industry&lt;/li&gt;&lt;li&gt;Process Requirements&lt;/li&gt;&lt;li&gt;Suggested Reading&lt;/li&gt;&lt;li&gt;It's All About the People&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-4438857940413898528?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/4438857940413898528/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=4438857940413898528' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4438857940413898528'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4438857940413898528'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2010/07/cliffs-notes-of-software-development.html' title='Cliffs Notes of Software Development'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-1184875084740122593</id><published>2010-03-11T22:03:00.000-06:00</published><updated>2010-03-11T22:03:38.121-06:00</updated><title type='text'>Top Software Estimating Mistakes</title><content type='html'>Aside from a complete lack of planning, this list is about &lt;b&gt;categories&lt;/b&gt; of software development that people are aware of during planning, but &lt;b&gt;horribly underestimate&lt;/b&gt;.  Even smart, experienced people that are usually pretty accurate with their estimates can miss the following things by a mile.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;In order from bad to worse in terms of project risk:&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;span style="font-size: large;"&gt;#4: The Amount of Testing Required For a Shippable Product&lt;br /&gt;&lt;/span&gt;&lt;/u&gt;&lt;br /&gt;This is actually one of the better known mistakes, especially if you've read &lt;a href="http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959"&gt;The Mythical Man Month&lt;/a&gt;.  Unfortunately, not enough people in our industry have. And even those that are well aware of the problem are often hard-pressed to effectively address it because it happens at the end of a project, when the buffer (if you even had one) has already been spent on earlier phases.&amp;nbsp; It is one challenge to build a &lt;b&gt;piece&lt;/b&gt; of a system, and it is an order of magnitude more difficult to build an &lt;b&gt;entire cohesive system&lt;/b&gt;.&amp;nbsp; Yes, test-driven development and better unit testing attitudes, tools and techniques have made a drastic improvement&lt;b&gt; in the right hands&lt;/b&gt;, but that last mile always takes much longer than you thought it would when you're trying to put all the pieces together.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;span style="font-size: large;"&gt;#3: Building Uncommon Features&lt;/span&gt;&lt;/u&gt;&lt;br /&gt;By uncommon features, I mean those features that are treading new ground in some aspect of the tools used to provide those features.  For example, nowadays AJAX support is pretty well included in most browsers and development frameworks.  But when the functionality was first made available, it was a total bear to develop anything with it.  A current example of this is the new features available in HTML 5.  Bleeding edge? Yes - blood spent by developers cutting themselves as they fumble through the learning curve and mature the specification.&lt;br /&gt;&lt;br /&gt;Knowing the problem is half the battle for these mistakes, and tackling each aspect in a simple and direct way is the best method. If you think the benefit for a particularly ground-breaking feature is worth it, go for it - just remember that it's not going to be predictable, and you will run into some very difficult technical problems that may have already been solved in more traditional ways.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;span style="font-size: large;"&gt;#2: Reporting&lt;/span&gt;&lt;/u&gt;&lt;br /&gt;The required energy for data reporting is often neglected, with heavy consequences.  Why?&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The domain of the data being reporting on is often a foreign concept to the people building the software, so we don't know a lot, and miss a lot of important details.&lt;/li&gt;&lt;li&gt;Reporting typically requires the rest of the system to be built first, and since it comes last, it's often the last thing on people's minds.&lt;/li&gt;&lt;li&gt;Flaws in the reporting design can often cause a major ripple effect on the parts of the system that were built to provide that reporting data.  This means massive refactoring, and gets even worse if you don't have good automated tests.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;u&gt;&lt;span style="font-size: large;"&gt;#1 - Data migration&lt;/span&gt;&lt;/u&gt;&lt;br /&gt;Lucky is the project that doesn't involve data migration, because it hurts.  It's no fun, it's messy, the business doesn't nurture it, and it almost always goes way over the estimate.  Experienced managers will know when a data migration effort will require its own sub-project, with a separate team and early schedule start.  Inexperienced leaders will scan a table structure and some sample data, and slap a 20 hour estimate on what turns out to be a 200 hour debacle.  Martin Fowler discusses this in his bliki &lt;a href="http://martinfowler.com/bliki/IncrementalMigration.html"&gt;here&lt;/a&gt;.  As is often the case, he sums up the problem and advice better than just about anyone else can.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So the next time you've got an estimate sitting in front of you, be sure to think about these categories of tasks and think hard about what it'll really take.  Then double it.  And add 30%.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-1184875084740122593?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/1184875084740122593/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=1184875084740122593' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1184875084740122593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1184875084740122593'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2010/03/top-software-estimating-mistakes.html' title='Top Software Estimating Mistakes'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-1388130885236451017</id><published>2010-03-06T20:50:00.005-06:00</published><updated>2010-03-06T21:04:44.297-06:00</updated><title type='text'>What kind of software mill do you work at?</title><content type='html'>&lt;b&gt;Signs indicating your shop resembles this scene:&lt;/b&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_lWbr1k8gyZ8/S4tNi9cX42I/AAAAAAAACGM/SxH5fbwC0lg/s1600-h/animal-mill.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_lWbr1k8gyZ8/S4tNi9cX42I/AAAAAAAACGM/SxH5fbwC0lg/s320/animal-mill.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;People talk about methodology more than features.&lt;/li&gt;&lt;li&gt;You're currently building software using products from IBM, Siebel, or Oracle.&lt;/li&gt;&lt;li&gt;The development manager and infrastructure manager are two different people, and their manager is located more than 30 feet away.&lt;/li&gt;&lt;li&gt;More than 20% of the developers can't solve the &lt;a href="http://c2.com/cgi/wiki?FizzBuzzTest"&gt;FizzBuzz&lt;/a&gt; test within 10 minutes.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Signs indicating your shop resembles this scene:&lt;/b&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/S4tQcGaUPWI/AAAAAAAACGU/tJ2QWlty8EQ/s1600-h/windmill.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/S4tQcGaUPWI/AAAAAAAACGU/tJ2QWlty8EQ/s320/windmill.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You have at least one app in production successfully running on a dynamic language.&lt;/li&gt;&lt;li&gt;Developers are the ones pushing specific technology to management; never the other way around.&lt;/li&gt;&lt;li&gt;Almost all of the developers sit in the same room or in adjacent offices.&lt;/li&gt;&lt;li&gt;Real consequences exist when people don't meet their commitments.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-1388130885236451017?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/1388130885236451017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=1388130885236451017' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1388130885236451017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1388130885236451017'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2010/03/what-kind-of-software-mill-do-you-work.html' title='What kind of software mill do you work at?'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_lWbr1k8gyZ8/S4tNi9cX42I/AAAAAAAACGM/SxH5fbwC0lg/s72-c/animal-mill.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-4333461214093573287</id><published>2010-01-21T22:17:00.000-06:00</published><updated>2010-01-21T22:17:05.421-06:00</updated><title type='text'>The Fresh Face Behavior Pattern</title><content type='html'>AKA the  "That's what we've been saying the whole time!" pattern.&lt;br /&gt;&lt;br /&gt;This is another pattern that is commonly experienced in consulting engagements.&amp;nbsp; It's the situation where the existing staff knows what the source of a problem is, but haven't been able to communicate it effectively, or haven't been able to get management to action on their recommendation. I've been on both sides of the equation.&amp;nbsp; It's fun to experience when you're the shiny new toy (the consultant), and is equally un-fun when you're the old hag being ignored (the current staff).&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Not to be confused with open, honest communication in a trusting environment where all parties simply want some validation or a second set of eyes to examine a tough problem.&amp;nbsp; This behavioral pattern is usually accompanied by a dysfunctional vibe where the existing management staff doesn't trust the people tasked to do the work.&amp;nbsp; The reason might be because the staff is under-qualified, or the management isn't delegating properly.&amp;nbsp; If the reason for the problem is under-qualified staff, the best outcome is that the consultant can train or mentor the staff into becoming qualified for the problem domain.&amp;nbsp; If the reason for the problem is due to lack of management trust regardless of qualifications, then the problem will repeat itself unless the management can establish a better relationship with the staff.&amp;nbsp; We're talking some serious therapy!&amp;nbsp; But as a consultant, I'm in no hurry to recommend this any time soon. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-4333461214093573287?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/4333461214093573287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=4333461214093573287' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4333461214093573287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4333461214093573287'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2010/01/fresh-face-behavior-pattern.html' title='The Fresh Face Behavior Pattern'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-3028255648653275056</id><published>2009-11-17T00:21:00.001-06:00</published><updated>2009-11-17T00:22:42.812-06:00</updated><title type='text'>Grails text input field advice trick</title><content type='html'>To save space and make the user experience a little better, there's a common technique to set a default value in an input text field to guide a user, that gets removed when the user clicks on the input field.  This is accomplished like so:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; &amp;lt;input name="q" type="text" value="Search" onclick="this.value = ''" /&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/SwI61WP04YI/AAAAAAAAB-Y/2Qbot5OxUw0/s1600/new-search.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/SwI61WP04YI/AAAAAAAAB-Y/2Qbot5OxUw0/s320/new-search.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;(clicking in the box would clear the results)&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;This is nice, but when used as a search input field, it's also nice to re-display to the user what they searched on when the search results are shown in case the user wants to tweak their existing search criteria.&lt;br /&gt;&lt;br /&gt;Here's how to add that feature with just a little bit more code in a Grails GSP page.&amp;nbsp; BTW - you can do the same in other languages, but the syntax will be a little different (e.g. Elvis operators are unique to Groovy).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;lt;input name="q" type="text" value="${params.q ?: 'Search'}" onclick="if (this.value=='Search') {this.value = '';}" /&amp;gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So now when the search results are displayed, the user will see what they searched on and tweak them if desired.&amp;nbsp; Nothing mind-blowing, but a nice little pair of features for your users with just a little code.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_lWbr1k8gyZ8/SwI8ZT-ijXI/AAAAAAAAB-g/MGao5287_Ls/s1600/already-searched.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_lWbr1k8gyZ8/SwI8ZT-ijXI/AAAAAAAAB-g/MGao5287_Ls/s320/already-searched.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;(clicking in the box won't clear the results)&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-3028255648653275056?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/3028255648653275056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=3028255648653275056' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/3028255648653275056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/3028255648653275056'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/11/grails-text-input-field-advice-trick.html' title='Grails text input field advice trick'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_lWbr1k8gyZ8/SwI61WP04YI/AAAAAAAAB-Y/2Qbot5OxUw0/s72-c/new-search.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-7267407603144469766</id><published>2009-10-30T22:40:00.004-05:00</published><updated>2009-10-31T00:05:17.209-05:00</updated><title type='text'>A luser's guide to Iometer</title><content type='html'>Hi, my name is Dan, and I'm a software development &lt;a href="http://en.wikipedia.org/wiki/Luser"&gt;luser&lt;/a&gt; who sometimes dreams of being a sysadmin.  Actually, what I really want is the authority to pick all the cool hardware, but with none of the "the server's down!" accountability.  If you hear of that job, lemmeno.  In the meantime...&lt;br /&gt;&lt;br /&gt;If you haven't lived under a rock during the last 5 years, you're aware that virtualization is taking over.  This is a good thing.  The trouble is, supporting virtualized environments requires a completely new skill set.  The ROI is there, but it takes a real knowledge investment!  And if you install virtualized servers in a company with overworked and stressed out &lt;a href="http://en.wikipedia.org/wiki/Bofh"&gt;BOFH&lt;/a&gt;'s that aren't able or willing to make that learning investment, you can end up worse off than before.&lt;br /&gt;&lt;br /&gt;In this particular case, I installed an instance of JIRA and Confluence for a client as part of our big development project.  I've installed it before at a couple other places, and performance has always been really good.  But at this client, it sucks.  As in 10-second-response-time sucks.  The instances are running on the VMWare ESX platform, which is the key variable that's different.  The trouble for me as a developer in this problem is that:&lt;br /&gt;a) I'm not a VMWare tuning expert.&lt;br /&gt;b) I'm not a BOFH, so naturally, the infrastructure group hates me. Just kidding, they really like me...I know that knife I found in my "Let's deploy EJBs and crush the souls of our poor operations staff" book was just for fun.&lt;br /&gt;&lt;br /&gt;But seriously, what we had here was a real failure to communicate.  &lt;span style="font-weight:bold;"&gt;I&lt;/span&gt; knew that this thing just wasn't running right.  But I didn't know how to narrow the problem down and quantitatively convince them of the issue.  I was able to see that it wasn't CPU bound just by watching the CPU meter.  I knew it wasn't the database, because I tried a couple different databases, each with the same performance.  During my local testing on my laptop, the full production instance ran great.  So I was &lt;span style="font-style:italic;"&gt;kinda&lt;/span&gt; sure that it was I/O bound, but I needed proof.&lt;br /&gt;&lt;br /&gt;Enter &lt;a href="http://www.iometer.org/"&gt;&lt;span style="font-weight:bold;"&gt;Iometer&lt;/span&gt;&lt;/a&gt;.   Iometer is an open source tool, originally written by Intel, and open-sourced in 2001.  It's become one of the most popular storage performance and benchmarking utilities available.  Even &lt;a href="http://communities.vmware.com/docs/DOC-3961"&gt;VMWare recommends&lt;/a&gt; it as a tool you can use to analyze storage throughput.&lt;br /&gt;&lt;br /&gt;I'm still an Iometer n00b, so take what I say with a grain of salt, and teach me if you know more than I do please!  e.g. One of the questions I have is &lt;a href="http://serverfault.com/questions/79564/iometer-canned-configuration-settings-for-categories-of-applications"&gt;this one&lt;/a&gt; over at serverfault.&lt;br /&gt;&lt;br /&gt;Short story long, the punchline is this:  I ran an Iometer test comparing performance between my development laptop (7200 RPM drive) and the virtual server instance running on a SAN.  Here's the results:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/Suu-Y3DJHEI/AAAAAAAAB9c/XYkdKua-F7I/s1600-h/IO-Performance.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 290px;" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/Suu-Y3DJHEI/AAAAAAAAB9c/XYkdKua-F7I/s400/IO-Performance.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5398617912636939330" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/Suu-perDchI/AAAAAAAAB9s/nXj8TwFDH1k/s1600-h/MBs-per-second.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 397px; height: 295px;" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/Suu-perDchI/AAAAAAAAB9s/nXj8TwFDH1k/s400/MBs-per-second.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5398618198151229970" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lWbr1k8gyZ8/Suu-pMpRb9I/AAAAAAAAB9k/u_Ma-5DjJB0/s1600-h/avg-IO-resp-time.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 262px;" src="http://3.bp.blogspot.com/_lWbr1k8gyZ8/Suu-pMpRb9I/AAAAAAAAB9k/u_Ma-5DjJB0/s400/avg-IO-resp-time.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5398618193311920082" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Pretty amazing, huh?  Amazingly bad for the server - it's &lt;span style="font-weight:bold;"&gt;nearly 3 times as slow&lt;/span&gt; as my feeble little laptop!  Like I mentioned, I'm not an Iometer expert by any means, and there are different ways to configure the tests.  But I'd be surprised if you could configure the tests to find this big of a performance difference between systems that were anywhere near each other's performance.&lt;br /&gt;&lt;br /&gt;On how to run the tests - here's one &lt;a href="http://articles.techrepublic.com.com/5100-10878_11-5735721.html"&gt;tutorial&lt;/a&gt; on configuring it, and here's &lt;a href="http://www.ocztechnologyforum.com/forum/showthread.php?t=60947"&gt;another&lt;/a&gt;.  The only tricky things I found:&lt;br /&gt;1. On the Disk Targets tab, there's a setting for the Maximum Disk Size, and it's specified in sectors.  It's been a couple centuries since I worked with sectors, but fortunately &lt;a href="http://www.zenez.com/tmp/ou8faqz/cache/88.html"&gt;google is your friend&lt;/a&gt;.&lt;br /&gt;2. The user guide is a little confusing about what a yellow disk target icon with a red slash through it means.  If it's yellow with a red slash, it just means that IOmeter will need to create its iobw.tst file on the drive when it starts the test - you don't have to do anything.  Do select the drive you want to test against though - this will be marked with a little X next to the drive when you select it.&lt;br /&gt;&lt;br /&gt;Turns out that diagnosing I/O performance is easier than I thought it would be.   Now that just leaves the hard part of trying to get our BOFH friends to fix problems like these when they happen...good luck!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-7267407603144469766?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/7267407603144469766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=7267407603144469766' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/7267407603144469766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/7267407603144469766'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/10/lusers-guide-to-iometer.html' title='A luser&apos;s guide to Iometer'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_lWbr1k8gyZ8/Suu-Y3DJHEI/AAAAAAAAB9c/XYkdKua-F7I/s72-c/IO-Performance.gif' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-678133459802234587</id><published>2009-09-21T23:08:00.004-05:00</published><updated>2009-09-22T12:45:32.640-05:00</updated><title type='text'>How to share google calendar with family and exchange</title><content type='html'>Update 9/22:  Google must've seen my post and reacted :)&lt;br /&gt;http://gmailblog.blogspot.com/2009/09/push-gmail-for-iphone-and-windows.html&lt;br /&gt;-------------&lt;br /&gt;&lt;br /&gt;A while back I gave my better half my old iphone.  I was all jazzed up to be able to sync our calendars, but it turned out to be not as easy as I thought it should be.  I know there's mac.me and all, but coughing up all that money to AT&amp;T for their service makes one want to act like their dad with their furnace thermostats. (Thank goodness for electronic thermostats, where you can wage the battle once and be done with it...but I digress.)&lt;br /&gt;&lt;br /&gt;Here was the situation:&lt;br /&gt;I have an iphone, have my work mail (and primary calendar) fed through an exchange server, and use google apps (gmail) for my personal email.&lt;br /&gt;My wife has an iphone, and a gmail account.&lt;br /&gt;&lt;br /&gt;The mission: Share our family calendar - allowing me to see family events that show up on her calendar, and vice-versa. &lt;br /&gt;&lt;br /&gt;You'd think this would be pretty easy, but anyone that's been screwing around with these stupid calendar syncing apps for the last few years knows that it's actually really hard.  You can get pretty close nowadays with google's default sharing, and even with neuvasync, but at least when I went through this experiment, neither of those solutions had implemented the ability to notify the invitees if the person adding the event did it through their phone.  See&lt;a href="http://www.google.com/support/forum/p/Google+Mobile/thread?tid=4f8241939ae9e3ae&amp;hl=en"&gt; this thread&lt;/a&gt; and &lt;a href="http://www.google.com/support/forum/p/Calendar/thread?tid=771a5d474617e869&amp;hl=en"&gt;this one&lt;/a&gt; as examples of the issue.  Notifications *do* work if the person adds an event via the google calendar website, but that doesn't help if you want to add an event through your phone.&lt;br /&gt;&lt;br /&gt;But what I did find to work was the above combo + &lt;a href="http://www.google.com/sync/index.html"&gt;google sync&lt;/a&gt;.  If I have that running, *and* have auto-accept turned on in my google calendar settings, any invitations that are added to my google calendar account get automatically sync'd to my exchange calendar, which are then pushed out to my phone...voila - near real-time synchonization.  This requires an extra step, and relies on the google sync app running, but it solves that problem.  Next up - wondering why she still prefers the dead-tree version...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-678133459802234587?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/678133459802234587/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=678133459802234587' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/678133459802234587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/678133459802234587'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/09/how-to-share-google-calendar-with.html' title='How to share google calendar with family and exchange'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-4280413292512235249</id><published>2009-09-05T22:16:00.001-05:00</published><updated>2009-09-06T18:25:01.868-05:00</updated><title type='text'>The Youth Soccer Project Pattern</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lWbr1k8gyZ8/SqMpOz7MtKI/AAAAAAAAB88/Nt6Lvw7oNMw/s1600-h/kidssoccer.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 200px; height: 159px;" src="http://1.bp.blogspot.com/_lWbr1k8gyZ8/SqMpOz7MtKI/AAAAAAAAB88/Nt6Lvw7oNMw/s400/kidssoccer.jpg" alt="" id="BLOGGER_PHOTO_ID_5378187714443916450" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Have you ever seen a soccer/football game played by 5 year olds?&lt;br /&gt;&lt;br /&gt;The Youth Soccer Project Pattern is an observation I've seen, regarding how the members of a project will run around as one big pack, chasing the ball all over the field in committees.  In this environment, there also tend to be lots of soccer moms yelling praises at the sidelines (AKA project managers).  There might one or two young stars that can make their way through the mess.  And there's also bound to be one or two kids that are just hanging out in some corner of the field, picking daisies.  In software projects those are often the testers that haven't been properly included in the team, or are those testers who are punching the clock and would rather pick daisies than really get into the action.&lt;br /&gt;&lt;br /&gt;Contrast this with experienced teams that have players qualified at every position, and know where they should be at all times.  Teamwork consists of short, well executed collaborations.  Not to mention the fact that the players have spent considerable time together already, so the osmotic communication is a given.   The players know exactly what their goal is.  Of course in software, this goal can change drastically based on the situation, but once you're coding, you better know what the end goal is.  Otherwise you're just wasting time, and maybe even heading in the wrong direction.&lt;br /&gt;&lt;br /&gt;So, what kind of team are you playing with or coaching?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-4280413292512235249?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/4280413292512235249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=4280413292512235249' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4280413292512235249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4280413292512235249'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/09/youth-soccer-project-pattern.html' title='The Youth Soccer Project Pattern'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_lWbr1k8gyZ8/SqMpOz7MtKI/AAAAAAAAB88/Nt6Lvw7oNMw/s72-c/kidssoccer.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-5935496852986005330</id><published>2009-08-05T12:01:00.001-05:00</published><updated>2009-08-05T15:34:05.068-05:00</updated><title type='text'>When evaluating design decisions, let the numbers talk</title><content type='html'>[The title of this article is as much a reminder to myself as it is advice to others.]&lt;br /&gt;&lt;br /&gt;One of my clients has a decision to make about when they should use an ESB to expose services in their upcoming architecture.&lt;br /&gt;&lt;br /&gt;What's interesting about this decision is that there is a heated debate around it (I say use them only when absolutely necessary, while the company's long-term services company says use them for every public service interface), and this is going to be an expensive decision.  It makes for some interesting dynamics in the decision making process.&lt;br /&gt;&lt;br /&gt;The conversation became useful when we started talking about concrete ways to compare the approaches for building a particular service.  We came up with this rough evaluation criteria:&lt;br /&gt;&lt;br /&gt;&lt;style type="text/css"&gt;.nobrtable br { display: none }&lt;/style&gt;&lt;br /&gt;&lt;div class="nobrtable"&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;&lt;tbody&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;Category&lt;/span&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;Tests&lt;/span&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;span style="font-weight: bold;"&gt;Metrics&lt;/span&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;Performance&lt;/td&gt;&lt;br /&gt;&lt;td&gt;1 user, 1 request&lt;/td&gt;&lt;br /&gt;&lt;td&gt;response time&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;Scalability&lt;/td&gt;&lt;br /&gt;&lt;td&gt;X users, Y requests per second&lt;/td&gt;&lt;br /&gt;&lt;td&gt;avg response time&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;Initial Effort&lt;/td&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;Number of hours to implement&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;Maintainability&lt;/td&gt;&lt;br /&gt;&lt;td&gt;Add an attribute&lt;/td&gt;&lt;br /&gt;&lt;td&gt;Number of hours to implement&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;Change the interface&lt;/td&gt;&lt;br /&gt;&lt;td&gt;Number of hours to implement&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/td&gt;&lt;br /&gt;&lt;td&gt;Version the service&lt;/td&gt;&lt;br /&gt;&lt;td&gt;Number of hours to implement&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;It's that last category that really intrigued me.  It's obviously a difficult thing to measure with all the variables involved, but I think you can get pretty close with some forethought, and maintainability is the key question here.  For example, you can eliminate massive developer differences by having the same person implement all variations of the approaches, or at least pick developers that are about the same in skill and speed levels.  You'd also want to eliminate (yet still measure) learning curve factors in any approach, since initial learning curves might inappropriately throw off the long-term comparison measurements.  You'd still want to measure those, since that's going to be a factor when you need to ramp up another person to support this application.&lt;br /&gt;&lt;br /&gt;Ideally there'd be something like the above in a standard format, much like how the Pet Store application is used to compare platform stacks.  I did a little bit of searching on this subject to see if there were any other standard operations to consider as part of an evaluation, but didn't find anything worth looking into.  What other metrics or tools have others found to be useful in situations like this?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-5935496852986005330?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/5935496852986005330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=5935496852986005330' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5935496852986005330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5935496852986005330'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/06/when-evaluating-design-decisions-let.html' title='When evaluating design decisions, let the numbers talk'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-3455732524407571538</id><published>2009-06-29T22:39:00.003-05:00</published><updated>2009-06-29T23:15:14.259-05:00</updated><title type='text'>Simple and easy site monitoring with PowerShell</title><content type='html'>In the *nix world, I really like monit for watching and managing small to medium apps.  A while back we wrote an intranet app in Grails, running on Tomcat on a Windows 2003 server.  The client was hosting the app themselves, but didn't have any IT staff whatsoever, so monitoring and managing this app was a little tricky.&lt;br /&gt;&lt;br /&gt;I searched around for something like monit for windows, but didn't find any good free or cheap tools to do what it does, which is primarily to monitor and restart services upon failure.  There's a million monitor and alert tools out there, but none that I found had a clean way to restart my Tomcat service if something went wrong.  The closest thing I found was Hyperic's open source monitoring solution, but after 30 minutes of futzing around, it seemed too klunky to me for this small problem.  I'm sure it's fine, and for bigger solutions it would probably fit well.&lt;br /&gt;&lt;br /&gt;Then I ran across a couple PowerShell scripts that intrigued me - the first was for scraping a web page.  After that find, it was just a matter of googling to find the remaining piece - restarting a windows service.  Bingo!  I hadn't done any PowerShell scripting yet, but it turns out to be a really sweet solution for this type of problem.  All I had to do after that was to tweak the code to be a little more reusable, and I also created a simple grails view that would exercise the integration features I wanted to include in my ping test.  From there it was just a matter of calling the script on a regular basis.  In my case, I used the windows task scheduler.   Here's what the script looks like:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre class="prettyprint"&gt;&lt;code&gt;&lt;span class="pln"&gt;$webClient &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="kwd"&gt;object&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;System&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="typ"&gt;Net&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="typ"&gt;WebClient&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="com"&gt;###################################################&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="com"&gt;# BEGIN USER-EDITABLE VARIABLES&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="com"&gt;# the URL to ping&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;$HeartbeatUrl &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"http://someplace.com/somepage/"&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="com"&gt;# the response string to look for that indicates things are working ok&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;$SuccessResponseString &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"Some Text"&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="com"&gt;# the name of the windows service to restart (the service name, not the display name)&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;$ServiceName &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"Tomcat6"&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="com"&gt;# the log file used for monitoring output&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;$LogFile &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"c:\temp\heartbeat.log"&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="com"&gt;# used to indicate that the service has failed since the last time we checked.&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;$FailureLogFile &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"c:\temp\failure.log"&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="com"&gt;# END USER-EDITABLE VARIABLES&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="com"&gt;###################################################&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="com"&gt;# create the log file if it doesn't already exist.&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(!(&lt;/span&gt;&lt;span class="typ"&gt;Test&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="typ"&gt;Path&lt;/span&gt;&lt;span class="pln"&gt; $LogFile&lt;/span&gt;&lt;span class="pun"&gt;))&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span class="typ"&gt;New&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="typ"&gt;Item&lt;/span&gt;&lt;span class="pln"&gt; $LogFile &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt;type file&lt;br /&gt;&lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;br /&gt;$startTime &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;get&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt;date&lt;br /&gt;$output &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; $webClient&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="typ"&gt;DownloadString&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;$HeartbeatUrl&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;$endTime &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;get&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt;date&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;$output &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt;like &lt;/span&gt;&lt;span class="str"&gt;"*"&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; $SuccessResponseString &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"*"&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span class="com"&gt;# uncomment the below line if you want positive confirmation&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span class="com"&gt;#"Success`t`t" + $startTime.DateTime + "`t`t" + ($endTime - $startTime).TotalSeconds + " seconds" &gt;&gt; $LogFile&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span class="com"&gt;# remove the FailureLog if it exists to indicate we're in good shape.&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="typ"&gt;Test&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="typ"&gt;Path&lt;/span&gt;&lt;span class="pln"&gt; $FailureLogFile&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span class="typ"&gt;Remove&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="typ"&gt;Item&lt;/span&gt;&lt;span class="pln"&gt; $FailureLogFile&lt;br /&gt;   &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="kwd"&gt;else&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span class="str"&gt;"Fail`t`t"&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; $startTime&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="typ"&gt;DateTime&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"`t`t"&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;$endTime &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt; $startTime&lt;/span&gt;&lt;span class="pun"&gt;).&lt;/span&gt;&lt;span class="typ"&gt;TotalSeconds&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;" seconds"&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="pln"&gt; $LogFile&lt;br /&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span class="com"&gt;# restart the service if this is the first time it's failed since the last successful check.&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(!(&lt;/span&gt;&lt;span class="typ"&gt;Test&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="typ"&gt;Path&lt;/span&gt;&lt;span class="pln"&gt; $FailureLogFile&lt;/span&gt;&lt;span class="pun"&gt;))&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;       &lt;/span&gt;&lt;span class="typ"&gt;New&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="typ"&gt;Item&lt;/span&gt;&lt;span class="pln"&gt; $FailureLogFile &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt;type file&lt;br /&gt;       &lt;/span&gt;&lt;span class="str"&gt;"Initial failure:"&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; $startTime&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="typ"&gt;DateTime&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;&gt;&gt;&lt;/span&gt;&lt;span class="pln"&gt; $FailureLogFile&lt;br /&gt;       &lt;/span&gt;&lt;span class="typ"&gt;Restart&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="typ"&gt;Service&lt;/span&gt;&lt;span class="pln"&gt; $ServiceName&lt;br /&gt;   &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;I posted my question (and my own answer eventually) on stackoverflow &lt;a href="http://stackoverflow.com/questions/663780/any-monit-like-equivalents-for-windows-os/1016122#1016122"&gt;here&lt;/a&gt;, so keep an eye on that if you're looking for improvements to it.  There's a lot more you can do with this script, like email upon failure, or monitor multiple sites.  Hopefully this helps some other folks out there with problems like this.  It was a really nice experience for me; simple and powerful.  So hats off to the authors of PowerShell  - I'll be reaching for that tool more and more in the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-3455732524407571538?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/3455732524407571538/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=3455732524407571538' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/3455732524407571538'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/3455732524407571538'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/06/simple-and-easy-site-monitoring-with.html' title='Simple and easy site monitoring with PowerShell'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-5576970542951093976</id><published>2009-06-28T22:25:00.003-05:00</published><updated>2009-06-28T23:36:53.459-05:00</updated><title type='text'>Domain names for daughters</title><content type='html'>Though the biggest domain name purchases are probably long-gone since the initial dot-com boom, they still remain a valued property.  They'll never be as valuable as real land of course, since we can always create more of them, as opposed to things like lake-front property.&lt;br /&gt;&lt;br /&gt;The recent &lt;a href="http://www.dailyfinance.com/2009/06/15/facebook-says-almost-6-million-usernames-are-taken-in-two-days/"&gt;mad rush&lt;/a&gt; for facebook profile names reminded me of this new global scale of gold rush activity.  And yes, I'm a little annoyed that someone that has been farming this interweb as long as I have was offered a name like dan.tanner&lt;span style="font-style: italic;"&gt;2&lt;/span&gt; (in &lt;span style="font-weight: bold;"&gt;my&lt;/span&gt; day, we used Mosiac.  And we liked it!).  It also reminded me of something I'm hoping will come in handy for my two daughters some day - their very own short and memorable domain names. &lt;br /&gt;&lt;br /&gt;Finding a decent available domain name is a tenaciously difficult PITA.  It's an exercise in creativity and luck, and girls names are especially tough.  Not only do you have to wrestle with the general lack of availability, but also the likelihood that they'll change their name when they get married.  In my case, that's sometime after age 28, when they've agreed to start dating.&lt;br /&gt;&lt;br /&gt;In my case, my girls are named Maria Mae and Daniela Teresa.  All good variants of maria and daniela were taken, which would've been ideal.  And no last names were considered because of the potential marriage name change.  After tinkering around for a while, here's what I ended up saving for them:&lt;br /&gt;mariamae.com and danielat.com&lt;br /&gt;They're both fairly mnemonic, and they're both flexible enough to last.  And they're both shorter than my domain name!&lt;br /&gt;&lt;br /&gt;It'll be a few years, but hopefully they'll be useful.  Not to mention give me a little boost in the cool dad category.  Not that I'll need any help in that category. &lt;br /&gt;&lt;br /&gt;Now...where did my favorite plaid pants go?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-5576970542951093976?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/5576970542951093976/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=5576970542951093976' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5576970542951093976'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5576970542951093976'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/06/domain-names-for-daughters.html' title='Domain names for daughters'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-8237761416641858400</id><published>2009-04-14T22:54:00.003-05:00</published><updated>2009-04-14T23:54:38.176-05:00</updated><title type='text'>In praise of refreshingly efficient meetings</title><content type='html'>Everybody dreads bad meetings.  Meetings are often too long, too often, or don't accomplish anything.  At some companies, this is what they are all like. &lt;br /&gt;&lt;br /&gt;You can implement processes to help have better meetings (which is another meeting of course).  Heck, I just attended a meeting last week whose title was how to structure our meetings to have less of them.&lt;br /&gt;&lt;br /&gt;Like everything else in the thought-based industries, the effectiveness of a meeting is 10% process and 90% people. &lt;br /&gt;&lt;br /&gt;The other day, I attended a meeting that was remarkably crisp and effective.  It was a brainstorming session, so I wouldn't have expected it.  The meeting started with a general leaning towards one solution to the problem, and 15 minutes later (15 minutes early), the meeting ended with a clear path towards the exact opposite style of solution. &lt;br /&gt;&lt;br /&gt;I walked out of the meeting thinking, "Wow! That was fun!"&lt;br /&gt;To which I quickly looked in the mirror wondering why the hell I would have just enjoyed being in a meeting.  Developers have been bred to hate meetings, so I obviously needed to do some serious soul-searching.&lt;br /&gt;&lt;br /&gt;What seemed unique to this meeting vs. so many others were the following attributes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;An inherent sense of urgency by role: The key person in the room was a company officer with a ton of experience making decisions on a limited schedule.  Sure, everybody's busy, and some people are really busy, and have that ability to keep people in the room at attention.  Maybe it goes with the title, maybe it's decades of experience, maybe a little of both.&lt;br /&gt;&lt;/li&gt;&lt;li&gt; Flexibility in thought (an open mind):  There weren't any fixed or hidden agendas, which allowed the discussion to flow quickly through the options without getting hung up.&lt;/li&gt;&lt;li&gt;Real-time calculations: Part of the discussion involved ROI.  We could've marked that data as follow-up items, which would've left the discussion muddy and forced another meeting, but it wasn't necessary.  With the business having a good handle on their critical numbers, and the technology team having a good rough estimate for the project size, we were able to do the math in our heads and flip through the choices in minutes.&lt;/li&gt;&lt;/ul&gt;The simplest written analogy to this that I've seen is the chapter titled "Rattle Yer Dags" in the book &lt;a href="http://www.amazon.com/Adrenaline-Junkies-Template-Zombies-Understanding/dp/0932633676"&gt;Adrenaline Junkies and Template Zombies&lt;/a&gt;, by the legendary Tom DeMarco and Atlantic Systems Guild.   (Highly recommended.)&lt;br /&gt;&lt;br /&gt;And you can follow the guidelines given when you google "how to run an effective meeting".  That's all good stuff...the unfortunate reality for most is that meetings like this don't happen often enough. &lt;br /&gt;&lt;br /&gt;So, cheers to refreshingly efficient meetings.&lt;br /&gt;&lt;br /&gt;Gotta go...I'm late for another meeting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-8237761416641858400?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/8237761416641858400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=8237761416641858400' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/8237761416641858400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/8237761416641858400'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/04/in-praise-of-refreshingly-efficient.html' title='In praise of refreshingly efficient meetings'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-5601236192455196955</id><published>2009-03-04T10:00:00.003-06:00</published><updated>2009-03-04T10:29:03.412-06:00</updated><title type='text'>Who needs developers when you have IBM?</title><content type='html'>It used to be that software vendors sold customers bridges based on the lie that business analysts could write the software with their awesome new tools...eliminating the need for programmers.&lt;br /&gt;&lt;br /&gt;I just ran across some interesting marketecture for IBM's Integration Developer product.  They appear to have conceded that a BA can't program with the tool.  But possibly even worse, the introduction to the product advertises the following:&lt;br /&gt;&lt;blockquote&gt;WebSphere Integration Developer enables integration developers to assemble complex business solutions that require minimal skills, whether they involve processes, mediations, adapters, or code components. Users can construct process and integration solutions using drag-and-drop technology without having a working knowledge of Java.&lt;/blockquote&gt;&lt;br /&gt;Sounds like a great plan, huh?  Hire an "integration developer" to implement a java-based integration without a working knowledge of java.  Because you're just "assembling" complex business solutions...IBM's products take away the complexity for you!  Show me someone that fits their target audience that can even properly define the words mediation and adapter.&lt;br /&gt;&lt;br /&gt;A couple years back, I saw a presentation at &lt;a href="http://www.nofluffjuststuff.com/"&gt;NFJS&lt;/a&gt; by Neal Ford that pretty much matched my viewpoint exactly in my own experience.  He sums it up in this &lt;a href="http://memeagora.blogspot.com/2009/02/tools-anti-behavior-soa-tarpit-of.html"&gt;blog series&lt;/a&gt;.  Yes, integration is hard.  Yes, it takes very experienced developers to get it even done at all, and even those very experienced developers will make a lot of mistakes and produce less than ideal solutions because this is a new field, and remote computing sucks regardless of how smart the solution is.&lt;br /&gt;&lt;br /&gt;The bottom line is that you can't hide the complexity under a rug.  Products like this will get you 80% of the way there, and by the time you figure out that they're not the right solution, it might be too late.  You might have run out of budget, haven't finished, and have a bunch of unhappy customers mad at you.  But congratulations, you've just helped your can't-get-fired-for-buying-vendor fund their next line of bridges to sell you.&lt;br /&gt;&lt;br /&gt;Want to do it right?  Simplify your problem by defining what information needs to go from A to B first, and then listen to the right people that have done this before and aren't getting paid based on how much of their product you buy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-5601236192455196955?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/5601236192455196955/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=5601236192455196955' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5601236192455196955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5601236192455196955'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/03/who-needs-developers-when-you-have-ibm.html' title='Who needs developers when you have IBM?'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-2552693463368686300</id><published>2009-03-01T14:10:00.013-06:00</published><updated>2009-03-03T22:23:57.864-06:00</updated><title type='text'>The Development and Infrastructure Team Dysfunctional Relationship</title><content type='html'>If you spend any time making software in a big company whose primary job isn't making software, the following patterns about the development and infrastructure teams probably apply:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The development and infrastructure manager are different people.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The managers and their staff sit too far apart for osmotic communication.&lt;/li&gt;&lt;li&gt;They are in calls or meetings together all the time.&lt;/li&gt;&lt;li&gt;Yet angst abounds between the two groups all the time, whether it's overt or simple passive aggression.&lt;/li&gt;&lt;/ul&gt;If you're lucky, the managers are technically competent and secure enough to have the good hard conversations that are necessary, thinking about things from the customers perspective and from each others perspective.  Or if they're not technically current enough to have the conversation themselves, hopefully they can step aside and get the right heads together from each team to figure out things out together correctly.&lt;br /&gt;&lt;br /&gt;Unfortunately, as the mighty &lt;a href="http://mchawking.com/"&gt;MC Hawking&lt;/a&gt; likes to riff, Order from disorder is a scientific rarity.&lt;br /&gt;&lt;br /&gt;Whether it's outright silly and misguided arguments, or the "WTF are they thinking?" kinds of conversations had within each group after a meeting, it seems these two groups consistently spend too much time acting like &lt;a href="http://slashdot.org/"&gt;slashdot&lt;/a&gt; commentors and not enough time reading &lt;a href="http://www.amazon.com/Peopleware-Productive-Projects-Teams-Second/dp/0932633439"&gt;Peopleware&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;What's difficult about this problem is that it's not a technical problem.   It's the natural result of two diametrically opposed organizational forces.&lt;br /&gt;&lt;br /&gt;If the developers would just stop writing crappy software.&lt;br /&gt;&lt;br /&gt;If the infrastructure manager would just stop being such a grump.&lt;br /&gt;&lt;br /&gt;If the business would just go away.&lt;br /&gt;&lt;br /&gt;Believe me - they'd love to.  This whole time they're wondering why your crappy system costs them millions of dollars, and still doesn't work as well as their free Picasa photo album, which arguably does more than your system that's shoveling bits from A to B just like all the other thousands of companies exactly like yours.  But that's a whole 'nother story coming up...(the software sausage factory from a normal person's point of view).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-2552693463368686300?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/2552693463368686300/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=2552693463368686300' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2552693463368686300'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2552693463368686300'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/03/development-and-infrastructure-team.html' title='The Development and Infrastructure Team Dysfunctional Relationship'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-8146993759613013020</id><published>2009-02-23T16:03:00.004-06:00</published><updated>2009-02-23T16:08:17.066-06:00</updated><title type='text'>Is this a cheeky feature, or an ironic bug?</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/SaMdwEH4rWI/AAAAAAAABrU/S9Lwdr7EPUg/s1600-h/skype_typo_typo.gif"&gt;&lt;img style="cursor: pointer; width: 400px; height: 290px;" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/SaMdwEH4rWI/AAAAAAAABrU/S9Lwdr7EPUg/s400/skype_typo_typo.gif" alt="" id="BLOGGER_PHOTO_ID_5306117497550318946" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-8146993759613013020?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/8146993759613013020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=8146993759613013020' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/8146993759613013020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/8146993759613013020'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/02/is-this-cheeky-feature-or-ironic-bug.html' title='Is this a cheeky feature, or an ironic bug?'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_lWbr1k8gyZ8/SaMdwEH4rWI/AAAAAAAABrU/S9Lwdr7EPUg/s72-c/skype_typo_typo.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-1202538224241862187</id><published>2009-02-19T22:13:00.004-06:00</published><updated>2009-02-19T22:37:53.254-06:00</updated><title type='text'>Line 6 BackTrack Review</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lWbr1k8gyZ8/SZ4zd-5X0wI/AAAAAAAABqM/cj686t2aYuw/s1600-h/backtrack.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 121px; height: 320px;" src="http://3.bp.blogspot.com/_lWbr1k8gyZ8/SZ4zd-5X0wI/AAAAAAAABqM/cj686t2aYuw/s320/backtrack.jpg" alt="" id="BLOGGER_PHOTO_ID_5304734001281880834" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I don't normally blog about the products I buy, but the &lt;a href="http://line6.com/backtrack/"&gt;Line 6 BackTrack&lt;/a&gt; rules.  I've looked for ages for a good &lt;a href="http://engine11.com/"&gt;band&lt;/a&gt; recording practice tool, and this is finally it.  In the past, I've used:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A digital 8 track (too cumbersome)&lt;/li&gt;&lt;li&gt;A portable mp3 recorder with an expensive portable mic (too clumsy and hard to balance, and I had to use some super flaky and buggy software to transfer files)&lt;/li&gt;&lt;li&gt;A laptop (again, too clumsy, and hard to work with on the fly)&lt;/li&gt;&lt;/ul&gt;Why does the BackTrack rule?&lt;br /&gt;&lt;ol&gt;&lt;li&gt;It just works.  You turn it on, and it records your stuff in really good quality for practice purposes.  Marking stuff you like on the fly is a nice little bonus to help sift through stuff later.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It automatically chops up  the files for you based on pauses between sound.  No more tedious manual splitting of tracks in Audacity or whatever your file splitting tool is.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;It's easy to get the files onto your computer - it works as a USB storage device, so you can drag and drop.&lt;/li&gt;&lt;li&gt;It fits into my guitar case.  No lugging some big piece of recording gear around any more, or even worse, forgetting it.&lt;/li&gt;&lt;/ol&gt;The only issue I had on the first night of practice with it was that I had configured it to a preset of Rock Band levels...meaning its recording threshold was pretty high and the mic gain was pretty low.  On one of our lovely ballads, it missed the song's intro because it was below the recording threshold.  (Or maybe it's a feature to discourage ballads.)  It was easy enough to solve though - I just lowered the recording threshold a little.&lt;br /&gt;&lt;br /&gt;All in all, some serious w00t factor...thank you Line 6!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-1202538224241862187?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/1202538224241862187/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=1202538224241862187' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1202538224241862187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1202538224241862187'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/02/line-6-backtrack-review.html' title='Line 6 BackTrack Review'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_lWbr1k8gyZ8/SZ4zd-5X0wI/AAAAAAAABqM/cj686t2aYuw/s72-c/backtrack.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-8199090992641105633</id><published>2009-02-01T13:34:00.002-06:00</published><updated>2009-02-01T13:49:47.070-06:00</updated><title type='text'>Why Jeff Atwood is one of my programming heroes</title><content type='html'>There are a lot of high IQ's in this world, and a proportionately high number of them are in the programming field.  But IQ isn't enough.  An unfortunately high proportion of the smarties don't have high EQs when it comes to what we're actually trying to accomplish in this field.  Jeff Atwood is one of those people whose blog I follow that really, really gets it.  Here's a snippet from a podcast between him and Joel Spolsky, where he absolutely nails this concept right on the head. &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The longer I think about this, the less I care about code hygiene issues (laughs). Because the unit of measure that really matters to me is, how quickly you can respond to real business needs with your code. And by that I mean, how well are you serving the people that are using your code. To me that's what it's all about. Anything that gets in the way of you fixing your code or improving your code in a way that your customers can appreciate, is a negative. If that means using Ruby, or having lots of unit tests: whatever's working for you: do that. But if it's getting in the way, if it becomes friction, like, "I'd love to have this great new feature but I'd have to have 1000 unit tests," that's a negative.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In my opinion, this is the difference between a journeyman programmer and a master.  A journeyman has all the mechanical skills that a master has; he knows all the patterns and most of the anti-patterns.  But what he lacks is the wisdom to know when to use them, and most importantly, when not to use them. &lt;br /&gt;&lt;br /&gt;Maybe someday I'll be able to give Jeff a coke, and he'll smile and throw me a smelly old jersey he used during the project :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-8199090992641105633?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/8199090992641105633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=8199090992641105633' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/8199090992641105633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/8199090992641105633'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2009/02/why-jeff-atwood-is-one-of-my.html' title='Why Jeff Atwood is one of my programming heroes'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-2648237358553171786</id><published>2008-12-01T21:09:00.004-06:00</published><updated>2008-12-01T21:30:01.346-06:00</updated><title type='text'>How To Make Skype More Private</title><content type='html'>With one of my sisters moving to Japan for a couple years, everyone in my family is now using Skype.  By default, Skype is installed to let anyone chat with you and request your contact details.  The problem is that you get a lot of &lt;a href="http://en.wikipedia.org/wiki/Spam_(electronic)"&gt;Spam &lt;/a&gt;and &lt;a href="http://en.wikipedia.org/wiki/Phishing"&gt;Phishing &lt;/a&gt;contact requests. &lt;br /&gt;&lt;br /&gt;So, the one thing I recommend everyone do after installing skype is to go into &lt;span style="font-weight:bold;"&gt;Tools -&gt; Options&lt;/span&gt; and change your &lt;span style="font-weight:bold;"&gt;Privacy &lt;/span&gt;settings to be like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_lWbr1k8gyZ8/STSqNT1zIeI/AAAAAAAABY8/O6Ul-imT6PE/s1600-h/SkypePrivacySettings.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 257px;" src="http://3.bp.blogspot.com/_lWbr1k8gyZ8/STSqNT1zIeI/AAAAAAAABY8/O6Ul-imT6PE/s320/SkypePrivacySettings.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5275028209198637538" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-2648237358553171786?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/2648237358553171786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=2648237358553171786' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2648237358553171786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2648237358553171786'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/12/how-to-make-skype-more-private.html' title='How To Make Skype More Private'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_lWbr1k8gyZ8/STSqNT1zIeI/AAAAAAAABY8/O6Ul-imT6PE/s72-c/SkypePrivacySettings.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-8574781680872376449</id><published>2008-10-24T21:08:00.002-05:00</published><updated>2008-10-24T22:09:11.534-05:00</updated><title type='text'>thought interruptions are life's choppy video</title><content type='html'>The other night I was watching the Daily Show through hulu.com in a hotel that had a slow internet connection.  About 10 minutes into the episode, the video started getting choppy.  I tried ignoring it, but even though the chop occurred only for a split-second, and happened every few seconds, it was distracting to the point where I couldn't watch the show any longer.  Everybody knows what that's like.  It's the same thing with a slightly scratched DVD.  You could theoretically keep watching, but there's something profoundly interrupting to that lack of continuity.&lt;br /&gt;&lt;br /&gt;That's the best layman's term analogy I can think of for what it takes to perform a job that requires a deep level of sustained thought.  Many have studied and written about this.  Some call it flow, some call it getting in the groove.  The latest prose in my field is by the gifted &lt;a href="http://memeagora.blogspot.com/2008/10/code-forrest-code.html"&gt;Neal Ford&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I make software for a living, which is a field that has a very difficult time quantifying the things that matter about it.  Examples at a low level are this:&lt;br /&gt;How do you quantify good code?  How do you quantify a good programmer?  To this day, it still takes a good programmer to tell them apart - no untrained eye or machine can.  The need for uninterrupted thought is another requirement that's easy to overlook and communicate, yet it's absolutely critical to making quality software.&lt;br /&gt;&lt;br /&gt;And oh yeah - a faster hotel internet connection.  That too. :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-8574781680872376449?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/8574781680872376449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=8574781680872376449' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/8574781680872376449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/8574781680872376449'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/10/thought-interruptions-are-lifes-choppy.html' title='thought interruptions are life&apos;s choppy video'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-5324467423826748729</id><published>2008-10-14T22:21:00.006-05:00</published><updated>2008-10-14T23:33:30.621-05:00</updated><title type='text'>The CDATA board of education</title><content type='html'>During my days on the web services team of a big bank a couple years ago, we wrote a ton of web services on the java platform.  Almost every service we wrote was SOAP based, and also conformed with a huge pile of enterprise standards that were actually pretty non-standard in the outside world.  &lt;br /&gt;&lt;br /&gt;The consequence of these slightly non-standard services were that first-time clients of our services sometimes had painful integrations with us.  Most notably .NET clients that wanted to auto-generate their client proxy classes.  The tool would simply not work with our WSDL, so they had to manually bind to our services, which greatly increased their cost and dates.  We didn't care though - the services we wrote were compliant according to our tools, and we simply didn't care that much about the clients that were having trouble connecting to our services.  Suck it up, you whiners.  We hand wrote all our services from the contract on down, and we're not going to bend over backwards for some whiny .NET'r that can't step outside the confines of his "Add Web Reference" tool.&lt;br /&gt;&lt;br /&gt;Fast forward to the last few months.  I've written client code for four different service providers.  One SOAP, one TCP (I didn't know people still wrote raw TCP-based services!), and a couple XML over HTTP services.  &lt;br /&gt;&lt;br /&gt;The integration that made me shameful of my former attitude was one of these XML "services" that consists of a large amount of non-normalized CDATA.  For example:&lt;br /&gt;&lt;br /&gt;&lt;SomeChunk&gt;&lt;br /&gt;&lt;[CDATA[&lt;br /&gt;ColumnHeaderA ColumnHeaderB ColumnHeaderC&lt;br /&gt;aaa bbb ccc&lt;br /&gt;ddd eee fff&lt;br /&gt;ggg hhh iii&lt;br /&gt;]]&gt;&lt;br /&gt;&lt;/SomeChunk&gt;&lt;br /&gt;&lt;br /&gt;My attitude was that any self-respecting programmer would not be serving up text data that should not be parsed by the XML parser and pass it off as a service, forcing clients to use regular expressions when they should instead be using a proper XML parsing tool.   The product manager couldn't understand why I felt that this service was no friend of mine.  Their opinion was that it was a perfectly good service, and any average programmer could crank it out in a week.  &lt;br /&gt;&lt;br /&gt;Why?  Because they wrote everything in perl!  &lt;br /&gt;&lt;br /&gt;It caused me to think back about those clients that I've wronged by not making their lives as easy as it could be.  Not to mention gave me another anti-pattern to look out for.  &lt;br /&gt;&lt;br /&gt;Words of wisdom?  When writing a public XML service, do eat your own dog food using different platforms and techniques to evaluate the palatability of your service.  Also, write client code for a few other public services to see what feels good, and what's painful from the client's perspective.  For example, do you really need to namespace your XML?  Does SOAP make it harder or easier for what you're trying to offer?  You might be surprised by what you find to be elegant from different sides of the service.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-5324467423826748729?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/5324467423826748729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=5324467423826748729' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5324467423826748729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5324467423826748729'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/10/cdata-board-of-education.html' title='The CDATA board of education'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-5073590205311644748</id><published>2008-10-14T22:10:00.003-05:00</published><updated>2008-10-14T22:18:48.163-05:00</updated><title type='text'>Want a survey?  Don't ask!</title><content type='html'>Here's a suggestion when you create a survey for your site:&lt;br /&gt;Don't ask for permission - just show the survey.&lt;br /&gt;&lt;br /&gt;Meaning, don't pop up a window after the user's completed their shopping, asking them if they wouldn't mind taking a minute to fill out your survey.  This is synonymous with telemarketing, and makes most people cringe.&lt;br /&gt;&lt;br /&gt;If your survey is really short and to the point, present the survey right then and there.  You've already popped up the window.  Give them a couple radio buttons at most, and the all-important open comments field.  That's where you'll get the most useful responses.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-5073590205311644748?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/5073590205311644748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=5073590205311644748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5073590205311644748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5073590205311644748'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/10/want-survey-dont-ask.html' title='Want a survey?  Don&apos;t ask!'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-2604981713096923674</id><published>2008-09-25T07:29:00.005-05:00</published><updated>2008-09-25T07:52:10.213-05:00</updated><title type='text'>What do I want?  System.Exit!</title><content type='html'>When do I want it? &lt;span style="font-weight:bold;"&gt;NOW!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Note to UI builders: When building a confirmation dialog for a user, please don't make them wait to answer the question.  I can't think of a time when it's ever really necessary to meditate before making a modal dialog decision.&lt;br /&gt;&lt;br /&gt;The most common example of this is Firefox's plugin installer that requires you to wait a few seconds before being allowed to install a chosen plugin.  At least you can turn this off in the configuration.  A really annoying example I just came across is some new VPN software I'm required to use for one of our clients.  Whenever you want to shut down the client, it pops up this dialog:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_lWbr1k8gyZ8/SNuHWihVRWI/AAAAAAAABBs/ljvBrXC-4Pk/s1600-h/forticlient_shutdown.PNG"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_lWbr1k8gyZ8/SNuHWihVRWI/AAAAAAAABBs/ljvBrXC-4Pk/s320/forticlient_shutdown.PNG" alt="" id="BLOGGER_PHOTO_ID_5249938611923928418" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_lWbr1k8gyZ8/SNuJOVafj4I/AAAAAAAABB0/5cM_2p15RYU/s1600-h/forticlient_shutdown2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_lWbr1k8gyZ8/SNuJOVafj4I/AAAAAAAABB0/5cM_2p15RYU/s320/forticlient_shutdown2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5249940669989883778" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It starts from 5, counting down to zero before you can click Yes.  Every time I see it, it feels like I'm stuck in a room with someone who's re-telling a bad joke for the 5th time.  (I'm sure my friends know what I mean :)&lt;br /&gt;&lt;br /&gt;So please, a concise confirmation dialog is quite enough.  &lt;br /&gt;Don't you think?  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Don't you think?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-2604981713096923674?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/2604981713096923674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=2604981713096923674' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2604981713096923674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/2604981713096923674'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/09/what-do-i-want-systemexit.html' title='What do I want?  System.Exit!'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_lWbr1k8gyZ8/SNuHWihVRWI/AAAAAAAABBs/ljvBrXC-4Pk/s72-c/forticlient_shutdown.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-5150736645508357014</id><published>2008-08-18T20:08:00.004-05:00</published><updated>2008-09-13T01:29:59.338-05:00</updated><title type='text'>Mark of the Be01100001st</title><content type='html'>Satanists and Puritans keep out - I just wanna be able to find where my stuff is in my house.  Imagine a world where trying to round up 4 AA batteries isn't a frustrating experience.  That's the litmus test for me with home RFID technology.  I know, I know...it's gonna be the end of our peaceful human existance (right).  I also remember DBAs telling me the same thing when I wanted to use synthetic keys.  Oh, the horror.&lt;br /&gt;&lt;br /&gt;To be serious, I know there are privacy concerns, and there will be growing pains, but I think this is a pretty minor concern for most situations.&lt;br /&gt;&lt;br /&gt;With the "find my rechargeable batteries" example, it could be just like the technology that currently exists to help you find your cordless phone from the charging cradle. You walk around the house with the little beacon device, and like a radio collared wild animal, the beeps get closer and closer until you find those batteries nesting smugly in that {thing-you-forgot-about}.&lt;br /&gt;&lt;br /&gt;I guess I'll have to check back in another couple years.  For now the price of the consumer level RFID tags are nearly a dollar each, and I can't find a consumer level tagging/searching device available yet.  But I definitely think it'll catch on big when it does.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-5150736645508357014?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/5150736645508357014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=5150736645508357014' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5150736645508357014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/5150736645508357014'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/08/mark-of-be01100001st.html' title='Mark of the Be01100001st'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-4108740046821421086</id><published>2008-08-06T00:07:00.002-05:00</published><updated>2008-08-06T00:36:58.736-05:00</updated><title type='text'>Easy .NET database migrations</title><content type='html'>If you've ever written code that accesses a database, then you've experienced the issues brought on in trying to keep the database and code in sync.  In their common and annoying form, it's when developer X does something like add a column in his local database, checks in the source code, and then developer Y does a checkout and her code breaks because it's looking for a column that doesn't exist in her local database.  In their ugly form, the DBA forgets to add a column when the code goes to production and the deployment is bogged down while people scramble to find and fix the issue.  Things like missing indexes can be the worst form of this problem, since the performance problems they can create can be very difficult to track down.&lt;br /&gt;&lt;br /&gt;When Mr. Fowler wrote about his colleagues' &lt;a href="http://martinfowler.com/articles/evodb.html"&gt;evolutionary database design&lt;/a&gt;, things got better in the development world.  I and many others soon hacked up some degree of database migration automation based on the principles outlined in that doc, and not too long later Rails popped up with a great implementation of them. &lt;br /&gt;&lt;br /&gt;In the .NET world, it took a little longer for people to come up with their own flavors of this automation.  When my &lt;a href="http://spiderlogic.com"&gt;homies and I&lt;/a&gt; wanted to standardize on a good solution, we found a few decent candidates, and landed on &lt;a href="http://code.google.com/p/migratordotnet/"&gt;migratordotnet&lt;/a&gt;.  It was pretty cool.  Then my smarty pants colleague &lt;a href="http://zorched.net"&gt;Geoff&lt;/a&gt; took it and made it production quality.  He added a bunch more functionality and did some major refactoring. &lt;br /&gt;&lt;br /&gt;Once you start using it, you'll never want to go back.  Someday you'll wonder how we ever managed without tools like this in our belts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-4108740046821421086?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/4108740046821421086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=4108740046821421086' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4108740046821421086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4108740046821421086'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/08/easy-net-database-migrations.html' title='Easy .NET database migrations'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-1753167364058902201</id><published>2008-07-23T20:06:00.002-05:00</published><updated>2008-07-23T21:42:57.931-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>The Interview Acronym Quiz</title><content type='html'>Here's an idea for your next technical interview - the acronym quiz!  Have you ever thought of all the acronyms you've picked up over the course of your career?  My first job out of school was as a programmer for a defense contracting company, where I was given an acronym reference book for our domain.  I remember someone mentioning an acronym depth competition they had, where the winner was a an acronym 5 levels deep.  (e.g. An example of an acronym 2 levels deep is SSA - &lt;span style="font-weight: bold;"&gt;S&lt;/span&gt;CUBA &lt;span style="font-weight: bold;"&gt;S&lt;/span&gt;chools &lt;span style="font-weight: bold;"&gt;I&lt;/span&gt;nternational.  5 levels may have been an exaggeration, but 2 and 3 levels were common, and it was a ton of otherwise useless insider information.&lt;br /&gt;&lt;br /&gt;But I digress.  This post was about the half-joking idea of adding an acronym quiz section to a technical interview.  Of course this has limited value, but it seems useful to answer if you need to go more in depth on a given topic or interview.  For example, quickly answer what each acronym means:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;SOA&lt;/li&gt;&lt;li&gt;XAML&lt;/li&gt;&lt;li&gt;JAXB&lt;/li&gt;&lt;li&gt;BFF&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;If your technical candidate didn't get #1, red flag.  If they are supposed to know .NET and didn't get #2, red flag.   Ditto in the java world for #3.   Answer them all, and you just might up end being #4! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-1753167364058902201?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/1753167364058902201/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=1753167364058902201' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1753167364058902201'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1753167364058902201'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/07/interview-acronym-quiz-game.html' title='The Interview Acronym Quiz'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-911990612214878719</id><published>2008-07-20T22:10:00.006-05:00</published><updated>2008-07-20T22:57:56.515-05:00</updated><title type='text'>Netflix and the case of the missing download selection</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_lWbr1k8gyZ8/SIQIdTHvavI/AAAAAAAAAxQ/JSOG9GoocUM/s1600-h/fat_american_walking_dog_from_car.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_lWbr1k8gyZ8/SIQIdTHvavI/AAAAAAAAAxQ/JSOG9GoocUM/s200/fat_american_walking_dog_from_car.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5225310767098587890" /&gt;&lt;/a&gt;&lt;br /&gt;So I got a Roku box for Netflix a few weeks back.  I was excited, because I feel it's a great next step in the evolution of media deliver.  We took a step back for a while there - long ago we had to actually get off the couch to change the channel.  Then we got remotes.  Thirty years later people were running up to their office computer to change the stream.  Definitely not good - especially if we're gonna keep up our American Image.&lt;br /&gt;&lt;br /&gt;The good news is that the Roku box and the Watch It Now service works great for the movies they offer.  The bad news is that I've watched all 5 of the decent movies they offer. For real.  95% of the movies they offer for their Watch It Now service are either:&lt;br /&gt;a. really old&lt;br /&gt;b. really bad&lt;br /&gt;c. all of the above&lt;br /&gt;&lt;br /&gt;Think I'm exaggerating?  As an example, the #4 most popular title last week in the Watch It Now collection is "Blushing Bloopers".  You can't even *find* that title in IMDB.  Other Netflix customers rated it 2.1.  Netflix's estimated rating for me was 1.9.  Yes, I have exquisite taste; only movies like &lt;a href="http://www.imdb.com/title/tt0076723/"&gt;Slap Shot&lt;/a&gt; get a 5 star rating from &lt;span style="font-style:italic;"&gt;me&lt;/span&gt;.  Space Jam was number 10 on the most popular list last week.  I did see Dexter in there, which is a must-see IMO for anyone that hasn't seen it. &lt;br /&gt;&lt;br /&gt;After my own reaction, I figured a google search would uncover the reason for the skimpy selections, or at least show a thousand other similar opinions, but so far there aren't many people complaining about it at all.  For something that's definitely the future, it seems like Netflix is being too tentative in their content offerings.  Great - they've solved the delivery problem for another huge potential chunk of the consumer population.  But if they're going to succeed, they've gotta offer content worth delivering.  I'm sure it's not completely their fault (another case of license extortion?), but they need to solve that problem before they'll get beyond a beta stage of this solution.&lt;br /&gt;&lt;br /&gt;So in all, I like my Roku box, but I hope that soon enough I'll be able to waste time watching good TV instead of blogging about bad TV.  I'm a busy guy, and I have things to do.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-911990612214878719?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/911990612214878719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=911990612214878719' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/911990612214878719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/911990612214878719'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/07/netflix-and-case-of-missing-download.html' title='Netflix and the case of the missing download selection'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_lWbr1k8gyZ8/SIQIdTHvavI/AAAAAAAAAxQ/JSOG9GoocUM/s72-c/fat_american_walking_dog_from_car.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-7990850811166904784</id><published>2008-05-12T14:30:00.005-05:00</published><updated>2008-07-23T21:44:25.540-05:00</updated><title type='text'>what, me worry about good stack traces?</title><content type='html'>Those of us fortunate enough to get to build an application inside sharepoint are often confronted with this error message:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_lWbr1k8gyZ8/SCibTsH7LhI/AAAAAAAAAvY/1RbyrJQNsho/s1600-h/unknown_error.gif"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_lWbr1k8gyZ8/SCibTsH7LhI/AAAAAAAAAvY/1RbyrJQNsho/s320/unknown_error.gif" alt="" id="BLOGGER_PHOTO_ID_5199576532363456018" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Pretty useful, huh?&lt;br /&gt;&lt;br /&gt;What you quickly learn is that the real error is usually found in the shared log, which is usually more descriptive.  But every now and then you get a real treat like this as your only source of information:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;05/12/2008 14:29:32.84     w3wp.exe (0x03A4)                           0x0588    Windows SharePoint Services       General                           8dzz    High        Exception Type: System.NullReferenceException  Exception Message: Object reference not set to an instance of an object.&lt;/span&gt;     &lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Those of us familiar with java development are used to seeing worthless NullPointerExceptions like this, except that further down the stack trace is the clue to what's missing.  In this case however, you don't get that clue.&lt;br /&gt;&lt;br /&gt;Good thing it's so easy to write functional automated tests in sharepoint :)&lt;br /&gt;&lt;br /&gt;My wise colleague Jon Jones pointed me to a roundup of great logging and debugging tips by Andrew Connell &lt;a href="http://andrewconnell.com/blog/archive/2008/06/11/SharePoint-Debugging-and-Logging-Tips-and-Tricks.aspx"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;On a positive note, my talented colleague Brian Kapellusch wrote a nice wrapper around Spring.NET and NHibernate, which our project is using as the container for our business logic and data access.  Craptacular?  Yes.  Needed?  Yes.  At least until MS finally gets around to producing a production quality MVC framework, which is probably at least a year off.   Without it, I'd have a lot tougher time isolating and testing things like this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-7990850811166904784?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/7990850811166904784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=7990850811166904784' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/7990850811166904784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/7990850811166904784'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/05/what-me-worry-about-good-stack-traces.html' title='what, me worry about good stack traces?'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/_lWbr1k8gyZ8/SCibTsH7LhI/AAAAAAAAAvY/1RbyrJQNsho/s72-c/unknown_error.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-4683049039407907273</id><published>2008-03-08T21:45:00.005-06:00</published><updated>2008-03-09T11:40:31.695-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='books'/><category scheme='http://www.blogger.com/atom/ns#' term='business'/><title type='text'>World's Shortest Business Book Synopses</title><content type='html'>Welcome to the world's shortest synopses on some of the best selling business titles from the last few years.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Rich-Dad-Poor/dp/0751532711/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1205034969&amp;amp;sr=8-1"&gt;Rich Dad, Poor Dad&lt;/a&gt;: Doing something you like is for suckers.  Money rules!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Good-Great-Companies-Leap-Others/dp/0066620996/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1205034672&amp;amp;sr=8-1"&gt;Good To Great&lt;/a&gt;: Step1. Hire smart people.   Step 2 ???    Step 3. Profit!!!&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;Side question - how many executives have lifted the book's title for one of their presentations?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Leadership-Self-Deception-Getting-Out/dp/1576751740/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1205034993&amp;amp;sr=8-1"&gt;Leadership and Self-Deception&lt;/a&gt;: I'm OK, you're not OK is not OK.  And think outside the &lt;strike&gt;bun&lt;/strike&gt;box.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Me personally, I'm waiting for &lt;a href="http://www.amazon.com/Red-Queen-Evolution-Human-Nature/dp/0060556579"&gt;The Red Queen&lt;/a&gt; to become required reading in all executive management training programs.  Unfortunately, I still think we're in &lt;a href="http://en.wikipedia.org/wiki/Kansas_evolution_hearings"&gt;Kansas&lt;/a&gt;, Toto.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-4683049039407907273?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/4683049039407907273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=4683049039407907273' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4683049039407907273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4683049039407907273'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/03/worlds-shortest-business-book-synopses.html' title='World&apos;s Shortest Business Book Synopses'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-7095799176001424284</id><published>2008-02-26T20:58:00.004-06:00</published><updated>2008-03-09T11:40:58.876-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='nhibernate'/><title type='text'>One Real World NHibernate vs. TableAdapter comparison</title><content type='html'>If you're new to the hibernate vs. old-school data access debate, you hear arguments like:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;"hibernate is slow and too hard for regular programmers!"&lt;/li&gt;&lt;li&gt;"manual data access is tedious and non-productive!"&lt;/li&gt;&lt;li&gt;"hibernate is a software &lt;a href="http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx"&gt;Viet Nam&lt;/a&gt;!"&lt;/li&gt;&lt;li&gt;"manual data access &lt;a href="http://www.imdb.com/title/tt0070723/"&gt;is people!&lt;/a&gt;"&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Frankly, most java folks have been sick of this argument long before NHibernate came around.  There's truth and FUD on both sides of the argument, but how many people have the time or inclination to compare the two styles of implementation in a real project? (I'd love to hear your real stories - not just "my brother's cousin said that their team totally failed/succeeded on this one big project".)&lt;br /&gt;&lt;br /&gt;On a recent small .NET project for a client, I started out creating the implementation using NHibernate, but was then told after my first draft that they'd prefer to stay away from third party tools due to their concerns over maintainability (that's a whole 'nother discussion in itself).  So I got to rewrite the exact same functionality using Table Adapters.  Since my data access was behind interfaces, it was a great way to see some metrics comparing the two implementations.&lt;br /&gt;&lt;br /&gt;The most interesting metric: &lt;span style="font-weight: bold;"&gt;lines of code&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;NHibernate DAO: &lt;span style="font-weight: bold;"&gt;29&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Table Adapter DAO: &lt;span style="font-weight: bold;"&gt;534&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;This was for a DAO with about 30 attributes in its main table, and about 6 one-to-many tables.  Of course there were differences in the supporting code, but they were fairly equal in size (actually, NHibernate's supporting code was much smaller too).  The biggest "&lt;a href="http://weblogs.asp.net/scottgu/"&gt;I-can't-believe-Scott-Gu-tells-people-to-do-this&lt;/a&gt;" bloat in the TableAdapter code was things like this:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;If Not row.IsFooFlagNull Then&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    ep.FooFlag = row.FooFlag&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;End If&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And all the other garbage syntax that TableAdapters require, including the already-more-verbose manual one-to-many code that has to be written.  Yuck - at least that's my opinion for this particular application of the technology.&lt;br /&gt;&lt;br /&gt;Not that I'm a Hibernate bigot - I have seen those scenarios where Hibernate simply falls down when dealing with massive amounts of objects, and I'll be the first to say "stored proc?"  (Well, maybe not the first.)  But for those that are dealing with .NET versions that don't support ORM yet, you really should consider NHibernate for your project.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-7095799176001424284?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/7095799176001424284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=7095799176001424284' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/7095799176001424284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/7095799176001424284'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/02/one-real-world-nhibernate-vs.html' title='One Real World NHibernate vs. TableAdapter comparison'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-8701844560595587057</id><published>2008-02-02T12:23:00.002-06:00</published><updated>2008-03-09T11:41:50.147-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='design'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>The wrong milk is coming out of my nose!</title><content type='html'>How many times have you grabbed the wrong type of milk and only noticed when you got home?  Don't you just hate that?  My regional grocer has &lt;span style="font-weight: bold;"&gt;22&lt;/span&gt; types of milk sold just under their label, and this type of packaging is sure to elicit some four letter words.  Here's a sample of the problem:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_lWbr1k8gyZ8/R6UulCtjRlI/AAAAAAAAAqo/x5FPPNwK7GU/s1600-h/classic_skim.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp2.blogger.com/_lWbr1k8gyZ8/R6UulCtjRlI/AAAAAAAAAqo/x5FPPNwK7GU/s320/classic_skim.jpg" alt="" id="BLOGGER_PHOTO_ID_5162583761768105554" border="0" /&gt;&lt;/a&gt; &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_lWbr1k8gyZ8/R6UwJitjRoI/AAAAAAAAArA/pULDnSKJ6ZI/s1600-h/classic_one.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp0.blogger.com/_lWbr1k8gyZ8/R6UwJitjRoI/AAAAAAAAArA/pULDnSKJ6ZI/s320/classic_one.jpg" alt="" id="BLOGGER_PHOTO_ID_5162585488344958594" border="0" /&gt;&lt;/a&gt; &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_lWbr1k8gyZ8/R6UvjitjRnI/AAAAAAAAAq4/RH_0LosGg48/s1600-h/classic_whole.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp0.blogger.com/_lWbr1k8gyZ8/R6UvjitjRnI/AAAAAAAAAq4/RH_0LosGg48/s320/classic_whole.jpg" alt="" id="BLOGGER_PHOTO_ID_5162584835509929586" border="0" /&gt;&lt;/a&gt;  &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_lWbr1k8gyZ8/R6UulStjRmI/AAAAAAAAAqw/b7mXYarU4GU/s1600-h/regular_skim.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp3.blogger.com/_lWbr1k8gyZ8/R6UulStjRmI/AAAAAAAAAqw/b7mXYarU4GU/s320/regular_skim.jpg" alt="" id="BLOGGER_PHOTO_ID_5162583766063072866" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Quick - grab a 1/2 gallon of non-RBGH skim for me, wouldja?  Oh, and your 3 year old is whining for some chocolate milk.   Better hope you don't grab the  juiced-up-cow version on accident, or even worse, the friggin &lt;span style="font-style: italic;"&gt;whole&lt;/span&gt; milk.&lt;br /&gt;&lt;br /&gt;So if there are any graphic designers out there looking for a foot in the door at a &lt;a href="http://www.lundsandbyerlys.com/"&gt;certain grocer&lt;/a&gt;, here's a good opportunity to show them the light.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-8701844560595587057?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/8701844560595587057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=8701844560595587057' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/8701844560595587057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/8701844560595587057'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2008/02/wrong-milk-is-coming-out-of-my-nose.html' title='The wrong milk is coming out of my nose!'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_lWbr1k8gyZ8/R6UulCtjRlI/AAAAAAAAAqo/x5FPPNwK7GU/s72-c/classic_skim.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-3732856904255241697</id><published>2007-11-30T18:27:00.001-06:00</published><updated>2007-11-30T23:16:03.476-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rails'/><category scheme='http://www.blogger.com/atom/ns#' term='capistrano'/><title type='text'>Capistrano on Site5</title><content type='html'>Capistrano makes deployment management easy, once it's configured correctly for the site you're working with.  My sites are hosted on site5...the configuration below is a basic example of a working site.  It doesn't have mongrel setup, but hopefully that part isn't too much harder after this. &lt;br /&gt;&lt;br /&gt;BTW - don't bother trying to get it running on windows/cygwin.  It's such a PITA, and I never even got it working, despite many many hours of trying and crying.   I eventually used VMWare workstation with an Ubuntu 7.1 installation as my OS.  There's some decent documentation out there to get the proper ruby/rails/gems/ and other supporting cast setup for *nix.  But site5 also has many required configuration quirks. &lt;br /&gt;&lt;br /&gt;So here's the page I created on their wiki:&lt;br /&gt;&lt;a href="http://wiki.site5.com/Example_Site5_Capistrano_Configuration"&gt;http://wiki.site5.com/Example_Site5_Capistrano_Configuration&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you find this useful, please pay it forward by keeping that wike page up to date.  Their sticky forum pages are a mess.  Even better would be a total step by step guide, since there's a lot of other steps that need to happen (covered by other guides)..but it'd be nice to have an all-in-one source somewhere.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-3732856904255241697?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/3732856904255241697/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=3732856904255241697' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/3732856904255241697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/3732856904255241697'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2007/11/capistrano-on-site5.html' title='Capistrano on Site5'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-4443269857365699021</id><published>2007-11-30T17:13:00.000-06:00</published><updated>2007-11-30T18:20:09.520-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='travel'/><title type='text'>The Best Care In The Air (but not on land)</title><content type='html'>Yeah, another jab at an airline's nonsensical customer service.  But rather than just whine about it, I thought I'd contrast actual  interactions between Midwest Airlines and Newegg.com.  Midwest, I love your plush leather seats and those oh-so-generous arm rests, but your operations area could learn a little something from the folks that grew Newegg from just another cut-throat online electronics competitor to today's best web retailer...&lt;br /&gt;&lt;br /&gt;Here's an email I sent to newegg a while back when their online system charged me a restock fee for a defective product I was returning:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);font-family:courier new;" class="nfakPe" &gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);font-family:courier new;" class="nfakPe" &gt;From&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);font-family:courier new;" &gt;: Dan &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);font-family:courier new;" &gt;Subject: RMA - 12345 - why restock fee for defective product?&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);font-family:courier new;" &gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Hi,&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;I just completed an RMA form for a DVD burner I'm returning for being defective.  Can you remove the restocking fee on the refund?  It seems wrong that I paid for shipping on this drive twice (here and back to you), and will have to pay for a restocking fee for a drive that's not working right, and then will also have to pay for shipping when I order a replacement burner from you (different brand - I don't want to get that same one).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Thanks,&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;Dan&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;/span&gt;And here's their reply:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(0, 0, 0);font-family:courier new;" &gt;Dear Customer,&lt;br /&gt;&lt;br /&gt;Thank you for contacting Newegg.&lt;br /&gt;&lt;br /&gt;Please kindly note that I have issued a credit of $4.87 to cover the cost for the restocking fee of RMA # 205XXX as this item is defective. We humbly apologize for this inconvenience and please allow your card issuer 3-5 business days to process and make the funds available.&lt;br /&gt;&lt;br /&gt;In addition, as you are our valued customer, I would like to extend our service by providing a shipping credit of $6.00 towards your next order. Please feel free to let us know by replying back to this email with your new order number so that we can issue the shipping credit onto your account, thank you in advance for your patience and understanding.&lt;br /&gt;&lt;br /&gt;If you have any further questions or concerns, please do not hesitate to contact us.&lt;br /&gt;&lt;br /&gt;Thank you,&lt;br /&gt;&lt;br /&gt;[&lt;span style="font-style: italic;"&gt;CSR's Name&lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(0, 0, 0);font-family:courier new;" &gt;&lt;/span&gt;&lt;/span&gt;Pretty cool, huh?  Now contrast that with a business trip that I'm on right now.  I should be flying home right now to avoid an oncoming snow storm that's about to hit Minneapolis tomorrow morning, but instead I'm in my hotel writing negative press about Midwest Airlines.  Here's the online chat I had with them yesterday:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(0, 0, 102);font-family:courier new;" &gt;Nick: Hello, welcome to Midwest Airlines Online Customer Service. This is Nick. How may I help you?&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 0, 0);font-family:courier new;" &gt;dan: hi, i'd like to fly back a day early for conf# MXBVBH...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 0, 0);font-family:courier new;" &gt;dan: the problem is that the rebooking fee is too high because of the fri/sat night stay restriction.  is it possible to get that number down to the $50 fee?&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);font-family:courier new;" &gt;Nick: Unfortunately not. The administrative fee on this ticket is $100 plus any difference in the fare.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);font-family:courier new;" &gt;dan: or even $150?  i can't authorize a full ticket purchase, and i'd much rather continue flying midwest in the future than NWA &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);font-family:courier new;" &gt;Nick: There's nothing that can be done about the fees. They are set in with the rules of the ticket.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);font-family:courier new;" &gt;dan: c'mon - you can do anything you want...this is my first experience with midwest with many more potential flights to/from MKE in the future, you have the space, and there's a storm coming saturday morning.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);font-family:courier new;" &gt;Nick: Which flight are you looking at changing it to?&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);font-family:courier new;" &gt;dan: anything friday evening or night would work&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);font-family:courier new;" &gt;Nick: It's an availability issue with the flights, which is why there is the high price. There's nothing we can do as we really don't have anything to work with.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);font-family:courier new;" &gt;dan: I see 50 seats available on the 9 o'clock flight...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);font-family:courier new;" &gt;Nick: You do not have the same advance purchase requirement that you got when the ticket was booked inititially.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);font-family:courier new;" &gt;dan: I'm now painfully aware of the arbitrary rules that are in place.  what i'm asking for is a minor exception to be made for a change that won't cost you anything, and will ensure more happy future business from me.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);font-family:courier new;" &gt;Nick: The only instance in which exceptions are made are in medical emergencies that we can verify. &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 0, 0);font-family:courier new;" &gt;dan: well, thanks for your time.  In the future, I'll be sure to choose another airline.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;Not so cool, huh?&lt;br /&gt;&lt;br /&gt;In newegg's case, they &lt;span style="font-weight: bold;"&gt;lost &lt;/span&gt;a little bit of money on the transaction, but the strategy has paid off well in the thousands of dollars I've spent there since.  Their management gives the customer service reps real authority and a simple guideline to make customers happy (within reason of course).&lt;br /&gt;In Midwest's case, they could have made an &lt;span style="font-weight: bold;"&gt;extra &lt;/span&gt;$150 and ensured my repeat business in the future.  No ticket price algorithms.  No artificial policy restrictions when talking to a customer. &lt;br /&gt;&lt;br /&gt;It's not altruism - it's business.  Making customers happy means more money for you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-4443269857365699021?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/4443269857365699021/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=4443269857365699021' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4443269857365699021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/4443269857365699021'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2007/11/best-care-in-air-but-not-on-land.html' title='The Best Care In The Air (but not on land)'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-1793438178967160973</id><published>2007-11-06T20:57:00.000-06:00</published><updated>2007-11-06T21:12:29.775-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='code'/><title type='text'>Oh, so this is how you use hibernate.</title><content type='html'>I've been using hibernate for a pretty long time (I was one of the micro donors to help them get hibernate.org), but it's always been a fairly black box to me.  It seems every time I use it for a project, I understand something that I was not-so-blissfully ignorant of in the past.  Today as I was writing some NHibernate mappings, I ran across this &lt;a href="http://ndpsoftware.com/HibernateMappingCheatSheet.html"&gt;cheatsheet&lt;/a&gt;.  It's a little out of date (substitute "role" with "name"), but it brings clarity in 30 seconds what the hibernate documentation rarely seems to do for me.  It's not that the hibernate docs are bad, it's just that there's so many minute details, and not enough simple samples.&lt;br /&gt;&lt;br /&gt;Anyway - kudos to the folks at NDP software.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-1793438178967160973?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1793438178967160973'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/1793438178967160973'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2007/11/oh-so-this-is-how-you-use-hibernate.html' title='Oh, so this is how you use hibernate.'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-6356202990208824436</id><published>2007-10-11T09:29:00.000-05:00</published><updated>2007-11-06T21:15:57.268-06:00</updated><title type='text'>more than $20 bucks?</title><content type='html'>My father-in-law has a running joke about how much things cost. "Is it more than $20 bucks?" is the question.  The objects in question are things like boats and rooms at four star hotels.  It's a good way to break the ice and have a jolly conversation with someone.&lt;br /&gt;&lt;br /&gt;I couldn't help but think of that today as I was asked to take a look at my state's request for proposal (RFP) for a one-license-processing-system-to-rule-them-all.  Whoever created the plans for the system is well-versed in the latest industry buzzwords - there's workflow, ESB, hub and spoke, document management, and a whole slew of other systems to be built within this gargantuan vision.  Can you imagine one system being built in a state government to handle all 500 different types of licenses possible, replacing the 60 systems that are currently in place?  From barber to corrections officer to a license to work with peat - it's all lumped together.&lt;br /&gt;&lt;br /&gt;Back to my original amusing observation...on the state's public overview page describing each RFP, here's their estimated cost:&lt;br /&gt;&lt;span class="bodymain"&gt;&lt;span class="bodymain"&gt;&lt;span class="bodymain"&gt;&lt;span class="bodymain"&gt;&lt;span class="bodymain"&gt;&lt;span class="bodymain"&gt;&lt;b&gt;Estimated Cost:&lt;/b&gt;    Over $50,000&lt;br /&gt;&lt;br /&gt;My SWAG - solid seven digit figure.   &lt;a href="http://resources.bravenet.com/audio_clips/comedy_clips/beavis__butthead_-_the_famous_laugh/listen/"&gt;More than $20 bucks?&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="bodymain"&gt;&lt;span class="bodymain"&gt;&lt;span class="bodymain"&gt;&lt;span class="bodymain"&gt;&lt;span class="bodymain"&gt;&lt;span class="bodymain"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-6356202990208824436?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/6356202990208824436'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/6356202990208824436'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2007/10/more-than-20-bucks.html' title='more than $20 bucks?'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-6179958794694518483.post-7154474899399986072</id><published>2007-09-25T15:27:00.000-05:00</published><updated>2007-09-25T15:37:06.652-05:00</updated><title type='text'>someday/maybe - shower</title><content type='html'>So I just started a new job, and my todo list is huge.   Whenever I start a new job, one of the things I like to do is figure out where I can shower after biking in.  Makes for a slightly amusing GTD-style list entry on a phone without a full keyboard.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6179958794694518483-7154474899399986072?l=otherthanthink.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://otherthanthink.blogspot.com/feeds/7154474899399986072/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6179958794694518483&amp;postID=7154474899399986072' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/7154474899399986072'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6179958794694518483/posts/default/7154474899399986072'/><link rel='alternate' type='text/html' href='http://otherthanthink.blogspot.com/2007/09/somedaymaybe-shower.html' title='someday/maybe - shower'/><author><name>Dan Tanner</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp2.blogger.com/_lWbr1k8gyZ8/R9QWbX6nihI/AAAAAAAAAus/pBQgBS_MIAQ/S220/050904_133.jpg'/></author><thr:total>0</thr:total></entry></feed>
