<?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:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>CodeBetter.Com</title>
	
	<link>http://codebetter.com</link>
	<description>Stuff you need to Code Better!</description>
	<lastBuildDate>Sat, 10 Dec 2011 20:21:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
	
	
	       
    	<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/CodeBetter" /><feedburner:info uri="codebetter" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><item>
		<title>My appearance on Dot Net Rocks – SOPA</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/OM_M5gBDfGw/</link>
		<comments>http://codebetter.com/johnpetersen/2012/02/06/my-appearance-on-dot-net-rocks-sopa/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 12:49:18 +0000</pubDate>
		<dc:creator>johnvpetersen</dc:creator>
				<category><![CDATA[ACTA]]></category>
		<category><![CDATA[Dot Net Rocks]]></category>
		<category><![CDATA[IP Law]]></category>
		<category><![CDATA[SOPA]]></category>
		<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/johnpetersen/?p=148</guid>
					<description><![CDATA[Recently, I was a guest on Dot Net Rocks. As you can see from the comments, this episode stirred the pot a bit. As I&#8217;ve always said, if you are not ticking off&#160;at least a few people &#8211; you are&#160;&#8230; <a href="http://codebetter.com/johnpetersen/2012/02/06/my-appearance-on-dot-net-rocks-sopa/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Recently, I was a guest on <a href="http://www.dotnetrocks.com/default.aspx?showNum=736">Dot Net Rocks</a>. As you can see from the comments, this episode stirred the pot a bit. As I&#8217;ve always said, if you are not ticking off&nbsp;at least a few people &#8211; you are not trying hard enough! There is an update to this show that will be airing on 2/9. The original focus of the show was on <a href="http://en.wikipedia.org/wiki/Stop_Online_Piracy_Act">SOPA</a> &#8211; discussing what it is and perhaps more importantly, what it is not. During the show, I had added that one of the sources of intellectual property law are treaties that the United States ratifies. Seems like a non-consequential statement at the time. Turns out &#8211; it was not. For a few years, <a href="http://en.wikipedia.org/wiki/Anti-Counterfeiting_Trade_Agreement">ACTA </a>has been discussed&nbsp; &#8211; but the topic has not received too much air play given that SOPA was in the news. Now that SOPA has been removed from consideration, ACTA has now entered the limelight.</p>
<p>I want to be clear here &#8211; I don&#8217;t agree with those that say that laws like SOPA and treaties like ACTA &#8211; subvert free speech. Stealing the intellectual property of others is not something that should be tolerated. That said, there&nbsp;were some troubling aspects in SOPA &#8211; mostly arising form the lack of due process. The major problem was that based on a mere allegation &#8211; a&nbsp;site <strong><em>could be shut down</em></strong>. &nbsp;It remained to be seen how that law would have been enforced.</p>
<p>ACTA is another thing altogether in that it is a treaty. In my opinion, <a href="http://www.fsf.org/campaigns/acta/">organizations like the Free Software Foundation (FSF) &#8211; completely mis-represent what ACTA is</a>. If there is one thing about ACTA I think is worthy of criticism is the secrecy around the treaty negotiations.</p>
<p>In general, I&#8217;m a fan of the FSF. That said, the torch and pitchfork crowd goes a bit too far with their assertions. Here are the FSF&#8217;s points:</p>
<ol>
<li>It makes it more difficult to distribute free software: Without file sharing and P2P technologies like BitTorrent, distributing large amounts of free software becomes much harder, and more expensive. BitTorrent is a grassroots protocol that allows everyone to contribute to legally distributing free software.</li>
<li>It will make it harder for users of free operating systems to play media: Consumers may no longer be able to buy media without DRM &#8212; and DRMed media cannot be played with free software.</li>
<li>It increases the chances of getting your devices taken away: Portable media players that support free formats are less common than devices which support DRM, such as the iPod. Will this make them suspicious to border guards?</li>
<li>It creates a culture of surveillance and suspicion, in which the freedom that is required to produce free software is seen as dangerous and threatening rather than creative, innovative, and exciting.</li>
</ol>
<p>First off, folks need to read ACTA. It states pretty clearly that notions of due process and free speech must endure &#8211; that the manner of how ACTA is enforced must be consistient with those ideals. Put it this way, illegal activity occurs on cell phones and computers. Are we less likely to use those devices? Are those devices confiscated today? Of course not. File sharing technology supports legal activities. Indeed, it can support illegal activities as well. That however, does not mean those technologies will go away. This is where common sense and practicality have to kick in. For example &#8211; let&#8217;s say you in fact, have illegal copies of music on your iPod. How can you tell by looking at the device? More importantly, how could a customs tell? Do we really think this is going to be a priority?&nbsp; </p>
<p>The fact is &#8211; pirated software, music and counterfeit goods are a problem &#8211; and it is well within the province of rights-holders to prosecute and protect their rights. That said, it cannot and should not happen at the expense of our rights and our rights to use technology that has legitimate purposes. I happen to think that the MPAA and RIAA, while they have some legitimate concerns, are also comprised of people that for the most part &#8211; are clueless on how to deal with these matters. If there is one point to take from the DNR episodes it is this &#8211; GET INVOLVED AND STAY INFORMED. If there is one suggestion I&#8217;d make to those who have to craft legislation and ratify treaties &#8211; it is this &#8211; G</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="shr-publisher-148"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnpetersen%2F2012%2F02%2F06%2Fmy-appearance-on-dot-net-rocks-sopa%2F' data-shr_title='My+appearance+on+Dot+Net+Rocks+-+SOPA'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnpetersen%2F2012%2F02%2F06%2Fmy-appearance-on-dot-net-rocks-sopa%2F' data-shr_title='My+appearance+on+Dot+Net+Rocks+-+SOPA'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnpetersen%2F2012%2F02%2F06%2Fmy-appearance-on-dot-net-rocks-sopa%2F' data-shr_title='My+appearance+on+Dot+Net+Rocks+-+SOPA'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/OM_M5gBDfGw" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/johnpetersen/2012/02/06/my-appearance-on-dot-net-rocks-sopa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
					<feedburner:origLink>http://codebetter.com/johnpetersen/2012/02/06/my-appearance-on-dot-net-rocks-sopa/</feedburner:origLink></item>
	      
    	<item>
		<title>QA: A Hillbilly Love Story</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/zJD-Dn3ODko/</link>
		<comments>http://codebetter.com/kylebaley/2012/01/30/qa-a-hillbilly-love-story/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 21:34:15 +0000</pubDate>
		<dc:creator>Kyle Baley</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Conscientious Coding]]></category>
		<category><![CDATA[Development]]></category>
			<guid isPermaLink="false">http://codebetter.com/kylebaley/?p=263</guid>
					<description><![CDATA[The hillbilly turned forty last weekend! I’ve been anticipating this giddily because now, I can be crotchety and people will still find me adorable. I hate QA. Hate, hate, hate, HATE, HATE, HATE it. I despise it so much, I&#160;&#8230; <a href="http://codebetter.com/kylebaley/2012/01/30/qa-a-hillbilly-love-story/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>The hillbilly turned forty last weekend! I’ve been anticipating this giddily because now, I can be crotchety and people will still find me adorable.</p>
<p>I hate QA. Hate, hate, hate, HATE, <em>HATE</em>, <strong><em>HATE</em></strong> it. I despise it so much, I think I might swear. Here goes….I f&#8212;, okay, I can’t do it but I still &amp;*%$ hate it.</p>
<div style="background-color: #eee;margin: 5px;width: 200px;float: right;border: #ccc 1px solid;padding: 5px">Side note: I know <em>all</em> QA people weren’t raised by trolls and/or gnomes but I’m going to generalize here. If you are a QA person and were raised by evil leprechauns, please don’t take offense.</div>
<p>As a hillbilly, I’m an innately optimistic and forgiving person. An ugly codebase to me is a <a href="http://www.amazon.com/Brownfield-Application-Development-Donald-Belcham/dp/1933988711">sea of opportunity</a>. Changing requirements? Ha! I can put <a href="http://kyle.baley.org/2008/01/monitoring-code-coverage-or-how-to-descend-into-madness/">my OCD</a> up against any client. I can see the positive in almost anything. Except the emotional rollercoaster that is QA.</p>
<p>The end of an iteration is a time of celebration and relief for me. We’ve completed a significant piece of functionality on our application. We’ve followed best practices, left the code in a better state than when we started, and all our unit and UI tests are passing (more or less). Despite my past experience, I always feel great pride when I email our QA department:</p>
<blockquote><p>Hey there, QA folkery! I come bearing tidings of great joy! We have a new version of the application for your revelry and astonishment! You will surely faint in awe at the sheer glory of it! I await your token sign-off. Acclaim and praise is optional (but recommended).</p></blockquote>
<p>After that, I sit quietly for a few minutes to bask in my accomplishment of the last couple of weeks then dive into the next iteration, the previous one long since gone from the vestiges of my memory by that point.</p>
<p>The inevitable spartan response:</p>
<blockquote><p>Please fix the following issues:</p>
<ul>
<li>As per the spec, emails should be sent every hour, not daily</li>
<li>I got a 404 error when I went to the public booking URL</li>
<li>I know this wasn’t part of the iteration but we should display a message when someone confirms an appointment. Can you include this?</li>
<li>You spelled it “cancelled” in the settings screen but “canceled” on the calendar.</li>
</ul>
<p>Let me know when a new version is up for testing.</p></blockquote>
<p>By now you will not be surprised when I tell you that the QA process was invented by the Marquis de Sade.</p>
<p>QA goblins: surely you see my point, no? The iteration is <em>over</em>. Done. Finished. There’s no “D.S. al fine” at the end. In my head, I’ve moved on to new functionality. I’ve got tests written and prototypes completed. And you want me to forcibly <a href="http://twitter.com/#!/kbaley/status/87960607168528384">re-enter the past</a>?!? All the hard problems from that iteration have already been solved. I don’t care about your “cosmetics” or your “functionality”. That new feature you’ve requested? It’s KILLER! It’ll be a great asset to the app. When I get around to it. That 404 error? Just a configuration issue. It’ll be fixed when we deploy. And come on, spelling mistakes? Have you not been on Facebook lately?</p>
<p>In short: I. Don’t. Want. To. Do. It. Right. Now.</p>
<p>And I have to. Virtually everything brought up in a good QA process is valid from bugs to cosmetic issues to features that we need to include this iteration even though they weren’t in the list. Without them, we don’t have a usable product. Users will complain or worse, move on to something else. But my headspace is somewhere else. I’ve already compartmentalized the new features and have shifted my own personal Eye of Sauron on them. Now, there’s leakage that I thought I’d never have to deal with again.</p>
<p>Another psychological issue: I’ve poured everything I’ve got to deliver the best that I’ve got and it wasn’t good enough. It’s never good enough. I’ve just presented to you the end result of four years of university training and over a dozen years of experience as an “expert in the field”. And with a few phrases, you send me slinking back to my computer to do it over again.</p>
<p>It’s a little strange in some regard. I welcome criticism of my coding choices and style. I actively seek it out sometimes. <a href="http://kyle.baley.org/2010/06/rietveld-or-how-to-revamp-your-code-review-process/">Even code reviews can be made fun again</a>. But something about the subtly adversarial nature of QA raises my dander. The fact that it’s so essential to quality and that I can’t think of an effective way around it doesn’t help…</p>
<p>So to sum up:</p>
<ul>
<li>QA forces me to change my headspace. And I hate it for that.</li>
<li>QA points out my flaws as a developer. And I hate it for that.</li>
<li>QA is necessary and makes software better. And I hate it most of all for that.</li>
</ul>
<p>To end on a more positive note, most QA people (including those that do it as part of other duties) I’ve worked with are extremely nice. There’s no accusatory tone in the responses, no blame on messing things up, and no sense of “you’ve *really* screwed things up this time.” In their minds, they’ve done what’s expected and like me, have made the product better for it.</p>
<p>But I still hate you.</p>
<p>Kyle the Unadulterated</p>
<div class="shr-publisher-263"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F01%2F30%2Fqa-a-hillbilly-love-story%2F' data-shr_title='QA%3A+A+Hillbilly+Love+Story'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F01%2F30%2Fqa-a-hillbilly-love-story%2F' data-shr_title='QA%3A+A+Hillbilly+Love+Story'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F01%2F30%2Fqa-a-hillbilly-love-story%2F' data-shr_title='QA%3A+A+Hillbilly+Love+Story'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/zJD-Dn3ODko" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/kylebaley/2012/01/30/qa-a-hillbilly-love-story/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
					<feedburner:origLink>http://codebetter.com/kylebaley/2012/01/30/qa-a-hillbilly-love-story/</feedburner:origLink></item>
	      
    	<item>
		<title>The new OpenEverything organization</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/BJ1K2WpALkc/</link>
		<comments>http://codebetter.com/sebastienlambla/2012/01/30/the-new-openeverything-organization-2/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 11:51:44 +0000</pubDate>
		<dc:creator>Sebastien Lambla</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/sebastienlambla/?p=122</guid>
					<description><![CDATA[OpenRasta has been there for many years, and is the most widely used alternative framework for ReST applications. OpenWrap has been there for a year and a half, and has some usage for advanced users wanting a nicely-architected package manager&#160;&#8230; <a href="http://codebetter.com/sebastienlambla/2012/01/30/the-new-openeverything-organization-2/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>OpenRasta has been there for many years, and is the most widely used alternative framework for ReST applications.</p>
<p>OpenWrap has been there for a year and a half, and has some usage for advanced users wanting a nicely-architected package manager that doesn’t take dependencies on lots and lots of other technologies and doesn’t require VS.</p>
<p>And we have sub-projects, such as OpenFileSystem, an IO abstraction library that ought to&nbsp; make using the file system easier, shipping with an in-memory version that should work the same way as your target operating system.</p>
<p>Now all those projects are at varying stages in their life, and the amount of work I used to give to only OpenRasta has been vastly disolved, which in turns means that some users are <a href="http://dgondotnet.blogspot.com/2012/01/rest-raiding-openrasta.html">starting to get quite annoyed</a> with our dreadful homepage and our lack of binary downloads.</p>
<p>Add to this the competitive pressure on OpenRasta introduced by Nancy and the future openrasta copycat WebAPI from the photocopier machine Microsoft, and you’ll understand that the current trend is not sustainable.</p>
<p>This year I’ve decided to simplify my life and delegate much more of my work to a community that has been so far very supportive but very unwilling to contribute anything back. I also want to go back to enjoying working on OSS software to build great solutions and not focus my energy on simply competing with any tool and framework microsoft invents to duplicate existing OSS solutions. I have a vision and I want to deliver on that, OpenRasta and OpenWrap are two sides of that, and I want to start making them work together the way I want without having to be dragged in competitive races with Microsoft’s marketing dollars.</p>
<p>So we had a planning meeting with some of the companies that use OpenRasta in anger in London and want to step up their contributions (<a href="http://www.7digital.com/">7digital</a> and <a href="http://www.huddle.com/">huddle</a>, we love you guys!), and decided that we were going to change how things are done in the OpenEverything projects.</p>
<h2>Project organization</h2>
<p>First and foremost, I’m going to contribute much less to the 2.1 branch of OpenRasta, and patches / merges / new builds are going to be handled by the contributors that are given write access to the git repository. This gives away a lot of my power.</p>
<p>I’m going to be focusing on the outstanding modules for OpenRasta that add a whole bunch of functionality that will be rolled-back in 3.0: the caching module (soon to arrive in 0.2 version), the new config API (with compact fluent API and convention-based config) and the dynamic / json out-of-the-box support. There’s also a new openrasta-diagnostics module that I’ve started building and want to get out there. I’ll also contribute some work towards the async support that has been requested by some.</p>
<p>OpenFileSystem 2.0 is going to be under Henrik Feldt supervision, and will be a merge of the amazing work he did on long-path and transactional file system support.</p>
<p>All of our versioning is going to be a strict application of <a href="http://semver.org">http://semver.org</a> 2.0 (which is now the only standard in OpenWrap), so that will solve any breaking changes being introduced without knowing.</p>
<p>Of course, OSS is not a democracy, so I keep a veto right on certain changes that would impact future versions, or architectural changes that do not fit with the vision I have for all those projects. This is give and take, I give some of the control of more than 4 years worth of my development time, but I will keep the main architect role for the time being.</p>
<p>As for releases, anytime someone with commit access wants to create a new release, the process is very simple: they email on the mailing list, and if there’s no majority opposition, we have a new build. Simples.</p>
<h2>Orphaned projects</h2>
<p>Sadly, we do have some orphaned projects in all this. Mostly, the container support for each of the IoC containers is not up-to-date for StructureMap (tests are broken) and Unity (I have no understanding of the code, so while I *think* I fixed the latest build, I can’t try it out). At this stage, anyone with a vested interest in those projects should start contributing and come help out, or risk that code not being maintained anymore.</p>
<h2>OSS is not just take, it’s give too</h2>
<p>That leaves a real question for those companies that have used OpenRasta to make money and provide a killer-architecture and have contributed absolutely nothing back since the beginning.</p>
<p>I’ll let you in on a little secret. I give the code away on everything, so it is a company’s legal right to take and not give back. As a side-effect, it is my complete right to completely ignore those that make money on our hard work and want to keep it all to themselves, and my responsibility to not prioritize the needs of those that contributes over those that are selfish..</p>
<p>OSS is also about giving back, and this year it’s what is being enforced on the OpenEverything projects. Fostering contributions is what we want to get to. No more free-lunch though, that’s for sure.</p>
<h2>Conclusion</h2>
<p>This new organization should let OpenRasta absorb patches and get on the 2.1 release cycle faster, and then on to 2.2, etc. This will allow me to focus on what I want to build for 3.0, and this will also allow more contributors to own projects more directly than before.</p>
<p>If you have comments or feedback on all those new plans, please let us know on the now unified <a href="http://groups.google.com/group/openeverything-dev/topics">openeverything-dev mailing list</a>.</p>
<p><em>Please don’t use it for user questions, we’ve moved all support of all those frameworks to stackoverflow where google can do its job and users can find their answers more quickly.</em></p>
<div class="shr-publisher-122"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fsebastienlambla%2F2012%2F01%2F30%2Fthe-new-openeverything-organization-2%2F' data-shr_title='The+new+OpenEverything+organization'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fsebastienlambla%2F2012%2F01%2F30%2Fthe-new-openeverything-organization-2%2F' data-shr_title='The+new+OpenEverything+organization'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fsebastienlambla%2F2012%2F01%2F30%2Fthe-new-openeverything-organization-2%2F' data-shr_title='The+new+OpenEverything+organization'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/BJ1K2WpALkc" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/sebastienlambla/2012/01/30/the-new-openeverything-organization-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
					<feedburner:origLink>http://codebetter.com/sebastienlambla/2012/01/30/the-new-openeverything-organization-2/</feedburner:origLink></item>
	      
    	<item>
		<title>Mythical man month : 10 lines per developer day</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/IorIwRI3_ZI/</link>
		<comments>http://codebetter.com/patricksmacchia/2012/01/23/mythical-man-month-10-lines-per-developer-day/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 11:12:39 +0000</pubDate>
		<dc:creator>Patrick Smacchia</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/patricksmacchia/?p=482</guid>
					<description><![CDATA[The mythical book, Mythical man month quoted that no matter the programming language chosen, a professional developer will write in average 10 lines of code (LoC) day. After a bit more than 6 years of full-time development on the tool NDepend I’d like&#160;&#8230; <a href="http://codebetter.com/patricksmacchia/2012/01/23/mythical-man-month-10-lines-per-developer-day/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>The mythical book, <a href="http://en.wikipedia.org/wiki/The_Mythical_Man-Month">Mythical man month</a> quoted that no matter the programming language chosen, a professional developer will write in average 10 lines of code (LoC) day.</p>
<p>After a bit more than 6 years of full-time development on the tool <span style="line-height: 24px"><a href="http://www.NDepend.com" target="_blank">NDepend</a></span> I’d like to elaborate a bit here.</p>
<p>Let’s start with the definition of <strong>logical Line of Code</strong>. Basically, a logical LoC is a PDB sequence point except sequence points corresponding to opening and closing method brace. So here we have a 8 logical lines of code method for example:</p>
<p><a href="http://codebetter.com/patricksmacchia/files/2012/01/Method.jpg"><img class="alignnone size-full wp-image-483" src="http://codebetter.com/patricksmacchia/files/2012/01/Method.jpg" alt="" width="521" height="235" /></a></p>
<p>See here the post <a href="http://codebetter.com/blogs/patricksmacchia/archive/2007/10/03/how-do-you-count-your-number-of-lines-of-code-loc.aspx" target="_blank">How do you count your number of Lines Of Code (LOC)</a> ? for more details.</p>
<p>I already hear the bashing; LoC has nothing to do with productivity, Bill Gates said &#8220;<em>Measuring software productivity by lines of code is like measuring progress on an airplane by how much it weighs.</em>&#8220;.</p>
<p><strong>And indeed, measured on a few days or a few weeks range, LoC has nothing to do with productivity.</strong> Some days I write 200 LoC in a row, some days I spend 8 hours fixing a pesky bug by not even adding a LoC. Some day I clean dead code and remove some LoC. Some other days I refactor exiting code without, all in all, adding a single LoC. Some days I create a large and complex UI Form and the editor will generate automatically 300 additional LoC. Some days are dedicated solely to performance enhancement or planning upcoming code architecture…</p>
<p><strong>What is interesting is the average number of LoC obtained from the long term.</strong> And if I do the simple math I obtained around 80 LoC per day. Let&#8217;s precise that I abide by high code quality standard. Each LoC must be covered by <a href="http://codebetter.com/patricksmacchia/2012/01/10/non-trivial-and-real-world-feedbacks-on-writing-unit-tests/" target="_blank">unit-tests + all possible code contracts must be declared</a> (of course, not all LoC can, nor should, be checked by contracts and some classes are nit relevant for unit-testing, especially UI related classes).</p>
<p>So this average score of 80 LoC produced per day doesn’t sacrifice to code quality, and seems to be a sustainable rhythm. And what is really cool with LoC, is that, <strong>once calibrated, caring about counting LoC becomes an accurate estimation tool</strong>. After coding and measuring dozens of features achieved <strong>in this particular context of development</strong>, the size of any feature can be estimated accurately in terms of LoC. Hence with a simple math, the time it&#8217;ll take to deliver a feature to production can be accurately estimated. To illustrate this fact, here is a decorated treemap view of most NDepend components.</p>
<p><a href="http://codebetter.com/patricksmacchia/files/2012/01/TreemapLoc_600.png"><img class="alignnone size-full wp-image-484" src="http://codebetter.com/patricksmacchia/files/2012/01/TreemapLoc_600.png" alt="" width="600" height="893" /></a>Thanks to this treemap view, I can compare the size in terms of LoC of most components. Coupling this information with the fact that the average coding score if 80 LoC per day, and looking back on cost in times for each component, <strong>I have an accurate method to tune my way of coding and estimate future schedules</strong>.</p>
<p>Of course not all components are equals. Most of them are the result of a long evolutive coding process. For example, the code model had undergone much more refactoring since the beginning than say, the dependency graph for example that had been delivered out-of-the-box after some weeks of development.</p>
<p>There is something else interesting this picture is telling. I can see that <strong>all these years polishing the tool to meet high professional standards in terms of ergonomy and performance, consumed actually the bulk of LoC</strong>. For example just having a clean <em>Project Properties</em> management is implemented through (model + UI control) =(3.751+2.686) = 6.437 LoC. While a flagship feature such as the<em> interactive Dependency Graph</em> only consumes 2.897 LoC, not even a half of the <em>Project Properties</em> impelmentation. Of course the <em>interactive Dependency Graph</em> capitalize a lot on all the existing infrastructure developed for other features. But as a matter of fact, it took less effort to develop  the <em>interactive Dependency Graph </em>than to develop a clean <em>Project Properties</em> model and UI.</p>
<p>All this confirms an essential lesson for everyone that wishes to start an ISV. It is lightweight and easy to develop a nice and flashy prototype application that’ll bring enthusiast users. What is really costly is to transform it into something usable, stable, clean, fast with all possible ergonomy candy to make the life of the user easier. <strong>And these are all these non-functional requirements that will make the difference between a product used by a few dozens of enthusiast users only, and a product used by the mass.</strong></p>
<div class="shr-publisher-482"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fpatricksmacchia%2F2012%2F01%2F23%2Fmythical-man-month-10-lines-per-developer-day%2F' data-shr_title='Mythical+man+month+%3A+10+lines+per+developer+day'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fpatricksmacchia%2F2012%2F01%2F23%2Fmythical-man-month-10-lines-per-developer-day%2F' data-shr_title='Mythical+man+month+%3A+10+lines+per+developer+day'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fpatricksmacchia%2F2012%2F01%2F23%2Fmythical-man-month-10-lines-per-developer-day%2F' data-shr_title='Mythical+man+month+%3A+10+lines+per+developer+day'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/IorIwRI3_ZI" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/patricksmacchia/2012/01/23/mythical-man-month-10-lines-per-developer-day/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
					<feedburner:origLink>http://codebetter.com/patricksmacchia/2012/01/23/mythical-man-month-10-lines-per-developer-day/</feedburner:origLink></item>
	      
    	<item>
		<title>Review – Building Hypermedia APIs with HTML 5 and Node</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/pVSS1PMh6dA/</link>
		<comments>http://codebetter.com/glennblock/2012/01/22/324/#comments</comments>
		<pubDate>Sun, 22 Jan 2012 06:17:11 +0000</pubDate>
		<dc:creator>Glenn Block</dc:creator>
				<category><![CDATA[Hypermedia]]></category>
		<category><![CDATA[REST]]></category>
			<guid isPermaLink="false">http://codebetter.com/glennblock/?p=324</guid>
					<description><![CDATA[I rarely review books however the past few years there&#8217;s a few gems I&#8217;ve found in my REST travels that I have felt compelled to review. Mike Amundsen&#8217;s new book on hypermedia is one such work. Note: This review is a&#160;&#8230; <a href="http://codebetter.com/glennblock/2012/01/22/324/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p><a href="http://www.amazon.com/dp/1449306578/ref=rdr_ext_tmb" target="_blank"><img class="alignnone" src="http://ecx.images-amazon.com/images/I/51hEVCddqRL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA300_SH20_OU01_.jpg" alt="" width="300" height="300" /></a></p>
<p>I rarely review books however the past few years there&#8217;s a few gems I&#8217;ve found in my REST travels that I have felt compelled to review. Mike Amundsen&#8217;s new <a href="http://www.amazon.com/dp/1449306578/ref=rdr_ext_tmb">book</a> on <a href="http://codebetter.com/glennblock/2011/05/09/hypermedia-and-forms/">hypermedia</a> is one such work.</p>
<p><strong>Note:</strong> This review is a slightly modified version of what I posted at Amazon.com.</p>
<p>If you are a hypermedia developer you should read this book. If you are building web apis to reach multiple devices then you should read this book. If you are building web apis that will be around for a long time and evolve over many versions, then read this book. Hypermedia systems have been around since the dawn of the web, however they have mainly been HTML pages offered up to a browser agent. It is extremely rare that you see the usage of hypermedia in web apis / machine to machine scenarios.</p>
<p>Hypermedia is basically a black art that very few folks actually understand. I experienced this first hand when I was the PM for WCF Web API as hypermedia was something that we wanted to be able to support. I immediately discovered that there was very little literature on the concept, there was no definitive reference to turn to. The guidance was mainly spread through a set of articles and through thousands of mail threads. Mike is one of the few who actually gets it having many years of experience building such systems. He is one of the foremost experts on the topic. Just head to his <a href="http://amundsen.com/blog">blog</a> or the REST discussion list and you&#8217;ll see this is the case.</p>
<p>This book is important because with it Mike lifts the veil of mystery of how to build such systems, taking it from a black art to something broadly available to developers. Mike goes into depth defining what hypermedia is and the different ways it can manifest itself. He describes the different types of hypermedia controls and how best to use them. Mike also pays particular attention to using hypermedia in javascript agents running in the browser, something that is extremely relevant today considering the rise of rich ajax style applications using frameworks like jQuery and extjs. The book is not a book of theory, from start to finish it uses real world examples to illustrate the concepts.</p>
<p>The one thing I would have liked to have seen Mike elaborate on a bit more was why hypermedia itself was important. Throughout the book it does become more self-evident however for one who doesn&#8217;t understand what it is I felt that the book could have laid more of a foundation / done a bit more selling on the value. Mike does plenty of that in his blog though.</p>
<p>If you are building RESTful systems particularly in node (though the guidance is general applicable) then I highly recommend this book.</p>
<div class="shr-publisher-324"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F01%2F22%2F324%2F' data-shr_title='Review+-+Building+Hypermedia+APIs+with+HTML+5+and+Node'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F01%2F22%2F324%2F' data-shr_title='Review+-+Building+Hypermedia+APIs+with+HTML+5+and+Node'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F01%2F22%2F324%2F' data-shr_title='Review+-+Building+Hypermedia+APIs+with+HTML+5+and+Node'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/pVSS1PMh6dA" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/glennblock/2012/01/22/324/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
					<feedburner:origLink>http://codebetter.com/glennblock/2012/01/22/324/</feedburner:origLink></item>
	      
    	<item>
		<title>TDD/BDD as Architectural Tools</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/_TAFqnin3m4/</link>
		<comments>http://codebetter.com/jameskovacs/2012/01/19/tddbdd-as-architectural-tools/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 17:55:22 +0000</pubDate>
		<dc:creator>James Kovacs</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Presentations]]></category>
			<guid isPermaLink="false">http://codebetter.com/jameskovacs/?p=191</guid>
					<description><![CDATA[InfoQ has made another of my DevTeach talks available online &#8211; TDD/BDD as Architectural Tools. Enjoy! TDD/BDD as Architectural Tools As architects, we have all experienced the folly of BDUF (Big Design Up Front) &#8211; spending weeks or months perfecting&#160;&#8230; <a href="http://codebetter.com/jameskovacs/2012/01/19/tddbdd-as-architectural-tools/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>InfoQ has made another of my DevTeach talks available online &#8211; <em><a href="http://www.infoq.com/presentations/TDD-BDD-as-Architectural-Tools">TDD/BDD as Architectural Tools</a></em>. Enjoy!</p>
<h3>TDD/BDD as Architectural Tools</h3>
<p>As architects, we have all experienced the folly of BDUF (Big Design Up Front) &#8211; spending weeks or months perfecting an architecture that fails when it meets the real requirements and real code. Is it possible to design in the small? How can we avoid unintended complexity, which cripples so many code bases? Can we build enough of an architecture to start writing code and then flesh out our architecture as the code evolves? In this session we examine how Test-Driven Development (TDD) and Behaviour-Driven Development (BDD) allow us to solve these conundrums. We will see how we can use TDD/BDD to focus our architectural efforts in the high-value areas of our code base to achieve just-in-time architecture.</p>
<div class="shr-publisher-191"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjameskovacs%2F2012%2F01%2F19%2Ftddbdd-as-architectural-tools%2F' data-shr_title='TDD%2FBDD+as+Architectural+Tools'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjameskovacs%2F2012%2F01%2F19%2Ftddbdd-as-architectural-tools%2F' data-shr_title='TDD%2FBDD+as+Architectural+Tools'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjameskovacs%2F2012%2F01%2F19%2Ftddbdd-as-architectural-tools%2F' data-shr_title='TDD%2FBDD+as+Architectural+Tools'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/_TAFqnin3m4" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/jameskovacs/2012/01/19/tddbdd-as-architectural-tools/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
					<feedburner:origLink>http://codebetter.com/jameskovacs/2012/01/19/tddbdd-as-architectural-tools/</feedburner:origLink></item>
	      
    	<item>
		<title>HTTP is not a transport protocol, HTTP is not RPC</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/aw_zltJY6oQ/</link>
		<comments>http://codebetter.com/glennblock/2012/01/19/http-is-not-a-transport-protocol-http-is-not-rpc/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 07:46:24 +0000</pubDate>
		<dc:creator>Glenn Block</dc:creator>
				<category><![CDATA[HTTP]]></category>
		<category><![CDATA[REST]]></category>
			<guid isPermaLink="false">http://codebetter.com/glennblock/?p=308</guid>
					<description><![CDATA[Preamble: The intent of this post is to educate on how HTTP was designed to be used , clarify misconceptions and to give folks food for thought on different ways they can design a system. It is not to ignite&#160;&#8230; <a href="http://codebetter.com/glennblock/2012/01/19/http-is-not-a-transport-protocol-http-is-not-rpc/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Preamble: The intent of this post is to educate on how HTTP was designed to be used , clarify misconceptions and to give folks food for thought on different ways they can design a system. It is <strong>not</strong> to ignite a war against RPC. There are tradeoffs to consider when your design your system. If you are not designing a system that is to be consumed by many clients over a long time and where the server needs to evolve independently of the client, then using HTTP for RPC may be absolutely fine.</p>
<p>Recently there was a <a href="http://wcf.codeplex.com/discussions/286557">question</a> on the forums asking why we encourage usage of HttpRequestMessage&lt;T&gt; / HttpResponseMessage&lt;T&gt; in the signature of a web api implementation. The point made in the post is that if you have an ICalculator contract which your API implements, then it&#8217;s violating SOC / inappropriate to have those messages as params and in the contract. The argument is valid when looking at HTTP from the standpoint of an RPC mechanism, which is actually a quite common view.</p>
<p>Not of the HTTP authors though. If you read Roy Fielding&#8217;s <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/evaluation.htm">dissertation</a> you will see very clearly that:</p>
<p>HTTP is <strong><span style="text-decoration: underline">not</span></strong> a transport protocol and HTTP is <span style="color: #000000"><strong><span style="text-decoration: underline">not</span></strong></span> RPC.</p>
<p>You might be surprised, but it is true. There are real quantifiable reasons for this that underlie the foundations of how and why the web infrastructure was built. Roy explains it much better than I can, though I still continually <a href="http://www.infoq.com/presentations/Building-Systems-with-REST">attempt</a> to do it <img src='http://codebetter.com/glennblock/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  I recommend reading what <a href="http://roy.gbiv.com/untangled/">Roy</a> has to say on the subject <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/evaluation.htm">here</a> in sections 6.5.2 and 6.5.3.</p>
<p>Back to our HTTP messages. This has deep implications in your API design. Once you accept that the thing that you are exposing is an HTTP resource which clients interact with via the uniform interface and not a class with standard OOP methods, you design them differently. Your APIs become a gateway where HTTP concerns are addressed and then work is delegated off to the business domain rather than being part of the business domain. Once they do, you can safely use HttpRequestMessage&lt;T&gt; and HttpResponseMessage&lt;T&gt; without fear as they are specifically for addressing HTTP concerns.</p>
<p><a href="http://twitter.com/mamund">Mike Amundsen</a> has a really nice <a href="http://amundsen.com/blog/archives/1099">post</a> where he emphasizes this last point and why it is just better for us to embrace HTTP in our code and stop fighting it:</p>
<blockquote><p>&#8220;the better way to deal with HTTP is to <em>embrace</em> it. let HTTP lead system designers in the direction of lossy, chunky, state-less designs. accept HTTP as the stable rarely-changing foundation for your implementations. learn to &#8216;think&#8217; and &#8216;speak&#8217; HTTP so that all your dist-net designs reflect the power, stability, and reliability of HTTP itself. and don&#8217;t fuss with it.&#8221;</p></blockquote>
<p>You can read more about the design implications from a Web API perspective in my reply on the <a href="http://wcf.codeplex.com/discussions/286557">thread</a>.</p>
<p>Interested in your thoughts.</p>
<div class="shr-publisher-308"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F01%2F19%2Fhttp-is-not-a-transport-protocol-http-is-not-rpc%2F' data-shr_title='HTTP+is+not+a+transport+protocol%2C+HTTP+is+not+RPC'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F01%2F19%2Fhttp-is-not-a-transport-protocol-http-is-not-rpc%2F' data-shr_title='HTTP+is+not+a+transport+protocol%2C+HTTP+is+not+RPC'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F01%2F19%2Fhttp-is-not-a-transport-protocol-http-is-not-rpc%2F' data-shr_title='HTTP+is+not+a+transport+protocol%2C+HTTP+is+not+RPC'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/aw_zltJY6oQ" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/glennblock/2012/01/19/http-is-not-a-transport-protocol-http-is-not-rpc/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
					<feedburner:origLink>http://codebetter.com/glennblock/2012/01/19/http-is-not-a-transport-protocol-http-is-not-rpc/</feedburner:origLink></item>
	      
    	<item>
		<title>Use tasks you have to do around the house to improve your development skills</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/Wg21XVHyqMs/</link>
		<comments>http://codebetter.com/johnpetersen/2012/01/16/use-tasks-you-have-to-do-around-the-house-to-improve-your-development-skills/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 18:43:14 +0000</pubDate>
		<dc:creator>johnvpetersen</dc:creator>
				<category><![CDATA[Continuous Improvement]]></category>
		<category><![CDATA[Software Engineering]]></category>
			<guid isPermaLink="false">http://codebetter.com/johnpetersen/?p=135</guid>
					<description><![CDATA[A somewhat unorthodox and non-traditional suggestion I admit, but as Brad Meltzer often asks: &#8220;This may seem unlikely, but go with me on this&#8230;&#8221; How many times have you had to build that piece of furniture from Ikea, install window blinds,&#160;&#8230; <a href="http://codebetter.com/johnpetersen/2012/01/16/use-tasks-you-have-to-do-around-the-house-to-improve-your-development-skills/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>A somewhat unorthodox and non-traditional suggestion I admit, but as <a href="http://www.history.com/shows/brad-meltzers-decoded" target="_blank">Brad Meltzer</a> often asks: &#8220;This may seem unlikely, but go with me on this&#8230;&#8221;</p>
<p>How many times have you had to build that piece of furniture from Ikea, install window blinds, etc? In each case, you are solving a problem. You have to analyze and organize. It&#8217;s really not that different from development. It&#8217;s a project like anything else. It has a beginning, middle, end. Like development, if you misinterpret the requirements, you have to go back a few steps. That next thing you were going to do has to get pushed to a later time.</p>
<p>This past weekend, I had to install some Levolor Blinds into our spare bedroom. I also happened to be listening to the  <a href="http://thisdeveloperslife.com/" target="_blank">This Developer&#8217;s Life Podcast</a>. I was listening to <a href="http://thisdeveloperslife.com/post/1-0-6-abstraction" target="_blank">Episode 1.0.6: Abstraction</a>. A great episode (as they all are &#8211; and like really good things &#8211; you have to go through them a few times because you are likely to pick up something new and useful that you missed before.) The part that really struck me was the interview with <a href="http://c2.com/" target="_blank">Ward Cunningham</a>. It was then that I decided to use my blind installation task as an analog of sorts for development. The interview with Ward was the inspiration. The end game is to then reverse the flow &#8211; to perhaps use development as an analog for the blind installation task &#8211; assuming of course the blind installation task is successful!</p>
<p><strong>It begins with us&#8230;..</strong></p>
<p>The one thing that really struck me about Ward was his motivation &#8211; that he builds things form himself. The same was true with John Ressig and Dan Bricklin. Then it struck me that this is really a craftsmanship issue. True craftsmen always reserve the best stuff for themselves. Indeed, much of that good stuff accrues to the benefit the things that are released for public consumption. Craftsmen work product also shares another characteristic &#8211; what they produce is pleasing to look at and use by the harshest critic of them all &#8211; the craftsmen themselves.</p>
<p>Turning back to my window blind example, I wanted to ensure they would function properly, be pleasing to look at &#8211; much like what we strive for in our software.  For a satisfactory end result however, there has to be some measure of planning. Since I had two blinds to install, I wanted to make sure the second one had the benefit of the first &#8211; as to process and as to a completed product. My benchmarks were simple:</p>
<p><strong>Did I thoroughly understand the requirements?</strong></p>
<p><strong>Did I have a plan?</strong></p>
<p><strong>Was I organized?</strong></p>
<p><strong>As to tooling, did I have what I needed and were those tools readily available?</strong></p>
<p><strong>Was there improvement in the process?</strong></p>
<p>The great thing about tangible projects &#8211; particularly those you have to do around the house or wherever you may be, those projects provide immediate feedback. You know whether they look right. You know immediately whether something was hacked together. You know whether the finished product is pleasing to look at.  You also know what is lurking beneath the surface. I&#8217;m in the middle of the <a href="http://www.amazon.com/Steve-Jobs-Walter-Isaacson/dp/1451648537" target="_blank">Steve Jobs bio by Walter Isaacson</a>. Jobs was obsessive about quality (perhaps to an unhealthy extreme!!). His [Jobs] obsession was centered around the fact that quality of thing not seen was at least as important as what is seen.   That consideration absolutely applies to the software world. When we see properly working software, we can take pride that the things people don&#8217;t see are well constructed. With home projects &#8211; we know that something is not going to break or fall apart because the things people don&#8217;t see (like screws into the wall being well anchored) are well done.</p>
<p>Food for thought as you contemplate ways to continuously improve.</p>
<div class="shr-publisher-135"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnpetersen%2F2012%2F01%2F16%2Fuse-tasks-you-have-to-do-around-the-house-to-improve-your-development-skills%2F' data-shr_title='Use+tasks+you+have+to+do+around+the+house+to+improve+your+development+skills'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnpetersen%2F2012%2F01%2F16%2Fuse-tasks-you-have-to-do-around-the-house-to-improve-your-development-skills%2F' data-shr_title='Use+tasks+you+have+to+do+around+the+house+to+improve+your+development+skills'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnpetersen%2F2012%2F01%2F16%2Fuse-tasks-you-have-to-do-around-the-house-to-improve-your-development-skills%2F' data-shr_title='Use+tasks+you+have+to+do+around+the+house+to+improve+your+development+skills'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/Wg21XVHyqMs" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/johnpetersen/2012/01/16/use-tasks-you-have-to-do-around-the-house-to-improve-your-development-skills/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
					<feedburner:origLink>http://codebetter.com/johnpetersen/2012/01/16/use-tasks-you-have-to-do-around-the-house-to-improve-your-development-skills/</feedburner:origLink></item>
	      
    	<item>
		<title>AppEngine Thoughts, or “How to support a cloud”</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/p1d8fFzXOKA/</link>
		<comments>http://codebetter.com/kylebaley/2012/01/16/appengine-thoughts/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 20:05:44 +0000</pubDate>
		<dc:creator>Kyle Baley</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[BookedIN]]></category>
		<category><![CDATA[Google App Engine]]></category>
			<guid isPermaLink="false">http://codebetter.com/kylebaley/?p=261</guid>
					<description><![CDATA[AppEngine has new pricing as of November 7 which has generated much discussion, most of it as exciting as deciding which wine to serve with raccoon (answer: dandelion). So with the segue established, I shall pontificate on what I believe&#160;&#8230; <a href="http://codebetter.com/kylebaley/2012/01/16/appengine-thoughts/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>AppEngine has <a href="http://www.google.com/enterprise/cloud/appengine/pricing.html">new pricing</a> as of November 7 which has generated much discussion, most of it as exciting as deciding which wine to serve with raccoon (answer: dandelion). So with the segue established, I shall pontificate on what I believe is the single biggest thing keeping it from being a truly great product and a worthy competitor in the cloud hosting space.</p>
<p>First I’ll get out of my system a laundry list of lesser issues:</p>
<h2>1. Confusing pricing/configuration</h2>
<p>This could be a product of my Microsoft indoctrination but I still have trouble figuring out how we get charged for stuff. It’s based on usage which is a great model on paper. But the usage is broken down into, among other things:</p>
<ul>
<li>Front-end instance hours
<li>Back-end instance hours
<li>Datastore Write Operations
<li>Datastore Read Operations
<li>Datastore Small Operations
<li>Stanzas Sent
<li>Channels Created</li>
</ul>
<p>Furthermore, you can tweak things like the minimum and maximum idle instances and the minimum and maximum pending latency.</p>
<p>All this requires a lot of research and testing. And the only way to test various settings is: a) in production, or b) using load testing with a separate paid environment. Both of which will end up costing you dollars. But it must be said, those dollars probably won’t add up to the cost of setting up your own test environment. So far, we spend about the cost of a smoothie every day for all versions of our app (depending on where you find the ingredients).</p>
<h2>2. No built-in backup and restore</h2>
<p>Backing up the datastore is your responsibility. Now, it’s easy to set up a batch process running nightly. But you’re almost guaranteed to hit your Datastore Read Operations quota on a nightly basis once you reach a certain size. Also, the new-fangled High Replication datastore makes things more interesting by <a href="http://code.google.com/appengine/docs/python/tools/uploadingdata.html">not actually being supported</a> for this scenario.</p>
<h2>3. No built-in reporting mechanism</h2>
<p>The only way to interact directly with your data is through code you’ve written yourself or with GQL, a SQL-like language for the datastore. But you quickly hit limitations. First is that you can return only 20 results at a time (which you can up to 200 by adding a limit parameter to the URL…manually). Second is that you <em>have</em> to create indexes for fields you want to filter or order by. Doesn’t lend itself to ad hoc querying. </p>
<h2>4. Admin console bugs</h2>
<p>This one irks me almost as much as the fact that I have to restart my computer whenever I update the glorified Notepad that is Adobe Reader*. Too often for my tastes, when clicking around the console, I’ll get a general “An error has occurred” page. And the error page is not a pretty one:</p>
<p><a href="http://codebetter.com/kylebaley/files/2012/01/AppEngine-Error.png"><img style="border-right-width: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px;padding-top: 0px" border="0" alt="AppEngine Error" src="http://codebetter.com/kylebaley/files/2012/01/AppEngine-Error_thumb.png" width="670" height="485"></a></p>
<p>Even when it does work, until recently, I had to use Firefox or Internet Explorer to access one of the pages (Datastore Admin) because it didn’t load in Chrome.</p>
<p>Which leads me to the point of this post. The one killer issue in AppEngine that keeps its status below world class hosting environment:</p>
<h2>Support as a second-class citizen</h2>
<p>If you didn’t notice at first glance, take another look at the error page above. In particular, at the URL at the bottom, which is where the “report” link goes. It’s a Google Group page for AppEngine. To their credit, they’ve addressed <a href="http://kyle.baley.org/2011/04/google-ui-faux-pas-or-how-to-show-love-hillbilly-style/">many of the issues</a> I’ve had with Google Groups recently. Even so, for a world-class hosting environment and especially for apps we’re paying for, I’d much rather see something <a href="https://aws.amazon.com/support/">like this</a>.</p>
<p>Also, my experience with the group site has been pretty dismal. Much of the time, my questions get <a href="https://groups.google.com/forum/embed/?place=forum/google-appengine-java&amp;showsearch=true&amp;showpopout=true&amp;parenturl=http%3A%2F%2Fcode.google.com%2Fappengine%2Fforum%2Fjava-forum.html%3Fplace%3Dforum%2Fgoogle-appengine-java#!searchin/google-appengine-java/kyle/google-appengine-java/-uyBIianKxw/L_ygxSBGBPIJ">not</a> <a href="https://groups.google.com/forum/embed/?place=forum/google-appengine-java&amp;showsearch=true&amp;showpopout=true&amp;parenturl=http%3A%2F%2Fcode.google.com%2Fappengine%2Fforum%2Fjava-forum.html%3Fplace%3Dforum%2Fgoogle-appengine-java#!searchin/google-appengine-java/kyle/google-appengine-java/mKc4brfHcHQ/SGCKcRmX15QJ">a</a> <a href="https://groups.google.com/forum/embed/?place=forum/google-appengine-java&amp;showsearch=true&amp;showpopout=true&amp;parenturl=http%3A%2F%2Fcode.google.com%2Fappengine%2Fforum%2Fjava-forum.html%3Fplace%3Dforum%2Fgoogle-appengine-java#!searchin/google-appengine-java/kyle/google-appengine-java/1QDamqyanQc/rG8OhsHiYfAJ">single</a> <a href="https://groups.google.com/forum/embed/?place=forum/google-appengine-java&amp;showsearch=true&amp;showpopout=true&amp;parenturl=http%3A%2F%2Fcode.google.com%2Fappengine%2Fforum%2Fjava-forum.html%3Fplace%3Dforum%2Fgoogle-appengine-java#!searchin/google-appengine-java/kyle/google-appengine-java/8lPp0zxK0P4/Vl836qJxe2oJ">response</a> <a href="https://groups.google.com/forum/embed/?place=forum/google-appengine-java&amp;showsearch=true&amp;showpopout=true&amp;parenturl=http%3A%2F%2Fcode.google.com%2Fappengine%2Fforum%2Fjava-forum.html%3Fplace%3Dforum%2Fgoogle-appengine-java#!searchin/google-appengine-java/kyle/google-appengine-java/zqpxK602bTk/DdZn6Oo9vbkJ">except</a> <a href="https://groups.google.com/forum/embed/?place=forum/google-appengine-java&amp;showsearch=true&amp;showpopout=true&amp;parenturl=http%3A%2F%2Fcode.google.com%2Fappengine%2Fforum%2Fjava-forum.html%3Fplace%3Dforum%2Fgoogle-appengine-java#!searchin/google-appengine-java/kyle/google-appengine-java/SzdnBLvTdog/FgoTZq7aINsJ">mine</a>. Even reporting issues on the Google Code site leads to <a href="http://code.google.com/p/googleappengine/issues/detail?id=5774">sporadic responses</a>. I get slightly better averages on <a href="http://stackoverflow.com/questions/tagged/google-app-engine">StackOverflow</a>.</p>
<p>This came to a head for us recently when we converted from Master/Slave to High Replication late one Saturday night. Several of the problems I outline here occurred that night, including the 1990s error screen above. And I couldn’t find a single email address or phone number anywhere that I could contact for help and be assured of a response with even an unreasonable time. I made a post to the forum about an issue we saw the next day. The link is included above in the list of posts that have received no response.</p>
<p>Another support-related area that could use work is <a href="http://code.google.com/appengine/docs/roadmap.html">the roadmap</a>. Something I’ve noticed in all dealings with the AppEngine team is an almost fanatical abhorrence of delivery dates. Even at Google IO, the best we could get from the team was “we’re working on it” with a lot of nervous laughter when someone asked about SSL access on custom domains, which is one feature we’ve had to make decisions around. I gather it’s a hard problem but even if they said “probably 2012”, that would at least indicate to us “okay, it’s not anytime soon, time to decide which is more important in the short term.”</p>
<p>Had I written this post a couple of months ago, after our High Replication migration, it would have been a lot more acidic in tone. For a few weeks after that, I was actively checking out Amazon Web Services. A Microsoft rep reached out to us serendipitously that same week wanting to talk to us about Azure. If he had not dropped the ball and postponed our meeting at least three times, this here blog thingy might be back in .NET land by this time. (Likely not, but this wouldn’t be a blog if I didn’t make grandiose unsupportable claims that back up my argument.)</p>
<p>These days, I’m not so much frustrated as I am disappointed. For all its faults, there is a lot of good being offered by AppEngine. Like many startups, we have discussions about Google and AppEngine and the general consensus is that we’re happy to see Google focusing on what they’re good at. (Do I lose points if I point out my subtle digs?) But when it comes to support for AppEngine, it feels like it’s run by engineers for engineers. Yes, support is boring and customers can be confrontational and much of the time, the answer is a variation of “you’re doing it wrong”, etc, etc. But it’s not just another IoC container; it’s a <a href="http://m.infoworld.com/d/cloud-computing/demand-cloud-jobs-now-stratospheric-183664">cloud hosting platform</a>. I believe it needs a higher level of professionalism than what I’ve seen so far.</p>
<p>Kyle the Untenable</p>
<p><font size="1">*But not nearly as much as the fact that said update invariably adds an icon to my desktop. C’mon Adobe, who actually opens Reader and <em>then</em> opens a PDF file?</font></p>
<div class="shr-publisher-261"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F01%2F16%2Fappengine-thoughts%2F' data-shr_title='AppEngine+Thoughts%2C+or+%26ldquo%3BHow+to+support+a+cloud%26rdquo%3B'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F01%2F16%2Fappengine-thoughts%2F' data-shr_title='AppEngine+Thoughts%2C+or+%26ldquo%3BHow+to+support+a+cloud%26rdquo%3B'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F01%2F16%2Fappengine-thoughts%2F' data-shr_title='AppEngine+Thoughts%2C+or+%26ldquo%3BHow+to+support+a+cloud%26rdquo%3B'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/p1d8fFzXOKA" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/kylebaley/2012/01/16/appengine-thoughts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
					<feedburner:origLink>http://codebetter.com/kylebaley/2012/01/16/appengine-thoughts/</feedburner:origLink></item>
	      
    	<item>
		<title>WebAPI Developer Preview 6: Self Hosted Mode Example</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/DqoiAriBWt4/</link>
		<comments>http://codebetter.com/johnpetersen/2012/01/13/webapi-developer-preview-6-self-hosted-mode-example/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 13:40:20 +0000</pubDate>
		<dc:creator>johnvpetersen</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[WebAPI]]></category>
			<guid isPermaLink="false">http://codebetter.com/johnpetersen/?p=117</guid>
					<description><![CDATA[In case you missed it, the WebAPI Developer Preview is up to version 6. The CodePlex site provides all of the information you need to get started. To illustrate how to build a simple WebAPI, this example uses ASP.NET MVC&#160;&#8230; <a href="http://codebetter.com/johnpetersen/2012/01/13/webapi-developer-preview-6-self-hosted-mode-example/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>In case you missed it, the <a href="http://wcf.codeplex.com/releases/view/73423" target="_blank">WebAPI Developer Preview</a> is up to version 6. The CodePlex site provides all of the information you need to get started. To illustrate how to build a simple WebAPI, <a href="http://wcf.codeplex.com/wikipage?title=Getting started: Building a simple web api" target="_blank">this example</a> uses ASP.NET MVC as the host. While the example makes reference to the fact that you can create this example in self-hosted mode (not using ASP.NET/ASP.NET MVC) &#8211; there is no code that illustrates how to do this.</p>
<p>To get started, create a <strong>Console Application</strong> and follow the steps in the ASP.NET MVC example to use Nuget to download the WebAPI references and to create the Contact Manager classes. Once you have those items in place, all you need to do is outfit the application to fire up the web host. To do that, use this code:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using ContactManagerSelfHost.APIs;
using Microsoft.ApplicationServer.Http;

namespace ContactManagerSelfHost
{
    class Program
    {
        static void Main(string[] args)
        {

            using (var host = new HttpServiceHost(typeof(ContactsApi), &quot;http://localhost:9000/api/contacts&quot;))
            {
                host.Open();
                Console.WriteLine(&quot;Press any key to stop host...&quot;);
                Console.ReadKey();
            }
        }
    }
}
</pre>
<p>Simply run the app and navigate to the URL. That&#8217;s it!</p>
<div class="shr-publisher-117"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnpetersen%2F2012%2F01%2F13%2Fwebapi-developer-preview-6-self-hosted-mode-example%2F' data-shr_title='WebAPI+Developer+Preview+6%3A+Self+Hosted+Mode+Example'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnpetersen%2F2012%2F01%2F13%2Fwebapi-developer-preview-6-self-hosted-mode-example%2F' data-shr_title='WebAPI+Developer+Preview+6%3A+Self+Hosted+Mode+Example'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnpetersen%2F2012%2F01%2F13%2Fwebapi-developer-preview-6-self-hosted-mode-example%2F' data-shr_title='WebAPI+Developer+Preview+6%3A+Self+Hosted+Mode+Example'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/DqoiAriBWt4" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/johnpetersen/2012/01/13/webapi-developer-preview-6-self-hosted-mode-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
					<feedburner:origLink>http://codebetter.com/johnpetersen/2012/01/13/webapi-developer-preview-6-self-hosted-mode-example/</feedburner:origLink></item>
	      
    	<item>
		<title>A brief overview of type system metadata in various languages</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/DNc00j4bZMs/</link>
		<comments>http://codebetter.com/drusellers/2012/01/11/a-brief-overview-of-type-system-metadata-in-various-languages/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 22:58:41 +0000</pubDate>
		<dc:creator>Dru Sellers</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/drusellers/?p=248</guid>
					<description><![CDATA[So given that a class that is nothing more than a data bag. After all, each object is just a bag of dict&#8217;s which are pointers to some byte array some place. What can we introspect about the byte array&#160;&#8230; <a href="http://codebetter.com/drusellers/2012/01/11/a-brief-overview-of-type-system-metadata-in-various-languages/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>So given that a class that is nothing more than a data bag. After all, each object is just a bag of dict&#8217;s which are pointers to some byte array some place. What can we introspect about the byte array in each language?</p>
<p>The following is my attempt to document my metadata experiments.</p>
<p>Let&#8217;s start with .Net, its what I know the best and what I am ultimately comparing everything too.</p>
<h3>.Net</h3>
<pre>public class Loan
{
    public decimal Amount { get; set; }
}

var aLoan = new Loan {Amount=5};
aLoan.GetType();
//an instance of Type filled with data about Loan
for(var prop in aLoan.GetType().GetProperties())
{
    Console.WriteLine(prop.Name);
}
aLoan.GetType().GetProperty("Amount");
//returns an instance of PropertyInfo</pre>
<p>Links:</p>
<p>Type: http://msdn.microsoft.com/en-us/library/system.type.aspx<br />
PropertyInfo: http://msdn.microsoft.com/en-us/library/system.reflection.propertyinfo.aspx</p>
<h3>Ruby</h3>
<pre>class Loan
    attr_accessor :amount
    def initialize(initialAmount)
        @amount = initialAmount
    end
end

aLoan = Loan.new 5
aLoan.class #Loan
aLoan.method(:amount) #a method object</pre>
<p>After playing around, I couldn&#8217;t find anyway to get the type returned by the &#8216;amount&#8217; function. This is exactly what I expected, but wanted to confirm. I could get the number of arguments via the &#8216;arity&#8217; method. That said, I was able to extract a lot more information than I had expected. Special thanks to @jflanagan for the much need schooling in ruby.</p>
<p>Links:</p>
<p>http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Classes#Accessor_Methods</p>
<p>http://ruby-doc.org/core-1.9.3/Method.html</p>
<h3>Python</h3>
<pre>class Loan(object):
    def __init__(self, initialAmount):
        self._amount = initialAmount

    @property
    def amount(self):
        return self._amount

aLoan = Loan(5)
aLoan.__class__ #Loan
aLoan.amount #nope, this returns 5
dir(aLoan) #return 'all the things'</pre>
<p>Links</p>
<p>http://docs.python.org/library/functions.html#property</p>
<h3>JavaScript</h3>
<pre>function Loan(initialAmount) {
    //as recommended by Ryan Rauh
    this.amount = initialAmount;
    return this;
}

var aLoan = new Loan(5);
typeof(aLoan); //object
Object.getPrototypeOf(aLoan).constructor.name; //Loan
for(prop in aLoan) {console.log(prop)}; //prop is a string
typeof(aLoan['amount']); //number
//this is actual a typeof(5)</pre>
<p>I was again surprised at how much I could extract. Special thanks to @rauhryan for the JavaScript schooling.</p>
<h2>Beyond my reach (for now)</h2>
<p>So I wanted to do some other languages outside my comfort zone like lisp, haskell, and erlang. But my brain was exploded by the very different nature of the languages. What I do have is how I would set the structure up roughly in the various languages. I hope to come back overtime and update this as I learn or people share with me. <img src='http://codebetter.com/drusellers/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Lisp</p>
<pre>('Loan, ('Amount, 20))</pre>
<p>Haskell</p>
<pre>data Loan = Loan { Amount :: Int }</pre>
<p><a href="http://www.cs.auckland.ac.nz/references/haskell/haskell-intro-html/moretypes.html">http://www.cs.auckland.ac.nz/references/haskell/haskell-intro-html/moretypes.html</a></p>
<p>Erlang</p>
<pre>-record(Loan, { Amount })</pre>
<p>Links:</p>
<p><a href="http://www.erlang.org/doc/reference_manual/records.html">http://www.erlang.org/doc/reference_manual/records.html</a></p>
<p>&nbsp;</p>
<p>Any feedback on how to do these kinds of things in other languages will be most appreciated.</p>
<p>-d</p>
<div class="shr-publisher-248"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fdrusellers%2F2012%2F01%2F11%2Fa-brief-overview-of-type-system-metadata-in-various-languages%2F' data-shr_title='A+brief+overview+of+type+system+metadata+in+various+languages'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fdrusellers%2F2012%2F01%2F11%2Fa-brief-overview-of-type-system-metadata-in-various-languages%2F' data-shr_title='A+brief+overview+of+type+system+metadata+in+various+languages'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fdrusellers%2F2012%2F01%2F11%2Fa-brief-overview-of-type-system-metadata-in-various-languages%2F' data-shr_title='A+brief+overview+of+type+system+metadata+in+various+languages'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/DNc00j4bZMs" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/drusellers/2012/01/11/a-brief-overview-of-type-system-metadata-in-various-languages/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
					<feedburner:origLink>http://codebetter.com/drusellers/2012/01/11/a-brief-overview-of-type-system-metadata-in-various-languages/</feedburner:origLink></item>
	      
    	<item>
		<title>HTTP tour: Manchester, Edinburgh, Glasgow, Dundee and Aberdeen.</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/rS3ZVuxGNlY/</link>
		<comments>http://codebetter.com/sebastienlambla/2012/01/11/http-tour-manchester-edinburgh-glasgow-dundee-and-aberdeen/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 18:52:49 +0000</pubDate>
		<dc:creator>Sebastien Lambla</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/sebastienlambla/?p=114</guid>
					<description><![CDATA[I’ll be touring the north of Britain from the 18th of January with two talks: HTTP caching 101 and Links, forms and Unicorns. The details are at http://www.gep13.co.uk/blog/?p=609 so if you’re interested in HTTP or/and ReST, do come along!]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>I’ll be touring the north of Britain from the 18th of January with two talks: HTTP caching 101 and <em>Links, forms and Unicorns.</em></p>
<p>The details are at <a href="http://www.gep13.co.uk/blog/?p=609">http://www.gep13.co.uk/blog/?p=609</a> so if you’re interested in HTTP or/and ReST, do come along!</p>
<div class="shr-publisher-114"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fsebastienlambla%2F2012%2F01%2F11%2Fhttp-tour-manchester-edinburgh-glasgow-dundee-and-aberdeen%2F' data-shr_title='HTTP+tour%3A+Manchester%2C+Edinburgh%2C+Glasgow%2C+Dundee+and+Aberdeen.'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fsebastienlambla%2F2012%2F01%2F11%2Fhttp-tour-manchester-edinburgh-glasgow-dundee-and-aberdeen%2F' data-shr_title='HTTP+tour%3A+Manchester%2C+Edinburgh%2C+Glasgow%2C+Dundee+and+Aberdeen.'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fsebastienlambla%2F2012%2F01%2F11%2Fhttp-tour-manchester-edinburgh-glasgow-dundee-and-aberdeen%2F' data-shr_title='HTTP+tour%3A+Manchester%2C+Edinburgh%2C+Glasgow%2C+Dundee+and+Aberdeen.'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/rS3ZVuxGNlY" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/sebastienlambla/2012/01/11/http-tour-manchester-edinburgh-glasgow-dundee-and-aberdeen/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
					<feedburner:origLink>http://codebetter.com/sebastienlambla/2012/01/11/http-tour-manchester-edinburgh-glasgow-dundee-and-aberdeen/</feedburner:origLink></item>
	      
    	<item>
		<title>Non-trivial and real-world feedbacks on writing Unit-Tests</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/0pZIXrW2kHg/</link>
		<comments>http://codebetter.com/patricksmacchia/2012/01/10/non-trivial-and-real-world-feedbacks-on-writing-unit-tests/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 19:02:25 +0000</pubDate>
		<dc:creator>Patrick Smacchia</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/patricksmacchia/?p=472</guid>
					<description><![CDATA[I began writing tests around 8 years ago and I must say this revolutionized my way of developing code. In this blog post, I’d like to group and share several non-trivial feedbacks gained over all these years of practicing real-world&#160;&#8230; <a href="http://codebetter.com/patricksmacchia/2012/01/10/non-trivial-and-real-world-feedbacks-on-writing-unit-tests/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>I began writing tests around 8 years ago and I must say this revolutionized my way of developing code. In this blog post, I’d like to group and share several non-trivial feedbacks gained over all these years of practicing real-world testing.</p>
<h1></h1>
<h1>Test Organization</h1>
<p><strong>There must be a one-to-one correspondence between classes tested and test fixture classes</strong>. Very simple classes like pure immutable entity (i.e simple constructors, simple getters, and readonly backing fields) can only be tested through test fixture classes corresponding to more complex tested classes.</p>
<p>The one-to-one correspondence stated above makes the following operations easy and straightforward:</p>
<ul>
<li>writing a new test suite for a currently created class,</li>
<li>writing some new tests for an existing class,</li>
<li>refactoring tests when refactoring some classes,</li>
<li>identifying which test to run to test a class.</li>
</ul>
<p>Tests must be written in dedicated tests assemblies because product assemblies must not be weighted with test code. Hence <strong>tests and tested code lives in different VS projects</strong>. These projects can live in the same VS solutions, or in different VS solutions.</p>
<p>Having tested code VS projects and tests VS projects living in the same VS solution is useful to navigate easily across tested code and tests.</p>
<p>If tested code and tests live in different VS solution, a global VS solution containing both code and tests VS project is still needed. Indeed, such global VS solution is useful to use refactoring tools to refactor at the same time tested code and tests</p>
<h1></h1>
<h1>Test-First and specifications</h1>
<p>I don’t abide by the test-first theory. Tests concerning a code portion should be written at the same time than the code portion. The reason I advocate to do so, is because <strong>not all edge cases can be faced up-front, even by expert of a domain and professional testers. Edge cases are discovered only when thoroughly implementing an algorithm.</strong></p>
<p>Test-first is still useful when tests can be written up-front by a domain expert or a client, with dedicated tooling such as <a href="http://fitnesse.org/FitNesse.UserGuide.OneMinuteDescription">FitNesse</a>. In this conditions test-first is a great communication mean that can remove many pesky misunderstanding.</p>
<p>However only <strong>the code itself is the complete specification</strong>. Tests can be seen as a specification scaffold, that is removed at runtime. Tests can also be seen as a secondary less-detailed specification, useful to ensure that the main specification, i.e the code itself, respects a range of requirements, materialized by tests assertions.</p>
<h1></h1>
<h1>Test and Code Contracts</h1>
<p>Calls from tests to tested code, shouldn’t violate tested code contracts. When a contract is violated by running tests, it means that the tested code is buggy or (non-exclusive) that the test is buggy.</p>
<p><a href="http://codebetter.com/patricksmacchia/2010/07/26/code-contracts-and-automatic-testing-are-pretty-much-the-same-thing/">Assertions in tests are not much different than code contract assertions</a>. The only real difference is that assertions in tests are not checked at production-time. But both kind of assertions are here for correctness, to buzz as soon as something goes wrong when running the code.</p>
<h1></h1>
<h1>Test Coverage</h1>
<p>The number of tests is a completely meaningless metric. Dozens of <em>[TestCase]</em> can be written in minutes, while a tricky integration test can takes days to be written. When it comes to test, significant metrics are:</p>
<ul>
<li>percentage of code covered by tests and</li>
<li>number of different assertions executed.</li>
</ul>
<p><strong>Not all classes need to be 100% covered by tests or even covered at all.</strong> Typically UI code is decoupled from logic, and UI code is hard to test properly, despite the progress in this domain. Notice that UI code decoupling, which is a good design practice, is naturally enforced by tests.</p>
<p>When testing a class, covering it 100% is a necessary goal. 90% coverage is not enough because empirically we observe that the 10% non-tested code contains most of unidentified bugs.</p>
<p>If to cover 10% of the code of a class it takes as much effort as covering the other 90%, it means that this 10% of code needs to be redesigned to be easily testable. Hence <strong>the 100% coverage practice is costly only when it forces the code to be well designed</strong>.</p>
<p>Having zero dead code is a natural consequence of having code 100% covered.</p>
<p>It is a good practice to tag a class 100% covered with an arbitrary <em>[FullCovered]</em> attribute because it documents for future developers in charge of an eventual refactoring, that the class must remain 100% covered.</p>
<p><strong>Code 100% covered by tests + containing all relevant contracts, is very hard to break. This is the magical practice to be very close to bug-free code. </strong></p>
<p>Personally I consider that the job is done only when all classes that can be covered by tests are indeed 100% covered by tests.</p>
<h1></h1>
<h1>Test Execution</h1>
<p>The concrete difference between unit tests and integrations tests is that unit tests are in-process only, they don’t require touching a DB, network or the file system. The distinction is useful because unit-tests are usually one or several orders of magnitude faster to run.</p>
<p>Tests must be run from the build machine to validate any code before it is committed.</p>
<p>Test should be fast to run, like a few minutes maximum, because tests must also be ran often on the developer machine, to detect regression as soon as possible.</p>
<p>Having a one-to-one correspondence between tested class and test class + 100% coverage, makes easy to identify which tests to run for a particular piece of code.</p>
<h1></h1>
<h1>Test and Refactoring</h1>
<p>Last released version of the product that is working fine in production, should stress out that bugs are more likely to appear on newly developed code and refactored code. Hence tests must be written in priority for newly developed code and refactored code.</p>
<p>When some refactored code is not properly tested, it is a good practice to write tests that should have been written in the first place. However this practice of testing refactored code is not mandatory because it can be pretty time consuming.</p>
<p>Code 100% covered by tests + containing all relevant contracts, can be refactored at whim. In these conditions, there are very few chances to miss a behavior regression.</p>
<h1></h1>
<h1>Test and Design</h1>
<p>Code that is hard to be covered by tests is bug-prone and need to be redesigned to be easily coverable by easy tests. This situation often results in creating one or several classes dedicated to handle the logic implemented formerly by the code hard to cover by tests.</p>
<p>The previous point can be restated this way: <strong>writing a complete test suite naturally leads to good design, enforcing low coupling and high cohesio</strong>n.</p>
<p>Singletons should be prohibited because they make the code hard to test. It is harder to re-cycle and re-initialize a singleton object for each tests, than it is to create an object for each test.</p>
<p>Mocking should be used to transform integration tests into unit-test, by abstracting tests from out-of-proc consideration like DB access, network access or file system. In these conditions mocking helps separating concerns in the code and hence, increases the design value.</p>
<p>Mocking is also useful to isolate code completely un-coverable by tests, like calls to <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.messagebox.show.aspx">MessageBox.Show()</a>.</p>
<h1></h1>
<h1>Test Tooling</h1>
<p>Personally I am happy with:</p>
<ul>
<li><a href="http://www.nunit.org/">NUnit</a>, I like the fact that only the <em>NUnit.Framwork.dll</em> needs to be referenced from VS tests project and that NUnit is supported by all testing tools.</li>
<li><a href="http://www.ncover.com/">NCover</a>, it is the fastest code coverage tools available. Its performance are almost magic since in coverage mode tests are executed almost as fast as without coverage. Contrary to VS coverage, the assembly instrumentation phase is completely transparent for the user, and coverage results files are easier to work with. Also NCover is <em>very</em> easy to use and integrates with most testing tools.</li>
<li><a href="http://www.testdriven.net/">TestDriven.NET</a>, its flawless VS integration made me addicted to it. <a href="http://www.jetbrains.com/resharper/features/unit_testing.html">Resharper</a> also comes with cool testing facilities but my addiction to the simplicity of TD.NET is too high.</li>
<li>When it comes to testing NDepend is especially suited to create rules to <a href="http://codebetter.com/patricksmacchia/2008/04/09/make-the-most-of-your-test-coverage-data/">continuously check for code coverage by tests</a>, to <a href="http://codebetter.com/patricksmacchia/2008/07/10/are-you-sure-added-and-refactored-code-is-covered-by-tests/">ensure that new and refactored code is properly covered by tests</a> and to <a href="http://www.ndepend.com/Doc_VS_AppWide.aspx">navigate between tested code and tests across VS solutions opened in different VS instances</a>.</li>
<li>It is worth also keeping an eye to <a href="http://continuoustests.com/">ContinuousTests</a> currently in beta to identify which tests to run when a portion of code is touched, and run them in background.</li>
</ul>
<div class="shr-publisher-472"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fpatricksmacchia%2F2012%2F01%2F10%2Fnon-trivial-and-real-world-feedbacks-on-writing-unit-tests%2F' data-shr_title='Non-trivial+and+real-world+feedbacks+on+writing+Unit-Tests'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fpatricksmacchia%2F2012%2F01%2F10%2Fnon-trivial-and-real-world-feedbacks-on-writing-unit-tests%2F' data-shr_title='Non-trivial+and+real-world+feedbacks+on+writing+Unit-Tests'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fpatricksmacchia%2F2012%2F01%2F10%2Fnon-trivial-and-real-world-feedbacks-on-writing-unit-tests%2F' data-shr_title='Non-trivial+and+real-world+feedbacks+on+writing+Unit-Tests'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/0pZIXrW2kHg" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/patricksmacchia/2012/01/10/non-trivial-and-real-world-feedbacks-on-writing-unit-tests/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
					<feedburner:origLink>http://codebetter.com/patricksmacchia/2012/01/10/non-trivial-and-real-world-feedbacks-on-writing-unit-tests/</feedburner:origLink></item>
	      
    	<item>
		<title>Thank you CodeBetter, and my new blog</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/ogUpc6cRL9E/</link>
		<comments>http://codebetter.com/jeremymiller/2012/01/10/thank-you-codebetter-and-my-new-blog/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 14:20:17 +0000</pubDate>
		<dc:creator>Jeremy Miller</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/jeremymiller/?p=896</guid>
					<description><![CDATA[I&#8217;ve had a great 7 year run at CodeBetter, but I&#8217;ve decided to start my own little blog at http://jeremydmiller.com (RSS is http://jeremydmiller.com/feed/). Thank you to Brendan and everybody I&#8217;ve met through the CodeBetter community over the years for a great experience.&#160;&#8230; <a href="http://codebetter.com/jeremymiller/2012/01/10/thank-you-codebetter-and-my-new-blog/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>I&#8217;ve had a great 7 year run at CodeBetter, but I&#8217;ve decided to start my own little blog at <a href="http://jeremydmiller.com/">http://jeremydmiller.com</a> (RSS is <a href="http://jeremydmiller.com/feed/">http://jeremydmiller.com/feed/</a>).</p>
<p>Thank you to Brendan and everybody I&#8217;ve met through the CodeBetter community over the years for a great experience.</p>
<p>&nbsp;</p>
<div class="shr-publisher-896"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjeremymiller%2F2012%2F01%2F10%2Fthank-you-codebetter-and-my-new-blog%2F' data-shr_title='Thank+you+CodeBetter%2C+and+my+new+blog'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjeremymiller%2F2012%2F01%2F10%2Fthank-you-codebetter-and-my-new-blog%2F' data-shr_title='Thank+you+CodeBetter%2C+and+my+new+blog'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjeremymiller%2F2012%2F01%2F10%2Fthank-you-codebetter-and-my-new-blog%2F' data-shr_title='Thank+you+CodeBetter%2C+and+my+new+blog'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/ogUpc6cRL9E" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/jeremymiller/2012/01/10/thank-you-codebetter-and-my-new-blog/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
					<feedburner:origLink>http://codebetter.com/jeremymiller/2012/01/10/thank-you-codebetter-and-my-new-blog/</feedburner:origLink></item>
	      
    	<item>
		<title>Hypermedia and Web API. Design brain dump and samples</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/GVzmsMRmqfs/</link>
		<comments>http://codebetter.com/glennblock/2012/01/08/hypermedia-and-web-api-design-brain-dump-and-samples/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 02:16:50 +0000</pubDate>
		<dc:creator>Glenn Block</dc:creator>
				<category><![CDATA[Hypermedia]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[webapi]]></category>
			<guid isPermaLink="false">http://codebetter.com/glennblock/?p=265</guid>
					<description><![CDATA[Although I left WCF Web API, I am very passionate about continuing on my journey toward understanding REST and how it fits with Web API. For that reason you will likely continue to see posts on REST and Web API&#160;&#8230; <a href="http://codebetter.com/glennblock/2012/01/08/hypermedia-and-web-api-design-brain-dump-and-samples/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Although I left WCF Web API, I am very passionate about continuing on my journey toward understanding REST and how it fits with Web API. For that reason you will likely continue to see posts on REST and Web API here along with my new found love node.js.</p>
<p>If you head over to our codeplex site, one question commonly asked is “Does Web API support hypermedia?” To understand this question you have to first understand what hypermedia is. I am not going to cover that here, but there are many <a href="http://www.google.com/#hl=en&amp;sclient=psy-ab&amp;q=hypermedia+rest&amp;pbx=1&amp;oq=hypermedia+rest&amp;aq=f&amp;aqi=g1g-v1g-b1&amp;aql=&amp;gs_sm=e&amp;gs_upl=14774l15396l3l15586l5l4l0l0l0l0l213l558l1.2.1l4l0&amp;bav=on.2,or.r_gc.r_pw.r_qf.,cf.osb&amp;fp=d655ac5b2263df90&amp;biw=1784&amp;bih=901">articles</a> about it, a ton of discussions in the <a href="http://tech.groups.yahoo.com/group/rest-discuss/">REST Discuss Yahoo group</a> and a new <a href="http://www.amazon.com/Building-Hypermedia-APIs-HTML5-Node/dp/1449306578">book</a> by Mike Amundsen which is well worth reading. (I need to write a review for the book at some point). I gave a quick primer which doesn’t do justice, but will get you through this post <a href="http://codebetter.com/glennblock/2011/05/09/hypermedia-and-forms/">here</a>.</p>
<p>The answer to the question depends on your notion of support: </p>
<ul>
<li>If by support you mean, “Can I embed links within my responses which will indicate to my client available resources / state transitions?” then the answer is YES.
<li>If it means, “Will Web API automatically embed links for related resources out of the box?” the answer is no”.</li>
</ul>
<p>Web API was designed to be highly pluggable, especially as it relates to how a request is handled, or how the content is processed. You can take advantage of this for plugging in your own custom code for generating hypermedia. </p>
<p>In the rest of this post I will discuss various strategies for how as well as point you to several samples.</p>
<h1>Why formatters are a good choice</h1>
<p>There are several different ways you can technically attach hypermedia including formatters, message handlers, and operation handlers. Formatters are the way we would recommend as they are specifically responsible for taking the result of an operation (could be anything) and transforming it into some representation. That representation can contain hypermedia.</p>
<p><strong>How conneg and formatters work in Web API</strong></p>
<p>Each Web API host has a collection of formatters. Each formatter specifies information about the media types it supports. On any incoming request, if content is sent, Web API matches up the incoming request’s Content-Type against the available formatters to choose one to appropriately handle processing the content in the request. It invokes the matched formatter passing in the content of the request. The formatter then outputs a CLR object which is passed to the operation.</p>
<p>Once the operation has completed, Web API performs server side content-negotiation to determine the response representation. It looks at the accept header supplied by the client in the request and matches up against the available formatters. The algorithm will look for a best match based on the specified media type / media type ranges in the accept along with the q-values. Once a formatter is identified it will be invoked passing in the return value of the operation. The formatter takes the the incoming value and writes out the representation.&nbsp;&nbsp; </p>
<p>As the formatter is writing out the response, it can also embed hypermedia controls i.e. links and forms. If you read the <a href="http://codebetter.com/glennblock/2011/06/06/rest-in-practice-the-book-restbucks-the-sample/">REST in Practice</a> book they show a media type “application/vnd-restbucks+xml” which contains hypermedia. You can create a custom RestBucksFormatter that handles that media type. If you check the RestBucks sample for Web API on codeplex, you’ll see an example of <a href="http://restbucks.codeplex.com/">this</a>. </p>
<h1>Url / Link generation</h1>
<p>In a hypermedia based system, links are generated based on a state machine.&nbsp; Depending on the state of the resource, different links apply. As soon as you start writing the formatter you will have to deal with how to handle the generation of links. There’s a several approaches you can use.</p>
<h2>Generate links within the formatter.</h2>
<p>With this method, your formatter contains the state machine logic for generating links. In the case of an Order management API, the API implementation for GET can return an order. The formatter then comes a long and grabs the order and adds appropriate links based on the state of the order. I used to be a big fan of this approach as it keeps links as separate concern from the API code itself. I’ve since changed that opinion, as I don’t view links as a separate concern <img src='http://codebetter.com/glennblock/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  </p>
<p>The upside of this approach is everything is nicely encapsulated within the formatter. The downside is that it makes it harder for one to follow the logic of the system if they are reading the API code. They must also read the formatter. It also means that the link code is duplicated if you support different variants like xml and json that require the hypermedia.</p>
<p><u>Example: Hypermedia formatter for contacts</u></p>
<p>A while ago, <a href="http://www.amundsen.com/blog">Mike Amundsen</a> visited Microsoft and I was fortunate to have the chance to <a href="http://mamund.com/blog/archives/1105">brainstorm</a> with him around Media Type design. We took the ContactManager example and spiked on how it “could” look if it used hypermedia. The implementation used the approach I just described. Below is a snapshot of how the media type itself looks. The “.” for the uri is a placeholder as the uri doesn’t matter, it is opaque to the client. </p>
<script src="http://gist.github.com/1577326.js"></script><noscript><link rel="stylesheet" href="https://gist.github.com/stylesheets/gist/embed.css"><div id="gist-1577326" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="cp">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;</span></div><div class='line' id='LC2'><span class="nt">&lt;Root&gt;</span></div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="nt">&lt;Contacts</span> <span class="na">href=</span><span class="s">&quot;.&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Contact</span> <span class="na">href=</span><span class="s">&quot;.&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Name&gt;</span>Mike Amundsen<span class="nt">&lt;/Name&gt;</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Address&gt;</span>123 Any Street<span class="nt">&lt;/Address&gt;</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;City&gt;</span>Erlanger<span class="nt">&lt;/City&gt;</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;State&gt;</span>Kentucky<span class="nt">&lt;/State&gt;</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Zip&gt;</span>41018<span class="nt">&lt;/Zip&gt;</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Email&gt;</span>mca@mamund.com<span class="nt">&lt;/Email&gt;</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Twitter&gt;</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Tweets</span> <span class="na">href=</span><span class="s">&quot;.&quot;</span><span class="nt">/&gt;</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;DM</span> <span class="na">href=</span><span class="s">&quot;.&quot;</span><span class="nt">/&gt;</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Mention</span> <span class="na">href=</span><span class="s">&quot;.&quot;</span><span class="nt">/&gt;</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/Twitter&gt;</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/Contact&gt;</span></div><div class='line' id='LC17'>&nbsp;&nbsp;<span class="nt">&lt;/Contacts&gt;</span></div><div class='line' id='LC18'>&nbsp;&nbsp;<span class="nt">&lt;Queries&gt;</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Query</span> <span class="na">name=</span><span class="s">&quot;query-twitter-contacts&quot;</span> <span class="na">href=</span><span class="s">&quot;.&quot;</span><span class="nt">/&gt;</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Query</span> <span class="na">name=</span><span class="s">&quot;query-search&quot;</span> <span class="na">href=</span><span class="s">&quot;.&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;Name/&gt;</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;City/&gt;</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;State/&gt;</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/Query&gt;</span></div><div class='line' id='LC25'>&nbsp;&nbsp;<span class="nt">&lt;/Queries&gt;</span></div><div class='line' id='LC26'>&nbsp;&nbsp;<span class="nt">&lt;Response&gt;</span>  </div><div class='line' id='LC27'>&nbsp;&nbsp;<span class="nt">&lt;/Response&gt;</span></div><div class='line' id='LC28'><span class="nt">&lt;/Root&gt;</span></div><div class='line' id='LC29'><br/></div><div class='line' id='LC30'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1577326/6bfac4ec2c2cce0eef17fbce5917058ebdfa6ea7/gistfile1.html" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1577326#file_gistfile1.html" style="float:right;margin-right:10px;color:#666">gistfile1.html</a>
            <a href="https://gist.github.com/1577326">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</noscript>
<p>One thing to note here if you are familiar with hypermedia, is that it is not using the standard link element with “rel” and “href” attributes that you are probably accustomed to seeing. Instead a domain specific format is used to to represent links and forms. In this example, Tweets has an href indicating where to go to get tweets. DM is a form for sending a direct message. The query named “query-search” includes a form with fields for specifying search criteria. This type of approach of using domain specific hypermedia deserves it’s own post. It has several advantages in that it is more intention revealing, offers richer semantics than just being limited to a rel and href , and also doesn’t abuse the rel tag.</p>
<p>As to the implementation, <a href="https://github.com/mamund/HypermediaContacts/blob/master/APIs/ContactsApi.cs">here</a> you can see the operation within the ContactsApi. Then in a custom <a href="https://github.com/mamund/HypermediaContacts/blob/master/ContactsMediaTypeFormatterXml.cs">formatter</a> all the hypermedia affordances are attached. </p>
<p>You can find all the code for Mike’s example at his github repo <a href="https://github.com/mamund/HypermediaContacts">here</a></p>
<h2>Generate links close to the operation. </h2>
<p>I mentioned above how my perspective changed on this. My current understanding is that links relate completely to the core business logic of the system as opposed to being a cross-cutting concern like logging. They are NOT a separate concern. Think of your Web API as a bridge between HTTP and your business domain, not the domain itself. Thus the model being returned from your API being tailored to HTTP is completely valid. This is not about DTOs.</p>
<p> With this approach links will get generated by the operation. Your operation returns a model that has links on it. The formatter’s responsibility is then to take the model and encode the links correctly within the representation. This allows you to add new formatters easily without replicating the linking logic. You could have an ILinkable&lt;T&gt; type which your formatter understands for attaching links. This type is not sufficient for collections as in that case you have links nested at multiple levels. For that you can have an ILinkableCollection&lt;T&gt; that contains items of ILinkable&lt;T&gt;. Thus you can return an ILinkableCollection&lt;Order&gt; that contains within ILinkable&lt;Order&gt; instances each with their own links attached. </p>
<script src="http://gist.github.com/1577486.js"></script><noscript><link rel="stylesheet" href="https://gist.github.com/stylesheets/gist/embed.css"><div id="gist-1577486" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="k">interface</span> <span class="n">ILinkable</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="p">{</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="n">T</span> <span class="n">Instance</span> <span class="p">{</span><span class="k">get</span><span class="p">;}</span></div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="n">IList</span><span class="p">&lt;</span><span class="n">Link</span><span class="p">&gt;</span> <span class="n">Links</span> <span class="p">{</span><span class="k">get</span><span class="p">;}</span></div><div class='line' id='LC4'><span class="p">}</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'><span class="k">public</span> <span class="k">interface</span> <span class="n">ILinkableCollection</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;</span> <span class="p">:</span> <span class="n">IList</span><span class="p">&lt;</span><span class="n">ILinkable</span><span class="p">&lt;</span><span class="n">T</span><span class="p">&gt;&gt;</span> <span class="p">{</span></div><div class='line' id='LC7'>&nbsp;&nbsp;<span class="n">IList</span><span class="p">&lt;</span><span class="n">Link</span><span class="p">&gt;</span> <span class="n">Links</span> <span class="p">{</span><span class="k">get</span><span class="p">;}</span></div><div class='line' id='LC8'>&nbsp;&nbsp;<span class="k">void</span> <span class="nf">Add</span><span class="p">(</span><span class="kt">string</span> <span class="n">name</span><span class="p">,</span> <span class="n">Uri</span> <span class="n">uri</span><span class="p">,</span> <span class="kt">string</span> <span class="n">rel</span><span class="p">=</span><span class="s">&quot;&quot;</span><span class="p">);</span></div><div class='line' id='LC9'><span class="p">}</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'><span class="k">public</span> <span class="k">class</span> <span class="nc">Link</span> <span class="p">{</span></div><div class='line' id='LC12'>&nbsp;&nbsp;<span class="k">public</span> <span class="n">Uri</span> <span class="n">Uri</span> <span class="p">{</span><span class="k">get</span><span class="p">;</span><span class="k">set</span><span class="p">;}</span></div><div class='line' id='LC13'>&nbsp;&nbsp;<span class="k">public</span> <span class="kt">string</span> <span class="n">Rel</span> <span class="p">{</span><span class="k">get</span><span class="p">;</span><span class="k">set</span><span class="p">;}</span></div><div class='line' id='LC14'>&nbsp;&nbsp;<span class="k">public</span> <span class="kt">string</span> <span class="n">Name</span> <span class="p">{</span><span class="k">get</span><span class="p">;</span><span class="k">set</span><span class="p">;}</span> </div><div class='line' id='LC15'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1577486/504fcbca653cd802a5981213823a95fe88bbcfe2/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1577486#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/1577486">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</noscript>
<p>The link generation code itself does not have to sit within the operation itself. Introduce a separate service such as IOrderLinkService which has that specific responsibility and have it injected via an IoC container. The service exposes an AddLinks method which accepts&nbsp; ILinkable&lt;T&gt; or an ILinkableCollection&lt;T&gt;. Although the link logic does not exist within the service, it is easy to step through the code to debug the logic.&nbsp; </p>
<p><u>Example: Domain specific media type for Orders</u></p>
<p>Here’s a snippet of the Order API.</p>
<script src="http://gist.github.com/1576892.js"></script><noscript><link rel="stylesheet" href="https://gist.github.com/stylesheets/gist/embed.css"><div id="gist-1576892" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="k">class</span> <span class="nc">OrderApi</span> <span class="p">{</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="k">private</span> <span class="n">IOrderLinkService</span> <span class="n">_linkService</span><span class="p">;</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'>&nbsp;&nbsp;<span class="k">public</span> <span class="nf">OrderApi</span><span class="p">(</span><span class="n">IOrderLinkService</span> <span class="n">linkService</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">_linkService</span> <span class="p">=</span> <span class="n">linkService</span><span class="p">;</span></div><div class='line' id='LC7'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'><span class="na">  [WebGet(UriTemplate=&quot;{id}&quot;)]</span></div><div class='line' id='LC10'>&nbsp;&nbsp;<span class="k">public</span> <span class="n">Get</span> <span class="n">ILinkable</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;</span> <span class="n">Order</span><span class="p">(</span><span class="kt">int</span> <span class="n">id</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">var</span> <span class="n">order</span> <span class="p">=</span> <span class="c1">//get the order from somewhere</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">_linkService</span><span class="p">.</span><span class="n">AddLinks</span><span class="p">(</span><span class="n">order</span><span class="p">);</span></div><div class='line' id='LC13'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC14'><span class="p">}</span></div><div class='line' id='LC15'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1576892/7ea64c87869109d4639ad3ff4a486bdf34f48f95/OrderApi.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1576892#file_order_api.cs" style="float:right;margin-right:10px;color:#666">OrderApi.cs</a>
            <a href="https://gist.github.com/1576892">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</noscript>
<p>The link service is injected into the API. The Get method then invokes it passing the order. </p>
<p><font><script src="http://gist.github.com/1576898.js"></script><noscript><link rel="stylesheet" href="https://gist.github.com/stylesheets/gist/embed.css"><div id="gist-1576898" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="k">class</span> <span class="nc">OrderLinkService</span> <span class="p">:</span> <span class="n">IOrderLinkService</span><span class="p">,</span> <span class="n">ILinkService</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;</span> <span class="p">{</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="k">public</span> <span class="n">ILinkable</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;</span> <span class="n">AddLinks</span><span class="p">(</span><span class="n">Order</span> <span class="n">order</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">var</span> <span class="n">linkedOrder</span> <span class="p">=</span> <span class="k">new</span> <span class="n">Linkable</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;();</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="n">order</span><span class="p">.</span><span class="n">State</span> <span class="p">==</span> <span class="n">OrderStates</span><span class="p">.</span><span class="n">Created</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">linkedOrder</span><span class="p">.</span><span class="n">Links</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">OrderLinks</span><span class="p">.</span><span class="n">Approval</span><span class="p">,</span> <span class="n">GetApprovalUri</span><span class="p">(</span><span class="n">order</span><span class="p">.</span><span class="n">ID</span><span class="p">));</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">//other state logic here</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">linkedOrder</span><span class="p">;</span></div><div class='line' id='LC10'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC11'><br/></div><div class='line' id='LC12'>&nbsp;&nbsp;<span class="k">private</span> <span class="n">Uri</span> <span class="nf">GetApprovalUri</span><span class="p">(</span><span class="n">orderid</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">...</span></div><div class='line' id='LC14'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC15'><span class="p">}</span></div><div class='line' id='LC16'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1576898/ad8e41dc9277398943ab16edc14a8a4fd3392cf4/OrderLinkService.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1576898#file_order_link_service.cs" style="float:right;margin-right:10px;color:#666">OrderLinkService.cs</a>
            <a href="https://gist.github.com/1576898">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</noscript></font></p>
<p>Once the service is called it looks at the state of the order and adds links appropriately. Above you can see that when the order is in the created state, a link is added for an approval resource. </p>
<p>The code can definitely be refactored / made cleaner, but it illustrates the basic idea. As an example of something more sophisticated, the RestBucks port for Web API contains a <a href="http://restbucks.codeplex.com/SourceControl/changeset/view/c318a36da791#RestBucks%2fInfrastructure%2fLinking%2fResourceLinker.cs">ResourceLinker</a> service that generates links via accepting a lambda expression.</p>
<p>Lastly there is the formatter itself. It will take the linked order and write out the appropriate links.&nbsp; Below is a skeleton of such a formatter.</p>
<script src="http://gist.github.com/1576925.js"></script><noscript><link rel="stylesheet" href="https://gist.github.com/stylesheets/gist/embed.css"><div id="gist-1576925" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="k">class</span> <span class="nc">OrderMediaTypeFormatterJson</span> <span class="p">:</span> <span class="n">MediaTypeFormatter</span> </div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="k">public</span> <span class="nf">OrderMediaTypeFormatter</span><span class="p">()</span> <span class="p">{</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">SupportedMediaTypes</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">new</span> <span class="nf">MediaTypeHeaderValue</span><span class="p">(</span><span class="s">&quot;application/contoso.orders+json&quot;</span><span class="p">)</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">);</span></div><div class='line' id='LC7'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'>&nbsp;&nbsp;<span class="k">public</span> <span class="k">override</span> <span class="kt">object</span> <span class="nf">OnWriteToStream</span><span class="p">(</span><span class="n">Type</span> <span class="n">type</span><span class="p">,</span> <span class="kt">object</span> <span class="k">value</span><span class="p">,</span> <span class="n">System</span><span class="p">.</span><span class="n">IO</span><span class="p">.</span><span class="n">Stream</span> <span class="n">stream</span><span class="p">,</span> <span class="n">HttpContentHeaders</span> <span class="n">contentHeaders</span><span class="p">,</span> <span class="n">System</span><span class="p">.</span><span class="n">Net</span><span class="p">.</span><span class="n">TransportContext</span> <span class="n">context</span><span class="p">)</span> </div><div class='line' id='LC11'>&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">var</span> <span class="n">linkedOrder</span> <span class="p">=</span> <span class="k">value</span> <span class="k">as</span> <span class="n">ILinkable</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;();</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">dynamic</span> <span class="n">json</span> <span class="p">=</span> <span class="k">new</span> <span class="n">JsonObject</span><span class="p">()</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">//write the order to json</span></div><div class='line' id='LC15'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC16'><br/></div><div class='line' id='LC17'>&nbsp;&nbsp;<span class="k">public</span> <span class="k">void</span> <span class="nf">OnReadFromStream</span><span class="p">(</span><span class="n">Type</span> <span class="n">type</span><span class="p">,</span> <span class="n">System</span><span class="p">.</span><span class="n">IO</span><span class="p">.</span><span class="n">Stream</span> <span class="n">stream</span><span class="p">,</span> <span class="n">HttpContentHeaders</span> <span class="n">contentHeaders</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">throw</span> <span class="k">new</span> <span class="nf">NotImplementedException</span><span class="p">();</span></div><div class='line' id='LC19'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC20'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1576925/408369977d1d06b64a0047438e73aedd9943562b/OrderFormatter.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1576925#file_order_formatter.cs" style="float:right;margin-right:10px;color:#666">OrderFormatter.cs</a>
            <a href="https://gist.github.com/1576925">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</noscript>
<p><u>Example: HAL formatter</u></p>
<p><a href="http://stateless.co/hal_specification.html">HAL</a> is a media type in draft at IANA that is designed specifically for expressing resources and links. <a href="http://geekswithblogs.net/michelotti/Default.aspx">Steve Michelotti</a> has created a <a href="https://bitbucket.org/smichelotti/hal-media-type/overview">formatter</a> for HAL. The way it works is your operations return a <a href="https://bitbucket.org/smichelotti/hal-media-type/src/f5a0382f34ad/HalMediaType/HalResource.cs">HalResource</a> model. HalResource can recursively contain other resources thus you can have a very deep resource map. You can use it both on the client and the server. The formatter then takes that model and writes it out appropriately as HAL, it also do the reverse taking a HAL response and turning it back into a HAL model. You can read more about how to use it in Steve’s <a href="http://geekswithblogs.net/michelotti/archive/2011/06/06/understanding-custom-wcf-web-api-media-type-processors-on-both.aspx">post</a>. Hopefully we’ll see this on nuget soon!</p>
<p><u>Example: XHTML using the plain old XML formatter</u></p>
<p>Mike Amundsen talks quite a bit about XHTML in his new book. What makes XHTML interesting from a hypermedia perspective is that it contains native support for hypermedia affordances, and browsers naturally understand it. You can express links very easily using an &lt;a href=””&gt; construct. You can embed forms as well as it supports them natively.&nbsp; It also offers annotations like name, id and style which we can use in order to attach domain specifics to the elements. For an rich example of what you can achieve with XHTML check Mike’s <a href="http://amundsen.com/hypermedia/profiles/">ALPS micro-blogging specification</a>.</p>
<p>Web API supports the ability for you to return XML dom objects directly, for example you can return XmlDocument/XDocument instead of a model. The beauty of this is that you can easily represent any XHTML document using the XML dom. Thus in your operation you simply create an&nbsp; XmlDocument, populate it appropriately and return it. The formatter will very happily then write it out to XHTML. </p>
<p>Here’s a skeletal snippet illustrating what I mean</p>
<script src="http://gist.github.com/1577236.js"></script><noscript><link rel="stylesheet" href="https://gist.github.com/stylesheets/gist/embed.css"><div id="gist-1577236" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="n">pubic</span> <span class="k">class</span> <span class="nc">OrderApi</span></div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'><span class="na">  [WebGet(UriTemplate=&quot;{id}&quot;)]</span></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="k">public</span> <span class="n">XmlDocument</span> <span class="nf">Get</span><span class="p">(</span><span class="kt">int</span> <span class="n">id</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">var</span> <span class="n">order</span> <span class="p">=</span> <span class="c1">//get the order</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">var</span> <span class="n">document</span> <span class="p">=</span> <span class="c1">//create an XmlDocument for the order</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">document</span><span class="p">;</span></div><div class='line' id='LC8'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC9'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1577236/916966f0260d1326f2fdf8629f9da527da6230b7/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1577236#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/1577236">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</noscript>
<p>If you do use this approach one thing you will need to do is add the media type to the default XML formatter. You can do that off of the configuration object’s Formatters collection using code similar to the following:</p>
<script src="http://gist.github.com/1577289.js"></script><noscript><link rel="stylesheet" href="https://gist.github.com/stylesheets/gist/embed.css"><div id="gist-1577289" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="n">config</span><span class="p">.</span><span class="n">Formatters</span><span class="p">.</span><span class="n">XmlFormatter</span><span class="p">.</span><span class="n">SupportedMediaTypes</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="k">new</span> <span class="n">MediaTypeMapping</span><span class="p">(</span><span class="s">&quot;application/vnd-contoso.orders.xml&quot;</span><span class="p">));</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1577289/514a99b471a6bc6d75cab975a7ca0a99ba9cdfe0/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1577289#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/1577289">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</noscript>
<p><u>Example: XHTML formatter example using Razor</u></p>
<p>Recently I delivered a talk at <a href="http://techfests.com/Tulsa/2011/default.aspx">Tulsa TechFest</a> where I demonstrated RestBugs. A sample app written by <a href="http://codebetter.com/howarddierking">Howard Dierking</a>. It&nbsp; contains a web API for bug tracking which and supports XHTML via a custom formatter. The app also includes a console hypermedia client which I hope to cover in&nbsp; another post.&nbsp; You can watch the video from that talk <a href="http://www.usergroup.tv/videos/speaking-the-language-of-the-web-with-wcf-web-api">here</a>. If you jump to the last 30 minutes that’s where I get into RestBugs where I cover the API, formatter and the hypermedia client.</p>
<p>One interesting thing about the app is the formatter that is used. Instead of manually writing out the XML, Howard uses a custom Razor formatter. The formatter looks for a custom content header which specifies the template. It then uses ASP.NET’s Razor engine to take the model passed in along with the template to generate the XHTML. To illustrate here is the template for the bug list.</p>
<script src="http://gist.github.com/1577068.js"></script><noscript><link rel="stylesheet" href="https://gist.github.com/stylesheets/gist/embed.css"><div id="gist-1577068" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="nt">&lt;html&gt;</span></div><div class='line' id='LC2'>	<span class="nt">&lt;head&gt;</span></div><div class='line' id='LC3'>		<span class="nt">&lt;title&gt;&lt;/title&gt;</span></div><div class='line' id='LC4'>	<span class="nt">&lt;/head&gt;</span></div><div class='line' id='LC5'>	<span class="nt">&lt;body&gt;</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;table</span> <span class="na">border=</span><span class="s">&quot;1&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;tr&gt;</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td&gt;</span>ID<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td&gt;</span>Name<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td&gt;</span>Status<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td&gt;</span>Priority<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td&gt;</span>Rank<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td&gt;</span>Assigned To<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td&gt;</span>History<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td&gt;</span>Item Link<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/tr&gt;</span></div><div class='line' id='LC17'><br/></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@foreach (var item in @Model)</div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;tr</span> <span class="na">class=</span><span class="s">&quot;bug-data&quot;</span><span class="nt">&gt;</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td</span> <span class="na">class=</span><span class="s">&quot;id&quot;</span><span class="nt">&gt;</span>@item.Id<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td</span> <span class="na">class=</span><span class="s">&quot;name&quot;</span><span class="nt">&gt;</span>@item.Name<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td</span> <span class="na">class=</span><span class="s">&quot;status&quot;</span><span class="nt">&gt;</span>@item.Status<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td</span> <span class="na">class=</span><span class="s">&quot;priority&quot;</span><span class="nt">&gt;</span>@item.Priority<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td</span> <span class="na">class=</span><span class="s">&quot;rank&quot;</span><span class="nt">&gt;</span>@item.Rank<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td</span> <span class="na">class=</span><span class="s">&quot;assignedTo&quot;</span><span class="nt">&gt;</span>@LinkFromEntity(item.AssignedTo, &quot;assignedTo&quot;)<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td&gt;</span>@LinkFromEntity(&quot;history&quot;, item, &quot;history&quot;)<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;td&gt;</span>@LinkFromEntity(item, &quot;self&quot;)<span class="nt">&lt;/td&gt;</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/tr&gt;</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/table&gt;</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nt">&lt;/body&gt;</span></div><div class='line' id='LC33'><span class="nt">&lt;/html&gt;</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1577068/871b170075fb29f0b9703918944727f0ebc04aa7/gistfile1.html" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1577068#file_gistfile1.html" style="float:right;margin-right:10px;color:#666">gistfile1.html</a>
            <a href="https://gist.github.com/1577068">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</noscript>
<p>I really like this approach because it gives you absolute freedom to format things exactly the way you want them without jumping through a 1000 hoops in code. I know from discussions with Mike that using templates is really his only way to fly.</p>
<p>You don’t have to wait for that future post I eluded to (which might never happen) to try the code in the talk as I’ve put it on Dropbox <a href="http://dl.dropbox.com/u/6860088/restbugs.zip">here</a>. You’ll find RestBugs including the Razor formatter and the client.</p>
<h3>Generate links through middleware.</h3>
<p>This approach is more of a hybrid of the other two. Instead of generating links in the formatter or the operation, you use an operation handler. The operation handler takes the model that is returned like ILinkable&lt;Order&gt; and then adds the appropriate links.</p>
<p>Taking the above code, you can simply move the logic to an operation handler to achieve the same.</p>
<script src="http://gist.github.com/1577207.js"></script><noscript><link rel="stylesheet" href="https://gist.github.com/stylesheets/gist/embed.css"><div id="gist-1577207" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="k">class</span> <span class="nc">OrderLinkHandler</span> <span class="p">:</span> <span class="n">HttpOperationHandler</span><span class="p">&lt;</span><span class="n">ILinkable</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;,</span><span class="n">ILinkable</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;&gt;</span></div><div class='line' id='LC2'><span class="p">{</span></div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="k">public</span> <span class="n">ILinkable</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;</span> <span class="n">OnHandle</span><span class="p">(</span><span class="n">ILinkable</span><span class="p">&lt;</span><span class="n">Order</span><span class="p">&gt;</span> <span class="n">linkedOrder</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="p">(</span><span class="n">linkedOrder</span><span class="p">.</span><span class="n">Instance</span><span class="p">.</span><span class="n">State</span> <span class="p">==</span> <span class="n">OrderStates</span><span class="p">.</span><span class="n">Created</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">linkedOrder</span><span class="p">.</span><span class="n">Links</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">OrderLinks</span><span class="p">.</span><span class="n">Approval</span><span class="p">,</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">GetApprovalUri</span><span class="p">(</span><span class="n">order</span><span class="p">.</span><span class="n">ID</span><span class="p">));</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">//other state logic here</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">linkedOrder</span><span class="p">;</span></div><div class='line' id='LC11'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'>&nbsp;&nbsp;<span class="k">private</span> <span class="n">Uri</span> <span class="nf">GetApprovalUri</span><span class="p">(</span><span class="n">orderId</span><span class="p">)</span> <span class="p">{</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">...</span></div><div class='line' id='LC15'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC16'><span class="p">}</span></div><div class='line' id='LC17'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1577207/0ee8285079c6f5d268f5e2ff004bce753b7f6663/OrderLInkHandler.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1577207#file_order_l_ink_handler.cs" style="float:right;margin-right:10px;color:#666">OrderLInkHandler.cs</a>
            <a href="https://gist.github.com/1577207">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</noscript>
<p>The pros of this is that it still allows the link logic to be used cross formatters, and it makes the code within your operation much tighter. The downside, and why I no longer prefer it is that it makes the code harder to follow. You have to know that a handler was registered which applies the links and you have to find that handler to understand the link logic.</p>
<h1>How to generate the uris themselves</h1>
<p>Aside from the strategy to embed links there is the question of how best to generate uris. Here’s a couple of recommendations on how you can do this.</p>
<p><u>Relative uris</u></p>
<p>If you can get away with relative uris do it.&nbsp; What I mean by that is this, let’s say you have a link to an Order approval resource for order 5. You can generate a link for “/order/approval/5”. The client will take the uri and append it to the host url in order to navigate. This alleviates the need for you having to get access to the base url for the site when you generate urls.</p>
<p><u>Absolute uris</u> </p>
<p>If you have multiple domains where your resources live, or if you want clients to always get the full uri so that they can simply copy/paste, use absolute uris. </p>
<p>For absolute uris, create a service which is configured with a map of all the available uris and exposes methods for retrieving them. </p>
<script src="http://gist.github.com/1577547.js"></script><noscript><link rel="stylesheet" href="https://gist.github.com/stylesheets/gist/embed.css"><div id="gist-1577547" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">public</span> <span class="k">interface</span> <span class="n">IUriService</span> <span class="p">{</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="kt">string</span> <span class="n">OrdersBaseUri</span> <span class="p">{</span><span class="k">get</span><span class="p">;}</span></div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="kt">string</span> <span class="n">InventoryBaseUri</span> <span class="p">{</span><span class="k">get</span><span class="p">;</span><span class="k">set</span><span class="p">;}</span></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="kt">string</span> <span class="n">UspsBaseUri</span> <span class="p">{</span><span class="k">get</span><span class="p">;</span><span class="k">set</span><span class="p">;}</span></div><div class='line' id='LC5'><span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1577547/e315b62e174797b9c014d1178f960ec5fc462feb/gistfile1.cs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1577547#file_gistfile1.cs" style="float:right;margin-right:10px;color:#666">gistfile1.cs</a>
            <a href="https://gist.github.com/1577547">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</noscript>
<p>OrdersBaseUri returns “http://contoso.orders.com” the address of the order system, while InventoryBaseUri returns “http://constoso.inventory.com” for the inventory system. UspsBaseUri is a the address for a third party site for shipping . </p>
<p>The uri service can then get injected into the link uri service which can use it to generate absolute uris. </p>
<h1>Your mileage may vary</h1>
<p>As you can see from this post, there are many different ways to approach implementing a hypermedia system with WCF Web API. As building hypermedia systems for web apis is still a pretty young topic, I don’t think there’s a clear winner yet on which hypermedia design approach to use. By extension there is also no clear winner on implementation. Over time and with more people building hypermedia based systems, hopefully this will change and there will be more accepted standards.</p>
<p>What has worked for you? Do you have a particular approach you’d like to see better support for in the box?</p>
<div class="shr-publisher-265"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F01%2F08%2Fhypermedia-and-web-api-design-brain-dump-and-samples%2F' data-shr_title='Hypermedia+and+Web+API.+Design+brain+dump+and+samples'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F01%2F08%2Fhypermedia-and-web-api-design-brain-dump-and-samples%2F' data-shr_title='Hypermedia+and+Web+API.+Design+brain+dump+and+samples'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F01%2F08%2Fhypermedia-and-web-api-design-brain-dump-and-samples%2F' data-shr_title='Hypermedia+and+Web+API.+Design+brain+dump+and+samples'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/GVzmsMRmqfs" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/glennblock/2012/01/08/hypermedia-and-web-api-design-brain-dump-and-samples/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
					<feedburner:origLink>http://codebetter.com/glennblock/2012/01/08/hypermedia-and-web-api-design-brain-dump-and-samples/</feedburner:origLink></item>
	      
    	<item>
		<title>Deploying a new version of a GWT app</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/38Ptzn_q8JA/</link>
		<comments>http://codebetter.com/kylebaley/2012/01/06/deploying-a-new-version-of-a-gwt-app-2/#comments</comments>
		<pubDate>Sat, 07 Jan 2012 03:50:14 +0000</pubDate>
		<dc:creator>Kyle Baley</dc:creator>
				<category><![CDATA[BookedIN]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[GWT]]></category>
			<guid isPermaLink="false">http://codebetter.com/kylebaley/2012/01/06/deploying-a-new-version-of-a-gwt-app-2/</guid>
					<description><![CDATA[For the record, I’ve never even been offered a Microsoft MVP. How’s THAT for street cred! That said, if the MVP lead in my area is reading: even though I don’t speak at user groups these days and hardly blog&#160;&#8230; <a href="http://codebetter.com/kylebaley/2012/01/06/deploying-a-new-version-of-a-gwt-app-2/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>For the record, I’ve never even been offered a Microsoft MVP. How’s THAT for street cred! That said, if the MVP lead in my area is reading: even though I don’t speak at user groups these days and hardly blog (and even then, rarely about Microsoft products anymore), I still feel my lack of contribution to OSS projects should count for something…</p>
<p>Now back to our regularly scheduled hoe down.</p>
<p>One of the issues with GWT apps that’s only really discussed in hushed whispers in the back alleys of Google Groups is how to handle new versions. The nature of pure JavaScript applications is a bit of a hindrance in this case. </p>
<p>When converting a Java application to the necessary Javascript, GWT generates (depending on your set up):</p>
<ul>
<li>a .nocache.js file
<li>several .cache.js and .cache.html files
<li>several .gwt.rpc files</li>
</ul>
<p>The .nocache.js file has the same name every time you compile. But if you’ve changed any code, the cache files and rpc files will not. Here’s what my folder looks like today for BookedIN:</p>
<p><a href="http://codebetter.com/kylebaley/files/2012/01/FolderStructure.jpg"><img style="border-right-width: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px;padding-top: 0px" border="0" alt="FolderStructure" src="http://codebetter.com/kylebaley/files/2012/01/FolderStructure_thumb.jpg" width="869" height="604"></a></p>
<p>&nbsp;</p>
<p>The next time I GWT-compile (provided I’ve changed some code), the folders and files in red will be deleted and replaced with new ones with different names. Among other things, the scheduler.nocache.js file is used to locate these files on demand while the app is running.</p>
<p>We use the <a href="http://code.google.com/eclipse/">Google Plugin for Eclipse</a> to deploy our application to AppEngine. We almost always deploy to a new version in AppEngine as well so that we can play around with it ourselves before unleashing it on an unsuspecting public. The upshot of this process is that the new version will have new .cache and .gwt.rpc files but not the old ones.</p>
<p>So let’s run through a potential scenario:</p>
<ul>
<li>Our faithful user logs into <a href="http://getbookedin.com/?cid=17">BookedIN</a> and uses the default version, which I will call “Dandelion”.
<li>We deploy a new version, called “Thistle” and make it the new default version
<li>The user makes a request for a page that is, say, behind a code-split. One of GWT’s nice optimization features that lets you split JavaScript among several files and loads them dynamically as needed.</li>
</ul>
<p>At this point, the user has the main page and the .nocache.js file loaded in memory. When it tries to satisfy the request, it will look for a .cache.js file from version “Dandelion”. Only by refreshing the entire browser page will it then load the new .nocache.js file, which knows about version “Thistle”. But this being a GWT-type, AJAX-ified application, there is rarely much call for them to refresh the entire page.</p>
<p>Predictably, we get a 404 error:</p>
<p><a href="http://codebetter.com/kylebaley/files/2012/01/404.jpg"><img style="border-right-width: 0px;padding-left: 0px;padding-right: 0px;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px;padding-top: 0px" border="0" alt="404" src="http://codebetter.com/kylebaley/files/2012/01/404_thumb.jpg" width="1001" height="732"></a></p>
<p>This leads to some pretty nifty dancing when it comes to deployment time. For example, how do you take down the application for maintenance cleanly? If the user has the page loaded in memory and is just making AJAX calls, you can’t just throw up an appoffline.htm file and redirect all your traffic to it (says the guy who thought differently a few short months ago).</p>
<p>Even if you can take the app down for maintenance, I don’t want to. We’re trying to shorten our deployment cycles which doesn’t lend itself to a page that says “hey, paying user, we’re adding some cool new features so pardon us interrupting you using the old ones” every week even if it just shows for a few minutes. In short, what I’d really like is a hot deployment.</p>
<p>Based on my <a href="https://groups.google.com/forum/#!topic/google-web-toolkit/Z34hfHWtD2s">research and questions</a>, this isn’t 100% possible but we can get close. As was suggested in the previous link, we can trap the appropriate exception in RPC calls and display a message to the user asking them to refresh their browser. Similarly, for code-split .cache.js files, we can trap the 404 error in the onFailure of the RunAsyncCallback (or better yet, use <a href="http://code.google.com/p/gwt-platform/">GWTP</a> and have some main presenter implement AsyncCallFailHandler to make this easier) and do the same thing: notify the user that the page needs to be refreshed.</p>
<p>Initially, this kind of left a bad taste in my mouth. But from a marketing perspective, it’s not bad. We have a little popup that we display to users when we’ve implemented something new so this is a nice way to ensure they see it.</p>
<p>Another suggestion that was made (by one of the creators of GWTP, no less) was to use the <a href="http://code.google.com/appengine/docs/java/channel/">Channel API</a> to detect when a new version has been released. This has an advantage in that you don’t need to wait until the user does something before informing him of the change.</p>
<p>So far, much of this is theoretical for us because it was easier to write about it than to actually implement it. In any case, few people seem to be discussing it. Besides which, I had to write *something* after that little Microsoft MVP commentary.</p>
<p>Kyle the Filler</p>
<div class="shr-publisher-257"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F01%2F06%2Fdeploying-a-new-version-of-a-gwt-app-2%2F' data-shr_title='Deploying+a+new+version+of+a+GWT+app'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F01%2F06%2Fdeploying-a-new-version-of-a-gwt-app-2%2F' data-shr_title='Deploying+a+new+version+of+a+GWT+app'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F01%2F06%2Fdeploying-a-new-version-of-a-gwt-app-2%2F' data-shr_title='Deploying+a+new+version+of+a+GWT+app'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/38Ptzn_q8JA" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/kylebaley/2012/01/06/deploying-a-new-version-of-a-gwt-app-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
					<feedburner:origLink>http://codebetter.com/kylebaley/2012/01/06/deploying-a-new-version-of-a-gwt-app-2/</feedburner:origLink></item>
	      
    	<item>
		<title>A very few thoughts on the MVP program</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/M-GXBcIjVRA/</link>
		<comments>http://codebetter.com/jeremymiller/2012/01/05/a-very-few-thoughts-on-the-mvp-program/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 14:40:05 +0000</pubDate>
		<dc:creator>Jeremy Miller</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/jeremymiller/?p=882</guid>
					<description><![CDATA[TL;DR:  I don&#8217;t think there&#8217;s any need to give in to paranoia about the MVP program or look at it as a conspiracy or believe that it either damages or enhances your credibility as a developer. A couple folks that&#160;&#8230; <a href="http://codebetter.com/jeremymiller/2012/01/05/a-very-few-thoughts-on-the-mvp-program/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>TL;DR:  I don&#8217;t think there&#8217;s any need to give in to paranoia about the MVP program or look at it as a conspiracy or believe that it either damages <strong>or</strong> enhances your credibility as a developer.</p>
<p>A couple folks that are fairly visible and arguably very valuable OSS leaders or contributors <a href="http://devlicio.us/blogs/rob_eisenberg/archive/2012/01/04/how-i-lost-regained-and-then-turned-down-an-mvp-award.aspx">didn&#8217;t get renewed as Microsoft MVP&#8217;s this year</a> and it&#8217;s caused a minor fuss online.  After 5 straight years of receiving the MVP award for C#, I didn&#8217;t either.  No big deal, but a couple thoughts anyway:</p>
<ul>
<li>I was on 4-5 podcasts and spoke at CodeMash last year, but I didn&#8217;t do much writing and speaking otherwise.  I think I made it to one NUG meeting just because a colleague was speaking, but that was it.  The point is, I didn&#8217;t really do anything to meet the criteria as I understand it for being an MVP &#8212; plus I was distracted and didn&#8217;t get around to filling out the &#8220;why I deserve to be an MVP&#8221; form anyway.  I&#8217;m not exactly Mr. &#8220;Good at doing paperwork&#8221;</li>
<li>I did spend a very large amount of time devoted to OSS efforts last year, but as you probably know, the MVP program doesn&#8217;t really recognize OSS contributions.  That&#8217;s an old complaint and one that I&#8217;ve raised myself in years past.  Nuget notwithstanding, Microsoft has never really embraced OSS development on the .Net platform.*  I don&#8217;t think this will ever really change so we might as well just stop getting upset about it.**</li>
<li>MS apparently does have a program going where OSS contributors can get MSDN licenses and I&#8217;ll be getting myself hooked up at some point.  At some point this year I think we might be completely switched over to developing on Mono and MonoDevelop, but for now I want a working copy of VS.Net and ReSharper and I&#8217;ve got both.</li>
<li>I have no entitlement to any sort of reward or recognition from Microsoft.  It&#8217;s their program and they can do whatever they want with it using any criteria they come up with.</li>
<li>I really don&#8217;t need vindication or recognition from Microsoft.  You shouldn&#8217;t either.</li>
<li>My personal experience interacting with Microsoft teams is mixed.  I can point to a few things in Microsoft tools that were influenced by OSS work that I&#8217;m involved in, but I don&#8217;t think that the direct feedback I&#8217;ve given over the years has ever made any difference.</li>
<li>At no point did I ever feel pressured to self-censure my opinions online or at development events just because of my MVP award (probably should have anyway;)).  Neither did I particularly feel forced to toe the Microsoft line or push Microsoft tooling.  Heck, I got the MVP several times after helping author the silly EF Vote of No Confidence thing (I do think that my original verbiage was a lot less eye-poking than what got in there).  A couple people told me that I would be able to be a lot more honest and open with my opinions after losing the MVP.  I plan to do the opposite and stay out of nerd rage events like, say, claiming that FubuMVC is better than Rails just because someone did something dumb with ActiveRecord one time.</li>
</ul>
<p>* Yes, someone is going to rightfully say that Nuget has been a huge boon for .Net OSS development, but I&#8217;ll automatically respond by reminding you that Nuget effectively trashed a pair of ongoing OSS efforts from the community.  You might also say that Microsoft has embraced jQuery and I&#8217;ll tell you that they had absolutely no chance of competing with jQuery&#8217;s ecosystem and had to do that.  You&#8217;ll also remind me that the Azure team is suddenly really active in supporting Node.js and I&#8217;ll tell you that I think the Azure team had to do that for the sake of Azure adoption and remind you that Node.js didn&#8217;t originate from the Microsoft development community at all.</p>
<p>** As an aside, I&#8217;m no expert on Microsoft internal politics but it definitely seems to me that the Windows team has more or less put DevDiv under its thumb in the pecking order. I think this could help developers on the Windows platform by shifting the focus squarely towards making Windows a good platform to develop software for versus trying to push a pure Microsoft created development ecosystem from DevDiv. If that means supporting tools like Node.js or Nginx or PHP or even Rails on Windows instead of just pushing their own tools, we the developers can only win. Again, I&#8217;m no Mary Jo Foley, just my 2 cents.</p>
<div class="shr-publisher-882"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjeremymiller%2F2012%2F01%2F05%2Fa-very-few-thoughts-on-the-mvp-program%2F' data-shr_title='A+very+few+thoughts+on+the+MVP+program'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjeremymiller%2F2012%2F01%2F05%2Fa-very-few-thoughts-on-the-mvp-program%2F' data-shr_title='A+very+few+thoughts+on+the+MVP+program'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjeremymiller%2F2012%2F01%2F05%2Fa-very-few-thoughts-on-the-mvp-program%2F' data-shr_title='A+very+few+thoughts+on+the+MVP+program'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/M-GXBcIjVRA" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/jeremymiller/2012/01/05/a-very-few-thoughts-on-the-mvp-program/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
					<feedburner:origLink>http://codebetter.com/jeremymiller/2012/01/05/a-very-few-thoughts-on-the-mvp-program/</feedburner:origLink></item>
	      
    	<item>
		<title>What we did on our holidays: a classic guitar, an iPad, Fender and iRig</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/xUb6HKAbemU/</link>
		<comments>http://codebetter.com/petervanooijen/2011/12/28/what-we-did-on-our-holidays-a-classic-guitar-an-ipad-fender-and-irig-2/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 13:36:48 +0000</pubDate>
		<dc:creator>Peter van Ooijen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/petervanooijen/2011/12/28/what-we-did-on-our-holidays-a-classic-guitar-an-ipad-fender-and-irig-2/</guid>
					<description><![CDATA[This post is somewhere near the border of being off-topic but I consider it geeky enough myself to share it here. Like many others of my generation, living their high-school day in the end of the sixties/ beginning seventies, I’m&#160;&#8230; <a href="http://codebetter.com/petervanooijen/2011/12/28/what-we-did-on-our-holidays-a-classic-guitar-an-ipad-fender-and-irig-2/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>This post is somewhere near the border of being off-topic but I consider it geeky enough myself to share it here.</p>
<p>Like many others of my generation, living their high-school day in the end of the sixties/ beginning seventies, I’m a guitar kid. Despite my heroes like Hooker and Hendrix I never had more myself than a nylon stringed Spanish instrument. And love that. This holiday I tried to bridge some gaps using today’s technology.</p>
<p>There are wonderful apps for an iPad like <a href="http://www.ikmultimedia.com/amplitubeipad/features/">Amplitube</a> which emulates classical Fender guitar amps, complete with distortion and the like. Using an <a href="http://www.ikmultimedia.com/irig/features/">iRig</a> you can plug an electric guitar straight into your iPad (or iPhone). A pickup does not work on a nylon strings (no, don’t get me started on Takamine) but I did have an old Aria (a brand known over here mainly for its recorders) contact microphone. The output level of a (contact) microphone is less than that of an electric guitar, but perhaps it could work with an iRig. Googling around brought up a lot of ways to build your own contact microphone (on Youtube) but no answer to my question. So I went to a real life music shop (<a href="http://www.westerhaven.nl/">Westerhaven</a> in Groningen). They shared my doubt but offered to give it a try. In case it wouldn’t work I could just return the iRig. Where do you find that in a web-shop ?</p>
<p>And I’m going to keep it, it does work ! This is my setup:</p>
<p><a href="http://codebetter.com/petervanooijen/files/2011/12/iRig1.png"><img style="border-bottom: 0px;border-left: 0px;margin: 0px 0px 24px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="iRig" src="http://codebetter.com/petervanooijen/files/2011/12/iRig_thumb.png" width="458" height="591"></a></p>
<p>The signal is weak, just raise the input level in Amplitube’s settings.</p>
<p><a href="http://codebetter.com/petervanooijen/files/2011/12/Level.png"><img style="border-bottom: 0px;border-left: 0px;margin: 0px 0px 24px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="Level" src="http://codebetter.com/petervanooijen/files/2011/12/Level_thumb.png" width="475" height="535"></a></p>
<p>Of course the sound does not have the electric punch. The level of noise is acceptable with the noise filter switched off. In most settings switching that on filters out to much of the tones as well.&nbsp; The tremolo of a Fender Twin is not as deep as I had hoped. But the Super-Sonic really let’s the Christmas blues scream out.</p>
<p>That’s it, a nice combination of classic old stuff and new technology. I’m looking forward what surprises 2012 will bring. Happy new year !</p>
<div class="shr-publisher-683"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fpetervanooijen%2F2011%2F12%2F28%2Fwhat-we-did-on-our-holidays-a-classic-guitar-an-ipad-fender-and-irig-2%2F' data-shr_title='What+we+did+on+our+holidays%3A+a+classic+guitar%2C+an+iPad%2C+Fender+and+iRig'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fpetervanooijen%2F2011%2F12%2F28%2Fwhat-we-did-on-our-holidays-a-classic-guitar-an-ipad-fender-and-irig-2%2F' data-shr_title='What+we+did+on+our+holidays%3A+a+classic+guitar%2C+an+iPad%2C+Fender+and+iRig'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fpetervanooijen%2F2011%2F12%2F28%2Fwhat-we-did-on-our-holidays-a-classic-guitar-an-ipad-fender-and-irig-2%2F' data-shr_title='What+we+did+on+our+holidays%3A+a+classic+guitar%2C+an+iPad%2C+Fender+and+iRig'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/xUb6HKAbemU" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/petervanooijen/2011/12/28/what-we-did-on-our-holidays-a-classic-guitar-an-ipad-fender-and-irig-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
					<feedburner:origLink>http://codebetter.com/petervanooijen/2011/12/28/what-we-did-on-our-holidays-a-classic-guitar-an-ipad-fender-and-irig-2/</feedburner:origLink></item>
	      
    	<item>
		<title>I moved on from WCF Web API, but Web API IS still moving</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/3Ujzx5MAF_o/</link>
		<comments>http://codebetter.com/glennblock/2011/12/24/i-moved-on-from-wcf-web-api-but-web-api-is-still-moving/#comments</comments>
		<pubDate>Sat, 24 Dec 2011 00:05:29 +0000</pubDate>
		<dc:creator>Glenn Block</dc:creator>
				<category><![CDATA[node.js]]></category>
		<category><![CDATA[WCF]]></category>
		<category><![CDATA[WCF Web APIs]]></category>
			<guid isPermaLink="false">http://codebetter.com/glennblock/2011/12/24/i-moved-on-from-wcf-web-api-but-web-api-is-still-moving/</guid>
					<description><![CDATA[If you’ve my last few posts around the new Windows Azure SDK for Node.js and you have not been following me on twitter, then you might be suspicious. Let me remove the suspicion, I’ve moved on from the Web API&#160;&#8230; <a href="http://codebetter.com/glennblock/2011/12/24/i-moved-on-from-wcf-web-api-but-web-api-is-still-moving/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>If you’ve my last few posts around the new Windows Azure SDK for Node.js and you have not been following me on twitter, then you might be suspicious. Let me remove the suspicion, I’ve moved on from the Web API team about 5 months ago to help with our Node.js on Azure story. </p>
<h1>My ride with Web API</h1>
<p><a href="http://codebetter.com/glennblock/files/2011/12/MP9004024501.jpg"><img style="border-bottom: 0px;border-left: 0px;margin: 0px 0px 24px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="MP900402450[1]" src="http://codebetter.com/glennblock/files/2011/12/MP9004024501_thumb.jpg" width="184" height="274"></a></p>
<p>I’ve had a thrillingly fantastic ride being with the Web API team. When I first joined WCF after leaving the MEF team, I had a ton of folks pinging me on twitter asking me what in the world I was doing / why would I go to WCF. I told them there was an opportunity for WCF to do the right thing for customers building HTTP/RESTful APIS. I also said that we would not do it alone and we would work with the community. <a href="http://codebetter.com/sebastienlambla/">Sebastian Lambla</a> (@serialseb) can attest to this as he and I chatted before I even agreed to take the job. Seb was supportive and agreed to help us along with a bunch of other folks. </p>
<p>Since then we think we’ve delivered on that promise. At PDC last year we released our first drop of Web API on <a href="http://wcf.codeplex.com">Codeplex</a> and published our Mercurial <a href="http://wcf.codeplex.com/SourceControl/list/changesets">repo</a>, since then we’ve been releasing as frequently as we could including on <a href="http://nuget.org">Nuget</a>. </p>
<p>So far, we’ve heard that people like <a href="http://www.bizcoder.com/index.php/2010/10/28/wcf-http/">like</a> <a href="http://geekswithblogs.net/michelotti/archive/2010/11/07/the-time-is-now-to-start-checking-out-the-wcf.aspx">what</a> we are doing. We’ve been developing a library that really helps you take full advantage of HTTP and REST (if you desire) to support an evolving set of clients. Not only that, but it’s complexity bar is low and the simplicity bar is high. Also it plays much better with good principles of software design like separation-of-concerns, and offers good compatibility with good software practices like test-driven-development. </p>
<p>We’ve had a core set of advisors from the community helping us at every stage to build something useful in the real world, telling us what to do and more importantly what NOT to do. We’ve taken a ton of feedback from the broader community and driven it back to the product. Finally we’ve seen some great efforts from the community both <a href="http://weblogs.asp.net/cibrax/archive/tags/WCF+Web+Apis/default.aspx">in</a> <a href="http://pfelix.wordpress.com/tag/wcf-web-api/">education</a> <a href="http://geekswithblogs.net/michelotti/category/12065.aspx">on</a> <a href="http://blog.alexonasp.net/?tag=/web+api">how</a> to use it and in <a href="http://nuget.org/packages?q=webapicontrib+netfx-webapi+WebApi.Scaffolding&amp;sortOrder=package-download-count">extensions</a> to the core product.</p>
<p>&lt;mushy-stuff-follows&gt;</p>
<p>I am indebted deeply to the people I worked with on the Web API team. We accomplished a lot with the odds stacked against us. I am also indebted to our advisors who invested a lot of personal energy and time to helps guide us. I feel privileged to have worked with such stellar people, there’s too many of you to name, but you know who you are! </p>
<p>As for my part well, I felt like the <a href="http://www.hanselman.com/blog/ImAPhonyAreYou.aspx">phony</a> on the team with all the great minds that were around me. I did my part, but the real work was of the folks I mentioned.</p>
<p><strong>Web API <em><u>IS</u></em> still moving and it will ship</strong><a href="http://codebetter.com/glennblock/files/2011/12/MP9004386371.jpg"><img style="border-bottom: 0px;border-left: 0px;margin: 0px 0px 24px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="MP900438637[1]" src="http://codebetter.com/glennblock/files/2011/12/MP9004386371_thumb.jpg" width="399" height="267"></a></p>
<p>Since my last few posts and throughout my tweeting over the past few months, I’ve received a lot of questions from folks asking me “What about Web API”. Is it another dead carcass left in the framework graveyard? Is it another sacred text to be stored in the gigantic warehouse of Raiders of the Lost Ark*? The answer is an emphatic <strong>no</strong>!</p>
<p>* – Yes I am delusional</p>
<p>Yes, I’ve moved on, but <strong>Web API is moving on as well to bigger and brighter places</strong>. The team is pumped up and the product is moving like a high speed train going at 200 mph! You’ll have to take my word for it, but I believe it is headed in the best possible direction than I could have ever hoped for. I also believe it is the best outcome for <strong>you</strong>, our developers.&nbsp; I can’t talk about it now, but you will be hearing about it shortly in a big announcement. I am sure many of you can imagine what that will be.&nbsp; You can find a big teaser in <a href="http://wcf.codeplex.com/discussions/273995">this</a> discussion thread.</p>
<p>The meta point here is if you are investing in Web API, you’ve made a good decision. And if you haven’t, well you should probably start <img src='http://codebetter.com/glennblock/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  There’s much more goodness to come!</p>
<p>Keep watching <a href="http://weblogs.asp.net/scottgu/">ScottGu’s</a> and <a href="http://codebetter.com/howarddierking/">Howard Dierking’s</a> blog for details on the extremely bright future of Web API!</p>
<h1>Why Node.js?</h1>
<p><a href="http://codebetter.com/glennblock/files/2011/12/image1.png"><img style="border-bottom: 0px;border-left: 0px;margin: 0px;padding-left: 0px;padding-right: 0px;border-top: 0px;border-right: 0px;padding-top: 0px" border="0" alt="image" src="http://codebetter.com/glennblock/files/2011/12/image_thumb1.png" width="244" height="90"></a></p>
<p>I have been an avid mostly observer of <a href="http://nodejs.org/">Node.js</a> for the past two years. I first learned about it at <a href="http://www.oredev.org/2011">Øredev</a>. It offers a simplified model for building highly scalable web applications using server side JavaScript. I talked a bit about my own perspectives on Why Node in my interview <a href="http://channel9.msdn.com/Events/windowsazure/learn/Interview-with-Glenn-Block-Talking-About-Node-js-on-Windows-Azure">here</a>. Since it’s inception we’ve seen an explosion of interest in Node across the industry. Recently we’ve also seen a lot of interest around making Node.js work well for Windows. We’ve worked with <a href="http://www.joyent.com/">Joyent</a> to make that a reality, and we’ve also look at how to better integrate Node with Windows with efforts like <a href="https://github.com/tjanczuk/iisnode">iisnode</a>. </p>
<p>A few months back I was asked if I’d be interested in helping to take that support for Node.s to Windows Azure. Seeing the excitement around Node.js, the opportunity to make Azure a great place for developing Node.js applications, the opportunity to make Azure a truly open platform, and the bonus of doing it in ScottGu’s org, I jumped at the chance. </p>
<p>And so, if you look for me now going forward, you’ll find me on the Azure SDK team! Going forward you’ll see much more about the work we are doing in this space on my blog.</p>
<p>&lt;more-mushy-stuff&gt;</p>
<p><strong>Thank you all for your support!</strong> I am truly grateful for the opportunities you (and Microsoft) gives me to help you build better software. See you in the <a href="http://www.windowsazure.com/en-us/develop/nodejs/">cloud</a>!</p>
<div class="shr-publisher-261"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2011%2F12%2F24%2Fi-moved-on-from-wcf-web-api-but-web-api-is-still-moving%2F' data-shr_title='I+moved+on+from+WCF+Web+API%2C+but+Web+API+IS+still+moving'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2011%2F12%2F24%2Fi-moved-on-from-wcf-web-api-but-web-api-is-still-moving%2F' data-shr_title='I+moved+on+from+WCF+Web+API%2C+but+Web+API+IS+still+moving'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2011%2F12%2F24%2Fi-moved-on-from-wcf-web-api-but-web-api-is-still-moving%2F' data-shr_title='I+moved+on+from+WCF+Web+API%2C+but+Web+API+IS+still+moving'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/3Ujzx5MAF_o" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/glennblock/2011/12/24/i-moved-on-from-wcf-web-api-but-web-api-is-still-moving/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
					<feedburner:origLink>http://codebetter.com/glennblock/2011/12/24/i-moved-on-from-wcf-web-api-but-web-api-is-still-moving/</feedburner:origLink></item>
	      
    	<item>
		<title>A holiday.js gift for Azure Node.js developers</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/0U42zvbqSjw/</link>
		<comments>http://codebetter.com/glennblock/2011/12/23/a-holiday-js-gift-for-azure-node-js-developers-2/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 06:26:00 +0000</pubDate>
		<dc:creator>Glenn Block</dc:creator>
				<category><![CDATA[azure]]></category>
		<category><![CDATA[node.js]]></category>
			<guid isPermaLink="false">http://codebetter.com/glennblock/2011/12/23/a-holiday-js-gift-for-azure-node-js-developers-2/</guid>
					<description><![CDATA[It’s been 10 days since we release our first preview of Windows Azure SDK for Node.js. So far the community reaction has been really good. Feedback is starting to trickle in with feature requests / bugs, etc. We are listening&#160;&#8230; <a href="http://codebetter.com/glennblock/2011/12/23/a-holiday-js-gift-for-azure-node-js-developers-2/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>It’s been 10 days since we release our first preview of <a href="http://blogs.msdn.com/b/windowsazure/archive/2011/12/16/node-js-in-windows-azure-to-the-cloud-and-beyond.aspx">Windows Azure SDK for Node.js</a>. So far the community <a href="http://joyeur.com/2011/12/16/node-on-azure-and-sdk-release/">reaction</a> has been really good. Feedback is starting to trickle in with feature requests / bugs, etc. We are listening and <strong>really</strong> appreciate the feedback, so keep it coming.</p>
<p>Staying true to our commitment to release early and often, and in keeping with the holiday tradition, we bring you this gift, the <a href="http://go.microsoft.com/?linkid=9790229&amp;clcid=0x409">December update</a>. </p>
<p><a href="http://codebetter.com/glennblock/files/2011/12/MP9004022021.jpg"><img style="border-right-width: 0px;margin: 0px 0px 24px;padding-left: 0px;padding-right: 0px;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px;padding-top: 0px" border="0" alt="Christmas Present Wrapped in Gold and Silver 2000" src="http://codebetter.com/glennblock/files/2011/12/MP9004022021_thumb.jpg" width="244" height="196"></a>&nbsp;&nbsp; </p>
<h1>Highlights of this preview: </h1>
<ul>
<li>Windows Azure PowerShell for Node.js 0.5.1 update, including new cmdlets for easily enabling <a href="https://sn1prd0302.outlook.com/owa/redir.aspx?C=kPaCmbYahk-0wQIbPru2U1KqPLDGlM4IznbSovmuWD1mudT8_sXx72lt31g9gC-BMGaoXVcmsYM.&amp;URL=http%3a%2f%2fwww.windowsazure.com%2fen-us%2fdevelop%2fnodejs%2fcommon-tasks%2fenable-remote-desktop%2f">Remote Desktop</a>, as well as <a href="https://sn1prd0302.outlook.com/owa/redir.aspx?C=kPaCmbYahk-0wQIbPru2U1KqPLDGlM4IznbSovmuWD1mudT8_sXx72lt31g9gC-BMGaoXVcmsYM.&amp;URL=http%3a%2f%2fwww.windowsazure.com%2fen-us%2fdevelop%2fnodejs%2fcommon-tasks%2fenable-ssl%2f">SSL support</a>.
<li>iisnode 0.1.13 update, including significant performance improvements (&gt;2x throughput of the previous version)
<li>Node.js 0.6.6 update from Joyent, including a more stable npm
<li>Installer in-place upgrade support for all these components, so you can just click the <a href="https://sn1prd0302.outlook.com/owa/redir.aspx?C=kPaCmbYahk-0wQIbPru2U1KqPLDGlM4IznbSovmuWD1mudT8_sXx72lt31g9gC-BMGaoXVcmsYM.&amp;URL=http%3a%2f%2fwww.microsoft.com%2fweb%2fgallery%2finstall.aspx%3fappid%3dazurenodepowershell">WebPI link</a> (linked from the dev center) and it will upgrade your existing installation of these components if you already have the previous version, or install them all if you don’t.
<li>Numerous bug fixes in all three components </li>
</ul>
<h1>Enabling Remote Desktop access the easy way</h1>
<p>Remote Desktop allows you to connect directly to your VMs. It’s very useful in particular for debugging and diagnostics. </p>
<p>In our previous preview to enable RDP support to your VMs you needed to follow a bunch of manual steps which included among other things modifying config files, creating a certificate, and uploading the cert to the portal.</p>
<p>Now, all of the steps are taken care of for you via a <strong>single</strong> cmdlet, “Enable-AzureRemoteDesktop”! </p>
<p>Say these three words with me, “Enable, Publish, Connect”.</p>
<p>A picture tells a thousand words, so just glance at the screenshots below.</p>
<h2><strong>1. Enable:</strong></h2>
<p><img style="margin: 0px auto 24px;float: none" src="http://www.windowsazure.com/media/net/common-task-remote-desktop1-node-02.png" width="505" height="249"></p>
<h2><strong>2. Publish:</strong></h2>
<p><img style="margin: 0px auto 24px;float: none" src="http://www.windowsazure.com/media/net/common-task-remote-desktop1-node-03.png" width="511" height="255"></p>
<h2>3. <strong>Connect:</strong></h2>
<p><img style="margin: 0px auto 24px;float: none" src="http://www.windowsazure.com/media/net/common-task-remote-desktop1-node-10.png" width="505" height="316"></p>
<p>Any questions?</p>
<p>The release is also accompanied by an update of the <a href="https://sn1prd0302.outlook.com/owa/redir.aspx?C=kPaCmbYahk-0wQIbPru2U1KqPLDGlM4IznbSovmuWD1mudT8_sXx72lt31g9gC-BMGaoXVcmsYM.&amp;URL=http%3a%2f%2fwww.windowsazure.com%2fen-us%2fdevelop%2fnodejs%2f">Windows Azure Node.js dev center</a> content which includes new “How-To content” and “Common tasks”. </p>
<p><a href="http://www.microsoft.com/web/gallery/install.aspx?appid=azurenodepowershell">Enjoy</a> (download) and have a happy holiday.js!</p>
<div class="shr-publisher-253"></div><!-- Start Shareaholic LikeButtonSetBottom Automatic --><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><div class='shareaholic-like-buttonset' style='float:none;height:30px;'><a class='shareaholic-fblike' data-shr_layout='button_count' data-shr_showfaces='false' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2011%2F12%2F23%2Fa-holiday-js-gift-for-azure-node-js-developers-2%2F' data-shr_title='A+holiday.js+gift+for+Azure+Node.js+developers'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2011%2F12%2F23%2Fa-holiday-js-gift-for-azure-node-js-developers-2%2F' data-shr_title='A+holiday.js+gift+for+Azure+Node.js+developers'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2011%2F12%2F23%2Fa-holiday-js-gift-for-azure-node-js-developers-2%2F' data-shr_title='A+holiday.js+gift+for+Azure+Node.js+developers'></a></div><div style="clear: both; min-height: 1px; height: 3px; width: 100%;"></div><!-- End Shareaholic LikeButtonSetBottom Automatic --><img src="http://feeds.feedburner.com/~r/CodeBetter/~4/0U42zvbqSjw" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/glennblock/2011/12/23/a-holiday-js-gift-for-azure-node-js-developers-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
					<feedburner:origLink>http://codebetter.com/glennblock/2011/12/23/a-holiday-js-gift-for-azure-node-js-developers-2/</feedburner:origLink></item>
	  </channel>
</rss><!-- Dynamic page generated in 6.455 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-02-10 13:28:23 --><!-- Compression = gzip -->

