<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:media="http://search.yahoo.com/mrss/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Something Smells</title><link>http://blog.agilejedi.com/</link><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/SomethingSmells" /><description>Agile Methods and Software Engineering...</description><language>en</language><managingEditor>noreply@blogger.com (Orlando Giovanni)</managingEditor><lastBuildDate>Mon, 08 Feb 2010 11:30:23 PST</lastBuildDate><generator>Blogger http://www.blogger.com</generator><openSearch:totalResults xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">40</openSearch:totalResults><openSearch:startIndex xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">1</openSearch:startIndex><openSearch:itemsPerPage xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/">25</openSearch:itemsPerPage><feedburner:info uri="somethingsmells" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><media:category scheme="http://www.itunes.com/dtds/podcast-1.0.dtd">Technology/Software How-To</media:category><itunes:owner><itunes:email>noreply@blogger.com</itunes:email><itunes:name>Dan Pupek</itunes:name></itunes:owner><itunes:author>Dan Pupek</itunes:author><itunes:explicit>no</itunes:explicit><itunes:subtitle>Agile Methods and Software Engineering...</itunes:subtitle><itunes:category text="Technology"><itunes:category text="Software How-To" /></itunes:category><item><title>COBOL.Net is NUTS!!</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/sUKQjVxPxj8/cobolnet-is-nuts.html</link><category>COBOL</category><category>software engineering</category><category>C#</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Wed, 02 Sep 2009 19:54:57 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-8957582135831533902</guid><description>Just read an &lt;a href="http://www.codinghorror.com/blog/archives/001294.html"&gt;article about COBOL.Net&lt;/a&gt;.....who would really want to subject themselves to this horror.&lt;br /&gt;&lt;br /&gt;Let's take the sample code in C#:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;private void button1_Click(object sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;   button1.Text = "Call COBOL";&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Now here is the same method in COBOL:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;METHOD-ID. button1_Click PRIVATE.&lt;br /&gt;DATA DIVISION.&lt;br /&gt;LINKAGE SECTION.&lt;br /&gt;01 sender OBJECT REFERENCE CLASS-OBJECT.&lt;br /&gt;01 e OBJECT REFERENCE CLASS-EVENTARGS.&lt;br /&gt;PROCEDURE DIVISION USING BY VALUE sender e.&lt;br /&gt;   SET PROP-TEXT OF button1 TO "Call COBOL".&lt;br /&gt;END METHOD button1_Click.&lt;br /&gt;&lt;/pre&gt;Am I the only one that finds this maddening. OK, OK, for the record there are still more lines of COBOL running then any other language. It could be that COBOL is just that great or it could be the fear of re-engineering systems are working just fine.&lt;br /&gt;&lt;br /&gt;Any thoughs?&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-8957582135831533902?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/uLXwhAcoL_0LAHcIUvI2aJhcXNM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uLXwhAcoL_0LAHcIUvI2aJhcXNM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/uLXwhAcoL_0LAHcIUvI2aJhcXNM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/uLXwhAcoL_0LAHcIUvI2aJhcXNM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=sUKQjVxPxj8:jKaekkOApxk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=sUKQjVxPxj8:jKaekkOApxk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?i=sUKQjVxPxj8:jKaekkOApxk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=sUKQjVxPxj8:jKaekkOApxk:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=sUKQjVxPxj8:jKaekkOApxk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?i=sUKQjVxPxj8:jKaekkOApxk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=sUKQjVxPxj8:jKaekkOApxk:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/sUKQjVxPxj8" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-03T05:54:57.600+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total><feedburner:origLink>http://blog.agilejedi.com/2009/09/cobolnet-is-nuts.html</feedburner:origLink></item><item><title>Refactoring: Means versus Ends</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/lBuiGaIKuII/refactoring-means-versus-ends.html</link><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Thu, 06 Aug 2009 21:21:36 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-8875256783980215862</guid><description>First, I see 2 reasons to refactor:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Improve performance&lt;/li&gt;&lt;li&gt;Make code easier to maintain (and extend)&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Most other "&lt;a href="http://rpsetzer.blogspot.com/2006/10/reasons-to-refactor-your-code.html"&gt;reasons&lt;/a&gt;" that people use to justify refactoring are only a means to one of the 2 ends stated above. If you aren't ultimately reaching one of those ends, then reconsider refactoring. If your changes are to the detriment of one of these 2 means, &lt;span style="font-weight: bold;"&gt;then don't refactor&lt;/span&gt;. In fact cargo cult refactoring can be more harmful than helpful.&lt;br /&gt;&lt;br /&gt;Think about these:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Not all duplication is bad. Some blocks of code are more self explanatory then an oddly named method that wraps it. Saving 6 lines of code may come at the cost of flexibility and higher levels of coupling. &lt;/li&gt;&lt;li&gt;Overly abstract code can become highly unmaintainable, even cryptic. In an effort to write more concise code we inadvertently write less concise code. Specialization can be a good thing. &lt;a href="http://www.joelonsoftware.com/items/2008/05/01.html"&gt;Astronaut APIs&lt;/a&gt; can be bad.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;and of course...&lt;a href="http://www.c2.com/cgi/wiki?PrematureOptimization"&gt;premature optimization&lt;/a&gt; is the &lt;a href="http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf"&gt;root of all evil&lt;/a&gt;!&lt;/li&gt;&lt;/ol&gt;Just a few things to think about...&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-8875256783980215862?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/R0I5EQXPx3qfurPviU8q87UWPEY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/R0I5EQXPx3qfurPviU8q87UWPEY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/R0I5EQXPx3qfurPviU8q87UWPEY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/R0I5EQXPx3qfurPviU8q87UWPEY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=lBuiGaIKuII:GEVgSO0AXec:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=lBuiGaIKuII:GEVgSO0AXec:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?i=lBuiGaIKuII:GEVgSO0AXec:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=lBuiGaIKuII:GEVgSO0AXec:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=lBuiGaIKuII:GEVgSO0AXec:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?i=lBuiGaIKuII:GEVgSO0AXec:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=lBuiGaIKuII:GEVgSO0AXec:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/lBuiGaIKuII" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-07T07:21:36.918+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.agilejedi.com/2009/08/refactoring-means-versus-ends.html</feedburner:origLink></item><item><title>Ridding Your Garden of Bugs: Gardening the Backlog</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/pSjW5oNBUG4/ridding-your-garden-of-bugs-gardening.html</link><category>extreme programming</category><category>Project Management</category><category>Backlog Management</category><category>agile development</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Wed, 25 Mar 2009 21:04:48 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-6671310664585152131</guid><description>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;&lt;span style='border-collapse: separate; color: rgb(0, 0, 0); font-family: arial; font-size: 13px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;' class='Apple-style-span'&gt;&lt;div&gt;I'm not sure if I agree with this "&lt;a href='http://ayende.com/Blog/archive/2009/03/24/microsoft-connect-fail-yet-again.aspx'&gt;article&lt;/a&gt;" but, it is somewhat related to a discussion my boss (Dr. Rob Miller) and I were having earlier today. Ideally, we would like to focus every third (I just picked a number) release on "bug hunting" or finding and fixing bugs. Unfortunately, bugs are often a debt we live with for a long time, in the face of progress and new features. I have known few products that didn't have some glitch and the promise of new features often takes some of the edge off of these glitches.&lt;/div&gt;&lt;div&gt;&lt;br/&gt;&lt;/div&gt;&lt;div&gt;Conversely, some bugs can leave users with such a bad taste that they never quite trust your software again. In the article above the author describes a bug that was reported fixed but still remains broken....after 2 years. Furthermore, as more bugs slip through the cracks a system can slowly become more and more unstable.&lt;br/&gt;&lt;br/&gt;This suggests that, when planning product releases, stakeholders should balance the need for new features with the need for a stable system. I believe that, by better "gardening" a product's backlog, most products can avoid these pitfalls. So, here are a few points to consider when gardening your backlogs:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Are stakeholders keeping and gardening personal backlogs? When I say, "personal backlog" I am referring to the features, enhancement and bugs that each stakeholder or program manager would like to see implemented. At every release planning meeting these "personal backlogs" should be gardened and brought to the table for consideration in the "product backlog". &lt;br/&gt;&lt;/li&gt;&lt;li&gt;What have users been promised (explicitly or implicitly) and what is the impact of leaving those promises unfulfilled?&lt;/li&gt;&lt;li&gt;Do you know how "real" users feel about your software? How do you collect this information? Sometimes, we get ONE very vocal user (see above). Sometimes we have a quiet majority. When should a user's/client's opinions impact the requirements for a release?&lt;/li&gt;&lt;li&gt;When is a "bug hunting" expedition called for? Is there some threshold or event horizon? Do we have a good litmus test?&lt;/li&gt;&lt;li&gt;Finally, is there a single decision maker (&lt;a href='http://www.infoq.com/news/2009/02/product-owner-one-person' target='_blank'&gt;the one ringable neck&lt;/a&gt;) for the product backlog? Someone to take all of the personal backlogs and prioritize them. In XP this would be the&lt;span class='Apple-converted-space'&gt; &lt;/span&gt;&lt;a href='http://c2.com/cgi/wiki?OnsiteCustomer'&gt;On Site Customer&lt;/a&gt;&lt;span class='Apple-converted-space'&gt; &lt;/span&gt;and in SCRUM this would be the&lt;span class='Apple-converted-space'&gt; &lt;/span&gt;&lt;a href='http://www.mountaingoatsoftware.com/product-owner'&gt;Product Owner&lt;/a&gt;. I suggest that it NEVER be your development team. This person maintains the backlog, the &lt;a href='http://blog.agilejedi.com/2007/03/5-levels-of-planning-i-just-read.html' target='_blank'&gt;vision &lt;/a&gt;and the &lt;a href='http://blog.agilejedi.com/2007/03/5-levels-of-planning-i-just-read.html' target='_blank'&gt;roadmap&lt;/a&gt;.&lt;br/&gt;&lt;/li&gt;&lt;/ul&gt; It's not likely that you will squash all the bugs in any &lt;a href='http://bugsareeasy.wordpress.com/2009/01/03/abstraction-101-making-sense-of-complex-systems/' target='_blank'&gt;non-trivial system&lt;/a&gt; without writing some&lt;span class='Apple-converted-space'&gt; &lt;/span&gt;&lt;a href='http://thedailywtf.com/Articles/Writing_Bugfree_software.aspx'&gt;questionable code&lt;/a&gt;. So, you should take the time to test drive your software. Also, watch others "test drive" your software. This advice is not just for developers. In fact it's doubly important for non-developer stake holders and Decision Makers to "test-drive" the software. Kick the tires, check all the instruments. How's the suspension? Is it idling rough? Take it to a mechanic (engineer) and see if any maintenance is due (&lt;a href='http://onstartups.com/home/tabid/3339/bid/165/Development-Short-Cuts-Are-Not-Free-Understanding-Technology-Debt.aspx'&gt;technology debt&lt;/a&gt;). Next time you prioritize your backlog you may have a different perspective.&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;div&gt;Taking the time to garden your backlog will leave you&lt;span class='Apple-converted-space'&gt; &lt;/span&gt;&lt;a href='http://www.wildcat-adventures.com/images/gardens.jpg'&gt;smelling like roses&lt;/a&gt;. While just letting things grow out of control could have you&lt;span class='Apple-converted-space'&gt; &lt;/span&gt;&lt;a href='http://images.google.com/imgres?imgurl=http://lh4.google.com/kkettler/Rq_6ukq6htI/AAAAAAAABvs/iJ-6fnLMR0k/s400/July%252029,%25202007%2520730.jpg&amp;amp;imgrefurl=http://iwetmyplants.com/2007/08/&amp;amp;usg=__BEd8WHZfLOtvUXp2mTE96r762C4=&amp;amp;h=300&amp;amp;w=400&amp;amp;sz=52&amp;amp;hl=en&amp;amp;start=10&amp;amp;sig2=AH0KWA7hOOJiwHeM1iN1nQ&amp;amp;um=1&amp;amp;tbnid=dAEythp1BcBYAM:&amp;amp;tbnh=93&amp;amp;tbnw=124&amp;amp;prev=/images%3Fq%3Ddigging%2Bup%2Bweeds%26hl%3Den%26rlz%3D1B3GGGL_enUS215US215%26sa%3DG%26um%3D1&amp;amp;ei=pvTKSYHVHNa9twfp0pHmCQ'&gt;digging in the weed&lt;/a&gt;s!&lt;/div&gt;&lt;/span&gt;&lt;div class='blogger-post-footer'&gt;&lt;script type='text/javascript'&gt;&lt;br/&gt;&lt;/script&gt;&lt;br/&gt;&lt;script type='text/javascript'&gt;&lt;br/&gt;src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&amp;gt;&lt;br/&gt;&lt;/script&gt;&lt;/div&gt;&lt;div class='blogger-post-footer'&gt;&lt;script type='text/javascript'&gt;&lt;br/&gt;&lt;/script&gt;&lt;br/&gt;&lt;script type='text/javascript'&gt;&lt;br/&gt;src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&amp;gt;&lt;br/&gt;&lt;/script&gt;&lt;/div&gt;&lt;br/&gt;&lt;br/&gt;&lt;div class='zemanta-pixie'&gt;&lt;img src='http://img.zemanta.com/pixy.gif?x-id=4c2aa5ef-b325-44f8-827b-e60cb5323f1e' class='zemanta-pixie-img'/&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-6671310664585152131?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/WFiTQKXIJQDopmH65mgoIcPs07Y/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WFiTQKXIJQDopmH65mgoIcPs07Y/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/WFiTQKXIJQDopmH65mgoIcPs07Y/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/WFiTQKXIJQDopmH65mgoIcPs07Y/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=pSjW5oNBUG4:rzgt9I4gyec:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=pSjW5oNBUG4:rzgt9I4gyec:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?i=pSjW5oNBUG4:rzgt9I4gyec:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=pSjW5oNBUG4:rzgt9I4gyec:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=pSjW5oNBUG4:rzgt9I4gyec:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?i=pSjW5oNBUG4:rzgt9I4gyec:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=pSjW5oNBUG4:rzgt9I4gyec:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/SomethingSmells?a=pSjW5oNBUG4:rzgt9I4gyec:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/SomethingSmells?i=pSjW5oNBUG4:rzgt9I4gyec:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/pSjW5oNBUG4" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-26T07:04:48.772+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.agilejedi.com/2009/03/ridding-your-garden-of-bugs-gardening.html</feedburner:origLink></item><item><title>Profiling Nhibernate</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/kiSSk0ZqAsM/profiling-nhibernate.html</link><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Tue, 03 Feb 2009 21:07:53 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-732396718373769958</guid><description>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;I recently purchased 4 licenses of &lt;a href='http://ayende.com/Blog/Default.aspx' target='_blank'&gt;Ayenda's&lt;/a&gt; excellent &lt;a href='http://nhprof.com/' target='_blank'&gt;Nhibernate Profiler&lt;/a&gt; for my office. The tool truly is amazing. The real time metrics provided by the profiler have already helped us improve the performance of our applications and identify some not very efficient database calls.&lt;br/&gt;&lt;br/&gt;Here are a few features that we really like:&lt;br/&gt;&lt;ul&gt;&lt;li&gt;Realtime view of queries being sent to the database. This information includes a stack trace and properly formated SQL! You also get to see if the entities were pulled from the query cache, level 2 cache or directly from the database. The SQL view can really expose some nasty databse calls.&lt;br/&gt;&lt;/li&gt;&lt;li&gt;Number of sessions opened. The queries are broken down by session. You can see how many queries each session makes and a mirad of statistics.&lt;/li&gt;&lt;li&gt;Unique Query statistics. NH Profiler offers an aggregate view of how often each query was called and the average time it took. This is invauable information for improving performance.&lt;/li&gt;&lt;/ul&gt;This tool offers a ton of other features that we haven't even touched. If you use Nhibernate or ActiveRecord (as we do) I highly recommend you pay the fee and get a copy. You'll also be helping out a brilliant programmer (Oren Eini).&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-732396718373769958?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/IgM2heu0kHVF_RVyqCPNYrBrUH4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/IgM2heu0kHVF_RVyqCPNYrBrUH4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/IgM2heu0kHVF_RVyqCPNYrBrUH4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/IgM2heu0kHVF_RVyqCPNYrBrUH4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=2Dfa7btu"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=PIaU8Q5y"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=PIaU8Q5y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=cBlD9lZr"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=hJnbu2YD"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=hJnbu2YD" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=XNZA9No6"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=ybVyxAkM"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=ybVyxAkM" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/kiSSk0ZqAsM" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-04T08:07:53.475+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.agilejedi.com/2009/02/profiling-nhibernate.html</feedburner:origLink></item><item><title>AAAA Unit Testing</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/E9gvOYR6RBw/aaaa-unit-testing.html</link><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Fri, 26 Dec 2008 15:46:25 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-5003073555381830059</guid><description>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;A while back &lt;a href='http://ayende.com/Blog' target='_blank'&gt;Oren &lt;/a&gt;wrote about the &lt;a href='http://ayende.com/Blog/archive/2008/05/16/Rhino-Mocks--Arrange-Act-Assert-Syntax.aspx' target='_blank'&gt;Arrange, Act, Assert&lt;/a&gt; syntax for unit tests. I've seen several other discussions on this and I am not sure if he is the originator but I'll attribute him either way.&lt;br/&gt;&lt;br/&gt;The syntax I most commonly use ressembles an Arrange, Assert, Act and Assert (AAAA) pattern.&lt;br/&gt;&lt;ul&gt;&lt;li&gt;Arrange the system in it's initial configuration. Create any collaborators and mocks you may need. Initialize services.&lt;/li&gt;&lt;li&gt;Assert that the initial state is correct. For me this is important since so many layer of dependencies exist in modern applications. This is analogous to a control group in the scientific method. In this step I would also test the inverse of later assertion such as the non-existence of objects that should only exist after the Act step.&lt;/li&gt;&lt;li&gt;Act on the system by creating/deleting/updating new objects or invoking services.&lt;/li&gt;&lt;li&gt;Assert again that the system is in it's expected state.&lt;/li&gt;&lt;/ul&gt;I've caught a lot of bugs using this method. Asserting the initial state may also be a good way to expose weakness' in the design. &lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-5003073555381830059?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/edEQNwlj769YL0dbcEG9RTv03lY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/edEQNwlj769YL0dbcEG9RTv03lY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/edEQNwlj769YL0dbcEG9RTv03lY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/edEQNwlj769YL0dbcEG9RTv03lY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=uGs0VjBf"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=Of0eiPQD"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=Of0eiPQD" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=SRN15uaB"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=TD7kv07r"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=TD7kv07r" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=6DkIgTsn"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=nBc0ksif"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=nBc0ksif" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/E9gvOYR6RBw" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-27T02:46:25.936+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/12/aaaa-unit-testing.html</feedburner:origLink></item><item><title>Memcached for Monorail Update</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/MJfu6HRshq4/memcached-for-monorail-update.html</link><category>monorail</category><category>memcached</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Mon, 01 Dec 2008 21:03:24 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-4325688859529347747</guid><description>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;Memcached for Monorail is a session replacement for the Castle::Monorail framework. It uses memcached on the back end for distributing the session across a web farm. I have added some additional notes about &lt;a target="_blank" href="http://code.google.com/p/libagilejedi/wiki/MemcachedForMonorail?ts=1228193463&amp;amp;updated=MemcachedForMonorail"&gt;Memcached for Monorail&lt;/a&gt;. I have also uploaded a &lt;a href="http://code.google.com/p/libagilejedi/downloads/list" target="_blank"&gt;binary release&lt;/a&gt;. Although I recommend getting the &lt;a href="http://code.google.com/p/libagilejedi/source/checkout" target="_blank"&gt;source&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;No time to discuss much more but feel free to ask questions and I'll answer them. The Memcached session provider is currently being used in a production environment with great success but it definitely has room for improvement. It's aimed squarely at extending the &lt;a href="http://www.castleproject.org/MonoRail/" target="_blank"&gt;Castle::Monorail&lt;/a&gt; session so if you are looking for something more generic than please look else where...or consider switching to MVC with &lt;a href="http://www.castleproject.org/MonoRail/" target="_blank"&gt;Castle::Monorail&lt;/a&gt; ;-)&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-4325688859529347747?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/AoOWP1UXLWZq7Ed9D6saN75in_k/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AoOWP1UXLWZq7Ed9D6saN75in_k/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/AoOWP1UXLWZq7Ed9D6saN75in_k/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AoOWP1UXLWZq7Ed9D6saN75in_k/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=nF2XDQ7s"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=G6UjdlT8"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=G6UjdlT8" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=BCUGbAA1"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=qOAvizZr"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=qOAvizZr" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=KlQF8GwV"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=MLtCOoQm"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=MLtCOoQm" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/MJfu6HRshq4" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-02T08:03:24.749+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/12/memcached-for-monorail-update.html</feedburner:origLink></item><item><title>Monorail installed on a 64bit OS</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/dKVm5ox6QeE/monorail-installed-on-64bit-os.html</link><category>IIS Monorail CastleProject</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Mon, 01 Dec 2008 13:51:19 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-5477284494271986071</guid><description>Installing &lt;a href="http://www.castleproject.org/MonoRail/"&gt;Castle::Monorail&lt;/a&gt; on 64bit IIS7 proves to be much easier than I thought. You must use the 64bit handlers. To make this easy you can just add the handlers to your Web.Config:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div    style="background: white none repeat scroll 0% 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Courier New;font-size:10pt;color:black;"&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  136&lt;/span&gt; &lt;span style="color:blue;"&gt;  &lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;system.webServer&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;&lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  137&lt;/span&gt; &lt;span style="color:blue;"&gt;    &lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;handlers&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;&lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  138&lt;/span&gt; &lt;span style="color:blue;"&gt;      &lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;add&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;name&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;IconHandler&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;path&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;*.ico&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;verb&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;*&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;modules&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;StaticFileModule&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;resourceType&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;File&lt;/span&gt;"&lt;span style="color:blue;"&gt; /&gt;      &lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  139&lt;/span&gt; &lt;span style="color:blue;"&gt;      &lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;add&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;name&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;Monorail-64&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  140&lt;/span&gt; &lt;span style="color:blue;"&gt;           &lt;/span&gt;&lt;span style="color:red;"&gt;path&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;*&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;verb&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;*&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  141&lt;/span&gt; &lt;span style="color:blue;"&gt;           &lt;/span&gt;&lt;span style="color:red;"&gt;modules&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;IsapiModule&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  142&lt;/span&gt; &lt;span style="color:blue;"&gt;           &lt;/span&gt;&lt;span style="color:red;"&gt;scriptProcessor&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  143&lt;/span&gt; &lt;span style="color:blue;"&gt;           &lt;/span&gt;&lt;span style="color:red;"&gt;resourceType&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;Unspecified&lt;/span&gt;"&lt;span style="color:blue;"&gt; /&gt;&lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  144&lt;/span&gt; &lt;span style="color:blue;"&gt;      &lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;add&lt;/span&gt;&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;name&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;Monorail&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  145&lt;/span&gt; &lt;span style="color:blue;"&gt;           &lt;/span&gt;&lt;span style="color:red;"&gt;path&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;*&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;span style="color:red;"&gt;verb&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;*&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  146&lt;/span&gt; &lt;span style="color:blue;"&gt;           &lt;/span&gt;&lt;span style="color:red;"&gt;modules&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;IsapiModule&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  147&lt;/span&gt; &lt;span style="color:blue;"&gt;           &lt;/span&gt;&lt;span style="color:red;"&gt;scriptProcessor&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll&lt;/span&gt;"&lt;span style="color:blue;"&gt; &lt;/span&gt;&lt;/pre&gt; &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  148&lt;/span&gt; &lt;span style="color:blue;"&gt;           &lt;/span&gt;&lt;span style="color:red;"&gt;resourceType&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;"&lt;span style="color:blue;"&gt;Unspecified&lt;/span&gt;"&lt;span style="color:blue;"&gt; /&gt;&lt;/span&gt;&lt;/pre&gt;  &lt;pre style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;  149&lt;/span&gt; &lt;span style="color:blue;"&gt;    &lt;!--&lt;/span--&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;handlers&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;&lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;&lt;br /&gt;150&lt;/span&gt; &lt;span style="color:blue;"&gt;  &lt;!--&lt;/span--&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;system.webServer&lt;/span&gt;&lt;span style="color:blue;"&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt; &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;As you can see above, I have added handler mappings for both the 64bit and the 32bit. Notice that the 64bit is listed first, this is important. The 64bit script processor is:&lt;br /&gt;&lt;br /&gt;&lt;pre style="margin: 0px;"&gt;&lt;span style="color:blue;"&gt;%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;A more detailed overview can be found at &lt;a href="http://wiki.bittercoder.com/Default.aspx?Page=ConfiguringMonorailOnIIS7&amp;amp;AspxAutoDetectCookieSupport=1"&gt;BitterCoder&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-5477284494271986071?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/RDChGYyn5KzFVThiVIvzsCdtYKE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RDChGYyn5KzFVThiVIvzsCdtYKE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/RDChGYyn5KzFVThiVIvzsCdtYKE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/RDChGYyn5KzFVThiVIvzsCdtYKE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=1NS2fYYb"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=I5i4Rlef"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=I5i4Rlef" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=xF5GXh2W"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=i32dcTia"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=i32dcTia" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=4c2KtOHy"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=U10XG4yX"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=U10XG4yX" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/dKVm5ox6QeE" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-02T00:51:19.621+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/12/monorail-installed-on-64bit-os.html</feedburner:origLink></item><item><title>Javascript: Equality versus Identity</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/iPmEMMDaNZA/javascript-equality-versus-identity.html</link><category>javascript</category><category>software engineering</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Tue, 14 Oct 2008 04:33:36 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-7821512309558157273</guid><description>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;Javascript has 2 basic forms of &lt;a href="http://www.w3schools.com/JS/js_comparisons.asp" target="_blank"&gt;comparison operators&lt;/a&gt;: &lt;span style="font-family:Courier New;"&gt;===&lt;/span&gt; and &lt;span style="font-family:Courier New;"&gt;==&lt;/span&gt; .&lt;span style="font-family:Courier New;"&gt;==&lt;/span&gt; is the standard equality operator while &lt;span style="font-family:Courier New;"&gt;===&lt;/span&gt; is the identity operator. The equality operator will perform casting and usually test both sides as strings. The identity operator compares the value each side the type, but it does not work like instanceof.&lt;br /&gt;&lt;br /&gt;Recently we did some experiments with the different return values.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Expressions&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;table style="width: 707px; height: 322px;" border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-weight: bold;"&gt;Expression&lt;br /&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-weight: bold;"&gt;Result&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;"test" == "test"&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;true&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;"test" === "test"&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;true&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;String("test") === "test"&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;true&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;new String("test") == "test"&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;true&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;new String("test") === "test"&lt;/small&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New; color: rgb(255, 0, 0);"&gt;&lt;small&gt;false&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;new String("test") === new String("test")&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;Before Firefox 3.0.1: true&lt;br /&gt;After: &lt;span style="color: rgb(255, 0, 0);"&gt;false&lt;/span&gt;&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;new String("test") === String("test")&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New; color: rgb(255, 0, 0);"&gt;&lt;small&gt;false&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Here are some type tests we performed&lt;/span&gt;&lt;br /&gt;&lt;table style="width: 694px; height: 232px;" border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-weight: bold;"&gt;Expression&lt;br /&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-weight: bold;"&gt;Type&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;typeof("test")&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;"string"&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;typeof(String("test"))&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;"string"&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;typeof(new String("test"))&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;"object"&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;typeof(function(){})&lt;br /&gt;&lt;/small&gt;&lt;/td&gt;&lt;td style="width: 50%; height: 12%; font-family: Courier New;"&gt;&lt;small&gt;"function"&lt;/small&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What Did we Learn?&lt;/span&gt;&lt;br /&gt;First we see that a string is not always a string. Sometimes it's an object. It's easy to forget that Javascript still has the concept of primitives and objects. Integers, Strings and a few others are all primitives. When using the identity operator (===) you have to assume that it is comparing the value of the variable and it's type (as returned by typeof). Further compounding this is the fact that new String() does not type to a "STRING", while calling String as a function does.&lt;br /&gt;&lt;br /&gt;What this all suggests is that when dealing with primatives you might as well use the equality operator (==). If you feel it's safer to use the identity operator (===) then you should use &lt;span style="font-family:Courier New;"&gt;String()&lt;/span&gt; as a function and &lt;span style="font-weight: bold;"&gt;never &lt;/span&gt;use &lt;span style="font-family:Courier New;"&gt;new String()&lt;/span&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-7821512309558157273?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rl6PDUc0Ik6d4lyRCDZvPIFai48/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rl6PDUc0Ik6d4lyRCDZvPIFai48/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rl6PDUc0Ik6d4lyRCDZvPIFai48/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rl6PDUc0Ik6d4lyRCDZvPIFai48/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=M07MDzKR"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=Co1PnMpM"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=Co1PnMpM" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=YUBx7q56"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=c5bvIyVT"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=c5bvIyVT" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=hgENpKsc"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=dKhBXpzn"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=dKhBXpzn" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/iPmEMMDaNZA" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-14T14:33:36.204+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/09/javascript-equality-versus-identity.html</feedburner:origLink></item><item><title>Hire the Right People</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/JKmW0NmHp3s/hire-right-people.html</link><category>Hiring Practices</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Tue, 12 Aug 2008 20:24:06 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-1127777773474434649</guid><description>&lt;div style="font-family: arial;" xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;span&gt;I believe my team of engineers has been very successful. This is no accident. I look for, and like to, surround myself with smart people. I'm not being egotistical. I don't consider myself the sharpest tool in the shed, but I do know a sharp tool (smart engineer) when I talk to one.&lt;br /&gt;&lt;br /&gt;Hiring the right person is harder than it sounds. The top two impediments, in my experience, to hiring the right person have been "&lt;span style="font-style: italic;"&gt;Hiring People that are Non-Threatening&lt;/span&gt;" and "&lt;span style="font-style: italic;"&gt;knowing nothing about the job you are hiring for&lt;/span&gt;."&lt;br /&gt;&lt;br /&gt;Non-threatening can mean a lot of things. A non-threatening person can be a yes-man. Yes-men will agree with you on everything and never make you uncomfortable by pointing out flaws in your plan. Yes-men are often hired on the basis of philosophy rather than actual skill. Non-threatening people can also be that dull-tool that won't outshine the person who hired them. In both cases the company is stuck paying wages to an under performer.&lt;br /&gt;&lt;br /&gt;More often, though, I have seen poor hiring decisions made by managers that have no idea how to judge candidates for a job. These managers tend to rely heavily on applicants' resumes and sets of nebulous questions about work ethic or previous projects. Lacking a basic understanding of engineering practices and what makes a good engineer, these managers usually hire based on a feeling.&lt;br /&gt;&lt;br /&gt;So, how do I hire....smart people? First, I give a basic skills test. I actually test each applicant on basic problem solving skills using pseudo code. If they do well on the test, then I send them a practical exercise. I look for three things in the practical exercise: how well they followed the  directions, coding style, and does it work.&lt;br /&gt;&lt;br /&gt;The test and exercise help me weed out those applicants whose time would be wasted on an interview. If I am happy with the test and the practical exercise, I schedule an interview. I'm also a true believer in team buy-in on all new hires so I get as many engineers involved in the interview as we can afford.&lt;br /&gt;&lt;br /&gt;The interview includes some basic questions about relocating and what technologies the applicant is interested in, but the real meat of the interview is a set of problems the applicant must solve,  interactively, on a white board.  The problem solving progresses, "lecture style," with the applicant lecturing us on how the problems could best be solved.&lt;br /&gt;&lt;br /&gt;Engineers are free to ask questions and the applicant is encouraged to show all his work. After the interview, I discuss the applicant with the other engineers and prepare for the next interview.&lt;br /&gt;&lt;br /&gt;Once we have an adequate pool, we all sit down together to review, compare and contrast all the applicants.&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-1127777773474434649?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/f2oHw24E5JWrTmNq1-_6EBAcf_M/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/f2oHw24E5JWrTmNq1-_6EBAcf_M/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/f2oHw24E5JWrTmNq1-_6EBAcf_M/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/f2oHw24E5JWrTmNq1-_6EBAcf_M/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=h2iPoXSn"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=UutNtMps"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=UutNtMps" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=U3lHOpvL"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=BhdXGMzq"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=BhdXGMzq" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=kh0ftHSH"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=lg1mK1rG"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=lg1mK1rG" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/JKmW0NmHp3s" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-13T06:24:06.939+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/08/hire-right-people.html</feedburner:origLink></item><item><title>Watin Installed</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/n455ijOUCAk/watin-installed.html</link><category>tools</category><category>test driven development</category><category>extreme programming</category><category>watin</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Tue, 05 Aug 2008 22:12:05 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-8562434278374751056</guid><description>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;I've spent the last few days getting our testers up to speed on &lt;a target="_blank" href="http://watin.sourceforge.net/"&gt;Watin&lt;/a&gt;. Watin is an Automated Web Acceptance Test Tool We are using &lt;a target="_blank" href="http://sourceforge.net/project/showfiles.php?group_id=167632&amp;amp;package_id=266951"&gt;Watin CTP v2.0&lt;/a&gt;. So far I have learned a few things about Watin that I didn't know when I wrote my original Watin Review. If you are completely unfamiliar with Watin I recommend you read &lt;a href="http://blog.agilejedi.com/2008/02/webtest-tool-round-up-round-1watin.html" &gt;my review&lt;/a&gt; first.&lt;br /&gt;&lt;br /&gt;Our descision to go with Watin was based on 4 factors. (1) Watin handles AJAX applications very well, (2) Watin doesn't inject Javascript into your code, (3) Watin supports Firefox (Not 3.0 as of this writing) and (4) it's open source (we can mod the code).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Watin Smarts&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Watin has a good set of algorithms for handling the WaitForLoad stuff. WaitForLoadTimeout is the amount of time the underlying framework should wait for a page to load even though you have asked the framework to find an element.&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;&lt;pre class="c-sharp:nogutter:nocontrols"  name="code"&gt;&lt;br /&gt;browser.goto("http://www.google.com");&lt;br /&gt;browser.Button(Find.ByValue("submit")).Click();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In the example above the thread will reach the 2nd line before the page finishes loading. Watin is smart enough to wait for the page to load before clicking the button. This behavior is controled by the WaitForLoadTimeout property.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Nice Syntax&lt;/strong&gt;&lt;br /&gt;The Syntax for finding elements on a page is pretty nice. Here is an example:&lt;br /&gt;&lt;pre class="c-sharp:nogutter:nocontrols"  name="code"&gt; browser.Button(Find.ByValue("submit").And(Find.ByClass("pretty-btn")).Click();&lt;/pre&gt;The "Find" constraint has both an "AND" and an "OR" method. Both take a single Find as an argument. Testers will prefer this syntax to the more arcane XPath style syntax but I would have preferred something like this:&lt;br /&gt;&lt;pre class="c-sharp:nogutter:nocontrols"  name="code"&gt;browser.Button.Find.ByValue("submit").And.ByClass("pretty-button").Click();&lt;/pre&gt;Either way the Find constraint offers many ByXXX methods for do all sorts of neat tricks and if need be you can drop to regular expressions (well coded sites shouldn't require that). I also appreciate the &lt;a target="_blank" href="http://watin.sourceforge.net/htmlelementmapping.html"&gt;HTML mappings&lt;/a&gt; syntax.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Firefox Support&lt;/span&gt;&lt;br /&gt;You'll notice that the firefox support depends on a firefox plugin called &lt;a target="_blank" href="http://code.google.com/p/firewatir/downloads/list"&gt;jssh&lt;/a&gt;. JSSH opens up a telnet server that allows Watin (or any other framework) to issue automation commands that it then forwards to Firefox. Watin 2.0 comes with a version of JSSH in it's Mozilla folder. This version only works on Firefox 2.x. We have tried several "fixed" version and we have tried turning off compatibility and security checks in Firefox 3.x. All attempts to run JSSH failed. In Firefox 2.x we experienced great success. So, I have no doubt that support will come soon.&lt;br /&gt;&lt;br /&gt;Either way if you plan to support multiple browsers then you should use the BrowserFactory class. It has a create method that returns an IBrowser instance based on a BrowserType enum. In this way you can use the same tests for both Firefox and IE.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Final Thoughts&lt;/span&gt;&lt;br /&gt;One of the most attractive things to me, about Watin, is the fact that the tests live in source code along with all our other tests. They run using Nunit and the same tool set we use for Unit Testing.&lt;br /&gt;&lt;br /&gt;I also like that Watin does not want to inject javascript into our code. So far our testers seem excited and I hope we can keep up the momentum.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;br/&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type="text/javascript"&gt;&lt;br/&gt;src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;&lt;br/&gt;&lt;/script&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-8562434278374751056?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/256oXDVyzkl1X6HJPTaQUqUc5bw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/256oXDVyzkl1X6HJPTaQUqUc5bw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/256oXDVyzkl1X6HJPTaQUqUc5bw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/256oXDVyzkl1X6HJPTaQUqUc5bw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=9eL3IxgL"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=bl8SAny0"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=bl8SAny0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=F6w5oSmi"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=UntKnQV5"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=UntKnQV5" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=qHiEQNLY"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=C1TdYzzz"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=C1TdYzzz" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/n455ijOUCAk" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-06T08:12:05.992+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/08/watin-installed.html</feedburner:origLink></item><item><title>SVN LDAP and Active Directory</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/ELksZTcYA4M/svn-ldap-and-active-directory.html</link><category>tools</category><category>Version Control</category><category>Subversion</category><category>Configuration Management</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Sun, 13 Jul 2008 19:57:49 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-8298259361233446515</guid><description>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;We just upgraded to the 1.5 series of &lt;a href='http://subversion.tigris.org/' target='_blank'&gt;SVN&lt;/a&gt;. Almost all of our "team" tools have some hook into &lt;a href='http://en.wikipedia.org/wiki/Active_Directory' target='_blank'&gt;Active Directory&lt;/a&gt; (AD) for authentication. For SVN this is done via the AD LDAP interface. It turns out that some of SVN's auth_ldap libraries have changed and now our repository sits dead in the water.&lt;br/&gt;&lt;br/&gt;For those who don't know, SVN is really just a very elaborate Apache web application. Apache handles the network communications while SVN does the versioning stuff. That being the case the real problem exists with the instance of apache that comes with SVN 1.5.0. I believe the LDAP module libraries shipped with SVN are &lt;a href='http://blogs.open.collab.net/svn/2008/06/collabnet-subve.html#comment-120559448' target='_blank'&gt;out of date&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;I have considered switching to the mod_sspi for authentication. Others have got it to &lt;a href='http://svn.haxx.se/users/archive-2007-05/0886.shtml' target='_blank'&gt;work&lt;/a&gt;. Has anyone else had luck with this?&lt;br/&gt;&lt;br/&gt;The benefit (I suppose) of SSPI would be the seamless inferance of domain credentials. In short, the SVN client should use your windows logon credentials to authenticate against the server. This is how &lt;a href='http://www.cvsnt.org' target='_blank'&gt;CVSNT &lt;/a&gt;works but I'm not sure it's that easy with SVN.&lt;br/&gt;&lt;br/&gt;Oh well....more later.&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-8298259361233446515?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/aDguqhsM5YoYvveRoYG65Bv52Wc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aDguqhsM5YoYvveRoYG65Bv52Wc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/aDguqhsM5YoYvveRoYG65Bv52Wc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/aDguqhsM5YoYvveRoYG65Bv52Wc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=kaPzp5J5"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=Tamy3u4y"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=Tamy3u4y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=9Fo6dpjW"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=zMukADFp"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=zMukADFp" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=2RK11opd"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=Vz4Oghus"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=Vz4Oghus" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/ELksZTcYA4M" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-14T05:57:49.564+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/07/svn-ldap-and-active-directory.html</feedburner:origLink></item><item><title>A Project Dashboard</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/mfR9NKYpy-k/project-dashboard.html</link><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Sun, 06 Jul 2008 20:14:32 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-6693110142665975198</guid><description>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Lots of talk at work about implementing a project management suite. I'm not a big fan of any of the current offerings. So, I've been working on an &lt;a href='http://www.agilejedi.com/dashboard.xls' target='_blank'&gt;Excel spreadsheet&lt;/a&gt; to track project velocity and health. What I'm attaching pretty much tells me everything I need to know about a project's health. The spreadsheet has 2 worksheets; Data, Dashboard. &lt;br/&gt;&lt;br/&gt;&lt;span style='font-weight: bold;'&gt;The Data workbook&lt;/span&gt; holds all the raw data about each iteration. Only Columns A thru F should be filled in. The rest of the columns are calculated using those values. Also, I have hidden all the rows from below the last row to row 1400. I do this so these rows aren't calculated into the charts on the Dashboard worksheet. As I add rows I unhide it.&lt;br/&gt;&lt;br/&gt;&lt;span style='font-weight: bold;'&gt;The Dashboard workbook&lt;/span&gt; has several charts that I find useful. The release progress chart is a sort of burn down chart. It not only includes burn down but also tracks points completed. I like this chart because it gives me a rough estimate of a project's halfway point.  The estimation quality factor lets you track your estimates over time. The estimates are calculated automatically (&lt;span style='font-style: italic;'&gt;(Pts Remaining +AVGChange) / Velocity&lt;/span&gt;) but can be filled in manually if need be.&lt;br/&gt;&lt;br/&gt;For my next challenge I will move the dashboard to Google Docs.&lt;br/&gt;&lt;br/&gt;Take a look at the dashboard. Discuss it below....I'll post changes as requested!&lt;br/&gt;&lt;br/&gt;&lt;a href='http://www.agilejedi.com/dashboard.xls' target='_blank'&gt;Download Here!&lt;/a&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-6693110142665975198?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3dohiFUU1MZ9HmitoRn047UNdNU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3dohiFUU1MZ9HmitoRn047UNdNU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3dohiFUU1MZ9HmitoRn047UNdNU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3dohiFUU1MZ9HmitoRn047UNdNU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=httOovnR"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=n4qUr15P"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=n4qUr15P" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=Qor7qn5D"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=FwH6uVHA"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=FwH6uVHA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=2GJHKxuG"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=U1HLLgE6"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=U1HLLgE6" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/mfR9NKYpy-k" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-07-07T06:14:32.490+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><enclosure url="http://www.agilejedi.com/dashboard.xls" length="365056" type="application/octet-stream" /><media:content url="http://www.agilejedi.com/dashboard.xls" fileSize="365056" type="application/octet-stream" /><itunes:explicit>no</itunes:explicit><itunes:subtitle>Lots of talk at work about implementing a project management suite. I'm not a big fan of any of the current offerings. So, I've been working on an Excel spreadsheet to track project velocity and health. What I'm attaching pretty much tells me everything I</itunes:subtitle><itunes:author>Dan Pupek</itunes:author><itunes:summary>Lots of talk at work about implementing a project management suite. I'm not a big fan of any of the current offerings. So, I've been working on an Excel spreadsheet to track project velocity and health. What I'm attaching pretty much tells me everything I need to know about a project's health. The spreadsheet has 2 worksheets; Data, Dashboard. The Data workbook holds all the raw data about each iteration. Only Columns A thru F should be filled in. The rest of the columns are calculated using those values. Also, I have hidden all the rows from below the last row to row 1400. I do this so these rows aren't calculated into the charts on the Dashboard worksheet. As I add rows I unhide it. The Dashboard workbook has several charts that I find useful. The release progress chart is a sort of burn down chart. It not only includes burn down but also tracks points completed. I like this chart because it gives me a rough estimate of a project's halfway point. The estimation quality factor lets you track your estimates over time. The estimates are calculated automatically ((Pts Remaining +AVGChange) / Velocity) but can be filled in manually if need be. For my next challenge I will move the dashboard to Google Docs. Take a look at the dashboard. Discuss it below....I'll post changes as requested! Download Here! </itunes:summary><feedburner:origLink>http://blog.agilejedi.com/2008/07/project-dashboard.html</feedburner:origLink></item><item><title>Back from Iraq!</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/M5I5aUMQpcs/back-from-iraq.html</link><category>army</category><category>iraq</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Wed, 11 Jun 2008 19:55:00 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-5640947455670782196</guid><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm3.static.flickr.com/2404/2329784314_79354ffc76_m.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 255px; height: 191px;" src="http://farm3.static.flickr.com/2404/2329784314_79354ffc76_m.jpg" alt="" border="0" /&gt;&lt;/a&gt;As many of you know I have been in Iraq for about the last 12 months. I just returned and I am excited to get back to my family and job!&lt;br /&gt;&lt;br /&gt;I'm also excited to be blogging again!&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-5640947455670782196?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xAt3_suohCUMU14t02ptUpZBCz0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xAt3_suohCUMU14t02ptUpZBCz0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xAt3_suohCUMU14t02ptUpZBCz0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xAt3_suohCUMU14t02ptUpZBCz0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=X6KwWpZZ"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=1ScjeVZL"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=1ScjeVZL" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=V0QcbUpQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=6ye9sXAy"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=6ye9sXAy" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=DdW4xQki"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=0f3B6QUg"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=0f3B6QUg" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/M5I5aUMQpcs" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-06-12T05:55:00.516+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/06/back-from-iraq.html</feedburner:origLink></item><item><title>Accountability Model or Making Commitments</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/Lm98CdNgq_w/accountability-model-or-making.html</link><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Sun, 27 Apr 2008 11:43:14 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-1322598665599025583</guid><description>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Below is a post that I have mulled over for a while. I'm not satisfied with it but I would love some feedback.&lt;br/&gt;&lt;br/&gt;I'd like to address two areas that are often considered taboo in the Agile field; Accountability and commitment. Just like the pig in the "&lt;a href='http://www.agilejedi.com/chickenandpig' target='_blank'&gt;Chicken and Pig Make Breakfast&lt;/a&gt;" story, agile teams  make commitments. Teams commit to stories and they commit to estimates. As an agile project progresses through the &lt;a href='http://blog.agilejedi.com/2007/03/5-levels-of-planning-i-just-read.html' target='_blank'&gt;5 Levels of Planning&lt;/a&gt; it also moves through progressively higher levels of accountability; Nice Idea, Best Effort and Commitment.&lt;br class='DS_newline'/&gt;&lt;br class='DS_newline'/&gt;&lt;br class='DS_newline'/&gt;&lt;img src='http://www.agilejedi.com/AccountabilityModelexport.png' style='max-width: 800px; float: none;' ondblclick='parent.dsMidas.addImage(this);'/&gt;&lt;br class='DS_newline'/&gt;&lt;br class='DS_newline'/&gt;&lt;b&gt;&lt;br class='DS_newline'/&gt;Making Commitments&lt;/b&gt;&lt;br class='DS_newline'/&gt;The Accountability Model above is meant to illustrate how each level of planning helps the team zero in on an actual commitment. Since agile teams accept that requirements will change, the most detailed design estimates are held off until just before implementation. So, project stakeholders can expect The Release Plan to be more accurate than The Road Map and the Iteration Plan to be more accurate than the Release Plan.&lt;br class='DS_newline'/&gt;&lt;br class='DS_newline'/&gt;With higher levels of accuracy come higher levels of accountability while lower levels of accuracy call for lower levels of accountability. Let's take a look at the levels of accountability:&lt;br class='DS_newline'/&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Nice Idea&lt;/b&gt;&lt;br class='DS_newline'/&gt;&lt;span style='font-style: italic;'&gt;The Vision&lt;/span&gt; and the &lt;span style='font-style: italic;'&gt;Project Road Map&lt;/span&gt; serve as guidelines for prioritizing during the more detailed planning that takes place closer to the Iteration. As new requirements and unforeseen changes expose themselves &lt;span style='font-style: italic;'&gt;The Vision&lt;/span&gt; and &lt;span style='font-style: italic;'&gt;The Road Map&lt;/span&gt; WILL change. Management should shy away from holding anyone accountable for changes that occur in the Nice Idea level. Rather, they should embrace the change as nessecary or find ways to mitigate the change.&lt;br class='DS_newline'/&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Best Effort&lt;br class='DS_newline'/&gt;&lt;/b&gt;The Release Plan is a best effort estimate based on yesterday's weather. Iterations are timeboxed and most teams track velocity. This allows a project manager to produce an iteration schedule. The Release Plan, while more accurate than the Road Map, is less accurate at the front-end than at the back-end. For this reason, managers should consider using a confidence range chart or some other measurement of accuracy. Tracking a project's rate of change can also help mitigate risk. Managers should encourage change in the early iterations of a release but changes should stay within the scope of the current vision and roadmap. If you see either the vision or the roadmap changing you should consider wrapping up the release and starting a new release plan.&lt;b&gt;&lt;br class='DS_newline'/&gt;&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;span style='font-weight: bold;'&gt;Commitment&lt;/span&gt;&lt;br/&gt;Iterations are short and easily estimated. Teams with a well established velocity and a long history with the current project will be able to make the most reliable estimates. These teams should be able to fully commit to an Iteration of work. &lt;br/&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style='font-weight: bold;'&gt;Who's Accountable?&lt;/span&gt;&lt;br/&gt;Accountability is a hard subject to address in this field. A person can "be" accountable, "be held" accountable or account for someone else. In general, developers are accountable to the user, the team and themselves. Holding a team accountable for the completion of a project is usually a huge morale killer and often does more harm than good. Holding someone (coach, scrummaster, etc) accountable on behalf of the team will most likely fail as well.&lt;br/&gt;&lt;br/&gt;So who is accountable? How is accountability expressed on an agile project? On agile projects, developers hold themselves accountable. They hold themselves accountable to the team, the users, their pair partner, themselves, etc. For Agile teams to be successful a culture of accountability must be nurtured but not forced. &lt;br/&gt;&lt;br/&gt;&lt;span style='font-weight: bold;'&gt;Nurturing Accountability&lt;/span&gt;&lt;br/&gt;Nurturing a culture of accountability is easier said than done, but it can be done. The usual tools of evaluations, reviews and threats have no place on a self organizing team. You can apply incentives, a sense of accomplishment, team ownership and a little peer pressure.&lt;br/&gt;&lt;br/&gt;A good incentive suggested by Scrum is a burn down chart. On some teams the build server plays music or turns a light green when a build passes all tests. Involving the "Whole Team" in the planning and design is a surefire way of building team ownership. This leads to buy-in and allows developers feel a real sense of accomplishment. Also, large information radiators are a good way to keep the team focus.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;span style='font-weight: bold;'&gt;Final Thoughts&lt;/span&gt;&lt;br/&gt;So, what I'm suggesting is that teams should want to commit to an estimate. Teams who have "bought-in" to a project are more likely to hold themselves accountable. Kent's &lt;a href='http://itc.conversationsnetwork.org/shows/detail301.html' target='_blank'&gt;discussion about accountability&lt;/a&gt; was my original inspiration for this.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-1322598665599025583?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kYiy9jJ1YZENnRZuw3VUHWFmbSY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kYiy9jJ1YZENnRZuw3VUHWFmbSY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kYiy9jJ1YZENnRZuw3VUHWFmbSY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kYiy9jJ1YZENnRZuw3VUHWFmbSY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=sdWQ9mWN"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=Ag4sv7D2"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=Ag4sv7D2" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=HpHcnpqf"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=5QbeuLFR"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=5QbeuLFR" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=gw6gzWCk"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=GAOOjyqB"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=GAOOjyqB" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/Lm98CdNgq_w" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-27T21:43:14.611+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/04/accountability-model-or-making.html</feedburner:origLink></item><item><title>Memcached for Monorail Update</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/QuArCbH7DTI/memcached-for-monorail-update.html</link><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Sun, 06 Apr 2008 11:41:46 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-4916156593433370814</guid><description>&lt;div xmlns='http://www.w3.org/1999/xhtml'&gt;Memcached for Monorail (MfM) is my attempt at a simple, &lt;a href='http://www.socialtext.net/memcached/index.cgi?windows'&gt;memcached&lt;/a&gt;/&lt;a href='http://www.codeplex.com/EnyimMemcached' target='_blank'&gt;enyim&lt;/a&gt; based, session and caching facility for &lt;a href='http://www.castleproject.org/'&gt;Monorail&lt;/a&gt;. MfM offers a lightweight, fast, low friction, facility for balancing Monorail sessionstate and object caches accross multiple servers. You can read my &lt;a href='http://blog.agilejedi.com/2008/03/monorail-custom-session-factory-for.html'&gt;original post&lt;/a&gt;.&lt;br/&gt;&lt;br/&gt;Memcached offers an excellent solution for applications that need to balance object caches across multiple servers. It does so without the overhead of a database or even the use of the hard disk. Although, a major pitfall for memcached is it's unreliable nature. If a server in your memcached cluster fails then you lose all the objects cached on it. Memcached is just not meant for persisting object data permanently.&lt;br/&gt;&lt;br/&gt;The current release of MfM is capable of persisting sessionstate to a memcached cluster. If one or more memcached servers fails then that part of the session will be lost, permanently. For my projects, I found this unacceptable. I decided to add a DB persistence layer using ActiveRecord. &lt;br/&gt;&lt;br/&gt;I just started adding the database persistence layer to the custom session factory. My plan is to use ActiveRecord for the persistence. This will allow MfM to leverage the crossplatform support already built into ActiveRecord. Here is the psudo-logic I plan to implement:&lt;br/&gt;&lt;br/&gt;&lt;pre&gt;If Writing to the Session then Write value to DB AND&lt;br/&gt;delete the object stored on the Memcached Cluster.&lt;br/&gt;&lt;br/&gt;If Reading from then Session then retrieve from Memcached Cluster OR&lt;br/&gt;if value doesn't exist in Cluster then retrieve value from DB AND&lt;br/&gt;write the value to the Memcached Cluster. &lt;/pre&gt;&lt;br/&gt;I imagine I will want to implement some kind of locking. &lt;br/&gt;&lt;br/&gt;To learn more check out the &lt;a href='http://code.google.com/p/libagilejedi/wiki/MemcachedForMonorail' target='_blank'&gt;project website&lt;/a&gt;. You can also &lt;a href='http://code.google.com/p/libagilejedi/source/browse' target='_blank'&gt;browse the source repository&lt;/a&gt; or &lt;a href='http://code.google.com/p/libagilejedi/source/checkout' target='_blank'&gt;checkout the code&lt;/a&gt; yourself. &lt;br/&gt;&lt;br/&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-4916156593433370814?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/0g4cAUxzeR7zjgfcWF3C3KWwy_A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0g4cAUxzeR7zjgfcWF3C3KWwy_A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/0g4cAUxzeR7zjgfcWF3C3KWwy_A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0g4cAUxzeR7zjgfcWF3C3KWwy_A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=YA2OWqUN"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=NNJxz2VG"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=NNJxz2VG" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=RN7mJM4V"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=azoY2t7P"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=azoY2t7P" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=3Y7oqRJq"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=n2KsNL2d"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=n2KsNL2d" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/QuArCbH7DTI" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-06T21:41:46.886+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/04/memcached-for-monorail-update.html</feedburner:origLink></item><item><title>Writing User Stories and Pragmatic XP</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/0udefNfr5ZU/writing-user-stories-and-pragmatic-xp.html</link><category>User Story</category><category>extreme programming</category><category>agile development</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Wed, 13 Aug 2008 21:19:14 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-7116577453557832058</guid><description>&lt;table id="b4g5" style="margin-bottom: 1px; margin-right: 10px; color: rgb(0, 0, 0);" align="left" border="1" cellpadding="3" cellspacing="0"&gt; &lt;tbody id="e25r"&gt; &lt;tr id="t6i0"&gt; &lt;td id="lmul" bg="" style="color: rgb(255, 255, 153);" width="100%"&gt;&lt;b id="jcb2"&gt;&lt;span id="r61l" style="color: rgb(53, 28, 117);font-size:78%;" &gt;Writing  User Stories&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr id="kvze"&gt; &lt;td id="l63o" bgcolor="#ffffff" width="100%"&gt; &lt;p id="se0x"&gt;&lt;a id="u1:0" title="Part 1" href="http://blog.agilejedi.com/2007/05/writing-user-stories.html"&gt;Part 1&lt;/a&gt; &lt;/p&gt; &lt;p id="d:_o"&gt;&lt;a href="http://blog.agilejedi.com/2008/03/writing-user-stories-5-ws-way-writing.html"&gt;Part 2&lt;/a&gt; &lt;/p&gt; &lt;p id="e9im"&gt;Part 3&lt;/p&gt; &lt;p id="hli5"&gt; &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;My &lt;a href="http://blog.agilejedi.com/2008/03/writing-user-stories-5-ws-way-writing.html"&gt;previous post&lt;/a&gt; in this series generated a lot of commentary on the XP list. I honestly appreciate everyone's insight....it can only make me better.&lt;br /&gt;&lt;br /&gt;My intent (with respect to this series) was to suggest other approaches to writing stories. The series is aimed mostly at helping users. I try to make these approaches simple. Some users will find a "by the numbers" approach easier to wrap their mind around. The 5Ws method may also provoke a deeper analysis of the story as users try to describe each W. I also believe that some developers and testers might appreciate a more predictable user story. In the end though, users can bring us any scribble. Be it on a card, a sticky note or a napkin and we will do our best to make it a reality.&lt;br /&gt;&lt;br /&gt;The series was never meant to be a holistic commentary on writing stories. As a rule I try to avoid anything holistic. I do, these days, try to be pragmatic and a bit understated.&lt;br /&gt;&lt;br /&gt;When I first started down the path of XP (uhg, sounds way too cult-like) I worked in a shop with no formal method for developing software. When I discovered XP, I wasn't looking to be agile....I was looking to be methodical. My first instinct was to codify as best I could a fully functional set of XP policies and procedures. What mostly drove my efforts was a need to justify our wacky ideas (ie pair programming) to what was and primarily still is a government contracting company.&lt;br /&gt;&lt;br /&gt;It took me several years of struggling to realize that I missed the whole point of XP. Yes, XP does help you to be more methodical, but without the formalized process. XP's informal nature is what makes it "Agile". The practices are not rules but guidelines. The coach doesn't drive the bus (the team does) she simply points out the pot holes. Finally, this all works because each person values good software over the process. The point? We write and discriminate our user stories the same way.....with a lot of guidelines and very few rules.&lt;br /&gt;&lt;br /&gt;I wish I could say that I gained all of this insight many years ago...but I didn't. I really only got it in the last two or three years. One day I had to stop talking and start listening. To that end, I can mostly thank the insights of two of the smartest people I know (&lt;a target="_blank" href="http://www.waves.ky/"&gt;Gareth &lt;/a&gt;and Jason) and the never-ending patience of my boss Rob.&lt;br /&gt;&lt;br /&gt;In the words of the "&lt;a href="http://en.wikipedia.org/wiki/Wyld_Stallyns"&gt;Wyld Stallyns&lt;/a&gt;"...."Be excellent to each other!"&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-7116577453557832058?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Fp38HMp3WlfizYkqZpPAIAASXXs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Fp38HMp3WlfizYkqZpPAIAASXXs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Fp38HMp3WlfizYkqZpPAIAASXXs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Fp38HMp3WlfizYkqZpPAIAASXXs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=vH375nIB"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=CraJDP7E"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=CraJDP7E" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=qVRLco31"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=XacAmmdp"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=XacAmmdp" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=3IgWqtMU"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=ISObdNa8"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=ISObdNa8" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/0udefNfr5ZU" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-14T07:19:14.326+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/03/writing-user-stories-and-pragmatic-xp.html</feedburner:origLink></item><item><title>Shoot Yourself in the Foot!</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/mleVKp88VzU/shoot-yourself-in-foot.html</link><category>programming languages</category><category>humrous</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Fri, 28 Mar 2008 10:18:51 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-162555064968135499</guid><description>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;img src="http://lh6.google.com/Daniel.Pupek/R-0lGFzQXkI/AAAAAAAAACA/0XCqWoPcNBM/%5BUNSET%5D.jpg" style="max-width: 800px; float: left; margin-top: 10px; margin-bottom: 10px; margin-right: 10px; width: 126px; height: 94px;" /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;!WARNING!&lt;/span&gt; If you're not a major nerd or geek you won't get these jokes!&lt;br /&gt;Recently a friend of mine sent me some funny additions to the &lt;a style="border-bottom-style: groove;" href="http://www.gksoft.com/a/fun/shoot-foot.html"&gt;Shoot Yourself in the Foot!&lt;/a&gt; list. The list is a humours look a the logic you might need to "shoot yourself in the foot" in different programming languages. Here are his suggestions:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;b&gt;Python&lt;/b&gt;&lt;br /&gt;          You try to shoot yourself in the foot, but the gun refuses&lt;br /&gt;to go off because it doesn't have appropriate space around it.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Perl&lt;/b&gt;&lt;br /&gt;          You quickly create your own gun and shoot yourself in the&lt;br /&gt;foot. Witnesses are unable to explain what happened. No one else can&lt;br /&gt;figure out how to use the gun.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;JavaScript&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;          Your prototype gun admirably shoots feet during testing,&lt;br /&gt;but in production many users' hands are incompatible&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Flash&lt;/b&gt;&lt;br /&gt;          As you pull the trigger, the gun's barrels surge&lt;br /&gt;impressively to life. The muzzles flash, smoke billows, and the ring&lt;br /&gt;of pounds of expelled brass is barely audible over the deafening&lt;br /&gt;gunfire. After the smoke clears, your foot is unaffected and you&lt;br /&gt;realize nothing seems to have happened.&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;Here are a few of my own additions/revisions:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Visual Basic 6&lt;/b&gt;&lt;br /&gt;You take advantage of the very handy ShootMyselfInTheLeftFootOnce() method and wait three years for M$ to release a ShootMyselfInTheRightFootOnce() method.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;C#&lt;/b&gt;&lt;br /&gt;You spend several hours browsing through Intellisense drop downs and the object browser looking for the right combination of .Net classes and methods to shoot your foot and eventually decide to port the Java libShootMyFoot library.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Java&lt;/b&gt;&lt;br /&gt;You decide to take advantage of the libShootMyFoot library. After days of scanning painfully abstract API documentation you realize that, through some complex twist of logic that still can only be understood by developers working for Sun, the libShootMyFoot library was never intended to be used for shooting feet.&lt;br /&gt;&lt;br /&gt;Please post any additons you would like to see!&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-162555064968135499?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Ind1EFmCW_-ngz3VH5KdW_LFgPw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ind1EFmCW_-ngz3VH5KdW_LFgPw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Ind1EFmCW_-ngz3VH5KdW_LFgPw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ind1EFmCW_-ngz3VH5KdW_LFgPw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=WF0IJlRT"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=t0V7FOvC"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=t0V7FOvC" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=OdblOHqC"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=j5CU39NK"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=j5CU39NK" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=2Uc1jm89"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=gktjNoQk"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=gktjNoQk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/mleVKp88VzU" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-28T20:18:51.834+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/03/shoot-yourself-in-foot.html</feedburner:origLink></item><item><title>Monorail Custom Session Factory for Memcached</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/qcH3U-1vyTo/monorail-custom-session-factory-for.html</link><category>monorail</category><category>memcached</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Fri, 28 Mar 2008 00:43:11 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-340635571554724218</guid><description>&lt;h2 dtid="281474976710660"&gt;&lt;span dtid="281474976710661"  style="font-size:100%;"&gt;Introduction&lt;/span&gt; &lt;/h2&gt;&lt;p dtid="281474976710662"&gt;&lt;span dtid="281474976710663"  style="font-size:100%;"&gt;I have written a simple but effective  ICustomSessionFactory implementation that uses &lt;/span&gt;&lt;span dtid="281474976710664"  style="font-size:100%;"&gt;&lt;a href="http://www.socialtext.net/memcached/index.cgi?memcached" rel="nofollow"&gt;memcached&lt;/a&gt;&lt;/span&gt;&lt;span dtid="281474976710665"  style="font-size:100%;"&gt; storage on the back-end. If you don't know  why you should be using &lt;a href="http://www.socialtext.net/memcached/index.cgi?memcached" rel="nofollow"&gt;memcached&lt;/a&gt; then you should check it out first. If you want to  check out the code now, then &lt;a style="border-bottom-style: groove;" href="http://code.google.com/p/libagilejedi/wiki/MemcachedForMonorail"&gt;go  here&lt;/a&gt;. So far I think I have a passable Session Factory implementation that  uses &lt;a href="http://www.socialtext.net/memcached/index.cgi?memcached" rel="nofollow"&gt;memcached&lt;/a&gt; on the back end. In later posts I will give some  code examples and more details about deploying the Factory code. &lt;/span&gt;&lt;/p&gt;&lt;h2 dtid="281474976710666"&gt;&lt;span dtid="281474976710667"  style="font-size:100%;"&gt;Details&lt;/span&gt; &lt;/h2&gt;&lt;p dtid="281474976710668"&gt;&lt;span dtid="281474976710669"  style="font-size:100%;"&gt;Here are a few dependencies you will need to  get going: &lt;/span&gt;&lt;/p&gt;&lt;ul dtid="281474976710670"&gt;&lt;li dtid="281474976710671"&gt;&lt;span dtid="281474976710672"  style="font-size:100%;"&gt;&lt;a style="border-bottom-style: groove;" href="http://www.castleproject.org/" rel="nofollow"&gt;Castle::Monorail&lt;/a&gt;&lt;/span&gt;  &lt;/li&gt;&lt;li dtid="281474976710673"&gt;&lt;span dtid="281474976710674"  style="font-size:100%;"&gt;A &lt;a href="http://www.socialtext.net/memcached/index.cgi?memcached" rel="nofollow"&gt;memcached&lt;/a&gt; server or servers running on your network.  Memcached is a simple and fast distributed object server for balancing object  caches across many servers!&lt;/span&gt; &lt;/li&gt;&lt;li dtid="281474976710675"&gt;&lt;span dtid="281474976710676"  style="font-size:100%;"&gt;The latest release of &lt;a style="border-bottom-style: groove;" href="http://www.codeplex.com/EnyimMemcached/" rel="nofollow"&gt;Enyim&lt;/a&gt;. These  are the guys that did all the real client work! Thanks to them for a great  memcached client!&lt;/span&gt; &lt;/li&gt;&lt;li dtid="281474976710677"&gt;&lt;span dtid="281474976710678"  style="font-size:100%;"&gt;If you want to run the tests or plan on making  modifications then you will need the Nunit/RhinoMocks stack.  &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 dtid="281474976710679"&gt;&lt;span dtid="281474976710680"  style="font-size:100%;"&gt;Current Features&lt;/span&gt; &lt;/h3&gt;&lt;ul dtid="281474976710681"&gt;&lt;li dtid="281474976710682"&gt;&lt;span dtid="281474976710683"  style="font-size:100%;"&gt;A session dictionary that uses &lt;a href="http://www.socialtext.net/memcached/index.cgi?memcached" rel="nofollow"&gt;memcached&lt;/a&gt;&lt;/span&gt;&lt;span dtid="281474976710684"  style="font-size:100%;"&gt;on the backend. This is the real meat and  potatoes.&lt;/span&gt; &lt;/li&gt;&lt;li dtid="281474976710685"&gt;&lt;span dtid="281474976710686"  style="font-size:100%;"&gt;Almost complete IDictionary implementation  (The &lt;span style="font-style: italic;"&gt;Values&lt;/span&gt; property and enumeration are  not implemented). The default session in monorail doesn't seem to support the  &lt;span style="font-style: italic;"&gt;values&lt;/span&gt; property either. For that reason  and for performance reasons I have no plans to implement the &lt;span style="font-style: italic;"&gt;values&lt;/span&gt; property.&lt;/span&gt; &lt;/li&gt;&lt;li dtid="281474976710687"&gt;&lt;span dtid="281474976710688"  style="font-size:100%;"&gt;ICustomSessionFactory for &lt;/span&gt;&lt;span dtid="281474976710689"  style="font-size:100%;"&gt;&lt;a style="border-bottom-style: groove;" href="http://www.castleproject.org/"&gt;CASTLE::MONORAIL&lt;/a&gt;&lt;/span&gt; &lt;/li&gt;&lt;/ul&gt;&lt;h3 dtid="281474976710690"&gt;&lt;span dtid="281474976710691"  style="font-size:100%;"&gt;Planned/Missing Features&lt;/span&gt; &lt;/h3&gt;&lt;ul dtid="281474976710692"&gt;&lt;li dtid="281474976710693"&gt;&lt;span dtid="281474976710694"  style="font-size:100%;"&gt;Optional DB persistence of sessions  using activerecord/memcached fusion. Memcached storage isn't redundant and as a  rule caches should be considered unreliable. I would like to give developers the  option of turning on a DB persistence layer to ensure the reliability of the  session state.&lt;/span&gt; &lt;/li&gt;&lt;li dtid="281474976710695"&gt;&lt;span dtid="281474976710696"  style="font-size:100%;"&gt;Cache provider for monorail. Abiity to easily  add memcached caching into all of your service components.&lt;/span&gt; &lt;/li&gt;&lt;li dtid="281474976710697"&gt;&lt;span dtid="281474976710698"  style="font-size:100%;"&gt;Cache provider integration with  ActiveRecord.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 dtid="281474976710699"&gt;&lt;span dtid="281474976710700"  style="font-size:100%;"&gt;&lt;a style="font-weight: bold;" href="http://code.google.com/p/libagilejedi/wiki/MemcachedForMonorail?updated=MemcachedForMonorail&amp;amp;ts=1206648414"&gt;DOWNLOAD  MEMCACHEDFORMONORAIL!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Other  Memcached Goodies&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;&lt;span dtid="281474976710701"  style="font-size:100%;"&gt;I also intend to write a custom cache provider  for ActiveRecord / Monorail. So stay tuned!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-340635571554724218?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HH48ZRHYYZCuCC1ZXp2FLKtvcxc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HH48ZRHYYZCuCC1ZXp2FLKtvcxc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HH48ZRHYYZCuCC1ZXp2FLKtvcxc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HH48ZRHYYZCuCC1ZXp2FLKtvcxc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=oStVOZ2c"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=293YTuQn"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=293YTuQn" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=TGaznBSe"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=yrZMHEyi"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=yrZMHEyi" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=mwBxW6cK"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=YgsfLJte"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=YgsfLJte" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/qcH3U-1vyTo" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-28T10:43:11.205+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/03/monorail-custom-session-factory-for.html</feedburner:origLink></item><item><title>Writing User Stories the 5 Ws Way</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/gOxyPGTDIJY/writing-user-stories-5-ws-way-writing.html</link><category>User Story</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Wed, 02 Sep 2009 21:39:05 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-154259388080800826</guid><description>&lt;div id="wqm:" align="left"&gt; &lt;table id="b4g5" style="margin-bottom: 1px; margin-right: 10px; color: rgb(0, 0, 0);" align="left" border="1" cellpadding="3" cellspacing="0"&gt; &lt;tbody id="e25r"&gt; &lt;tr id="t6i0"&gt; &lt;td id="lmul" bg="" style="color: rgb(255, 255, 153);" width="100%"&gt;&lt;b id="jcb2"&gt;&lt;span id="r61l" style="color: rgb(53, 28, 117);font-size:78%;" &gt;Writing  User Stories&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr id="kvze"&gt; &lt;td id="l63o" width="100%" bgcolor="#ffffff"&gt; &lt;p id="se0x"&gt;&lt;a id="u1:0" title="Part 1" href="http://blog.agilejedi.com/2007/05/writing-user-stories.html"&gt;Part 1&lt;/a&gt; &lt;/p&gt; &lt;p id="d:_o"&gt;Part 2 &lt;/p&gt; &lt;p id="e9im"&gt;&lt;a href="http://blog.agilejedi.com/2008/03/writing-user-stories-and-pragmatic-xp.html"&gt;Part 3&lt;/a&gt;&lt;/p&gt; &lt;p id="hli5"&gt; &lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt; &lt;div id="hy04" align="left"&gt;This is Part 2 of my "Writing User Stories series". &lt;a id="u1:0" title="Part 1" href="http://blog.agilejedi.com/2007/05/writing-user-stories.html"&gt;Part 1&lt;/a&gt; focused on some common pitfalls while writing a user story. In this article I intend to outline a simple but effective method of writing a user story using the 5 Ws.&lt;/div&gt; &lt;p id="av2r"&gt; &lt;/p&gt; &lt;p id="k8md"&gt;A User Story is written by any User. The User Story should have a short but descriptive title and a longer narrative. The narrative should include the 5 Ws: Who, What, When, Where and Why.  &lt;/p&gt; &lt;ul id="zp_p"&gt; &lt;li id="b24v"&gt;&lt;b id="uuh7"&gt;WHO&lt;/b&gt;: Usually, the type of user (ie Admin, Student, Teacher)  &lt;/li&gt;&lt;li id="ljc:"&gt;&lt;b id="vg7i"&gt;WHAT&lt;/b&gt;: What the user in the WHO is going to do (clicks on the "new blog comment" button)  &lt;/li&gt;&lt;li id="xg0-"&gt;&lt;b id="pb6k"&gt;WHEN&lt;/b&gt;: "When" may describe a time or date or relative time (ie After logging in or after reading a blog)  &lt;/li&gt;&lt;li id="zg0a"&gt;&lt;b id="fz3b"&gt;WHERE&lt;/b&gt;: Where on the page or in the application.  &lt;/li&gt;&lt;li id="rc-i"&gt;&lt;b id="kmb0"&gt;WHY&lt;/b&gt;: What was the trigger for the user (user wants to suggest a change to the blog post)&lt;/li&gt;&lt;/ul&gt; &lt;p id="q80-"&gt; &lt;b id="qhop"&gt;Example 1&lt;/b&gt;: A student (&lt;i id="buno"&gt;who&lt;/i&gt;) clicks the new blog comment button (&lt;i id="p2r4"&gt;what&lt;/i&gt;) after reading a blog post (&lt;i id="q77e"&gt;when&lt;/i&gt;) located at the bottom of the blog post (&lt;i id="n4-q"&gt;where&lt;/i&gt;) in order to make a comment about the blog post (&lt;i id="qxz-"&gt;why&lt;/i&gt;).&lt;/p&gt; &lt;p id="jr9n"&gt; &lt;/p&gt; &lt;p id="pr:5"&gt;&lt;b id="h7n3"&gt;Discussion 1&lt;/b&gt;: Example 1 is pretty straight forward the who, what, when, where and why are well defined. Let's look a more complex example. &lt;/p&gt; &lt;p id="umkf"&gt; &lt;/p&gt; &lt;p id="drlf"&gt;&lt;b id="fl9b"&gt;Example 2&lt;/b&gt;: An instructor (&lt;i id="buno"&gt;who&lt;/i&gt;) has determined which students to put into which discussion groups(&lt;i id="cgfp"&gt;why,when&lt;/i&gt;). Viewing the student listing for a class (where) clicks the checkboxs next to several student names, selects a discussion group from the drop down and clicks the add to discussion group  (&lt;i id="p2r4"&gt;what&lt;/i&gt;).&lt;/p&gt; &lt;p id="a.sj"&gt; &lt;/p&gt; &lt;p id="ou0q"&gt;&lt;b id="bwkh"&gt;Discussion 2&lt;/b&gt;: Example 2 is a bit more complicated. The "what" is a bit more protracted and the "why" and "when" are combined. For more complex stories it may be easier to list the 5 Ws first:&lt;/p&gt; &lt;p id="tznw"&gt; &lt;/p&gt; &lt;p id="m171"&gt;&lt;b id="qpma"&gt;Who&lt;/b&gt;: An Instructor&lt;/p&gt; &lt;p id="cjab"&gt;&lt;b id="yf2o"&gt;What&lt;/b&gt;: Selects multiple students (at once) and adds them to a discussion group  &lt;/p&gt; &lt;p id="wx.v"&gt;&lt;b id="b8:j"&gt;When&lt;/b&gt;: After determining what students go in which groups.&lt;/p&gt; &lt;p id="pj5_"&gt;&lt;b id="tci4"&gt;Where&lt;/b&gt;: From the student listing screen.&lt;/p&gt; &lt;p id="flpo"&gt;&lt;b id="ap36"&gt;Why&lt;/b&gt;: To get students into discussion groups.&lt;/p&gt; &lt;p id="ax4b"&gt; &lt;/p&gt; &lt;p id="kb:q"&gt;In this format the when and the why come out a bit differently. Using the 5Ws method can greatly reduce the amount of time it takes for users to produce good stories. When all stories are written this way they become easier to estimate and the &lt;i id="j470"&gt;why&lt;/i&gt; element give valuable insight into what a user expects from the software.&lt;br /&gt;&lt;/p&gt;&lt;p id="kb:q"&gt;&lt;span style="font-weight: bold;"&gt;Note: (Added 2 Sep 2009)&lt;/span&gt; In fairness to the SCRUM world this could also be expressed in SCRUM Style:&lt;span style="font-weight: bold; font-style: italic;"&gt; As an instructor I want to add multiple students to the discussion groups from the student listing.&lt;/span&gt;&lt;br /&gt;&lt;/p&gt; &lt;p id="v9wa"&gt; &lt;/p&gt; &lt;p id="y_nz"&gt;Feel free to suggest additional examples or make comments!&lt;/p&gt; &lt;p id="jdqr"&gt; &lt;/p&gt; &lt;p id="cjrv"&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-154259388080800826?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/7kd3cA9ovRwOspyDrdxNRHVeO70/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7kd3cA9ovRwOspyDrdxNRHVeO70/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/7kd3cA9ovRwOspyDrdxNRHVeO70/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7kd3cA9ovRwOspyDrdxNRHVeO70/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=QdQYQeVf"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=K84NFp0w"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=K84NFp0w" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=WXc9BcWw"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=LdHZrg4D"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=LdHZrg4D" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=47MPhX2U"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=nX7a8U0W"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=nX7a8U0W" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/gOxyPGTDIJY" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-03T07:39:05.592+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/03/writing-user-stories-5-ws-way-writing.html</feedburner:origLink></item><item><title>8 Things You can do Now to Improve Your Software</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/6cvJxYIM08g/these-arent-new-ideas-but-they-are-true.html</link><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Thu, 27 Mar 2008 11:47:31 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-1726006914609340734</guid><description>&lt;p id="a9s."&gt;These aren't new ideas but they are true. The list below focus' on the things that organizations should be doing to help make their agile teams more productive.  &lt;/p&gt; &lt;ul id="diim"&gt; &lt;li id="uek7"&gt;&lt;b id="s3l0"&gt;LET USERS SUBMIT ISSUES!&lt;/b&gt;  Let users submit issue tickets. They may be bugs, feature requests...whatever. You need to start tracking it. Your users will sense that you place value on their needs and you will have invaluable data for prioritizing new user stories.  &lt;/li&gt;&lt;li id="qyqa"&gt;&lt;b id="ziym"&gt;GET USERS TALKING ABOUT YOUR SOFTWARE!&lt;/b&gt;   Create a discussion forum or bullitin board for users to discuss the software they use. Creating a community around your software will help endear your users to it. Your engineers, product managers and other stakeholders should be encouraged to actively participate. Your team will gain great insight into how users are using the software.  &lt;/li&gt;&lt;li id="ulw6"&gt;&lt;b id="mjuk"&gt;MAKE A USER AVAILABLE!&lt;/b&gt;  Developers should have real-live users to contact and ask questions. Most of what slows delivery of new features is a clear understanding of how a user will use them. Many new features end up looking nothing like what a user was asking for. These features sit around and remain unused.  &lt;/li&gt;&lt;li id="o7c2"&gt;&lt;b id="fb7a"&gt;TESTERS SHOULD BE USER EXPERIENCE EXPERTS!&lt;/b&gt;  Put user experience experts on your testing team. If you don't have a testing team then become a user experience expert. &lt;/li&gt;&lt;li id="hoay"&gt;&lt;b id="cdvj"&gt;CO-LOCATE THE "WHOLE TEAM"!&lt;/b&gt; XP defines the Whole Team as the developers, testers and users. Studies show that communication is a major linch-pin in the success of software development. Anything you can do to improve communication will pay off. &lt;/li&gt;&lt;li id="aaga"&gt;&lt;b id="f9yy"&gt;EAT YOUR DOG-FOOD!&lt;/b&gt; Dog-fooding is the process of using your own software internally (eating your own dog food). If you use it then you will fix it! &lt;/li&gt;&lt;li id="aom2"&gt;&lt;b id="bq3t"&gt;RELEASE OFTEN AND EARLY! &lt;/b&gt;Your users like to see new features! These days you absolutely MUST give users a sense that your software has a future. Your organization should never consider a project "complete". You must work iteratively and release smaller chuncks of functionality. &lt;/li&gt;&lt;li id="h20_"&gt;&lt;b id="kujr"&gt;ALLOW DEVELOPERS TO CHOOSE! &lt;/b&gt;The big boys know this one! Google does this and so does M$. Take advantage of your engineers' Creative Momentum and let them decide which project to work on. I would suggest that this can be done from iteration to iteration or release to release.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-1726006914609340734?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/83Tz636M37H2D_kDALZ1vLAINZ8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/83Tz636M37H2D_kDALZ1vLAINZ8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/83Tz636M37H2D_kDALZ1vLAINZ8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/83Tz636M37H2D_kDALZ1vLAINZ8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=uy3htl7M"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=kQyrlcD6"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=kQyrlcD6" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=ZDJNwfKI"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=decP5q2X"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=decP5q2X" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=ESIsvPSI"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=4OpuCpzn"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=4OpuCpzn" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/6cvJxYIM08g" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-27T21:47:31.030+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/03/these-arent-new-ideas-but-they-are-true.html</feedburner:origLink></item><item><title>Programmer at War (in Iraq)</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/Z9e0EottA6g/programmer-at-war-in-iraq.html</link><category>army</category><category>agile development</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Wed, 19 Mar 2008 10:20:50 PDT</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-8143823366460426627</guid><description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.flickr.com/photos/danandkir/2328169203/"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 272px; height: 204px;" src="http://farm4.static.flickr.com/3106/2327963011_79165b3732_m.jpg" alt="" border="0" /&gt;&lt;/a&gt;Most of those who read my blog are probably unaware that I am in Iraq. Normally, I am a Software Engineer/Chief Systems Architect for an Oklahoma based company. One weekend a month I am an Officer in the U.S. Army Reserves. Last summer I was deployed to Iraq.&lt;br /&gt;&lt;br /&gt;I am a Platoon Leader in a Medium Truck Company. It's quite interesting how different my civilian and Army jobs are. In my civilian job we are always going forward with new developments. In my Army job, each mission tends to be organized similarly and entail doing the same task over and over again. Although, sometimes, the enemy has a say in that.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.flickr.com/photos/danandkir/2328169203/"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 320px;" src="http://farm3.static.flickr.com/2353/2328169203_2b941c0d55_m.jpg" alt="" border="0" /&gt;&lt;/a&gt;In some ways though, my jobs are very similar. There is a great deal to be learned from my experience in the Army. Being an "agilisto", I really value communication and people. In the Army, the most successful leaders learn to communicate very well and place the needs of their soldiers before all else.&lt;br /&gt;&lt;br /&gt;On an agile project we plan and deliver value incrementally. This allows teams to embrace change. In the Army, it is understood that your enemy, the weather and the terain have the final say-so in all plans. Unfortunately, just as in the software engineering world, not everyone understands this concept and are unable to embrace change.&lt;br /&gt;&lt;br /&gt;I dealt with this recently. We were planning for a mission. Our higher echelon wanted us to push out on a certain day. I felt we could do it. The Platoon Sergeants had a "feeling" that we could not push out until 2 days later. Usually , in the agile world, the nod would go to the Platoon Sergeants (the team).&lt;br /&gt;&lt;br /&gt;99% of the time I would agree. Although, sometimes, we are presented with time sensitive requirements. I attended a workshop several years ago at AgileXP, that talked about Advanced Estimation. They suggested that, in some cases, you have to push the envelope to get requirements met on time. I felt this was a time to push the envelope.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm3.static.flickr.com/2181/2329888538_4a2a643c21_m.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 316px; height: 237px;" src="http://farm3.static.flickr.com/2181/2329888538_4a2a643c21_m.jpg" alt="" border="0" /&gt;&lt;/a&gt;Well, since I am the acting XO, I argued my point. Eventually, I was able to convince the Platoon Sergeants that we could "try" to meet the requested date. I suggested, we would keep our higher echelon (the customer) informed by passing up incremental updates and letting them know the risks upfront. As the date approaches, and things aren't looking good, we give them the option of changing the operational scope. If the scope is what they value most then we suggest they push the date to the right.&lt;br /&gt;&lt;br /&gt;Ideally, we want to stay pragmatic and plan our time accordingly, but in a few cases we have no choice but to work out some solution. A common argument from the Platoon Sergeants was that our higher echelon would consider this a solid commitment and our hands would be tied if something went wrong. Surprisingly (not really) our higher echelon was very understanding and, like everyone in Army, was prepared for a contingency in which we were unable to meet the mission.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-8143823366460426627?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/DjqfPvQ-7CmupJP7Q05_yeSFN60/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/DjqfPvQ-7CmupJP7Q05_yeSFN60/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/DjqfPvQ-7CmupJP7Q05_yeSFN60/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/DjqfPvQ-7CmupJP7Q05_yeSFN60/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=d3cP4e51"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=EZagWQrb"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=EZagWQrb" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=SMoK2e0p"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=ojXdE5gY"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=ojXdE5gY" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=1B8Ewi9k"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=07FSG5kV"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=07FSG5kV" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/Z9e0EottA6g" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-19T20:20:50.623+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/03/programmer-at-war-in-iraq.html</feedburner:origLink></item><item><title>Webtest Tool Round-up (Round 1:WatiN)</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/jgswkUtqHPA/webtest-tool-round-up-round-1watin.html</link><category>tools</category><category>test driven development</category><category>watin</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Sun, 24 Feb 2008 21:15:56 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-8243808148477379468</guid><description>This is the first article in a series of reviews. I plan to test a few Open Source automated Web-Testing tools. As I complete my tests I will publish the results to my blog.&lt;br /&gt;&lt;h3&gt;  The Test Procedure&lt;br /&gt;&lt;/h3&gt;The world has gone Ajax and Web 2.0 crazy. Any tool that doesn't handle dynamically changing DOMs is an instant failure. So, I decided to use one of the most Ajax intense applications I know of, &lt;a title="Gmail" target="_blank" href="http://mail.google.com/" id="v_yi"&gt;Gmail&lt;/a&gt;. Gmail uses Ajax and Iframes indiscriminately. The developers at google seem to obfuscate ALL the HTML element IDs which means that my web-tests have to do some real back-flips to find the buttons, hyperlinks and textfields required to send messages. I have no doubt that Gmail will adequately stress the tools in this line-up.&lt;br /&gt;&lt;p&gt;&lt;b&gt;Test Steps&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Log in to Gmail&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Send an Email&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Check the same email&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Apply a Label&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Archive it&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Check to see if it is in the label category.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Log Out&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h1&gt;Round 1: WatiN (v1.2.1)&lt;/h1&gt;&lt;br /&gt;&lt;div style="float: left; margin-right: 10px; margin-bottom: 10px; width: 200px;"&gt;&lt;div&gt;&lt;p&gt;&lt;a href="http://watin.sourceforge.net/" id="y6hv" target="_blank" title="homepage"&gt;homepage&lt;/a&gt; | &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=167632" id="shr_" target="_blank" title="download"&gt;download&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;Test Date&lt;/u&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;17FEB08&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;Environment&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;Windows XP Home&lt;br /&gt;Visual Studio 2005&lt;br /&gt;.Net 2.0&lt;br /&gt;IE 7&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;PROS&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;Easy Install&lt;br /&gt;Integrates w/ Nunit&lt;br /&gt;Good &lt;a title="DSL" target="_blank" href="http://en.wikipedia.org/wiki/Domain_specific_language" id="d181"&gt;DSL&lt;/a&gt;&lt;br /&gt;Integrates with most xUnit&lt;br /&gt;Spreadsheet Tool&lt;br /&gt;Recorder&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;u&gt;CONS&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;IE Only until v2.0&lt;br /&gt;Requires IE to be running.&lt;br /&gt;The &lt;a title="DSL" target="_blank" href="http://en.wikipedia.org/wiki/Domain_specific_language" id="nc-a"&gt;DSL&lt;/a&gt; could be more intuitive.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;WatiN Project Overview&lt;/b&gt;&lt;br /&gt;&lt;a href="http://watin.sourceforge.net/" id="hc1w" target="_blank" title="WatiN Homepage"&gt;WatiN&lt;/a&gt; started life as a .Net clone of &lt;a style="border-bottom-style: groove;" title="Watir" target="_blank" href="http://wtr.rubyforge.org/" id="i7ju"&gt;Watir&lt;/a&gt;. Rather than emulate a browser, WatiN uses the browser's own API to conduct web-tests. As of this writing, WatiN only supports IE7, but they promise that the 2.0 version will have FireFox support.&lt;br /&gt;&lt;br /&gt;WatiN is technically just an API for controlling Internet Explorer, reading the DOM structure of web pages and triggering events on DOM elements. The library includes many utility methods (something of a DSL) that make scripting the tests ahead of time fairly trivial. Tests are written in you're favorite .Net language using your favorite .Net IDE.&lt;br /&gt;&lt;br /&gt;For my tests I used the standard Visual Studio/Nunit stack that I use for unit testing. In short I created a class library of Nunit TestFixtures and used TestDriven.Net to start the tests.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Getting Started&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When you download WatiN you have several options: a .Net 1.0 or .Net 2.0 installer or zip packages. I chose the .Net 2.0 installer. The install was pretty smooth. The installer, oddly enough, does not create any shortcuts for the documentation. Since WatiN is just an assembly and no shortcuts are created, the installer seems a bit superfluous.&lt;br /&gt;&lt;br /&gt;WatiN has no command-line runner. As I mentioned above, WatiN is intended to provide an API/DSL for automating Internet Explorer. You write tests and run them using your favorite xUnit tools.&lt;br /&gt;&lt;br /&gt;Before beginning the Gmail tests I worked through the "&lt;a href="http://watin.sourceforge.net/gettingstarted.html" id="no:k" target="_blank" title="Getting Started with WatiN"&gt;Getting Started&lt;/a&gt;" tutorial on the WatiN site. The tutorial walks you through creating a console executable that automates Internet Explorer. Unfortunately, I immediately ran into an error:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="color: rgb(204, 102, 0);"&gt;&lt;span style="color: rgb(102, 0, 0);"&gt;COMException: Retrieving the COM class factory for component with CLSID {0002DF01-0000-0000-C000-000000000046} failed due to the following error: 80040154.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;After playing around with the code a bit I eventually discovered that IE must be running in order to get the console app to work properly. Once I started IE the Getting-Started app ran as expected. Internet Explorer opened and navigated to the appropriate pages. I could watch each click in the browser and it was kinda nice. Now I am ready to write some fixtures to pass my Gmail test!&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Bring on the Gmail&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I used &lt;a style="border-bottom-style: groove;" title="FireBug" target="_blank" href="http://www.getfirebug.com/" id="b_-s"&gt;FireBug&lt;/a&gt;'s excellent HTML inspection tool to find the element IDs of each button and text field I would need. I wrote all the tests as Nunit TestFixtures. This was very easy since I already write TestFixtures for all my other projects. I used the test Setup method to launch an Instance of IE and closed IE in the TearDown method. WatiN provides pretty intuitive methods for controlling the browser.&lt;br /&gt;&lt;br /&gt;The first thing that hits me while writing the fixture is the DSL. For the most part, I really like it. But, it could be re-factored a bit. In the example below, I wait for and then enter text into the email text box:&lt;br /&gt;&lt;pre name="code" class="c-sharp:nogutter:nocontrols"&gt;&lt;br /&gt;ie.TextField("Email").WaitUntilExists();&lt;br /&gt;&lt;br /&gt;ie.TextField("Email").TypeText("******@gmail.com");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I would prefer to do something like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div   style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Courier New;color:black;"&gt;&lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;   18&lt;/span&gt; ie.TextField(&lt;span style="color: rgb(163, 21, 21);"&gt;"Email"&lt;/span&gt;).WaitUntilExists().TypeText(&lt;span style="color: rgb(163, 21, 21);"&gt;"*****@gmail.com"&lt;/span&gt;);&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;I also discovered that WatiN requires STA Threading. The web site doesn't hide this fact either. This required a small work around in Nunit. To guarantee STA Threading in &lt;a title="Nunit" target="_blank" href="http://www.nunit.org/index.php" id="c1_4"&gt;Nunit&lt;/a&gt; (.Net 2.0) you must define it in your test assembly's config file:&lt;br /&gt;&lt;pre name="code" class="xml:collapse"&gt;  &amp;lt;configuration&amp;gt;&lt;br /&gt;&amp;lt;configSections&amp;gt;&lt;br /&gt;  &amp;lt;sectionGroup name="NUnit"&amp;gt;&lt;br /&gt;    &amp;lt;section name="TestRunner" type="System.Configuration.NameValueSectionHandler"/&amp;gt;&lt;br /&gt;  &amp;lt;/sectionGroup&amp;gt;&lt;br /&gt;&amp;lt;/configSections&amp;gt;&lt;br /&gt;&amp;lt;NUnit&amp;gt;&lt;br /&gt;  &amp;lt;TestRunner&amp;gt;&lt;br /&gt;    &amp;lt;!-- Valid values are STA,MTA. Others ignored. --&amp;gt;&lt;br /&gt;    &amp;lt;add key="ApartmentState" value="STA" /&amp;gt;&lt;br /&gt; &amp;lt;/TestRunner&amp;gt;&lt;br /&gt;&amp;lt;/NUnit&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;/pre&gt;The Gmail tests went surprisingly well. The browser opened up. The appropriate items were clicked, textfields were filled in and my emails were sent. As with most tests, I found a lot of overlap in the web-tests. The login and logout routines were used quite often as well as other routines. In order to simplify the tests and practice good "Once and Only Once", I re-factoring the logoff and login into separate utility methods.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Other WatiN Tools&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;WatiN also has two other contributed tool projects; &lt;a title="Wax" target="_blank" href="http://www.codeplex.com/wax/" id="cj9x"&gt;Wax&lt;/a&gt; and &lt;a title="WatiN Recorder" target="_blank" href="http://watintestrecord.sourceforge.net/" id="g7ow"&gt;WatiN Recorder&lt;/a&gt;. With Wax you can write simple test suites in an excel spreadsheet (think FIT but easier) and run them directly. WatiN Recorder is a fairly robust recording tool that will help when you are writing tests for legacy code.&lt;br /&gt;&lt;h2&gt;Final Thoughts About WatiN&lt;/h2&gt;I found WatiN to be quite impressive.  WatiN includes about as much DOM search functionality as you could ask for. You can find anything including elements embedded in IFrames. You can trigger any event you wish. The DSL is fairly intuitive but if need be you can drop into XPath style searches. Keep your tests simple by searching for element IDs. Write your tests first and design the UI that the tests are written for. You can check out their &lt;a title="API to HTML mappings" target="_blank" href="http://watin.sourceforge.net/htmlelementmapping.html" id="y:cn"&gt;API to HTML mappings&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For me the fact that the tests are written in .Net/Visual Studio was very nice. This allows you to leverage Visual Studio's intellisense and the full power of the .Net framework. Your testers may not find it as easy to write Nunit tests. I would recommend using Wax tests in those cases. It doesn't support the most complex features of WatiN but I would suggest your site should stay away from an overly complex UI.&lt;br /&gt;&lt;br /&gt;While the tutorial project was refreshing in the fact that it has no dependencies, other than WatiN. I worry that those developers who remain uninitiated into the world of TDD will read this as the accepted method fr running WatiN. I would prefer to see a tutorial that employs a unit testing tool.&lt;br /&gt;&lt;br /&gt;Most shops will have many reasons for implementing an automated web-testing tool. For me, the most compelling reason is the value it brings to your user experience design. By writing automated tests first, you are forcing your UI design to be simple. In short, the UI you create, to pass the tests, will do the simplest thing that could possibly work. This allows you to deliver "any kind of value immediately". The cool stuff (web2.0) can be added later AFTER the necessary stuff is done.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Here is the source of my &lt;a href="http://www.agilejedi.com/WatiNTest.zip"&gt;test project&lt;/a&gt;. Don't forget to install &lt;a href="http://www.nunit.org"&gt;Nunit&lt;/a&gt; and &lt;a href="http://watin.sf.net"&gt;Watin&lt;/a&gt;!&lt;/span&gt;&lt;br /&gt;&lt;h2&gt;Round 2?&lt;/h2&gt;&lt;i&gt;For Round 2 I plan to test &lt;/i&gt;&lt;a style="border-bottom-style: groove;" title="Selenium" target="_blank" href="http://selenium.openqa.org/" id="b_80"&gt;&lt;i&gt;Selenium&lt;/i&gt;&lt;/a&gt;&lt;i&gt;! So stay tuned....&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-8243808148477379468?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/hq3sUPwTPzgmU9mw6HCUwx8_EwM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hq3sUPwTPzgmU9mw6HCUwx8_EwM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/hq3sUPwTPzgmU9mw6HCUwx8_EwM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/hq3sUPwTPzgmU9mw6HCUwx8_EwM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=r6xbMuDJ"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=k5kFXgTc"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=k5kFXgTc" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=n52CTz7p"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=6h3dw2vQ"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=6h3dw2vQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=1liqsLCJ"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=yfxPxXRX"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=yfxPxXRX" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/jgswkUtqHPA" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-25T08:15:56.968+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><enclosure url="http://www.agilejedi.com/WatiNTest.zip" length="3894" type="application/octet-stream" /><media:content url="http://www.agilejedi.com/WatiNTest.zip" fileSize="3894" type="application/octet-stream" /><itunes:explicit>no</itunes:explicit><itunes:subtitle>This is the first article in a series of reviews. I plan to test a few Open Source automated Web-Testing tools. As I complete my tests I will publish the results to my blog. The Test Procedure The world has gone Ajax and Web 2.0 crazy. Any tool that doesn</itunes:subtitle><itunes:author>Dan Pupek</itunes:author><itunes:summary>This is the first article in a series of reviews. I plan to test a few Open Source automated Web-Testing tools. As I complete my tests I will publish the results to my blog. The Test Procedure The world has gone Ajax and Web 2.0 crazy. Any tool that doesn't handle dynamically changing DOMs is an instant failure. So, I decided to use one of the most Ajax intense applications I know of, Gmail. Gmail uses Ajax and Iframes indiscriminately. The developers at google seem to obfuscate ALL the HTML element IDs which means that my web-tests have to do some real back-flips to find the buttons, hyperlinks and textfields required to send messages. I have no doubt that Gmail will adequately stress the tools in this line-up. Test Steps Log in to Gmail Send an Email Check the same email Apply a Label Archive it Check to see if it is in the label category. Log Out Round 1: WatiN (v1.2.1) homepage | download Test Date 17FEB08 Environment Windows XP Home Visual Studio 2005 .Net 2.0 IE 7 PROS Easy Install Integrates w/ Nunit Good DSL Integrates with most xUnit Spreadsheet Tool Recorder CONS IE Only until v2.0 Requires IE to be running. The DSL could be more intuitive. WatiN Project Overview WatiN started life as a .Net clone of Watir. Rather than emulate a browser, WatiN uses the browser's own API to conduct web-tests. As of this writing, WatiN only supports IE7, but they promise that the 2.0 version will have FireFox support. WatiN is technically just an API for controlling Internet Explorer, reading the DOM structure of web pages and triggering events on DOM elements. The library includes many utility methods (something of a DSL) that make scripting the tests ahead of time fairly trivial. Tests are written in you're favorite .Net language using your favorite .Net IDE. For my tests I used the standard Visual Studio/Nunit stack that I use for unit testing. In short I created a class library of Nunit TestFixtures and used TestDriven.Net to start the tests. Getting Started When you download WatiN you have several options: a .Net 1.0 or .Net 2.0 installer or zip packages. I chose the .Net 2.0 installer. The install was pretty smooth. The installer, oddly enough, does not create any shortcuts for the documentation. Since WatiN is just an assembly and no shortcuts are created, the installer seems a bit superfluous. WatiN has no command-line runner. As I mentioned above, WatiN is intended to provide an API/DSL for automating Internet Explorer. You write tests and run them using your favorite xUnit tools. Before beginning the Gmail tests I worked through the "Getting Started" tutorial on the WatiN site. The tutorial walks you through creating a console executable that automates Internet Explorer. Unfortunately, I immediately ran into an error: COMException: Retrieving the COM class factory for component with CLSID {0002DF01-0000-0000-C000-000000000046} failed due to the following error: 80040154. After playing around with the code a bit I eventually discovered that IE must be running in order to get the console app to work properly. Once I started IE the Getting-Started app ran as expected. Internet Explorer opened and navigated to the appropriate pages. I could watch each click in the browser and it was kinda nice. Now I am ready to write some fixtures to pass my Gmail test! Bring on the Gmail I used FireBug's excellent HTML inspection tool to find the element IDs of each button and text field I would need. I wrote all the tests as Nunit TestFixtures. This was very easy since I already write TestFixtures for all my other projects. I used the test Setup method to launch an Instance of IE and closed IE in the TearDown method. WatiN provides pretty intuitive methods for controlling the browser. The first thing that hits me while writing the fixture is the DSL. For the most part, I really like it. But, it could be re-factored a bit. In the example below, I wait for and then enter text into the email text box: ie.TextField("Email").WaitUntilExists(); ie.T</itunes:summary><itunes:keywords>tools, test driven development, watin</itunes:keywords><feedburner:origLink>http://blog.agilejedi.com/2008/02/webtest-tool-round-up-round-1watin.html</feedburner:origLink></item><item><title>Microsoft MVC or Is the Monorail off it's track?</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/9-GBbDO6lOw/microsoft-mvc-or-is-monorail-off-its.html</link><category>tools</category><category>MVC Framework</category><category>monorail</category><category>microsoft</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Wed, 20 Feb 2008 09:15:25 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-6912034649770181913</guid><description>For those of you who didn't know, Microsoft has been working on it's own &lt;a href="http://weblogs.asp.net/scottgu/archive/2008/02/12/asp-net-mvc-framework-road-map-update.aspx?CommentPosted=true#commentmessage"&gt;MVC framework&lt;/a&gt;.  I haven't used it yet since I am in the middle of testing several Web-testing tools for an upcoming article. That said, I have done a little research on the web and here are a few things that &lt;a href="http://www.castleproject.org/monorail/"&gt;Monorail &lt;/a&gt;users may want to know:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://hammett.castleproject.org/"&gt;Hammett&lt;/a&gt;, the founder of Castle::Monorail, &lt;span style="text-decoration: underline;"&gt;has helped &lt;/span&gt; MS by making suggestions about their implementation. See his comment below:&lt;br /&gt;&lt;blockquote&gt;I'm not actively collaborating with MS regarding the MS MVC. I've offered help due to my expertise with complex web sites we have built using MonoRail, I was invited to fly to Redmond and analyze their product, and discuss things, make suggestions.&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;It's been suggested (in comments) that Monorail may become a wrapper for the MS Framework, if the MS MVC framework progresses well.&lt;/li&gt;&lt;li&gt;The MS Framework does support intellisense in it's views. Views are written in your .Net language of choice.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;ASP.Net controls are available for use in Views.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The MS Framework does not forbid the use of ActiveRecord but with LINQ on the horizon developers may choose it. (I haven't played with the LINQ extensions yet)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Monorail is more time tested (and just works)! Also, the MS framework is closed source.&lt;/li&gt;&lt;li&gt;The MS MVC framework will allow you to use any xUnit framework and any Mocking framework you choose but, as of this writing the MS solution has nothing nearly as kewl as the Monorail BaseControllerTest.&lt;/li&gt;&lt;li&gt;I can find nothing about IoC support in the MS offering.&lt;/li&gt;&lt;li&gt;Some people believe the routing engine in the MS offering is easier to configure. I'll have to test this assumption.&lt;/li&gt;&lt;/ul&gt;I personally have no plan to switch to the Microsoft framework yet. I DO believe the MS Framework will introduce MS developers to how great MVC can be. I also believe that Microsoft will slowly position the MVC framework as it's preferred web-app architecture.  The ASP.Net architecture, while successful, was a fundamentally flawed offering that should be abandoned quickly.&lt;br /&gt;&lt;br /&gt;As Microsoft moves into this new territory we'll start to see a subtle change in how they do business. The .Net framework was their last major move ( just had it's 6 year anniversary). The latest signs of change are already out there;  LINQ, extension methods, the MVC architecture. Things to look for now; Redesigning the Ajax.Net library, functional programming with F#, greater support for DSLs.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Some Interesting Links&lt;/span&gt;&lt;a style="border-bottom-style: groove;" href="http://mikehadlow.blogspot.com/2008/01/writing-unit-tests-for-mvc-framework.html"&gt;&lt;br /&gt;&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a style="border-bottom-style: groove;" href="http://mikehadlow.blogspot.com/2008/01/writing-unit-tests-for-mvc-framework.html"&gt;Code Rant: Writing Unit Tests with the MVC Framework&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Hammett's article about his &lt;a href="http://hammett.castleproject.org/?p=219"&gt;visit to MS&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Oren discusses &lt;a href="http://www.ayende.com/Blog/archive/2007/12/13/Dont-like-visibility-levels-change-that.aspx"&gt;protected methods in the MS MVC&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Oren discusses the &lt;a href="http://www.ayende.com/Blog/archive/2007/12/08/Configuration-over-Convention.aspx"&gt;ControllerActionAtribute&lt;/a&gt;. This has alreay been removed by MS...&lt;/li&gt;&lt;li&gt;Ryan doom &lt;a href="http://www.ryandoom.com/Blog/tabid/57/articleType/ArticleView/articleId/42/ASP-NET-MVC-vs-Monorail-Castle-Project.aspx"&gt;asks which Framework to Go with...&lt;/a&gt;&lt;/li&gt;&lt;li&gt;The &lt;a href="http://www.castleproject.org/monorail/"&gt;Castle::Monorail site&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-style: italic;"&gt;Let me know if you have any other questions. I'll try to answer them as I play with the new framework.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-6912034649770181913?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CzbQYA_dvlbXnnwC_OYE9AsUfho/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CzbQYA_dvlbXnnwC_OYE9AsUfho/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CzbQYA_dvlbXnnwC_OYE9AsUfho/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CzbQYA_dvlbXnnwC_OYE9AsUfho/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=l2FpUDaX"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=wTTtVKoO"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=wTTtVKoO" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=uMhgzlqr"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=za7oFhxe"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=za7oFhxe" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=1wUwgGao"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=Qv0izIOo"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=Qv0izIOo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/9-GBbDO6lOw" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-20T20:15:25.395+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">6</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/02/microsoft-mvc-or-is-monorail-off-its.html</feedburner:origLink></item><item><title>Getting the Data out of my Controller Tests</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/a654nPgGmYQ/getting-data-out-of-my-controller-tests.html</link><category>mocks</category><category>test driven development</category><category>monorail</category><category>software engineering</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Sun, 24 Feb 2008 11:30:36 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-4748864205632531731</guid><description>&lt;p&gt;While working on &lt;a href="http://code.google.com/p/planningpokeronrails/"&gt;PlanningPokerOnRails &lt;/a&gt;I started writing a unit test for my LoginController. The &lt;a href="http://www.castleproject.org/monorail/"&gt;Monorail &lt;/a&gt;BaseControllerTest makes this easy. I am also using &lt;a href="http://www.ayende.com/projects/rhino-mocks.aspx" style="border-bottom-style: groove;"&gt;Rhino Mocks&lt;/a&gt; and &lt;a href="http://www.nunit.org/index.php"&gt;Nunit&lt;/a&gt;. Here is the test:&lt;br /&gt;&lt;/p&gt;&lt;pre name="code" class="c-sharp"&gt;&lt;br /&gt;[TestFixture]&lt;br /&gt;public class LoginTests : BaseControllerTest{&lt;br /&gt; Rhino.Mocks.MockRepository mocks = new MockRepository();&lt;br /&gt; Controllers.LoginController loginController;&lt;br /&gt;&lt;br /&gt; protected override IMockResponse BuildResponse(){&lt;br /&gt;&lt;br /&gt;  return mocks.CreateMock&amp;lt;IMockResponse&amp;gt;();&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [SetUp]&lt;br /&gt; public void Setup_context(){&lt;br /&gt;&lt;br /&gt;  loginController = new LoginController();&lt;br /&gt;&lt;br /&gt;  PrepareController(loginController);&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; [Test(Description="Proper Login")]&lt;br /&gt; public void ProperLoginTest(){&lt;br /&gt;&lt;br /&gt;  using (mocks.Record()){&lt;br /&gt;&lt;br /&gt;   // First redirects to the index page&lt;br /&gt;&lt;br /&gt;   Response.Redirect("/Home/Index.rails");&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  using (mocks.Playback()){&lt;br /&gt;&lt;br /&gt;   Request.Params.Add("ReturnUrl", "/Home/Index.rails");&lt;br /&gt;&lt;br /&gt;   loginController.Login("dan", "danny");&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  Assert.IsNotNull(loginController.Context.CurrentUser);&lt;br /&gt;  Assert.IsInstanceOfType(typeof(CardPlayer), loginController.Context.CurrentUser);&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The test is very simple. First, it sets a single recorded expectation that a Redirect will occur:&lt;br /&gt;&lt;br /&gt;&lt;div    style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Courier New;font-size:10pt;color:black;"&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 34&lt;/span&gt; &lt;span style="color:blue;"&gt;using&lt;/span&gt; (mocks.Record())&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 35&lt;/span&gt; {&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 36&lt;/span&gt; &lt;span style="color:green;"&gt;// First redirects to the index page&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 37&lt;/span&gt; Response.Redirect(&lt;span style="color: rgb(163, 21, 21);"&gt;"/Home/Index.rails"&lt;/span&gt;);&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 38&lt;/span&gt; }&lt;/p&gt; &lt;/div&gt;&lt;br /&gt;Next, the playback is run and the code emulates a few things that users might do...like login with Request params for a ReturnUrl:&lt;br /&gt;&lt;br /&gt;&lt;div    style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Courier New;font-size:10pt;color:black;"&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 39&lt;/span&gt; &lt;span style="color:blue;"&gt;using&lt;/span&gt; (mocks.Playback())&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 40&lt;/span&gt; {&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 41&lt;/span&gt; Request.Params.Add(&lt;span style="color: rgb(163, 21, 21);"&gt;"ReturnUrl"&lt;/span&gt;, &lt;span style="color: rgb(163, 21, 21);"&gt;"/Home/Index.rails"&lt;/span&gt;);&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 42&lt;/span&gt; loginController.Login(&lt;span style="color: rgb(163, 21, 21);"&gt;"dan"&lt;/span&gt;, &lt;span style="color: rgb(163, 21, 21);"&gt;"danny"&lt;/span&gt;);&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 43&lt;/span&gt; }&lt;/p&gt; &lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;p style="margin: 0px; font-weight: bold;" face="arial"&gt;Writing the Code to Pass this Test&lt;/p&gt; &lt;p style="margin: 0px;" face="arial"&gt;Next I wrote the CardPlayer component (my user) and the LoginController. Seeking to do the simplest thing that could possibly work I merely had the CardPlayer inherit from the &lt;a href="http://www.castleproject.org/ActiveRecord/"&gt;ActiveRecord &lt;/a&gt;base.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0px;" face="arial"&gt;This made writing the controller easy, the ActiveRecord base has plenty of good methods for instantiating. I only have to call the FindOne method on the CardPlayer:&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0px;"&gt; &lt;/p&gt; &lt;div    style="background: white none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;font-family:Courier New;font-size:10pt;color:black;"&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 104&lt;/span&gt; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;CardPlayer&lt;/span&gt; FindCardPlayer(&lt;span style="color:blue;"&gt;string&lt;/span&gt; UserName,&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 105&lt;/span&gt; &lt;span style="color:blue;"&gt;string&lt;/span&gt; Password){&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 106&lt;/span&gt;&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 107&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;CardPlayer&lt;/span&gt; user = FindOne(NHibernate.Expression.&lt;span style="color: rgb(43, 145, 175);"&gt;Expression&lt;/span&gt;.And(&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 108&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;Expression&lt;/span&gt;.Eq(&lt;span style="color: rgb(163, 21, 21);"&gt;"Username"&lt;/span&gt;, UserName),&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 109&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;Expression&lt;/span&gt;.Eq(&lt;span style="color: rgb(163, 21, 21);"&gt;"Password"&lt;/span&gt;, Password)));&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 110&lt;/span&gt; &lt;span style="color:blue;"&gt;return&lt;/span&gt; user;&lt;/p&gt; &lt;p style="margin: 0px;"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt; 111&lt;/span&gt; }&lt;/p&gt; &lt;/div&gt; &lt;p style="margin: 0px;"&gt; &lt;/p&gt; &lt;b&gt;&lt;br /&gt;So why all the Problems?&lt;/b&gt;&lt;br /&gt;I never intended to initialize ActiveRecord, in my tests assembly. I believe that test data should only be used for Acceptance Tests. It turns out that the test fails because no ActiveRecord config or initialization exists.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;How do I solve this?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I forgot to implement good Dependency Injection. The way I would normally grab an instance of a component (like the CardPlayer) is through a service container (or repository). MVC architectures generally have two types of Model objects; Components (like the CardPlayer) and Services (like the CardPlayer Service I should have written). The services usually act like or wrap a repository of Components. In my opinion, ActiveReecord already provides the repository.&lt;br /&gt;&lt;br /&gt;It turns out my solution is to write a CardPlayer Service container. This object will go into the IoC container (winsor) and be automatically injected into whatever controller requires it (like the LoginController). The service will use the ActiveRecordMediator to instantiate new CardPlayers and I can remove the ActiveRecordBase from my CardPlayer component.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Wait why does this help?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Well by forcing all instantiation to go through injected Services your tests can easily inject a Mock Service (I use Rhino Mocks) and tell the Mock to provide predefined instances of components. Since you have mocked the service layer you no longer need ActiveRecord in your tests!&lt;br /&gt;&lt;br /&gt;&lt;p style="margin: 0px;" face="arial"&gt;&lt;b&gt;Keeping the Data&lt;/b&gt;&lt;br /&gt;Now that I've convinced you to write a service layer, I am going to tell you that you may not need it! While you can mock the Services going to your controllers you cannot easily get rid of ActiveRecord when testing the services. For most simple lookups a test may not be appropriate but in many cases your component lookup up and other operations will be non-trivial. For these cases you will want to test the service layer and you may have to initialize ActiveRecord.&lt;br /&gt;&lt;br /&gt;You could decide to Mock the ActiveRecordMediator or you could use an approach similar to &lt;a style="border-bottom-style: groove;" href="http://www.ayende.com/Blog/archive/2006/10/14/7183.aspx"&gt;Oren's&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0px;" face="arial"&gt; &lt;/p&gt; &lt;p style="margin: 0px;" face="arial"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;&lt;p style="margin: 0px;" face="arial"&gt;&lt;b&gt;I'm Confused...&lt;/b&gt;&lt;/p&gt; &lt;p style="margin: 0px;" face="arial"&gt;I admit that this is some advanced stuff. I promise to come back to this post and update it with more concise information.&lt;/p&gt;&lt;br /&gt;&lt;p style="margin: 0px; font-family: arial;"&gt;&lt;i&gt;Please leave comments on ways I can do this without a service layer. Thanks!&lt;/i&gt;&lt;/p&gt; &lt;p style="margin: 0px;"&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-4748864205632531731?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/kNwXAaVdkotQPfQuVSlWoso8X5U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kNwXAaVdkotQPfQuVSlWoso8X5U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/kNwXAaVdkotQPfQuVSlWoso8X5U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/kNwXAaVdkotQPfQuVSlWoso8X5U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=5mtRBCuu"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=j2eNgsyY"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=j2eNgsyY" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=zWVJkKK4"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=lKC3YeOe"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=lKC3YeOe" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=tBbU3EKD"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=I8B65sk3"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=I8B65sk3" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/a654nPgGmYQ" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-24T22:30:36.933+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/02/getting-data-out-of-my-controller-tests.html</feedburner:origLink></item><item><title>Is this a SourceForge Killer?</title><link>http://feedproxy.google.com/~r/SomethingSmells/~3/LrA1h_-V-VA/is-this-sourceforge-killer.html</link><category>open source</category><category>projects</category><category>tools</category><author>noreply@blogger.com (Dan Pupek)</author><pubDate>Thu, 07 Feb 2008 01:05:00 PST</pubDate><guid isPermaLink="false">tag:blogger.com,1999:blog-27472404.post-5828985340857478117</guid><description>I doubt that the &lt;a style="border-bottom-style: groove;" href="http://code.google.com/hosting/"&gt;Google Code Projects&lt;/a&gt;&lt;a style="border-bottom-style: groove;" href="http://code.google.com/hosting/"&gt; Hosting&lt;/a&gt; will compete with &lt;a href="http://www.sf.net/"&gt;SourceForge &lt;/a&gt;anytime soon but it does put Google one step closer to being the next &lt;a href="http://en.wikipedia.org/wiki/Skynet_%28fictional%29"&gt;SkyNet&lt;/a&gt;. I've been hosting one of my recent &lt;a style="border-bottom-style: groove;" href="http://code.google.com/p/planningpokeronrails/"&gt;open source projects&lt;/a&gt; there and been quite pleased. Here are a few features of note:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It's &lt;span style="font-weight: bold;"&gt;FREE&lt;/span&gt;! (So is SourceForge by the way)&lt;/li&gt;&lt;li&gt;Provides a &lt;span style="font-weight: bold;"&gt;Subversion Repository&lt;/span&gt; with a really slick online browser. &lt;a style="border-bottom-style: groove;" href="http://code.google.com/p/planningpokeronrails/source/browse"&gt;Check it out here&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Most of the interface is a just a frontend to a &lt;span style="font-weight: bold;"&gt;smart wiki&lt;/span&gt;. So you can use wiki code just about anywhere.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;You can add &lt;span style="font-weight: bold;"&gt;users &lt;/span&gt;into different roles.&lt;/li&gt;&lt;li&gt;The Issue Tracker is relatively complete and fairly customizable since it's a highly specialized wiki. It allows you to assign tasks and track the workflow in your own way.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Plain old &lt;span style="font-weight: bold;"&gt;Wiki&lt;/span&gt;. For all your other needs there is a fairly robust wiki.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Package Download&lt;/span&gt; system allows you to upload your latest builds, documentation or whatever.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;100MB of storage&lt;/span&gt; for your source (you can request more).&lt;/li&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;Google account&lt;/span&gt; logins are used. As a matter of fact an Google Account login can be used.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Limited customization of the &lt;span style="font-weight: bold;"&gt;look and feel&lt;/span&gt;.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;What has impressed me the most is it's barebones nature. No banner ads poping out. Searching is fast. Most of all, it seems to be growing in features. When I first started my project they had no source browser available. Now it has one of the best SVN browsers I have seen (FishEye would be better). I also feel like they are driven by user's needs. If enough people request a feature then they just build it in!&lt;br /&gt;&lt;br /&gt;Finally, I really think that Google's approach to software development is very Agile. They always build the simplest thing that could possibly work and then add new features as users ask for them. We could learn a lot from this approach.&lt;div class="blogger-post-footer"&gt;&lt;script type="text/javascript"&gt;&lt;!--
google_ad_client = "pub-5346106515112371";
/* BLOG 234x60, created 2/7/08 */
google_ad_slot = "2921275346";
google_ad_width = 234;
google_ad_height = 60;
//--&gt;
&lt;/script&gt;
&lt;script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27472404-5828985340857478117?l=blog.agilejedi.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/G5hls-Wjf6LjHG3T4Qx8-OKJSyA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/G5hls-Wjf6LjHG3T4Qx8-OKJSyA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/G5hls-Wjf6LjHG3T4Qx8-OKJSyA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/G5hls-Wjf6LjHG3T4Qx8-OKJSyA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=lpTdHogr"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=41" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=4D2Bmktk"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=4D2Bmktk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=xLuWA9wR"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=43" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=ikXQnWwJ"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=ikXQnWwJ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=vutEEiXd"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?d=50" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/SomethingSmells?a=sZ3IyEch"&gt;&lt;img src="http://feeds.feedburner.com/~f/SomethingSmells?i=sZ3IyEch" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/SomethingSmells/~4/LrA1h_-V-VA" height="1" width="1"/&gt;</description><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-07T12:05:00.698+03:00</app:edited><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.agilejedi.com/2008/02/is-this-sourceforge-killer.html</feedburner:origLink></item><media:credit role="author">Dan Pupek</media:credit><media:rating>nonadult</media:rating></channel></rss>
