<?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.2</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>Slice of Life: Converting my Personal Site</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/vpokd2F_W2o/</link>
		<comments>http://codebetter.com/drusellers/2012/05/13/slice-of-life-converting-my-personal-site/#comments</comments>
		<pubDate>Sun, 13 May 2012 16:32:36 +0000</pubDate>
		<dc:creator>Dru Sellers</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/drusellers/?p=265</guid>
					<description><![CDATA[Over the last few months I have been having a lot of fun converting my personal site (http://drusellers.com) from a pure static html site, to one that uses a back end server side language. When I first started the main&#160;&#8230; <a href="http://codebetter.com/drusellers/2012/05/13/slice-of-life-converting-my-personal-site/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Over the last few months I have been having a lot of fun converting my personal site (http://drusellers.com) from a pure static html site, to one that uses a back end server side language.</p>
<p>When I first started the main purpose was to learn a little more about python. So I started off using Flask, a micro framework for python. Flask is a lot like Sinatra for ruby and the comparison was a lot of fun because my good friend Ryan Rauh (RyRy) was writing a site in Sinatra at the time so we were able to compare and contrast the two approaches quite easily.</p>
<p>As I learned more about flask and all that it could do, I was impressed by how much I could do with so little. It served as a solid reminder that we should strive for simpler solutions.</p>
<p>In addition to learning python I also took the time to dive into LESS. Organizing the CSS content of applications has always been difficult for me. Finally, with LESS I had variables and the ability to nest selectors. Basically, all of the things that I have wanted CSS to do for a very long time. I started out using the runtime compilation modes of LESS, but as I learned more I eventually switched to running the watch mode on the compiler and then stripping that functionality out of the app. Right now, I really like this approach. It feels more like PROD vs DEV, but I still have the ability to iterate quickly. The real choice to use LESS, was that the popular CSS framework from Twitter called Bootstrap had just launched. By studying their approach and trying to deconstruct things I have learned a lot about CSS and its application to better CSS approaches.</p>
<p>But as with all things in the technical world, a change was on the horizon. That change was SASS/SCSS. RyRy read a post somewhere comparing SCSS and LESS and he came away with the impression that SCSS RULED, and LESS DROOLED. This was one of those moments, where I gave RyRy a stern look and then sat down to start converting my website from LESS to SCSS, because when the guy you ask all of your questions too, changes directions sometimes its just easier to go with the flow. Thankfully it wasn&#8217;t that hard, allowed me to revisit my CSS and improve things further.</p>
<p>Around the same time, I discovered semantic.gs, a SCSS friendly grid system, finally I can get rid of the BS classes like span-4 and what not that have been plaguing me since I first found blueprint.css and 960grid. Whoot! I have been able to further clean up the website&#8217;s CSS approach.</p>
<p>Well, of course the project can come to a close quite that simply. After improving my CSS and getting an understanding of python, I of course, had to completely rebuild it something new and shiny. Damn, my attention span.</p>
<p>So, yeah. Node.js the new shiny language/framework. My JavaScript skills have always suffered, so I rationalized changing my backend code to JavaScript as a means to improve my JS skillset. So, I converted my site again, learned a lot about JavaScript in the process, melted my brain trying to get things to work in this under powered language (under powered because I am used to my language providing much more to me).</p>
<p>So now my site is running Node.js &#8211; its a whole lot cleaner and easier to work on. I love how simple the underlying code is, and I have really learned a lot about some of the new languages and frameworks out there.</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%2Fdrusellers%2F2012%2F05%2F13%2Fslice-of-life-converting-my-personal-site%2F' data-shr_title='Slice+of+Life%3A+Converting+my+Personal+Site'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fdrusellers%2F2012%2F05%2F13%2Fslice-of-life-converting-my-personal-site%2F' data-shr_title='Slice+of+Life%3A+Converting+my+Personal+Site'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fdrusellers%2F2012%2F05%2F13%2Fslice-of-life-converting-my-personal-site%2F' data-shr_title='Slice+of+Life%3A+Converting+my+Personal+Site'></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/vpokd2F_W2o" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/drusellers/2012/05/13/slice-of-life-converting-my-personal-site/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
					<feedburner:origLink>http://codebetter.com/drusellers/2012/05/13/slice-of-life-converting-my-personal-site/</feedburner:origLink></item>
	      
    	<item>
		<title>Azure SDK for node 0.5.4 is out! More secure and now with less angle brackets</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/_bH0Q0BRVV8/</link>
		<comments>http://codebetter.com/glennblock/2012/05/12/azure-sdk-for-node-0-5-4-is-out-more-secure-and-now-with-less-angle-brackets/#comments</comments>
		<pubDate>Sat, 12 May 2012 18:33:15 +0000</pubDate>
		<dc:creator>Glenn Block</dc:creator>
				<category><![CDATA[node.js]]></category>
			<guid isPermaLink="false">http://codebetter.com/glennblock/?p=411</guid>
					<description><![CDATA[As Yavor said, Azure SDK for node 0.5.4 is out with a bunch of goodies! Closing a security hole Recently a vulnerability was detected in node.exe that could theoretically allow an attacker to perform a header-spoofing attack. Version 0.6.17 contains&#160;&#8230; <a href="http://codebetter.com/glennblock/2012/05/12/azure-sdk-for-node-0-5-4-is-out-more-secure-and-now-with-less-angle-brackets/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>As Yavor said, <a href="http://hashtagfail.com/post/22865195229/node-sdk-0-5-4">Azure SDK for node 0.5.4 is out</a> with a bunch of goodies!</p>
<h1>Closing a security hole</h1>
<p>Recently a <a href="http://blog.nodejs.org/2012/05/07/http-server-security-vulnerability-please-upgrade-to-0-6-17/">vulnerability</a> was detected in node.exe that could theoretically allow an attacker to perform a header-spoofing attack. Version 0.6.17 contains a fix for this attack. We take security very seriously, so we’re releasing this update which includes node 0.6.17 to remove the vulnerability.</p>
<p>Please go <a href="http://www.microsoft.com/web/gallery/install.aspx?appid=azurenodepowershell">download </a>the latest bits to remove this vulnerability!</p>
<p><strong>Less angle brackets, more YAML</strong></p>
<p><a href="https://github.com/tjanczuk/iisnode">iisnode</a> offers some really nice hosting capabilities like spinning up and managing multiple node procs, allowing access to logs over HTTP, providing good debugger errors in the browser for diagnostics and supporting node-inspector for debugging.</p>
<p>To access any of these benefits however you have to travel the sea of angle brackets known as web.config. For .NET / Windows developers, this is the norm. However, we heard a lot of feedback from folks in the node-a-verse, in particular coming from on a Mac / *nix that this feels very strange that they have use web.config in order to config node-specific things in Windows Azure, especially in light of the other offerings out there. Looking around we saw that a common pattern was to use a simple key-value format for specifying similar settings with <a href="http://yaml.org/">YAML</a> being a very popular format.</p>
<h2>iisnode.yml</h2>
<p>And so our team <a href="https://github.com/tjanczuk/iisnode/issues/158">racked our brains</a> a bit, got a bunch of feedback and <a href="http://tomasz.janczuk.org/2012/05/yaml-configuration-support-in-iisnode.html">iisnode.yml</a> was born and implemented by Tomek! iisnode.yml is an optional file that sits along side web.config. It allows you to set all of our iisnode <a href="https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/iisnode.yml">settings</a> without having to ever touch web.config. Below is a really simple example.</p>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px"><span style="color: #800000">#</span> <span style="color: #800000">This</span> <span style="color: #800000">is</span> <span style="color: #800000">a</span> <span style="color: #800000">really</span> <span style="color: #800000">simple</span> <span style="color: #800000">iisnode</span>.<span style="color: #800000">yml</span> <span style="color: #800000">file</span></pre>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px"></pre>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px"><span style="color: #800000">node</span>_<span style="color: #800000">env</span>: <span style="color: #800000">development</span></pre>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px"><span style="color: #800000">devErrorsEnabled</span>: <span style="color: #800000">true</span></pre>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px"><span style="color: #800000">logggingEnabled</span>: <span style="color: #800000">true</span></pre>
<p>&nbsp;</p>
<p>The settings set the node_env environment variable to development, enables logging all node.exe output and enables developer errors.</p>
<p>For example, the code below has an error in that it requires a module that does not exist, also it uses spaces in the module name.</p>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px"><span style="color: #0000ff">var</span> http = require('http');</pre>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px"><span style="color: #0000ff">var</span> notPresent = require('some awesome module');</pre>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px">http.createServer(<span style="color: #0000ff">function</span> (req, res) {</pre>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px">  <span style="color: #0000ff">throw</span> "<span style="color: #8b0000">error</span>";</pre>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px">  res.writeHead(200, {'Content-Type': 'text/plain'});</pre>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px">  notPresent.doSomethingAwesome();</pre>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px">  res.end('Hello World Again\n');</pre>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px">}).listen(process.env.PORT);</pre>
<p>&nbsp;</p>
<p>If I don’t enable devErrors this is what I get when I do a request.</p>
<p><a href="http://codebetter.com/glennblock/files/2012/05/Screen-Shot-2012-05-12-at-11.10.45-AM.png"><img style="margin: 0px 0px 24px;padding-left: 0px;padding-right: 0px;padding-top: 0px;border: 0px" src="http://codebetter.com/glennblock/files/2012/05/Screen-Shot-2012-05-12-at-11.10.45-AM_thumb.png" alt="Screen Shot 2012-05-12 at 11.10.45 AM" width="587" height="209" border="0" /></a></p>
<p>However, look at what I get when I enable devErrors with logging.</p>
<p><a href="http://codebetter.com/glennblock/files/2012/05/Screen-Shot-2012-05-12-at-11.04.40-AM.png"><img style="margin: 0px 0px 24px;padding-left: 0px;padding-right: 0px;padding-top: 0px;border: 0px" src="http://codebetter.com/glennblock/files/2012/05/Screen-Shot-2012-05-12-at-11.04.40-AM_thumb.png" alt="Screen Shot 2012-05-12 at 11.04.40 AM" width="563" height="387" border="0" /></a></p>
<p>Above you an see that an error occurred because it could not find my wacky module.</p>
<p>Developer errors is a pretty cool feature that allows iis to output in the response any errors that occurred right in the browser. Combined with logging, it’s really useful for debugging on a remote/staging server.</p>
<p>Of course you don’t want anyone seeing that in your live production site, so you should probably shut that off.</p>
<h2>myfile.yml</h2>
<p>By convention we look for iisnode.yml. If you are not happy with that name however, you can set your own name in the iisnode element of web.config by using the configOverrides property.</p>
<pre style="background-color: #ffffff;margin: 0em;width: 100%;font-family: consolas,'Courier New',courier,monospace;font-size: 12px"><span style="color: #0000ff">&lt;</span><span style="color: #800000">iisnode</span> <span style="color: #ff0000">configOverrides</span>=<span style="color: #0000ff">"myfile.yml"</span><span style="color: #0000ff">/&gt;</span></pre>
<p><strong>Note</strong>: configOverrides also allows you to do environment variable expansion. Thus instead of having a static file name you can have a name that includes an environment variable value. More on that in the future.</p>
<p><strong>But wait, don’t I still need a web.config when I publish to Windows Azure?</strong></p>
<p>Great question! Today you still need a web.config though as Tomek said that can be boilerplate and you don’t have to look at it. Tomorrow however…. <img src='http://codebetter.com/glennblock/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Go get the latest SDK <a href="http://www.microsoft.com/web/gallery/install.aspx?appid=azurenodepowershell">here</a>.</p>
<div class="shr-publisher-411"></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%2F05%2F12%2Fazure-sdk-for-node-0-5-4-is-out-more-secure-and-now-with-less-angle-brackets%2F' data-shr_title='Azure+SDK+for+node+0.5.4+is+out%21+More+secure+and+now+with+less+angle+brackets'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F05%2F12%2Fazure-sdk-for-node-0-5-4-is-out-more-secure-and-now-with-less-angle-brackets%2F' data-shr_title='Azure+SDK+for+node+0.5.4+is+out%21+More+secure+and+now+with+less+angle+brackets'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F05%2F12%2Fazure-sdk-for-node-0-5-4-is-out-more-secure-and-now-with-less-angle-brackets%2F' data-shr_title='Azure+SDK+for+node+0.5.4+is+out%21+More+secure+and+now+with+less+angle+brackets'></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/_bH0Q0BRVV8" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/glennblock/2012/05/12/azure-sdk-for-node-0-5-4-is-out-more-secure-and-now-with-less-angle-brackets/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
					<feedburner:origLink>http://codebetter.com/glennblock/2012/05/12/azure-sdk-for-node-0-5-4-is-out-more-secure-and-now-with-less-angle-brackets/</feedburner:origLink></item>
	      
    	<item>
		<title>Honored to have participated in the ACT Fly-In</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/UCkoIV83oIc/</link>
		<comments>http://codebetter.com/johnvpetersen/2012/05/11/honored-have-participated-in-the-act-fly-in/#comments</comments>
		<pubDate>Fri, 11 May 2012 12:03:47 +0000</pubDate>
		<dc:creator>johnvpetersen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ACT]]></category>
		<category><![CDATA[Privacy]]></category>
		<category><![CDATA[Regulation]]></category>
		<category><![CDATA[Spectrum]]></category>
			<guid isPermaLink="false">http://codebetter.com/johnvpetersen/?p=469</guid>
					<description><![CDATA[You can read about the event here. Every so often, you get the opportunity to participate in a process that affords you the opportunity to talk to those who make policy that affects our personal and business lives. During the&#160;&#8230; <a href="http://codebetter.com/johnvpetersen/2012/05/11/honored-have-participated-in-the-act-fly-in/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>You can read about the event <a href="http://actonline.org/act-blog/archives/2465" target="_blank">here</a>.</p>
<p><a href="http://www.flickr.com/photos/77818064@N03/7006537886/sizes/l/in/photostream/" target="_blank"><img class="alignnone" src="http://actonline.org/act-blog/files/ACT-at-White-House-300x186.jpg" alt="" width="300" height="186" /></a></p>
<p>Every so often, you get the opportunity to participate in a process that affords you the opportunity to talk to those who make policy that affects our personal and business lives. During the Fly-In, a group of us engaged with members of Congress on topics that ranged from privacy, bandwidth and entrepreneurship.</p>
<p>My two big issues: privacy and the available bandwidth spectrum.</p>
<p><strong>Privacy:</strong></p>
<p>What people need is the ability to provide informed consent. It&#8217;s very difficult, if not impossible, for government to formulate regulations that covers every conceivable behavior. All these regulations serve to do is stiffle innovation and harm those that play by the rules. What we do know when we see it is bad conduct. The FTC has broad enforcement and police power and they need to use the power Congress gave them. Punish the bad actors and make an example out of them to provide the necessary incentives to handle online privacy the right way.</p>
<p><strong>Bandwidth Spectrum:</strong></p>
<p>Recently, <a href="http://news.heartland.org/newspaper-article/2012/02/24/congress-mandates-fcc-spectrum-auctions" target="_blank">Congress mandated FCC Spectrum Auctions</a>. Are you tired of dead spots and sluggish performance over 3G/4G networks? Did you know the carriers stand at the ready to fund the billions of $&#8217;s necessary to put up and light up more towers? To make that work, the amount of available bandwidth has to be increased. Congress has taken an important first step &#8211; but more needs to be done. Increasingly, we rely on more than just plain text. Mobile Apps are providing (at least are trying to provide) rich content. What&#8217;s holding things back? Lack of available bandwidth. The bandwidth is out there, we just need to make it available and use it.</p>
<div class="shr-publisher-469"></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%2Fjohnvpetersen%2F2012%2F05%2F11%2Fhonored-have-participated-in-the-act-fly-in%2F' data-shr_title='Honored+to+have+participated+in+the+ACT+Fly-In'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnvpetersen%2F2012%2F05%2F11%2Fhonored-have-participated-in-the-act-fly-in%2F' data-shr_title='Honored+to+have+participated+in+the+ACT+Fly-In'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnvpetersen%2F2012%2F05%2F11%2Fhonored-have-participated-in-the-act-fly-in%2F' data-shr_title='Honored+to+have+participated+in+the+ACT+Fly-In'></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/UCkoIV83oIc" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/johnvpetersen/2012/05/11/honored-have-participated-in-the-act-fly-in/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
					<feedburner:origLink>http://codebetter.com/johnvpetersen/2012/05/11/honored-have-participated-in-the-act-fly-in/</feedburner:origLink></item>
	      
    	<item>
		<title>Node.js and Azure on .NET Rocks!</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/ViM3ELV3PNc/</link>
		<comments>http://codebetter.com/glennblock/2012/05/09/node-js-and-azure-on-net-rocks/#comments</comments>
		<pubDate>Wed, 09 May 2012 08:26:28 +0000</pubDate>
		<dc:creator>Glenn Block</dc:creator>
				<category><![CDATA[azure]]></category>
		<category><![CDATA[node.js]]></category>
			<guid isPermaLink="false">http://codebetter.com/glennblock/?p=405</guid>
					<description><![CDATA[Recently I had the privilege to talk to my good friends Richard and Carl about the work we’re doing enabling Node.js development with Windows Azure along with our friends in the node community. It was also a great opportunity for&#160;&#8230; <a href="http://codebetter.com/glennblock/2012/05/09/node-js-and-azure-on-net-rocks/">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 had the privilege to talk to my good friends Richard and Carl about the work we’re doing enabling Node.js development with Windows Azure along with our friends in the node community. It was also a great opportunity for me to practice my new subdued Glenn persona <img src='http://codebetter.com/glennblock/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  You have to listen to believe it!</p>
<p><a href="http://dotnetrocks.com/default.aspx?showNum=763">http://dotnetrocks.com/default.aspx?showNum=763</a></p>
<blockquote><p>Carl and Richard talk to Glenn Block about node.js on Azure. Glenn digs into how node.js has grown in popularity, and points to the Cloud9 IDE as a development environment in the Cloud as an example of a node.js application &#8211; which happens to be able to build node.js applications. And Cloud 9 can deploy node.js to Azure. The conversation digs into the Azure stack and the diversity of technologies (including node.js) that run great in the cloud.</p>
</blockquote>
<div class="shr-publisher-405"></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%2F05%2F09%2Fnode-js-and-azure-on-net-rocks%2F' data-shr_title='Node.js+and+Azure+on+.NET+Rocks%21'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F05%2F09%2Fnode-js-and-azure-on-net-rocks%2F' data-shr_title='Node.js+and+Azure+on+.NET+Rocks%21'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F05%2F09%2Fnode-js-and-azure-on-net-rocks%2F' data-shr_title='Node.js+and+Azure+on+.NET+Rocks%21'></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/ViM3ELV3PNc" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/glennblock/2012/05/09/node-js-and-azure-on-net-rocks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
					<feedburner:origLink>http://codebetter.com/glennblock/2012/05/09/node-js-and-azure-on-net-rocks/</feedburner:origLink></item>
	      
    	<item>
		<title>I’ll be at GOTO CPH and QCON NYC spreading the node.js love</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/AN2T1dzoesY/</link>
		<comments>http://codebetter.com/glennblock/2012/05/04/ill-be-at-goto-cph-and-qcon-nyc-spreading-the-node-js-love/#comments</comments>
		<pubDate>Fri, 04 May 2012 08:06:56 +0000</pubDate>
		<dc:creator>Glenn Block</dc:creator>
				<category><![CDATA[azure]]></category>
		<category><![CDATA[node.js]]></category>
			<guid isPermaLink="false">http://codebetter.com/glennblock/?p=383</guid>
					<description><![CDATA[Conference season is coming again. I am excited this year that I’ll be finally speaking at goto AND that I’ll be speaking at the first QCon NYC. The topic, well you guessed it, node.js and Windows Azure. May 21-23 First&#160;&#8230; <a href="http://codebetter.com/glennblock/2012/05/04/ill-be-at-goto-cph-and-qcon-nyc-spreading-the-node-js-love/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Conference season is coming again. I am excited this year that I’ll be finally speaking at goto AND that I’ll be speaking at the <strong>first</strong> QCon NYC. The topic, well you guessed it, node.js and Windows Azure.</p>
<p><strong>May 21-23</strong></p>
<p style="text-align: center"><a href="http://gotocon.com/cph-2012/"><img class="aligncenter" style="border-style: initial;border-color: initial;border-width: 0px" src="http://codebetter.com/glennblock/files/2012/05/image.png" alt="image" width="368" height="140" border="0" /></a></p>
<p style="text-align: left">First stop will be Copenhagen where I will be <a href="http://gotocon.com/cph-2012/speaker/Glenn+Block">speaking</a> at goto in the “Microsoft, beyond the echo chamber track”  I am really looking forward to this event. I’ve watched it for years before when it was JAOO but never got the chance to attend. I am happy to say this year that will be changing. I hope to see you there!</p>
<p>Presentation: <a href="http://gotocon.com/cph-2012/presentation/Breaking%20the%20Barrier%20with%20Node.js%20on%20Windows%20and%20Azure">Breaking the Barrier with Node.js on Windows and Azure</a></p>
<p><strong>June 18-22</strong></p>
<p style="text-align: center"><a href="http://codebetter.com/glennblock/files/2012/05/image1.png"><img class="aligncenter" style="margin-top: 0px;margin-bottom: 24px;padding-left: 0px;padding-right: 0px;padding-top: 0px;border-style: initial;border-color: initial;border-width: 0px" src="http://codebetter.com/glennblock/files/2012/05/image_thumb.png" alt="image" width="316" height="170" border="0" /></a></p>
<p>I’ll be <a href="http://qconnewyork.com/qcon-nyc-2012/speaker/Glenn+Block">speaking</a> at QCon NYC in the “Battle of the Clouds track”. If you are planning to attend, you can save $100 by using this promotion code when you register: <strong>BLOC100</strong></p>
<p>Presentation: <a href="http://qconnewyork.com/qcon-nyc-2012/presentation/Unlock+your+Inner+Node.js+in+the+Cloud+with+Windows+Azure">&#8220;Unlock your Inner Node.js in the Cloud with Windows Azure&#8221;</a>. I’m planning to show some really cool stuff that we have coming down the pike soon at this event, so be there!</p>
<p>After the event, I’ll also be delivering two half day tutorials on node.js.</p>
<ul>
<li>“node.js, jumping in with both feet”. This tutorial will be a basic primer around node.js and take you from 0 to 60 with node.js development. It will cover the basics, common practices as well as popular third party modules.</li>
<li>“node.js in Windows Azure”. In this tutorial we will dive into deploying node.js applications to Windows Azure as well as using Azure storage services and ServiceBus from within your node.js apps. We’ll also cover development tools like <a href="http://c9.io">Cloud9 IDE</a> that you can use for deploying node apps to Azure.</li>
</ul>
<p>If you are looking to get up to speed with node or to start deploying node apps to Azure come to these tutorials.</p>
<p>While I am in town for both events I’ll be doing a bunch of user group meetups and such. I’ll cover that in my next post</p>
<div class="shr-publisher-383"></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%2F05%2F04%2Fill-be-at-goto-cph-and-qcon-nyc-spreading-the-node-js-love%2F' data-shr_title='I%26rsquo%3Bll+be+at+GOTO+CPH+and+QCON+NYC+spreading+the+node.js+love'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F05%2F04%2Fill-be-at-goto-cph-and-qcon-nyc-spreading-the-node-js-love%2F' data-shr_title='I%26rsquo%3Bll+be+at+GOTO+CPH+and+QCON+NYC+spreading+the+node.js+love'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fglennblock%2F2012%2F05%2F04%2Fill-be-at-goto-cph-and-qcon-nyc-spreading-the-node-js-love%2F' data-shr_title='I%26rsquo%3Bll+be+at+GOTO+CPH+and+QCON+NYC+spreading+the+node.js+love'></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/AN2T1dzoesY" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/glennblock/2012/05/04/ill-be-at-goto-cph-and-qcon-nyc-spreading-the-node-js-love/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
					<feedburner:origLink>http://codebetter.com/glennblock/2012/05/04/ill-be-at-goto-cph-and-qcon-nyc-spreading-the-node-js-love/</feedburner:origLink></item>
	      
    	<item>
		<title>Cron and AppEngine</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/PhmgQdh-yFY/</link>
		<comments>http://codebetter.com/kylebaley/2012/04/28/cron-and-appengine-2/#comments</comments>
		<pubDate>Sat, 28 Apr 2012 15:52:14 +0000</pubDate>
		<dc:creator>Kyle Baley</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Google App Engine]]></category>
			<guid isPermaLink="false">http://codebetter.com/kylebaley/?p=285</guid>
					<description><![CDATA[Quick PSA on using cron jobs with Google App Engine because it almost wreaked havoc for us. App Engine has a lovely feature of having different versions of your app. You can upload a new version but not make it&#160;&#8230; <a href="http://codebetter.com/kylebaley/2012/04/28/cron-and-appengine-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>Quick PSA on using cron jobs with <a href="https://developers.google.com/appengine/docs/java/config/cron" target="_blank">Google App Engine</a> because it almost wreaked havoc for us.</p>
<p>App Engine has a lovely feature of having different versions of your app. You can upload a new version but not make it the default until you’re good and ready. We do this all the time for deployment. Deploy to a new version and try it out, then make it the default when we’re ready to unleash it. Often, we deploy to the new version a day or so in advance.</p>
<p>Cron jobs, it seems, are handled outside this versioning mechanism. If you upload a new cron.xml file, it’s active. Right now. Doesn’t matter if the version it was deployed in is the default or not. As soon as it’s uploaded, it’s the new cron-ness.</p>
<p>Where this almost bit us is that we added a new cron job in our most recent release (deployed yesterday but not active) to use a <a href="https://developers.google.com/appengine/docs/java/backends/" target="_blank">dynamic backend</a>. As soon as the cron job got uploaded, it started running. I didn’t notice until this morning when our backend usage reflected the new cron job. Some <a href="http://www.mail-archive.com/google-appengine@googlegroups.com/msg34752.html" target="_blank">quick research</a> and here we are.</p>
<p>What this means long term is that cron.xml is no longer going to be deployed as part of our application anymore. It now becomes an entirely separate process. I’m a little annoyed that we have to wait until we pull the trigger on the new version before we can upload the new cron.xml but it’s a quick step.</p>
<p>Kyle the Mis-scheduled</p>
<div class="shr-publisher-285"></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%2F04%2F28%2Fcron-and-appengine-2%2F' data-shr_title='Cron+and+AppEngine'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F04%2F28%2Fcron-and-appengine-2%2F' data-shr_title='Cron+and+AppEngine'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F04%2F28%2Fcron-and-appengine-2%2F' data-shr_title='Cron+and+AppEngine'></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/PhmgQdh-yFY" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/kylebaley/2012/04/28/cron-and-appengine-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
					<feedburner:origLink>http://codebetter.com/kylebaley/2012/04/28/cron-and-appengine-2/</feedburner:origLink></item>
	      
    	<item>
		<title>State Machines and Business Users</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/GNAWhdpfUjA/</link>
		<comments>http://codebetter.com/gregyoung/2012/04/24/state-machines-and-business-users-2/#comments</comments>
		<pubDate>Tue, 24 Apr 2012 09:21:13 +0000</pubDate>
		<dc:creator>gregyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/gregyoung/?p=297</guid>
					<description><![CDATA[I was at a workshop over the weekend talking about the use of Finite State Machines as coordination mechanisms for systems. These things might be called sagas, activities, workflows, process managers (my preferred term lately from PEI), orchestrations, choreographers, and&#160;&#8230; <a href="http://codebetter.com/gregyoung/2012/04/24/state-machines-and-business-users-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>I was at a workshop over the weekend talking about the use of Finite State Machines as coordination mechanisms for systems. These things might be called sagas, activities, workflows, process managers (my preferred term lately from PEI), orchestrations, choreographers, and I am sure I am leaving out a few.</p>
<p>One of the guys in the talk (quite knowledgable) brought up that they used to use petri nets for this as well as pure finite state machines and there had been a push to more procedural mechanisms as business users don&#8217;t think in terms of finite state machines. I noted that while we have been moving to more procedural methods, as most of these procedural methods are in their hearts asynchronous our procedural techniques tend to be domain specific languages that internally generate state machines anyways, often based in the join calculus (think futures or the async keyword in C# when joining).</p>
<p>However later in the day I had a realization connecting two things. We like to describe business situations in gherkin style (not strict) specifications.</p>
<p>Given: Some initial starting point<br />
When: Something happens<br />
Then: Something occurred</p>
<p>We as an industry have been very successful getting specifications written in this style. We regularly do analysis and write acceptance criteria using this style. Business users seem to have been fairly capable of understanding it.</p>
<p>This style is basically describing a state machine. </p>
<p>Given: some initial state<br />
When: a stimulus<br />
Then: Something occurred (message/transition depending on style of testing)</p>
<p>How can we be so successful with this style of specification and in the next breath say that business users can&#8217;t understand state machines? The trick is they don&#8217;t understand the actual machine but they understand (and can specify very well) the exterior behaviours of such a machine.</p>
<p>Try getting a business user to create for you the state machine to control a simple DVD player for you. Likely they will scratch their heads and politely become very busy so they won&#8217;t be able to attend the next meeting. Try getting them to specify </p>
<p>Given a video is playing<br />
When fast forward is pressed<br />
Then the play goes at double speed</p>
<p>Maybe the problem here that caused our move towards procedural style controllers was the goal all the middleware seems to push of having business users <strong>writing</strong> the activities as opposed to reading about/specifying/understanding them. I have yet to see in all the organizations I have been to a single one where the dream of having business users creating these types of long running procedures actually panned out. <em>to be fair: I have seen it work but the business user had formerly been a developer and BA</em></p>
<div class="shr-publisher-297"></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%2Fgregyoung%2F2012%2F04%2F24%2Fstate-machines-and-business-users-2%2F' data-shr_title='State+Machines+and+Business+Users'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fgregyoung%2F2012%2F04%2F24%2Fstate-machines-and-business-users-2%2F' data-shr_title='State+Machines+and+Business+Users'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fgregyoung%2F2012%2F04%2F24%2Fstate-machines-and-business-users-2%2F' data-shr_title='State+Machines+and+Business+Users'></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/GNAWhdpfUjA" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/gregyoung/2012/04/24/state-machines-and-business-users-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
					<feedburner:origLink>http://codebetter.com/gregyoung/2012/04/24/state-machines-and-business-users-2/</feedburner:origLink></item>
	      
    	<item>
		<title>The Economics of Ergonomics</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/msUCpyZ6v-Y/</link>
		<comments>http://codebetter.com/kylebaley/2012/04/22/the-economics-of-ergonomics/#comments</comments>
		<pubDate>Sun, 22 Apr 2012 22:04:39 +0000</pubDate>
		<dc:creator>Kyle Baley</dc:creator>
				<category><![CDATA[Sundry]]></category>
		<category><![CDATA[Working Remotely]]></category>
			<guid isPermaLink="false">http://codebetter.com/kylebaley/?p=281</guid>
					<description><![CDATA[Let it not be said there are no downsides to living in the Bahamas (though if you’ll permit a little boasting, a shortage of fantastic venues if you’re lucky enough to be in a band is not one of them).&#160;&#8230; <a href="http://codebetter.com/kylebaley/2012/04/22/the-economics-of-ergonomics/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Let it not be said there are no downsides to living in the Bahamas (though if you’ll permit a little boasting, a shortage of <a href="http://cocodimama.com/">fantastic venues</a> if you’re lucky enough to be in a band is not one of them).</p>
<p>The desk where I work is too high, plain and simple. So much so that I’ve recently abandoned my <a href="http://codebetter.com/kylebaley/2009/04/25/re-review-of-kinesis/">Kinesis keyboard</a> because it is not what you might consider “low form factor”. I’ve started feeling some twinges in my lower forearm that my unscientific diagnosis is attributing to the height of my hands while I type. Dumping the Kinesis has helped but it has also led to the return of stress in other areas of my hands. And no amount of raccoon skinning seems to alleviate the pain.</p>
<p>Getting a lower desk is easy enough but I’d actually like to do a little experimenting with two alternatives. Alas, neither are easily done in the Bahamas. The underlying problem is availability. The desks/equipment I want to test are not available here so I would have to order them in. Which means both shipping charges and import duties, the latter of which is a major source of income for the Bahamian government to offset the fact that there is no income tax. So returning said equipment is just not practical if it doesn’t work out. Nor is there much of a reseller market.</p>
<p>So I’m hoping I can get some comments from people who have done something similar.</p>
<h2>Adjustable height desk</h2>
<p align="left">These are, of courses, desks where you can <a href="http://www.geekdesk.com/">adjust the height</a> easily. I like the idea of these for two reasons:</p>
<ul>
<li>
<div align="left">They can be set low</div>
<li>
<div align="left">They can be set high</div>
</li>
</ul>
<p align="left">I’ve never tried a desk that you stand at but I’ve always wanted to. Working on my own, I tend to get up and wander a lot while I’m thinking. I also pace when I’m on the phone with someone for any length of time so it would be more convenient to walk up to the computer during the conversation should the need arise. (“You want to know the right pattern of plaid for a first date with your second cousin? Let me look that up.”)</p>
<p align="left">I went desk-shopping over the weekend and the closest thing I saw was in an office supply store. And it wasn’t on the showroom floor. Off in the corner of the store were the employee desks. They were all essentially plywood based, laminated desktops all mounted in warehouse style shelving frames. They sat on brackets in the frame which means you could set the height to whatever you want. It wasn’t something you could easily adjust on the fly and my wife wasn’t too thrilled at the industrial look so it was a fleeting idea at best.</p>
<h2>Command centre<a href="http://www.gizmag.com/go/4797/picture/16743/" target="_blank"><img style="border-right-width: 0px;margin: 5px;float: right;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px" alt="computer workstation furniture MYPCE Computer Workstation Furniture" align="right" src="http://ergonomicofficefurnitures.com/wp-content/uploads/2009/12/computer-workstation-furniture-MYPCE.jpg" width="213" height="240"></a></h2>
<p>This is an idea I’ve had ruminating in my head for a while now. I would get rid of the desk altogether in favour of a comfortable command-centre style or <a href="https://www.google.com/search?hl=en&amp;q=command+center+chair#q=gaming+chair&amp;hl=en&amp;prmd=imvnsr&amp;source=univ&amp;tbm=shop&amp;tbo=u&amp;sa=X&amp;ei=-j2UT7SmNcjItge2jf21Cw&amp;sqi=2&amp;ved=0CF0QrQQ&amp;bav=on.2,or.r_gc.r_pw.r_cp.,cf.osb&amp;fp=c14441ddb21d9ff7">gaming chair</a>. In front of it it, I’d mount my monitors on a couple of <a href="http://www.ergotron.com/Products/tabid/65/PRDID/9/language/en-GB/Default.aspx">flexible arms</a> somehow, possibly on the armrests or on stands on either side of the chair. The important thing is that I can slide the monitors out of my way when I want to get out of the chair, and slide them back in when I sit down.</p>
<p>The keyboard would rest either on my lap or on some flat surface on my lap. Or maybe go with a <a href="http://www.kinesis-ergo.com/freestyle.htm">split keyboard</a> (though one without a wire between the two) and have one piece mounted on each armrest. Haven’t quite worked out how the mouse would fit in though. A trackball on some little platform on the side makes sense but I’ve got one now and it doesn’t feel as productive as just a regular mouse.</p>
<p>I feel like this would be more comfortable and would reduce much of the muscle stress that seems to have become more prominent since hitting 40 earlier this year. All of this kind of makes sense in my head but the logistics of getting the stuff here is such that I don’t want to make the investment unless I’ve had a chance to try it out at least for a few days. There’s a chance my tendency to get up and wander might make this impractical. Or maybe cord management would be an ongoing problem.</p>
<p>The <a href="http://www.gizmag.com/go/4797/picture/16743/" target="_blank">device shown at right</a>, which I discovered while researching this article, is essentially what I’ve described. It’s some US$2750. Duty would add about 50% and shipping would likely bring the total price above five large. There’s another potential hurdle in that it may not be available anymore given the <a href="http://www.mypce.com" target="_blank">company’s domain</a> seems to point to a parking spot. But even building my custom version will cost enough in non-refundable cash dollars for me not to head over eBay.</p>
<p>Instead, I hunt for a standard desk about four to six inches lower than the one I’ve got. Not as exciting, possibly not as ergonomic, but easier to replace.</p>
<p>So my question to you, my honorary hillbillies, for anecdotal evidence. Have you tried either of these devices? What’s good and bad? Good return for the money or does it sit in the garage next to the Bowflex you bought in a fit of New Year’s anxiety?</p>
<p>Kyle the Unreturnable</p>
<div class="shr-publisher-281"></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%2F04%2F22%2Fthe-economics-of-ergonomics%2F' data-shr_title='The+Economics+of+Ergonomics'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F04%2F22%2Fthe-economics-of-ergonomics%2F' data-shr_title='The+Economics+of+Ergonomics'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F04%2F22%2Fthe-economics-of-ergonomics%2F' data-shr_title='The+Economics+of+Ergonomics'></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/msUCpyZ6v-Y" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/kylebaley/2012/04/22/the-economics-of-ergonomics/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
					<feedburner:origLink>http://codebetter.com/kylebaley/2012/04/22/the-economics-of-ergonomics/</feedburner:origLink></item>
	      
    	<item>
		<title>Sunday Thought: Patient / Fast</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/VYWHVOOFqTM/</link>
		<comments>http://codebetter.com/drusellers/2012/04/22/sunday-thought-patient-fast/#comments</comments>
		<pubDate>Sun, 22 Apr 2012 14:38:55 +0000</pubDate>
		<dc:creator>Dru Sellers</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/drusellers/?p=274</guid>
					<description><![CDATA[Some times I am such a dolt. I open a new OSS project and my first thoughts are usually &#8220;This library is ^&#38;*$% it doesn&#8217;t do anything right.&#8221;  &#8220;RAGE! (╯°□°）╯︵ ┻━┻&#8221;  don&#8217;t they know that, MY WAY is better! Its&#160;&#8230; <a href="http://codebetter.com/drusellers/2012/04/22/sunday-thought-patient-fast/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Some times I am such a dolt.</p>
<p>I open a new OSS project and my first thoughts are usually &#8220;This library is ^&amp;*$% it doesn&#8217;t do anything right.&#8221; </p>
<p>&#8220;RAGE! <span style="color: #000000;font-family: sans-serif;font-size: 13px;font-style: normal;font-variant: normal;font-weight: normal;letter-spacing: normal;line-height: 19px;text-align: -webkit-center;text-indent: 0px;background-color: #f9f9f9;float: none">(╯°□°）╯︵ ┻━┻</span>&#8221;  don&#8217;t they know that, MY WAY is better!</p>
<p>Its sad, but that is exactly what I am thinking. I am on such an immediate gratification high, thanks to my 8 core, 8GB RAM, SSD, super high speed internet capable machine that I forget that not everything can be measured in sub-second latency. Things like instant on-demand movies, and Amazon 2 day shipping don&#8217;t help with my attitude either. When it comes to learning, this demand for instant gratification has, many times, gotten in the way of what it is I really want to accomplish.</p>
<p>So, I ran into this situation again this week, and after IM&#8217;ing the maintainer &#8211; complaining about how this and that worked (ok, lets be honest &#8211; I was whining like a 4 year old) &#8211; I kinda just snapped out of it. I recalled a quote from the book <a href="http://www.amazon.com/The-Toyota-Way-Management-Manufacturer/dp/0071392319">The Toyota Way</a>, where they stated that the #1 problem with new engineers is that they can&#8217;t slow down. They just want to charge into things head first and solve all of the problems. Hmm, sounds a lot like me. Except that I have 10 years underneath my belt now. So, why am I still acting like a new developer? My biggest guess, is that I haven&#8217;t really honed my process. I need more people to catch me acting this way and to call me on it. But that can be hard to find in our community, because we all tend to act this way.</p>
<p>We, developers, are always on the look out for the next shiny library or framework that we can &#8220;learn&#8221; and by learn I mean implement. We like libraries so simple that a new programmer could understand them. We don&#8217;t want a learning curve at all. I think that this is one of the reasons things like express.js, flask, and sinatra play so well in our community. You can see, immediately, how it works. They have almost no abstraction over the underlying concepts. Let&#8217;s not forget, that its the abstractions that bring the real power, and that not every abstraction is a poor or leaky one.</p>
<p>Its Sunday, which is an introspective day for me, and I want to try and improve myself. I think that if I could work on this aspect of my skills and attitude, I would become a better developer. Being a better developer is something that I want to be. Ok, so how am I going to do this. After much thought, I was reminded of a similar experience that worked well for me outside of the software development world.</p>
<p><img style="float: right" src="http://codebetter.com/drusellers/files/2012/04/patientfast.jpg" alt="Patientfast" width="149" height="200" border="0" /></p>
<p>For that last three months I have been training in <a href="http://en.wikipedia.org/wiki/Olympic_weightlifting">Olympic Lifting</a>. Now for those of you that have never performed olympic lifts, you need to know that while strength is a big part of it, skill also plays a huge part. You can&#8217;t just hoist 150 pounds over your head with out a level of skill. The snatch is an explosive lift, that requires an insane amount of patience and balance. My coach and teammates have a phrase that I have come to love. &#8221;Patient / Fast&#8221;, which means to me that you have to move fast, but at the same time be patient in the pull. It took me a long time to really grok that concept. It feels like a damn Zen <a href="http://en.wikipedia.org/wiki/K%C5%8Dan">koan</a> at times, but I keep repeating the phrase and each day it reveals itself to me a bit more.</p>
<p>So there I was, at the keyboard, about to burst a vein, when I woke myself up from my emotions, calmed down &#8211; and asked myself what would &#8220;Patient / Fast&#8221; look like here? I decided that I would patiently look through the code, asks questions to myself via comments and then go answer them, and start to understand what the code was doing, on the flip side I would be very fast to start writing, running, and debugging unit tests to get ahold of the code base. Sure enough, the code started to reveal itself to me, I could see the author&#8217;s intentions much better now. I started to build up a good amount of understanding, and was able to effectively solve my problem but was also even able to make a nice pull request back to the library that I think cleaned up a very small part of the code base. <img src='http://codebetter.com/drusellers/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  </p>
<p>In the end, I spent more time than the old me would have liked understanding the library. But the reality of it is, this small investment in understanding a key part of my infrastructure is going to pay dividends in the long run. And less than a day understanding how a critical part of my system works, is indeed a small investment. So, from here on out I am going to remember. <strong>Patient / Fast</strong></p>
<div class="shr-publisher-274"></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%2F04%2F22%2Fsunday-thought-patient-fast%2F' data-shr_title='Sunday+Thought%3A+Patient+%2F+Fast'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fdrusellers%2F2012%2F04%2F22%2Fsunday-thought-patient-fast%2F' data-shr_title='Sunday+Thought%3A+Patient+%2F+Fast'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fdrusellers%2F2012%2F04%2F22%2Fsunday-thought-patient-fast%2F' data-shr_title='Sunday+Thought%3A+Patient+%2F+Fast'></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/VYWHVOOFqTM" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/drusellers/2012/04/22/sunday-thought-patient-fast/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
					<feedburner:origLink>http://codebetter.com/drusellers/2012/04/22/sunday-thought-patient-fast/</feedburner:origLink></item>
	      
    	<item>
		<title>Ruby and RSpec: Powerful Languages Allow Simpler Frameworks</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/prchq5r5S5I/</link>
		<comments>http://codebetter.com/jameskovacs/2012/04/19/ruby-and-rspec-powerful-languages-allow-simpler-frameworks/#comments</comments>
		<pubDate>Fri, 20 Apr 2012 04:32:51 +0000</pubDate>
		<dc:creator>James Kovacs</dc:creator>
				<category><![CDATA[Ruby]]></category>
			<guid isPermaLink="false">http://codebetter.com/jameskovacs/?p=209</guid>
					<description><![CDATA[Recently I was doing a simple kata &#8211; the Roman Numeral kata &#8211; to practice my Ruby and RSpec skills. (The Roman Numeral kata is to build an algorithm test-first that converts a number into its Roman numeral equivalent. For&#160;&#8230; <a href="http://codebetter.com/jameskovacs/2012/04/19/ruby-and-rspec-powerful-languages-allow-simpler-frameworks/">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 doing a simple kata &#8211; <a href="http://codingdojo.org/cgi-bin/wiki.pl?KataRomanNumerals">the Roman Numeral kata</a> &#8211; to practice my Ruby and RSpec skills. (The Roman Numeral kata is to build an algorithm test-first that converts a number into its Roman numeral equivalent. For example, 1 to i, 7 to vii, 10 to x, etc. The problem is intended to be simple so that you can focus on the process.) I had the following RSpec code:</p>
<pre class="brush: ruby; title: ; notranslate">
require 'roman_numeral'

describe RomanNumeral do
  # specify is just an alias for it. specify reads better in this case
  specify '1 should be i' do
    numeral = RomanNumeral.new(1)
    numeral.to_s.should == 'i'
  end
end
</pre>
<p>I go through the Red/Green/Refactor cycle and get this first spec working. (I won&#8217;t show the production code as it&#8217;s not that interesting.) I move onto the second spec.</p>
<pre class="brush: ruby; title: ; notranslate">
require 'roman_numeral'

describe RomanNumeral do
  specify '1 should be i' do
    numeral = RomanNumeral.new(1)
    numeral.to_s.should == 'i'
  end

  specify '2 should be ii' do
    numeral = RomanNumeral.new(2)
    numeral.to_s.should == 'ii'
  end
end
</pre>
<p>Red/Green/Refactor and all is good. But I&#8217;m seeing some repetition in my specs and it&#8217;s only going to get worse. The specs are almost identical except for the data. So I start hunting through the RSpec docs for something akin to NUnit&#8217;s [TestCase] or xUnit&#8217;s [Theory]. I find nothing. Maybe, <a href="http://stackoverflow.com/questions/6121421/is-it-possible-to-create-data-driven-tests-with-mspec">like MSpec</a>, RSpec wasn&#8217;t designed to do this sort of data-driven testing.</p>
<p>Undaunted I turn to Google and stumble upon <a href="http://stackoverflow.com/questions/5524056/rspec-scenario-outlines-multiple-test-cases">this StackOverflow question</a> asking exactly the same question that I had. <a href="http://www.mattdipasquale.com/">Matt Di Pasquale</a>, the OP (original poster), found his own answer and that answer was fascinating! No, RSpec doesn&#8217;t have a syntax for test cases because it doesn&#8217;t need one. Use the Ruby, Luke!</p>
<pre class="brush: ruby; title: ; notranslate">
require 'roman_numeral'

describe RomanNumeral do
  cases = {
    1 =&gt; 'i',
    2 =&gt; 'ii'
  }

  cases.each do |k, v|
    specify &quot;#{k} should print as #{v}&quot; do
      numeral = RomanNumeral.new(k)
      numeral.to_s.should == v
    end
  end
end
</pre>
<p>For those not as well-versed in Ruby, &#8220;cases&#8221; is simply a variable that contains a hash. I then iterate over the key/value pairs and define my specifications. It&#8217;s that simple. I didn&#8217;t need any special attributes or framework support from RSpec. I didn&#8217;t need to learn the inner workings of RSpec to write my own custom extension or attributes. I simply wrote some Ruby code. Let that sink in for a second. <strong>I simply wrote some Ruby code.</strong></p>
<p>Now think about that a bit more. I&#8217;m writing regular Ruby code to implement the notion of test cases. Rather than defining test cases, I could have used very similar code to define a benchmark that verifies an algorithm scales linearly with number of input elements. Or I could have <a href="http://en.wikipedia.org/wiki/Fuzz_testing">fuzz tested</a> an external API for my application. The possibilities are only limited by my imagination and don&#8217;t require me to gain an ever deeper understanding of my testing/specing framework to implement.</p>
<p>For someone who cut his teeth on C, C++, and C# (with some JavaScript thrown in for good measure) and is used to learning (or building) frameworks to solve problems, the notion that you can just write plain old code to solve these types of meta problems is eye-opening. It is one of those ah-ha moments that matures you as a developer. Not every problem needs a framework to solve it. Sometimes it just requires a little code.</p>
<div class="shr-publisher-209"></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%2F04%2F19%2Fruby-and-rspec-powerful-languages-allow-simpler-frameworks%2F' data-shr_title='Ruby+and+RSpec%3A+Powerful+Languages+Allow+Simpler+Frameworks'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjameskovacs%2F2012%2F04%2F19%2Fruby-and-rspec-powerful-languages-allow-simpler-frameworks%2F' data-shr_title='Ruby+and+RSpec%3A+Powerful+Languages+Allow+Simpler+Frameworks'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjameskovacs%2F2012%2F04%2F19%2Fruby-and-rspec-powerful-languages-allow-simpler-frameworks%2F' data-shr_title='Ruby+and+RSpec%3A+Powerful+Languages+Allow+Simpler+Frameworks'></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/prchq5r5S5I" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/jameskovacs/2012/04/19/ruby-and-rspec-powerful-languages-allow-simpler-frameworks/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
					<feedburner:origLink>http://codebetter.com/jameskovacs/2012/04/19/ruby-and-rspec-powerful-languages-allow-simpler-frameworks/</feedburner:origLink></item>
	      
    	<item>
		<title>Using oData with the NuGet API</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/ZCwXIkL0iKU/</link>
		<comments>http://codebetter.com/johnvpetersen/2012/04/15/using-odata-with-the-nuget-api/#comments</comments>
		<pubDate>Sun, 15 Apr 2012 16:49:49 +0000</pubDate>
		<dc:creator>johnvpetersen</dc:creator>
				<category><![CDATA[NuGet]]></category>
		<category><![CDATA[oData]]></category>
			<guid isPermaLink="false">http://codebetter.com/johnvpetersen/?p=436</guid>
					<description><![CDATA[Update&#8230; As a commenter astutely pointed out, we can see the generated URL in LinqPad.. Still good to know and understand how to use Fiddler &#8211; especially if you want to flip between json and xml formats!! &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; Quick tip&#160;&#8230; <a href="http://codebetter.com/johnvpetersen/2012/04/15/using-odata-with-the-nuget-api/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Update&#8230;</p>
<p>As a commenter astutely pointed out, we can see the generated URL in LinqPad..</p>
<p><a href="http://codebetter.com/johnvpetersen/files/2012/04/image10.png"><img src="http://codebetter.com/johnvpetersen/files/2012/04/image10-300x240.png" alt="" width="300" height="240" class="alignnone size-medium wp-image-464" /></a></p>
<p>Still good to know and understand how to use Fiddler &#8211; especially if you want to flip between json and xml formats!!</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Quick tip here on using <a href="http://www.odata.org/" target="_blank">oData</a> with <a href="http://www.nuget.org" target="_blank">NuGet</a>.</p>
<p>If you have visited the <a href="http://www.nuget.org" target="_blank">NuGet Gallery</a>, you may have wondered were the RSS feed is. Try as you might, you won&#8217;t find it. There&#8217;s good reason for that given the fact that NuGet is backed by a data feed &#8211; a data feed with many data fields that you can query to properly scope your request. NuGet has a rich API -which you will see in a moment. Usually, when we work with NuGet, we do so via the NuGet Package Manager Dialog and/or the Package Manager Console. There may be times when you wish the raw feed. To do that, you need the API url. By default, NuGet gives you one package source, the official public NuGet Feed &#8211; which can be found at <a href="https://nuget.org/api/v2" target="_blank">https://nuget.org/api/v2</a>. The following image illustrates how the official feed is wired into your NuGet installation. You can get to this dialog by navigating to:</p>
<p>Tools\Library Package Manager\Package Manger Settings</p>
<p><a href="http://codebetter.com/johnvpetersen/files/2012/04/image12.png"><img class="alignleft size-medium wp-image-440" src="http://codebetter.com/johnvpetersen/files/2012/04/image12-300x174.png" alt="" width="300" height="174" /></a></p>
<p>One of the most useful features in .NET is Linq and the best tool available to learn Linq is <a href="http://www.linqpad.net/" target="_blank">LinqPad</a>. In the following image, I set a connection to https://nuget.org/api/v2. As you can see, there are a number of fields in the package feed. With LinqPad, it&#8217;s easy to enter a Linq Query (whether it is the long form or as a lambda expression).</p>
<pre><a href="http://codebetter.com/johnvpetersen/files/2012/04/image22.png"><img class="alignnone size-medium wp-image-441" src="http://codebetter.com/johnvpetersen/files/2012/04/image22-300x240.png" alt="" width="300" height="240" /></a>
<pre class="brush: csharp; title: ; notranslate">
Packages.OrderByDescending (x =&gt; x.LastUpdated)
   .Select (
	  x =&gt;
		 new
		 {
			Id = x.Id,
			Tags = x.Tags,
			Title = x.Title,
			Description = x.Description,
			ProjectUrl = x.ProjectUrl,
			GalleryDetailsUrl = x.GalleryDetailsUrl,
			Version = x.Version,
			LastUpdated = x.LastUpdated
		 }
   )
</pre>
<p>In this query, we are taking certain data fields and are ordering by the LastUpdated DateTime field descending.</p>
<p>Another useful tool is fiddler. The combination of LinqPad and Fiddler makes it easy to see how Linq queries get translated to oData URL's:</p>
<p><a href="http://codebetter.com/johnvpetersen/files/2012/04/image31.png"><img class="alignnone size-medium wp-image-442" src="http://codebetter.com/johnvpetersen/files/2012/04/image31-300x183.png" alt="" width="300" height="183" /></a></p>
<p>Here's how the oData URL appears as rendered in a browser:</p>
<p><a href="http://codebetter.com/johnvpetersen/files/2012/04/image42.png"><img class="alignnone size-medium wp-image-443" src="http://codebetter.com/johnvpetersen/files/2012/04/image42-300x163.png" alt="" width="300" height="163" /></a></p>
<p>Here is the URL:</p>
<p><a href="http://nuget.org/api/v2/Packages()?$orderby=LastUpdated%20desc&amp;$select=Id,Tags,Title,Description,ProjectUrl,GalleryDetailsUrl,Version,LastUpdated">http://nuget.org/api/v2/Packages()?$orderby=LastUpdated%20desc&amp;$select=Id,Tags,Title,Description,ProjectUrl,GalleryDetailsUrl,Version,LastUpdated</a></p>
<p>Going back to Fiddler, if you want JSON returned instead of XML, just tweak the Accept Header to:</p>
<p>Accept: application/atom+json,application/json</p>
<p><a href="http://codebetter.com/johnvpetersen/files/2012/04/image5.png"><img class="alignnone size-medium wp-image-444" src="http://codebetter.com/johnvpetersen/files/2012/04/image5-300x183.png" alt="" width="300" height="183" /></a></p>
<p>That's all there is to accessing NuGet data via the NuGet API with oData.</p>
<div class="shr-publisher-436"></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%2Fjohnvpetersen%2F2012%2F04%2F15%2Fusing-odata-with-the-nuget-api%2F' data-shr_title='Using+oData+with+the+NuGet+API'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnvpetersen%2F2012%2F04%2F15%2Fusing-odata-with-the-nuget-api%2F' data-shr_title='Using+oData+with+the+NuGet+API'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnvpetersen%2F2012%2F04%2F15%2Fusing-odata-with-the-nuget-api%2F' data-shr_title='Using+oData+with+the+NuGet+API'></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/ZCwXIkL0iKU" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/johnvpetersen/2012/04/15/using-odata-with-the-nuget-api/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
					<feedburner:origLink>http://codebetter.com/johnvpetersen/2012/04/15/using-odata-with-the-nuget-api/</feedburner:origLink></item>
	      
    	<item>
		<title>Why I’m moving away from Apple, and specifically, the iPhone and going to the store</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/FXseYLQKeao/</link>
		<comments>http://codebetter.com/johnvpetersen/2012/04/14/why-im-moving-away-from-apple-and-specifically-the-iphone-and-going-to-the-store/#comments</comments>
		<pubDate>Sat, 14 Apr 2012 20:52:51 +0000</pubDate>
		<dc:creator>johnvpetersen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Apple Store King of Prussia]]></category>
		<category><![CDATA[iPhone]]></category>
			<guid isPermaLink="false">http://codebetter.com/johnvpetersen/?p=430</guid>
					<description><![CDATA[And it has nothing to do with technology for the most part. On balance, Apple makes some great products. But there are two things that Apple sucks at: - Customer Service (especially at an Apple Store &#8211; more on this&#160;&#8230; <a href="http://codebetter.com/johnvpetersen/2012/04/14/why-im-moving-away-from-apple-and-specifically-the-iphone-and-going-to-the-store/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>And it has nothing to do with technology for the most part. On balance, Apple makes some great products. But there are two things that Apple sucks at:</p>
<p>- Customer Service (especially at an Apple Store &#8211; more on this later)<br />
- Battery life</p>
<p>First off, I&#8217;d like to thank Luke C., one of the managers at the King of Prussia Apple Store for wasting 90 min of my life today. The same goes for the other manager of whom I didn&#8217;t get his name.</p>
<p>I have said this every time I&#8217;ve gone into an Apple Store lately&#8230;.&#8221;Never again.&#8221; They are crowded and unless you are there to buy something, the Apple retail crew is not really interested in helping you. The tough thing with batteries is that you have to go through some difficulty to get issues addressed. That often means going to the store &#8211; and make an appointment at the &#8220;Genius Bar.&#8221; Don&#8217;t know about you, but when I pay premium prices for a product, I expect superior customer service. And more often than not, I usually get it. Tumi is a great example of a company that stands behind their products.</p>
<p>Anyway, for some time now, I&#8217;ve had issues with battery life wtih my iPhone. I had the phone replace in December &#8211; and for the most part &#8211; it&#8217;s been OK. Today, Luke C. stated that they had their process. They had to make sure it wasn&#8217;t a software related problem. I was agreeable. Fast forward 50 minutes and while they told me everything was OK &#8211; turns out that it wasn&#8217;t. The battery drains at a rate of about 1% every 2-3 min. The funny thing is, when confronted wtih an outcome he didn&#8217;t expect, Luke and his buddy stated &#8211; &#8220;I could buy a new battery for $89.&#8221; I then became disagreeable. What is it with these folks that work at the Apple Stores? Is it a requirement to be a pendantic d-bag? They clearly have lying down to a fine art. Whatever &#8211; I have to consider the source. These guys work in retail and are a reminder why I prefer the online experience when it comes to making purchases.</p>
<p>Often, when considering things like phones, tablets, etc &#8211; we evaluate based on technology. We really should be looking at customer service as well. And in the case of Apple, that charges a premium price for their products &#8211; they have a greater responsibility to provide superior customer service. The irony as to the store is that for all of the &#8220;experience&#8221; the Apple folks worry about, an Apple store today, has got to be the worse customer experience out there today. Others may disagree &#8211; but that is my opinion.</p>
<p>I&#8217;m just one guy and Apple won&#8217;t care as it&#8217;s market cap continues to creep toward a trillion dollars. <a href="http://www.pcmag.com/article2/0,2817,2400611,00.asp" target="_blank">Apple makes a profit of over $350 per iPhone and it is hypothesized that Apple generates $30 of profit on an iPhone for every $1 of labor</a>. And the $89 battery? What&#8217;s that cost? $5&#8230;maybe. </p>
<p>I&#8217;m all for companies making as much as they can. I&#8217;m a capitalist. But&#8230;I&#8217;m also a &#8220;fairist&#8221; as well. In other words, I believe that companies should earn the premium they charge. Standing behind their products, when they are defective, is such a case when they need to earn that premium. Well&#8230;I have my remedy as well. </p>
<div class="shr-publisher-430"></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%2Fjohnvpetersen%2F2012%2F04%2F14%2Fwhy-im-moving-away-from-apple-and-specifically-the-iphone-and-going-to-the-store%2F' data-shr_title='Why+I%27m+moving+away+from+Apple%2C+and+specifically%2C+the+iPhone+and+going+to+the+store'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnvpetersen%2F2012%2F04%2F14%2Fwhy-im-moving-away-from-apple-and-specifically-the-iphone-and-going-to-the-store%2F' data-shr_title='Why+I%27m+moving+away+from+Apple%2C+and+specifically%2C+the+iPhone+and+going+to+the+store'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnvpetersen%2F2012%2F04%2F14%2Fwhy-im-moving-away-from-apple-and-specifically-the-iphone-and-going-to-the-store%2F' data-shr_title='Why+I%27m+moving+away+from+Apple%2C+and+specifically%2C+the+iPhone+and+going+to+the+store'></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/FXseYLQKeao" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/johnvpetersen/2012/04/14/why-im-moving-away-from-apple-and-specifically-the-iphone-and-going-to-the-store/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
					<feedburner:origLink>http://codebetter.com/johnvpetersen/2012/04/14/why-im-moving-away-from-apple-and-specifically-the-iphone-and-going-to-the-store/</feedburner:origLink></item>
	      
    	<item>
		<title>Audit Fields in Google AppEngine</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/712B9ldEi0c/</link>
		<comments>http://codebetter.com/kylebaley/2012/04/07/audit-fields-in-google-appengine/#comments</comments>
		<pubDate>Sat, 07 Apr 2012 23:52:41 +0000</pubDate>
		<dc:creator>Kyle Baley</dc:creator>
				<category><![CDATA[Google App Engine]]></category>
			<guid isPermaLink="false">http://codebetter.com/kylebaley/?p=275</guid>
					<description><![CDATA[Executive summary: Here’s how we’re implementing audit fields in AppEngine. IT’S BETTER THAN THE WAY YOU’RE DOING IT! I considered saying “I hope there’s a better way of doing it” but I believe I’ll get more responses if I frame&#160;&#8230; <a href="http://codebetter.com/kylebaley/2012/04/07/audit-fields-in-google-appengine/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Executive summary: Here’s how we’re implementing audit fields in AppEngine. IT’S BETTER THAN THE WAY YOU’RE DOING IT!</p>
<p>I considered saying “I hope there’s a better way of doing it” but I believe I’ll get more responses if I frame it in the form of a challenge.</p>
<p>For all entities in our datastore, we want to store:</p>
<ul>
<li>dateCreated
<li>dateModified
<li>dateDeleted
<li>createdByUser
<li>modifiedByUser
<li>deletedByUser</li>
</ul>
<p>Here are the options we’ve considered</p>
<h2>Datastore callbacks/Lifecycle callbacks</h2>
<p><img style="border-right-width: 0px;padding-left: 0px;padding-right: 0px;float: right;border-top-width: 0px;border-bottom-width: 0px;border-left-width: 0px;padding-top: 0px" border="0" alt="Audit" align="right" src="http://codebetter.com/kylebaley/files/2012/04/Audit.png" width="240" height="159">AppEngine supports <a href="https://developers.google.com/appengine/docs/java/datastore/callbacks">datastore callbacks</a> natively. If you use Objectify, they have <a href="http://code.google.com/p/objectify-appengine/wiki/IntroductionToObjectify#Lifecycle_Callbacks">lifecycle callbacks</a> for @PrePersist and @PostLoad. The former works fantastic for dateCreated, dateModified, and dateDeleted. Objectify can handle all three easily as well provided you use soft deletes, which we do. (And they <a href="http://weblogs.asp.net/fbouma/archive/2009/02/19/soft-deletes-are-bad-m-kay.aspx">aren’t as bad</a> as <a href="http://ayende.com/blog/4157/avoid-soft-deletes">people would have you believe</a>, especially in AppEngine. You’d be surprised how many user experience problems you discover strolling through deleted data.)</p>
<p>Both of these led to problems for us when we tried to use them for the createdByUser et al methods. We store the current user in the session and access it through a UserRetrievalService (which, at its core, just retrieves the current HttpSession via a Guice provider).</p>
<p>If we want to use this with the Objectify lifecycle callbacks, we would need to inject either our UserRetrievalService or a Provider&lt;HttpSession&gt; into our domain entities. This isn’t something I’m keen on doing so we didn’t pursue this too rigorously.</p>
<p>The datastore callbacks have an advantage in that they can be stored completely separately from the entities and the repositories. But we ran into two issues.</p>
<p>First, we couldn’t inject anything into them, either via constructor injection or static injection. It looks like there’s something funky about how they hook into the process that I don’t understand and my guess is that they are instantiated explicitly somewhere along the line. Regardless, it meant we couldn’t inject our UserRetrievalService or a Provider&lt;HttpSession&gt; into the class.</p>
<p>The next issue was automating the build. When I try to compile the project with a callback in it, the javac task complained about a missing datastorecallbacks.xml file. This file gets created when you build the project in Eclipse but something about how I was doing it via ant obviously wasn’t right. This also leads me to believe there’s something going on behind the scenes.<img style="margin: 5px;float: left" align="left" src="http://rlv.zcache.com/auditing_it_is_tshirt-p235602047235350805z8npz_400.jpg" width="400" height="400"></p>
<p>Neither of these problems is unsurmountable, I don’t think. There is obviously some way of accessing the current HttpSession somehow because Guice is doing it. And clearly you can compile the application when there’s a callback because Eclipse does it. All the same, both issues remaining unsolved by us, which is a shame because I kind of like this option.</p>
<h2>Pass the User to Repository</h2>
<p>This is what was suggested in the <a href="http://stackoverflow.com/questions/9952538/audit-fields-for-appengine-entities">StackOverflow question</a> I posed on the topic. We have repositories for most of our entities so instead of calling put( appointment ), we’d call put( appointment, userWhoPerformedTheAction ).</p>
<p>&nbsp;</p>
<p>I don’t know that I like this solution (as indicated in my comments). To me, passing the current user into the DAO/Repository layer isn’t something the caller should have to worry about. But that’s because in my .NET/NHibernate/SQL Server experience, you can set things up so you don’t have to. Maybe it’s common practice in AppEngine because it’s still relatively new.</p>
<p>(Side note: This question illustrates a number of reasons why I don’t like asking questions on StackOverflow. I usually put a lot of effort into phrasing the question and people often still end up misunderstanding the goal I’m trying to achieve. Which is my fault more than theirs but still means I tend to shy away from SO as a result.)</p>
<h2>Add a User property to each Entity</h2>
<p>I can’t remember where I saw this suggestion. It’s kind of the opposite of the previous one. Each entity would have a User property (marked as @Transient) and when the object is loaded, this is set to the current user. Then in your repositories, it’s trivial to set the user who modified or deleted. This has the same issue I brought up with the last one in that the caller is responsible for setting the User object.</p>
<p>Also, when new objects are created, we’d need to set the property there as well. If you’re doing this on the client, you may have some issues there since you won’t have access to the HttpSession until you send it off to the server.</p>
<h2>Do it yourself</h2>
<p>This is our current implementation. In our repositories, we have a prePersist method that is called before the actual “save this to the datastore” method. Each individual repository can override this as necessary. The UserRetrievalService is injected in and we can use it to set the relevant audit fields before saving to the repository.</p>
<p>This works just fine for us and we’ve extended it to perform other domain-specific prePersist actions for certain entities. I’m not entirely happy with it though. Our repositories tend not to favour composition over inheritance and as such, it is easy to forget to make a call to super.prePersist somewhere along the way. Plus there’s the nagging feeling that it should be cleaner and more testable than this.</p>
<p>Related to this is the underlying problem we’re trying to solve: retrieve the user from the session. In AppEngine, the session is really just the datastore (and memcache) with a fancy HttpSession wrapper around it. So when you get the current user from the session, you’re really just getting it from the datastore anyway using a session ID that is passed back and forth from the client. So if we *really* wanted to roll our own here, we’d implement our own session management which would be more easily accessible from our repositories.</p>
<p>So if you’re an AppEngine user, now’s where you speak up and describe if you went with one of these options or something else. Because this is one of the few areas of our app that fall under the category of “It works but…” And I don’t think it should be.</p>
<p>Kyle the Pre-persistent</p>
<div class="shr-publisher-275"></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%2F04%2F07%2Faudit-fields-in-google-appengine%2F' data-shr_title='Audit+Fields+in+Google+AppEngine'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F04%2F07%2Faudit-fields-in-google-appengine%2F' data-shr_title='Audit+Fields+in+Google+AppEngine'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fkylebaley%2F2012%2F04%2F07%2Faudit-fields-in-google-appengine%2F' data-shr_title='Audit+Fields+in+Google+AppEngine'></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/712B9ldEi0c" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/kylebaley/2012/04/07/audit-fields-in-google-appengine/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
					<feedburner:origLink>http://codebetter.com/kylebaley/2012/04/07/audit-fields-in-google-appengine/</feedburner:origLink></item>
	      
    	<item>
		<title>Microsoft and Open Source</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/Gi-3a1qqsVg/</link>
		<comments>http://codebetter.com/sebastienlambla/2012/04/05/microsoft-and-open-source-2/#comments</comments>
		<pubDate>Thu, 05 Apr 2012 11:44:09 +0000</pubDate>
		<dc:creator>Sebastien Lambla</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://codebetter.com/sebastienlambla/?p=143</guid>
					<description><![CDATA[I have been a vocal, and sometimes harsh, critic of Microsoft’s approach to Open Source Software. I call that activism, some call it whining, ranting or pisser dans la soupe. People are entitled to their opinion, and mine has been&#160;&#8230; <a href="http://codebetter.com/sebastienlambla/2012/04/05/microsoft-and-open-source-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>I have been a vocal, and sometimes harsh, critic of Microsoft’s approach to Open Source Software. I call that activism, some call it whining, ranting or <em>pisser dans la soupe.</em> People are entitled to their opinion, and mine has been formed after working in the Microsoft sphere for more or less 14 years.</p>
<p>Over the years, the various component organizations within Microsoft have had various levels of involvement with Open Source, with different philosophies, and from what I have gathered over the years from post-conference drinks, internal conflicts that can be quite a challenge.</p>
<p>As this post is going to be long, I’m going to sum-up the problem, and you can go to the conclusion bit to read what I believe should be done differently.</p>
<p>Microsoft has no <em>vision</em> when it comes to Open-Source, no strategy and no leadership. Some groups are seen as more progressive, and do tend towards a better approach to OSS. Some people consider those steps as sufficient to stop pressuring Microsoft towards responsible OSS, and I disagree: it’s only some groups, and even within those groups, the advances are still very much one of exporter. Recognizing Microsoft as an OSS-friendly player is like recognizing the People’s Republic of China under the Reagan administration, it’s a step in the direction of normalization, not a recognition of the Human Right lifetime achievements of Mao Tsedung.</p>
<p><a href="http://codebetter.com/sebastienlambla/files/2012/04/Untitled6.jpg"><img style="margin: 0px 0px 24px;padding-left: 0px;padding-right: 0px;float: right;padding-top: 0px;border-width: 0px" src="http://codebetter.com/sebastienlambla/files/2012/04/Untitled6_thumb.jpg" alt="Untitled6" width="244" height="157" align="right" border="0" /></a>You know why I <strong>know</strong> Microsoft has no leadership and vision when it comes to Open-Source? Because I asked Steve Ballmer when he was in London, and he replied with this: “I don’t know, but we won’t impose any view on our divisions. I’ll come back to you by email though.” Steve, my email is still <a href="mailto:seb@serialseb.com">seb@serialseb.com</a> and I’m looking forward to your views.</p>
<h2>Where we come from</h2>
<p>The current state of affairs is not bad, considering where Microsoft was years ago. We’re talking about a company that positioned itself as the defender of private code, vilifying OSS licenses, having no visible OSS project going and providing its value as the integrated stack: it’s all MS or none. We have certainly come a long way.</p>
<h2>Opening up slowly</h2>
<p>I think under the influence of Scott Guthrie, an internal change started deep within the asp.net team ranks, certainly a movement that resulted in the recent announcement of the opening up of the asp.net webstack as a true Open-Source project.</p>
<p>Now <strong>that’s </strong>commendable, and I applaud the move. Open-Sourcing and opening up to collaborative development for stuff you’ve built is great. Well done.</p>
<h2>Not invented in Redmond syndrome</h2>
<p>Let’s be clear. The goal of MVC was to build a better Monorail, as opposed to help Monorail productize their framework for inclusion in Visual Studio.</p>
<p>The exact same thing happened with Nuget. With multiple projects with different approaches already in the work, Microsoft started their NPack project (I seem to recall someone at Oredev mentioning it was originally built as part of the WebPages tooling). It wasn’t to be open-source to start with, hence why the existing OSS projects didn’t get the news until much later.</p>
<p>But, I hear you say, Nuget is an open-source project from Outercurve, and they combined their code with another project. The open-sourcing was decided very late in that process, once the investment in code was so large that the ship had left already and nothing would stop it. And on a side-note, there was no merging of the code, the Outercurve foundation’s press release was inaccurate, just look at the history.</p>
<p>What really happens when a new project gets produced by Microsoft? It sucks the air out of a lot of community projects, often including all the best ideas of said projects, and Microsoft gives nothing back. If you’re in that boat, you either redraw your plans based on their new announcements (usually rewriting on top of the new shiny stuff), or you dissolve your group and join their OSS project (the Nuget / Nubular case).</p>
<p>Certain projects (like nhibernate and nunit) continue to happily go forward, and maybe the OSS alternatives that are impacted by Microsoft entering a space just were not good enough. I don’t know, we’ll see in a few years.</p>
<h2>Adoption of existing projects</h2>
<p>Of course it can be said, and there again, I commend Microsoft for the move, that libraries such as jQuery, modernizr and now Newtonsoft.Json, are being used, supported by Microsoft and shipped alongside the product.</p>
<p>This is also a great departure from time immemorials. Makes no mistake however, Microsoft is being pushed by market pressure to integrate with those frameworks. The change is only that they’re abandoning slowly the idea that they’ll release until they gain marketshare, in those domains where Microsoft has historically been slow at releasing compared to alternative platforms.</p>
<p>This is only an opinion piece, but I’ll suggest that the move to gain web development share has pushed Microsoft towards dropping the projects they had and failed to make popular (the asp.net  AJAX stuff that got more or less killed when jQuery was adopted). And I think that’s great.</p>
<p>Pragmatism is also the reason why newtonsoft.json is being used by Web API. The current Json providers on .net are broken, there is no way to provide the customization people want, and fixing them cannot be done in the same release cycles as MVC, as some are part of the core framework (and may or may never be fixed, but certainly not in time for the next release).</p>
<p>It was not chosen because Microsoft wants to adopt more external OSS projects as their core vision. It was chosen because they couldn’t fix what was broken and rebuilding would have been silly.</p>
<p><em>On a side-note, twitter conversations started going in the direction of why Newtonsoft.Json was chosen over other libraries. I made the assertion that provided it’s an internal implementation with no exposed surface, the choice of *any* json lib would’ve been fine. ScottHa said it was because the library was the most popular, and testing was done on their part. That lead me to the assertion that if the only library under consideration was chosen for popularity, <strong>and</strong> there is no exposed surface of that lib on public APIs, the choice is one of brand-surfing and gives extra marketing points to their OSS credentials. If some of the API is exposed, it was probably a reasonable choice. I don’t care which library you chose, I care the process you used to chose which library and the reasoning behind it. I question (and by question, I mean discuss) the motives, not the solution.</em></p>
<p><em>[Edit: After looking for it (as the twiterverse didn’t reply to the specific of the discussion), one object from json.net *is* exposed on the <a href="http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/55f7dc693838#src%2fSystem.Net.Http.Formatting%2fFormatting%2fJsonMediaTypeFormatter.cs">JsonMediaTypeFormatter</a>, so that is that and I’ll stick to my original analysis, it’s probably a reasonable choice.]</em></p>
<p>There is no vision, because there is no systemic approach to deciding between building and joining communities.</p>
<p>Asp.net Web API could have quite happily join existing OSS projects that dealt with this problem area years ago, but it wasn’t to be. Nuget funding could have been used on top of existing projects, instead of a pure creation, but it wasn’t to be either. What is the decision process behind the rebuild or join decision?</p>
<p>And can anyone that has had their project get the oxygen sucked out of, with nothing given back, be blamed for distrusting the company?</p>
<h2><a href="http://codebetter.com/sebastienlambla/files/2012/04/220px-Borg_Queen_2372.jpg"><img style="margin: 0px 0px 24px;padding-left: 0px;padding-right: 0px;float: right;padding-top: 0px;border-width: 0px" src="http://codebetter.com/sebastienlambla/files/2012/04/220px-Borg_Queen_2372_thumb.jpg" alt="220px-Borg_Queen_2372" width="129" height="158" align="right" border="0" /></a>The corporation</h2>
<p>When the Web API project was being kicked off, <a href="http://codebetter.com/glennblock/">Glenn Block</a> called me asking me if I thought he should take the job, and if he did, would I help. I told him what I’m telling you now: Yes, you can’t do as bad as the previous attempts, and I’ll happily help to make sure the architecture and model fits the reality of what developers want, we’ll all win. I helped because I was asked. Ideally I’d rather they had asked me to work on OpenRasta and create a new version with us, but it was not to be. In the end, the two frameworks may have very different code, but most of the concepts and conventions are exactly the same, so everyone will feel right at home on both platforms, and that’s in no small measure because the brilliant minds behind Web API respected HTTP as much as I and the other advisors did.</p>
<p>More recently, <a href="http://www.twitter.com/anglicangeek">Drew Miller</a> from the NuGet team has been very active in opening communication channels with OpenWrap, something that has not existed ever, and he should be applauded for it: I can now have a discussion about our interop story with someone that wants to make things better. Again, I’d rather the NuGet team had joined OpenWrap rather than communicate to us their imminent release, way too late to get any positive outcome, but at least it’s a step in the right direction.</p>
<p>Those are individuals, not the company, and out of all the voices out there, they are a minority. You cannot judge the whole company on specific individuals, and teams cannot use the excuse <em>Microsoft is really many companies</em>. That is certainly true, but completely irrelevant to external agents when judging how the company deals with OSS.</p>
<h2><a href="http://codebetter.com/sebastienlambla/files/2012/04/transparency.jpg"><img style="margin: 0px 0px 24px;padding-left: 0px;padding-right: 0px;float: right;padding-top: 0px;border-width: 0px" src="http://codebetter.com/sebastienlambla/files/2012/04/transparency_thumb.jpg" alt="transparency" width="217" height="320" align="right" border="0" /></a>How to fix this</h2>
<p>Three words, transparency, transparency, transparency.</p>
<p>When you have an idea for a product, and there are existing Open-Source projects out there that have adoption and could really help the resources of a big vendor, try and justify the choice.</p>
<p>If you’re going to rebuild, take the phone, call the leader, explain your plans, and don’t be a douche about it (aka telling someone “we realize we are stepping on toes here but we’re big so it’ll happen” is not particularly a great way to deliver the news). Chances are, they’ll probably understand the reasoning. ISVs have had <a href="http://www.ericsink.com/item_10169.html">that communication channel from Microsoft for years</a>, and get to know about competing products way in advance, but it’s not the case for OSS projects.</p>
<p>Be open about the process afterwards too. The policy of not mentioning anyone, or pretending you cannot look at existing projects at all in public, would make anyone think you have something to hide. It probably is against some corporate policy somewhere, but make that change, you did do it about the no-OSS policy.</p>
<p>And finally, value the people on your platform, the loud mouths like me and the small guys that abandon their projects because you started yours. We are on your platform because we like it, and we want to make it better. And maybe if you’re going to step on people’s toes, try to find a band aid for them to sweeten the blow, and find a way to collaborate on something else with them. Don’t lose the people that have been developing the ideas you’re going to be building on, it’s not good business.</p>
<p>If these things had happened in the last few years, I wouldn’t distrust Microsoft-the-company as much as I do now. But the bridges that are being built by bright individuals inside the company do go in the right direction.</p>
<p>Is that going to be enough? I sincerely don’t know, but until we’re there, I’ll continue shouting at the top of my voice for Microsoft to become the business partner my OSS projects wants to be dealing with.</p>
<p>It’s called tough love, silly.</p>
<p><em>[Edit: added an additional paragraph to project competition]</em></p>
<p><em>[Edit 2: added a bit on the json.net choice]</em></p>
<div class="shr-publisher-143"></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%2F04%2F05%2Fmicrosoft-and-open-source-2%2F' data-shr_title='Microsoft+and+Open+Source'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fsebastienlambla%2F2012%2F04%2F05%2Fmicrosoft-and-open-source-2%2F' data-shr_title='Microsoft+and+Open+Source'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fsebastienlambla%2F2012%2F04%2F05%2Fmicrosoft-and-open-source-2%2F' data-shr_title='Microsoft+and+Open+Source'></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/Gi-3a1qqsVg" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/sebastienlambla/2012/04/05/microsoft-and-open-source-2/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
					<feedburner:origLink>http://codebetter.com/sebastienlambla/2012/04/05/microsoft-and-open-source-2/</feedburner:origLink></item>
	      
    	<item>
		<title>Moving from Action Filters to Message Handlers</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/0HJhKFSYaf0/</link>
		<comments>http://codebetter.com/johnvpetersen/2012/04/04/moving-from-action-filters-to-message-handlers/#comments</comments>
		<pubDate>Wed, 04 Apr 2012 12:57:05 +0000</pubDate>
		<dc:creator>johnvpetersen</dc:creator>
				<category><![CDATA[ASP.NET MVC 4]]></category>
		<category><![CDATA[ASP.NET Web API]]></category>
			<guid isPermaLink="false">http://codebetter.com/johnvpetersen/?p=414</guid>
					<description><![CDATA[The updated code for the Web API project can be found here In the last post on Making Your ASP.NET Web API&#8217;s Secure, I received some very useful comments. Thanks to Pedro Reys for pointing out my non-use of HttpMessageHandlers.&#160;&#8230; <a href="http://codebetter.com/johnvpetersen/2012/04/04/moving-from-action-filters-to-message-handlers/">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 updated code for the Web API project can be found <a href="https://docs.google.com/open?id=0B6Zn8tqUVSf1MFBzcElyNVJUdG02NWtjSmMyR1Mydw" target="_blank">here</a> In the last post on <a title="Making your ASP.NET Web API’s secure" href="http://codebetter.com/johnvpetersen/2012/04/02/making-your-asp-net-web-apis-secure/" target="_blank">Making Your ASP.NET Web API&#8217;s Secure</a>, I received some very useful comments. Thanks to Pedro Reys for pointing out my non-use of HttpMessageHandlers. Pedro is absolutely correct in his observation that through the use of handlers, we can detect issues BEFORE processing gets into the controller context. If you are concerned about performance (and we all should be!!) &#8211; Http Message Handling is where you want to be. It turned out to be a pretty easier conversion. As you may recall, there were 3 actions filters that enforced:</p>
<ol>
<li>HTTPS</li>
<li>A valid authorization token</li>
<li>A valid IP Host source</li>
</ol>
<p>Here are the 3 new handlers:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace WebAPI
{
 public class HttpsHandler : DelegatingHandler
 {
  protected override Task SendAsync(HttpRequestMessage request,
   CancellationToken cancellationToken)
  {
   if (!String.Equals(request.RequestUri.Scheme, &quot;https&quot;, StringComparison.OrdinalIgnoreCase))
   {
    return Task.Factory.StartNew(() =&gt;
    {
     return new HttpResponseMessage(HttpStatusCode.BadRequest)
     {
      Content = new StringContent(&quot;HTTPS Required&quot;)
     };
    });
   }
   return base.SendAsync(request, cancellationToken);
  }
 }
}
</pre>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using WebAPI.Models;

namespace WebAPI
{
 public class TokenValidationHandler : DelegatingHandler
 {
  protected override Task SendAsync(HttpRequestMessage request,
   CancellationToken cancellationToken)
  {
   string token;

   try
   {
    token = request.Headers.GetValues(&quot;Authorization-Token&quot;).FirstOrDefault();
   }
   catch (System.InvalidOperationException)
   {
    return Task.Factory.StartNew(() =&gt;
    {
     return new HttpResponseMessage(HttpStatusCode.BadRequest)
     {
      Content = new StringContent(&quot;Missing Authorization-Token&quot;)
     };
    });
   }

   try
   {
    var foundUser = AuthorizedUserRepository.GetUsers().FirstOrDefault(x =&gt; x.Name == RSAClass.Decrypt(token));
    if (foundUser == null)
     return Task.Factory.StartNew(() =&gt;
     {
      return new HttpResponseMessage(HttpStatusCode.Forbidden)
      {
       Content = new StringContent(&quot;Unauthorized User&quot;)
      };
     });
   }
   catch (RSAClass.RSAException)
   {
    return Task.Factory.StartNew(() =&gt;
    {
     return new HttpResponseMessage(HttpStatusCode.InternalServerError)
     {
      Content = new StringContent(&quot;Error encountered while attempting to process authorization token&quot;)
     };
    });
   }
   return base.SendAsync(request, cancellationToken);
  }
 }
}
</pre>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using WebAPI.Models;

namespace WebAPI
{
 public class IPHostValidationHandler : DelegatingHandler
 {
   protected override Task SendAsync(HttpRequestMessage request,
   CancellationToken cancellationToken) {

    var context = request.Properties[&quot;MS_HttpContext&quot;] as System.Web.HttpContextBase;
    string userIP = context.Request.UserHostAddress;

    var foundIP = AuthorizedIPRepository.GetAuthorizedIPs().FirstOrDefault(x =&gt; x == userIP);
    if (foundIP == null)
     return Task.Factory.StartNew(() =&gt;
     {
      return new HttpResponseMessage(HttpStatusCode.Forbidden)
      {
       Content = new StringContent(&quot;Unauthorized IP Address&quot;)
      };
     });

    return base.SendAsync(request, cancellationToken);

   }
 }
}
</pre>
<p>I went ahead and created a specific exception to address situations when the RSA encryption/description process throws the generic bad data exception. Here is the revised RSAClass:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace WebAPI
{
 public class RSAClass
 {
  private static string _privateKey = &quot;s6lpjspk+3o2GOK5TM7JySARhhxE5gB96e9XLSSRuWY2W9F951MfistKRzVtg0cjJTdSk5mnWAVHLfKOEqp8PszpJx9z4IaRCwQ937KJmn2/2VyjcUsCsor+fdbIHOiJpaxBlsuI9N++4MgF/jb0tOVudiUutDqqDut7rhrB/oc=AQAB&lt;/pre&gt;
3J2+VWMVWcuLjjnLULe5TmSN7ts0n/TPJqe+bg9avuewu1rDsz+OBfP66/+rpYMs5+JolDceZSiOT+ACW2Neuw==
&lt;pre&gt;&lt;q&gt;0HogL5BnWjj9BlfpILQt8ajJnBHYrCiPaJ4npghdD5n/JYV8BNOiOP1T7u1xmvtr2U4mMObE17rZjNOTa1rQpQ==&lt;/q&gt;jbXh2dVQlKJznUMwf0PUiy96IDC8R/cnzQu4/ddtEe2fj2lJBe3QG7DRwCA1sJZnFPhQ9svFAXOgnlwlB3D4Gw==evrP6b8BeNONTySkvUoMoDW1WH+elVAH6OsC8IqWexGY1YV8t0wwsfWegZ9IGOifojzbgpVfIPN0SgK1P+r+kQ==LeEoFGI+IOY/J+9SjCPKAKduP280epOTeSKxs115gW1b9CP4glavkUcfQTzkTPe2t21kl1OrnvXEe5Wrzkk8rA==HD0rn0sGtlROPnkcgQsbwmYs+vRki/ZV1DhPboQJ96cuMh5qeLqjAZDUev7V2MWMq6PXceW73OTvfDRcymhLoNvobE4Ekiwc87+TwzS3811mOmt5DJya9SliqU/ro+iEicjO4v3nC+HujdpDh9CVXfUAWebKnd7Vo5p6LwC9nIk=&quot;;
  private static string _publicKey = &quot;s6lpjspk+3o2GOK5TM7JySARhhxE5gB96e9XLSSRuWY2W9F951MfistKRzVtg0cjJTdSk5mnWAVHLfKOEqp8PszpJx9z4IaRCwQ937KJmn2/2VyjcUsCsor+fdbIHOiJpaxBlsuI9N++4MgF/jb0tOVudiUutDqqDut7rhrB/oc=AQAB&quot;;
  private static UnicodeEncoding _encoder = new UnicodeEncoding();

  public static string Decrypt(string data)
  {

   try
   {
    var rsa = new RSACryptoServiceProvider();
    var dataArray = data.Split(new char[] { ',' });

    byte[] dataByte = new byte[dataArray.Length];
    for (int i = 0; i &lt; dataArray.Length; i++)
    {
     dataByte[i] = Convert.ToByte(dataArray[i]);
    }

    rsa.FromXmlString(_privateKey);
    var decryptedByte = rsa.Decrypt(dataByte, false);
    return _encoder.GetString(decryptedByte);

   }
   catch (Exception)
   {
    throw new RSAException();
   }

  }

  public static string Encrypt(string data)
  {

   try
   {
    var rsa = new RSACryptoServiceProvider();
    rsa.FromXmlString(_publicKey);
    var dataToEncrypt = _encoder.GetBytes(data);
    var encryptedByteArray = rsa.Encrypt(dataToEncrypt, false).ToArray();
    var length = encryptedByteArray.Count();
    var item = 0;
    var sb = new StringBuilder();
    foreach (var x in encryptedByteArray)
    {
     item++;
     sb.Append(x);

     if (item &lt; length)
      sb.Append(&quot;,&quot;);
    }

    return sb.ToString();

   }
   catch (Exception)
   {
    throw new RSAException();
   }
  }

  public class RSAException : Exception {

   public RSAException() : base(&quot;RSA Encryption Error&quot;) {}

  }
 }
}
</pre>
<p>The one difference I did notice between the action filter and handler was in the way unhandled errors were passed back to the client. For example, with an action filter, a missing authorization token would have the following rendered to the client: </p>
<p><a href="http://codebetter.com/johnvpetersen/files/2012/04/image11.png"><img src="http://codebetter.com/johnvpetersen/files/2012/04/image11-300x83.png" alt="" width="300" height="83" /></a></p>
<p>On the other and, the message handler would render the same error the client this way:</p>
<p><a href="http://codebetter.com/johnvpetersen/files/2012/04/image11.png"><img src="http://codebetter.com/johnvpetersen/files/2012/04/image21-300x122.png" alt="" width="300" height="122" /></a></p>
<p>You may have noticed I changed the linq calls from First to FirstOrDefault. I got flamed a bit for using just First &#8211; and then letting the exception deal with the results in the event a value could not be found. I still contend that using an exception or checking the nullity of a value doesn&#8217;t make that much of a difference. In the case of checking for the existence of a header, it&#8217;s a moot point because if you invoke code like this:</p>
<pre class="brush: csharp; title: ; notranslate">
var token =
  request.Headers.GetValues(&quot;Authorization-Token&quot;).FirstOrDefault();
</pre>
<p>and the Authorization-Token header does not exist, you never get to the FirstOrDefault() Linq Query&#8230;:-) As it turns out, you have to wrap that call in a try catch anyway &#8211; at least if you wish to present to the client a predictable and useful message. Always take with a grain of salt when somebody espouses &#8220;best practice&#8221; or something being a &#8220;bad practice&#8221; or &#8220;bad form&#8221;. No question, there are established good/best practices out there. Those practices however, are quantifiable and verifiable through empirical evidence. Anything else is simply a matter of opinion and preference. AND &#8211; context means everything. What may be a good/best practice in one scenario may not be so in another scenario. And often, technology has little to nothing to do with the equation. For example, Dependency Injection is a good practice and is often, a best practice. BUT &#8211; in a shop where the concept is new, foreign or not understood, if it presents a bar to shipping software, it may not be a best practice for that shop &#8211; at that time. One of the many reasons why I quickly brush off notions of what best practices are and are not when asked.. <img src='http://codebetter.com/johnvpetersen/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  A bit of a rant on my part. I definitely appreciate the comments &#8211; but rest assured, I&#8217;ll push back a bit when I think conclusions are offered absent a premise. Sorry..that&#8217;s the lawyer in me that is now hard wired!!</p>
<div class="shr-publisher-414"></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%2Fjohnvpetersen%2F2012%2F04%2F04%2Fmoving-from-action-filters-to-message-handlers%2F' data-shr_title='Moving+from+Action+Filters+to+Message+Handlers'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnvpetersen%2F2012%2F04%2F04%2Fmoving-from-action-filters-to-message-handlers%2F' data-shr_title='Moving+from+Action+Filters+to+Message+Handlers'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnvpetersen%2F2012%2F04%2F04%2Fmoving-from-action-filters-to-message-handlers%2F' data-shr_title='Moving+from+Action+Filters+to+Message+Handlers'></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/0HJhKFSYaf0" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/johnvpetersen/2012/04/04/moving-from-action-filters-to-message-handlers/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
					<feedburner:origLink>http://codebetter.com/johnvpetersen/2012/04/04/moving-from-action-filters-to-message-handlers/</feedburner:origLink></item>
	      
    	<item>
		<title>Making your ASP.NET Web API’s secure</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/5_-DQL7e4Uw/</link>
		<comments>http://codebetter.com/johnvpetersen/2012/04/02/making-your-asp-net-web-apis-secure/#comments</comments>
		<pubDate>Mon, 02 Apr 2012 21:03:22 +0000</pubDate>
		<dc:creator>johnvpetersen</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[ASP.NET MVC 4]]></category>
			<guid isPermaLink="false">http://codebetter.com/johnvpetersen/?p=389</guid>
					<description><![CDATA[Note: Code for this example is on Google Docs. SecureWebAPI SecureWebAPITest NOTE: DO NOT USE THE PUBLIC/PRIVATE KEYS IN THIS EXAMPLE IN YOUR PRODUCTION APPLICATION!!!! BE SURE TO GENERATE YOUR OWN KEYS!! OTHERWISE, YOUR APPLICATION WILL NOT BE SECURE AS&#160;&#8230; <a href="http://codebetter.com/johnvpetersen/2012/04/02/making-your-asp-net-web-apis-secure/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>Note: Code for this example is on Google Docs.</p>
<p><a href="https://docs.google.com/open?id=0B6Zn8tqUVSf1Z0RiNzFPODdUOGVDRXFfS3JHaHYtUQ" target="_blank">SecureWebAPI</a><br />
<a href="https://docs.google.com/open?id=0B6Zn8tqUVSf1bDh3eVI3ZTRTZGE5NGVkZjBILW1FUQ" target="_blank">SecureWebAPITest</a></p>
<p>NOTE: DO NOT USE THE PUBLIC/PRIVATE KEYS IN THIS EXAMPLE IN YOUR PRODUCTION APPLICATION!!!! BE SURE TO GENERATE YOUR OWN KEYS!! OTHERWISE, YOUR APPLICATION WILL NOT BE SECURE AS THE PRIVATE KEY WILL BE IN THE FIELD!!!! <img src='http://codebetter.com/johnvpetersen/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Recently, I&#8217;ve been exploring the new ASP.NET Web API. So far, I&#8217;ve been impressed with how easy it is to build RESTful web interfaces. In the examples I&#8217;ve published, none have been secure. In the real world &#8211; the world that exists beyond the world of samples and demos &#8211; security is a matter than cannot be brushed aside. In this post, I squarely tackle that issue by showing you an approach that locks down and secures your ASP.NET Web API.</p>
<p>In research this topic, looking what others have done this far, I came away with a lot of approaches that in my opinion, where too complicated and quite frankly, a pain to setup. It was also questionable what the value proposition was for all that pain. In other words, how was my site made more secure by implementing one approach or another. Two big topics that I won&#8217;t discuss today are oAuth and OpenID. Sure, those approaches each solve a segment of the overall problem. oAuth is about authorization. For example, I can use my credentials in Twitter to gain access to another site. The relationship with oAuth is one app authorizing another app. OpenID on the other hand is about authentication. I have an Openid and I use that as the basis for an application to authenticate who I am  &#8211; without the need for that application to maintain my security details. With OpenID, it&#8217;s one security mechanism used for many applications. In any application, you need to be both authenticated and authorized. Once a user gets access to an application, the process still needs to be secure &#8211; especially if HIPPA related type data is presented. </p>
<p>For many applications, OpenID or oAuth can work fine. But for a Web API, it really does not work. First, RESTful apis are just that &#8211; RESTful &#8211; which means they are stateless. To be effective, we cannot make assumptions from one call to the next. We have to supply credentials with each and every request, whether it is a GET, POST, PUT or DELETE. Like Any API, a Web API should, in my opinion be self sufficient as to controlling how people get to the site. Indeed, things like oAuth and OpenID can work. However, I think the process can be made simpler &#8211; with techniques that have been around a while and are as relevant as ever &#8211; with all due respect to their newer counterparts. </p>
<p><strong>HTTPS</strong></p>
<p>Of all the things that can be done to make your API,  more secure, requiring it to run over HTTPS is the easiest thing to implement. This does nothing for authorization and authentication &#8211; which I will get to in a moment. HTTPS however, does afford encryption that is not present in regular HTTP traffic. With HTTPS, your traffic is far less likely to be subject to packet sniffing eavesdropping attacks. The key is, how can you ensure that your Web API is only accessed via HTTPS? The answer lies in one of the most useful features in ASP.NET MVC &#8211; that has also been implemented in ASP.NET Web API: Action Filters. And in this case, I&#8217;ll make the action filter a global action filter &#8211; eliminating the need to manually add the filter to every controller action.</p>
<p>Here is the custom action filter</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Linq;
using System.Net.Http;
using System.Web.Http.Filters;
using System.Web.Http.Controllers;

namespace WebAPI
{
 public class CustomHttpsAttribute : ActionFilterAttribute
 {
  public override void OnActionExecuting(HttpActionContext actionContext)
  {
   if (!String.Equals(actionContext.Request.RequestUri.Scheme, &quot;https&quot;, StringComparison.OrdinalIgnoreCase))
   {
    actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
    {
     Content = new StringContent(&quot;HTTPS Required&quot;)
    };
    return;
   }
  }
 }
}
</pre>
<p>Nothing very complicated going on here. If https is not present in the URL, a response is fabricated indicating a bad request (error 400). A message is also added to the response content as well.</p>
<p><a href="http://codebetter.com/johnvpetersen/files/2012/04/image1.png"><img src="http://codebetter.com/johnvpetersen/files/2012/04/image1-300x162.png" alt="" width="300" height="162" /></a></p>
<p>As the previous figure illustrates, when we attempt to navigate to the Web API with HTTP, as opposed to HTTPS, a response with status code 400 results &#8211; along with a friendly message in the response body that describes the error.</p>
<p><strong>Tokens based on Public/Private Keys</strong></p>
<p>Of all the ways to authorize and authenticate, it seems to me that tokens have done a good at this task. A token can be used to authorize, and for the most part, authenticate a user. Of course, it is possible for a key to get passed around. I&#8217;ll address that in the next section. That said, it may be perfectly fine to assume that if a visitor has a properly encrypted token, that visitor is who he/she/it claims to be (in cases where its an application, not a person, it is the right pronoun!!)  </p>
<p>The idea behind a private and public key pair is simple. A token is encrypted with the public key. In some cases, the public key sits in the field. In cases where data has to be encrypted by the client to be decrypted on the server, the public key needs to be in the field. The server is the only thing that should have the private key. It&#8217;s the private key that handles the decryption. To get this working, we need a simple class to handle our encryption needs:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace WebAPI
{
 public class RSAClass
 {
  private static string _privateKey = &quot;&lt;RSAKeyValue&gt;&lt;Modulus&gt;s6lpjspk+3o2GOK5TM7JySARhhxE5gB96e9XLSSRuWY2W9F951MfistKRzVtg0cjJTdSk5mnWAVHLfKOEqp8PszpJx9z4IaRCwQ937KJmn2/2VyjcUsCsor+fdbIHOiJpaxBlsuI9N++4MgF/jb0tOVudiUutDqqDut7rhrB/oc=&lt;/Modulus&gt;&lt;Exponent&gt;AQAB&lt;/Exponent&gt;&lt;P&gt;3J2+VWMVWcuLjjnLULe5TmSN7ts0n/TPJqe+bg9avuewu1rDsz+OBfP66/+rpYMs5+JolDceZSiOT+ACW2Neuw==&lt;/P&gt;&lt;Q&gt;0HogL5BnWjj9BlfpILQt8ajJnBHYrCiPaJ4npghdD5n/JYV8BNOiOP1T7u1xmvtr2U4mMObE17rZjNOTa1rQpQ==&lt;/Q&gt;&lt;DP&gt;jbXh2dVQlKJznUMwf0PUiy96IDC8R/cnzQu4/ddtEe2fj2lJBe3QG7DRwCA1sJZnFPhQ9svFAXOgnlwlB3D4Gw==&lt;/DP&gt;&lt;DQ&gt;evrP6b8BeNONTySkvUoMoDW1WH+elVAH6OsC8IqWexGY1YV8t0wwsfWegZ9IGOifojzbgpVfIPN0SgK1P+r+kQ==&lt;/DQ&gt;&lt;InverseQ&gt;LeEoFGI+IOY/J+9SjCPKAKduP280epOTeSKxs115gW1b9CP4glavkUcfQTzkTPe2t21kl1OrnvXEe5Wrzkk8rA==&lt;/InverseQ&gt;&lt;D&gt;HD0rn0sGtlROPnkcgQsbwmYs+vRki/ZV1DhPboQJ96cuMh5qeLqjAZDUev7V2MWMq6PXceW73OTvfDRcymhLoNvobE4Ekiwc87+TwzS3811mOmt5DJya9SliqU/ro+iEicjO4v3nC+HujdpDh9CVXfUAWebKnd7Vo5p6LwC9nIk=&lt;/D&gt;&lt;/RSAKeyValue&gt;&quot;;
  private static string _publicKey = &quot;&lt;RSAKeyValue&gt;&lt;Modulus&gt;s6lpjspk+3o2GOK5TM7JySARhhxE5gB96e9XLSSRuWY2W9F951MfistKRzVtg0cjJTdSk5mnWAVHLfKOEqp8PszpJx9z4IaRCwQ937KJmn2/2VyjcUsCsor+fdbIHOiJpaxBlsuI9N++4MgF/jb0tOVudiUutDqqDut7rhrB/oc=&lt;/Modulus&gt;&lt;Exponent&gt;AQAB&lt;/Exponent&gt;&lt;/RSAKeyValue&gt;&quot;;
  private static UnicodeEncoding _encoder = new UnicodeEncoding();

  public static string Decrypt(string data)
  {
   var rsa = new RSACryptoServiceProvider();
   var dataArray = data.Split(new char[] { ',' });
   byte[] dataByte = new byte[dataArray.Length];
   for (int i = 0; i &lt; dataArray.Length; i++)
   {
    dataByte[i] = Convert.ToByte(dataArray[i]);
   }

   rsa.FromXmlString(_privateKey);
   var decryptedByte = rsa.Decrypt(dataByte, false);
   return _encoder.GetString(decryptedByte);
  }

  public static string Encrypt(string data)
  {
   var rsa = new RSACryptoServiceProvider();
   rsa.FromXmlString(_publicKey);
   var dataToEncrypt = _encoder.GetBytes(data);
   var encryptedByteArray = rsa.Encrypt(dataToEncrypt, false).ToArray();
   var length = encryptedByteArray.Count();
   var item = 0;
   var sb = new StringBuilder();
   foreach (var x in encryptedByteArray)
   {
    item++;
    sb.Append(x);

    if (item &lt; length)
     sb.Append(&quot;,&quot;);
   }

   return sb.ToString();
  }
 }
}
</pre>
<p>In this simple RSAClass, I have embedded the public/private RSA Parameters. To create and export new parameters, you would issue the following code outlined in the next image:</p>
<p><a href="http://codebetter.com/johnvpetersen/files/2012/04/image41.png"><img src="http://codebetter.com/johnvpetersen/files/2012/04/image41-300x93.png" alt="" width="300" height="93" /></a></p>
<pre class="brush: csharp; title: ; notranslate">
[Test]
 public void RSAParameters() {

  var rsa = new RSACryptoServiceProvider();
  var privateParameters = rsa.ExportParameters(true);
  var publicParameters = rsa.ExportParameters(false);

  //Export private parameter XML representation of privateParameters
  //object created above
  Debug.WriteLine(rsa.ToXmlString(true));

  //Export private parameter XML representation of publicParameters
  //object created above
  Debug.WriteLine(rsa.ToXmlString(false));
 }
</pre>
<p>The following is a simple test that illustrates how to encrypt and decrypt a string with the public/private key pair:</p>
<pre class="brush: csharp; title: ; notranslate">
[Test]
  public void VerifyToken() {

   var token = &quot;User1&quot;;
   var encryptedToken = RSAClass.Encrypt(token);
   var decryptedToken = RSAClass.Decrypt(encryptedToken);

   Assert.AreEqual(token,decryptedToken);

  }
</pre>
<p>In this case, the encrypted 128 byte token that results for &#8220;User1&#8243; is:</p>
<pre class="brush: csharp; title: ; notranslate">
57,46,60,70,93,230,85,33,98,19,10,46,84,91,218,43,207,42,159,
167,5,25,157,4,224,142,235,8,160,199,123,100,107,58,37,204,133,
81,138,196,237,190,56,119,158,7,224,89,84,85,208,169,44,179,102,
218,55,60,76,134,144,22,208,230,165,179,83,125,86,57,224,42,
29,58,188,45,73,33,160,87,165,105,131,139,132,137,209,67,92,36,
168,73,176,205,251,48,240,228,14,39,197,36,42,21,216,242,172,
4,160,234,138,77,156,28,191,63,111,207,221,31,103,213,58,62,
186,123,221,230
</pre>
<p>You may wish to modify this by having a smaller encrypted token. This is but one approach of many that are possible.</p>
<p>The next thing we need is an action filter to make sure the token is present in each and every request:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Linq;
using System.Net.Http;
using System.Web.Http.Filters;
using System.Web.Http.Controllers;
using WebAPI.Models;

namespace WebAPI
{
 public class TokenValidationAttribute : ActionFilterAttribute
 {
  public override void OnActionExecuting(HttpActionContext actionContext)
  {
   string token;

   try
   {
    token = actionContext.Request.Headers.GetValues(&quot;Authorization-Token&quot;).First();
   }
   catch (Exception)
   {
    actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
    {
     Content = new StringContent(&quot;Missing Authorization-Token&quot;)
    };
    return;
   }

   try
   {
    AuthorizedUserRepository.GetUsers().First(x =&gt; x.Name == RSAClass.Decrypt(token));
    base.OnActionExecuting(actionContext);
   }
   catch (Exception)
   {
    actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
    {
     Content = new StringContent(&quot;Unauthorized User&quot;)
    };
    return;
   }
  }
 }
}
</pre>
<p>There are two levels of checking here. The first is whether or not the authorization token is present in the header. If not, a bad request response (error 400) is returned. If the token was provided but does not resolve to an authorized user, then an unauthorized response (error 401) is returned. The following illustrates how to setup Fiddler with the Authorization-Token in the header:</p>
<p><a href="http://codebetter.com/johnvpetersen/files/2012/04/image2.png"><img src="http://codebetter.com/johnvpetersen/files/2012/04/image2-300x80.png" alt="" width="300" height="80" /></a></p>
<p>The following illustrates the results of the call in the previous image:</p>
<p><a href="http://codebetter.com/johnvpetersen/files/2012/04/image3.png"><img src="http://codebetter.com/johnvpetersen/files/2012/04/image3-300x162.png" alt="" width="300" height="162" /></a></p>
<p>For purposes of this demo, I established a simple authorized user repository that has a list of pre-defined users:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Collections.Generic;
using System.Linq;

namespace WebAPI.Models
{
 public class AuthorizedUserRepository
 {
   public static IQueryable&lt;User&gt; GetUsers() {

      IList&lt;User&gt; users = new List&lt;User&gt;();
      users.Add(new User(&quot;User1&quot;));
      users.Add(new User(&quot;User2&quot;));
      users.Add(new User(&quot;User3&quot;));
      users.Add(new User(&quot;Administrator&quot;));

      return users.AsQueryable();
   }
 }
}
</pre>
<p>Within this approach, there are all sorts of variants you could employ. For example, you could swap out the public/private keys on some periodic basis. Of course, that means you will have to issue new tokens to users who have access to your API!!</p>
<p><strong> IP Filtering</strong></p>
<p>Up to this point, while the system is pretty secure, it can be locked down further. Right now, tokens could be moved from location to location. It may be that you only want to authorize traffic from certain IP addresses and hosts. For purposes of this demo, I created a simple Authorized IP Repository:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Collections.Generic;
using System.Linq;

namespace WebAPI.Models
{
 public class AuthorizedIPRepository
 {
    public static IQueryable&lt;string&gt; GetAuthorizedIPs() {

      var ips = new List&lt;string&gt;();

      ips.Add(&quot;127.0.0.1&quot;);
      ips.Add(&quot;::1&quot;);

      return ips.AsQueryable();
    }
 }
}
</pre>
<p>In actual practice, I might take the extra step of linking specific tokens to a specific IP range. I&#8217;ll leave that exercise to you! The following is the action filter that restricts traffic from a defined IP list:</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Linq;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Net.Http;
using WebAPI.Models;

namespace WebAPI
{
 public class IPHostValidationAttribute : ActionFilterAttribute
 {
  public override void OnActionExecuting(HttpActionContext actionContext)
  {

   var context = actionContext.Request.Properties[&quot;MS_HttpContext&quot;] as System.Web.HttpContextBase;
   string userIP = context.Request.UserHostAddress;
   try
   {
    AuthorizedIPRepository.GetAuthorizedIPs().First(x =&gt; x == userIP);
   }
   catch (Exception)
   {
    actionContext.Response =
       new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden)
       {
        Content = new StringContent(&quot;Unauthorized IP Address&quot;)
       };
    return;
   }
  }
 }
}
</pre>
<p>To make these action filters global, the following code in the Global.asax Application_Start() will do the trick:</p>
<pre class="brush: csharp; title: ; notranslate">
var config = GlobalConfiguration.Configuration;
config.Filters.Add(new TokenValidationAttribute());
config.Filters.Add(new CustomHttpsAttribute());
config.Filters.Add(new IPHostValidationAttribute());
</pre>
<p>If you wished to initiate a request from your C# code, you might have a utility method like this:</p>
<pre class="brush: csharp; title: ; notranslate">
  WebRequest getRequest(string method, string contentType, string endPoint)
  {
   var request = WebRequest.Create(endPoint);
   request.Method = method;
   request.ContentType = contentType;

   ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

   request.Headers.Add(&quot;Authorization-Token&quot;, &quot;57,46,60,70,93,230,85,33,98,19,10,46,84,91,218,43,207,42,159,167,5,25,157,4,224,142,235,8,160,199,123,100,107,58,37,204,133,81,138,196,237,190,56,119,158,7,224,89,84,85,208,169,44,179,102,218,55,60,76,134,144,22,208,230,165,179,83,125,86,57,224,42,29,58,188,45,73,33,160,87,165,105,131,139,132,137,209,67,92,36,168,73,176,205,251,48,240,228,14,39,197,36,42,21,216,242,172,4,160,234,138,77,156,28,191,63,111,207,221,31,103,213,58,62,186,123,221,230&quot;);

   return request;
  }
</pre>
<p>This request has the necessary information to make an API request </p>
<p>That&#8217;s pretty much it. Now we have a ASP.NET Web API that requires requests to be under the HTTPS protocol, requires an encrypted authorization token and requires traffic to only come from a predefined population of IP addresses. There are any number of ways you can vary this implementation. My goal with this post was to make it easy to get started. With this approach, you don&#8217;t have to worry about cumbersome query string parameters, etc. In this example, I am putting authentication details where they belong &#8211; in the header &#8211; which means it will work for anything. No need to deal with clumsy query string parameters either. </p>
<p>Enjoy!!</p>
<div class="shr-publisher-389"></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%2Fjohnvpetersen%2F2012%2F04%2F02%2Fmaking-your-asp-net-web-apis-secure%2F' data-shr_title='Making+your+ASP.NET+Web+API%27s+secure'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnvpetersen%2F2012%2F04%2F02%2Fmaking-your-asp-net-web-apis-secure%2F' data-shr_title='Making+your+ASP.NET+Web+API%27s+secure'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fjohnvpetersen%2F2012%2F04%2F02%2Fmaking-your-asp-net-web-apis-secure%2F' data-shr_title='Making+your+ASP.NET+Web+API%27s+secure'></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/5_-DQL7e4Uw" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/johnvpetersen/2012/04/02/making-your-asp-net-web-apis-secure/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
					<feedburner:origLink>http://codebetter.com/johnvpetersen/2012/04/02/making-your-asp-net-web-apis-secure/</feedburner:origLink></item>
	      
    	<item>
		<title>Continuous Testing</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/8or_fGgDDqU/</link>
		<comments>http://codebetter.com/gregyoung/2012/04/02/continuous-testing-3/#comments</comments>
		<pubDate>Mon, 02 Apr 2012 11:53:22 +0000</pubDate>
		<dc:creator>gregyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Continuous Testing]]></category>
		<category><![CDATA[Mighty Moose]]></category>
			<guid isPermaLink="false">http://codebetter.com/gregyoung/?p=289</guid>
					<description><![CDATA[On my build times post from &#8220;Don&#8221; And you want to run your tests _every time_ you hit ctrl+s !? Actually I have run into this viewpoint quite a bit. I see it most commonly from people who are not&#160;&#8230; <a href="http://codebetter.com/gregyoung/2012/04/02/continuous-testing-3/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p>On my build times post from &#8220;Don&#8221;</p>
<blockquote><p>And you want to run your tests _every time_ you hit ctrl+s !? </p></blockquote>
<p>Actually I have run into this viewpoint quite a bit. I see it most commonly from people who are not doing TDD. The reasoning seems to be that in the process of working on a feature they may save 20 times over a few hours then try to build. The &#8220;Save&#8221; mode is 100% for TDD workflows. If you are not doing TDD workflows then it probably is not for you. That said after having this discussion many times there are other options that better match non-TDD workflows. Let&#8217;s go through all four workflows.</p>
<h3>Realtime / Saving modes</h3>
<p>The realtime (as you type) and saving (when you save) modes are the default modes and are focused on people who are interested in very short TDD feedback cycles. Both automated both your build and will figure out which tests to run and run them after the build is completed. If you type (or save over the top) existing runs are fully or partially cancelled depending where they are in the run.</p>
<h3>Auto</h3>
<p>Auto will no longer automate your builds. Basically it waits for you to build in Visual Studio and when it succeeds will automate the finding and running of the necessary unit tests. This uses the build in VS as the &#8220;commit&#8221;, not the saving of  file. </p>
<h3>Manual</h3>
<p>The last mode that is available is Manual mode. In this mode no automation will occur (except for us seeing your builds and keeping our graphs updated). The software will not automate any builds or tests. </p>
<p>Many people have asked &#8220;Why does manual mode exist?&#8221;.</p>
<p>Manual mode actually has a fairly powerful workflow associated with it that may be beneficial in some scenarios that are not good candidates for continuous testing. In this mode Mighty Moose works just like most manual test runners with a small twist there is a feature called &#8220;Run Related Tests&#8221; (ctrl+shift+y,r).</p>
<p>Run Related Tests is quite interesting for those who are not in a situation to benefit from continuous testing. Let&#8217;s try a quick walk through.</p>
<p>type:</p>
<p>[Test]<br />
public void MyFirstTest() {<br />
    Assert.AreEqual(Foo.Bar(3));<br />
}</p>
<p>static class Foo {<br />
    public static int Bar(int x) { throw new UnimplementedException(); }<br />
}</p>
<p>Now hit ctrl+shift+y,u with the cursor inside of the test. It will tell you that the test has run (failed). </p>
<p>With cursor on &#8220;Bar&#8221; f12 (goto definition)… replace code with</p>
<p>return 3;</p>
<p>from current cursor location ctrl+shift+y,r (run related tests). 1 test run one test passes. Imagining they are in different files now use ctrl+f6 and back in your tests. You can just keep flipping back and forth like this.</p>
<div class="shr-publisher-289"></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%2Fgregyoung%2F2012%2F04%2F02%2Fcontinuous-testing-3%2F' data-shr_title='Continuous+Testing'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fgregyoung%2F2012%2F04%2F02%2Fcontinuous-testing-3%2F' data-shr_title='Continuous+Testing'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fgregyoung%2F2012%2F04%2F02%2Fcontinuous-testing-3%2F' data-shr_title='Continuous+Testing'></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/8or_fGgDDqU" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/gregyoung/2012/04/02/continuous-testing-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
					<feedburner:origLink>http://codebetter.com/gregyoung/2012/04/02/continuous-testing-3/</feedburner:origLink></item>
	      
    	<item>
		<title>REST Resources</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/m3owRcR70BQ/</link>
		<comments>http://codebetter.com/howarddierking/2012/03/27/rest-resources/#comments</comments>
		<pubDate>Tue, 27 Mar 2012 19:11:52 +0000</pubDate>
		<dc:creator>Howard Dierking</dc:creator>
				<category><![CDATA[architecture]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Web API]]></category>
			<guid isPermaLink="false">http://codebetter.com/howarddierking/?p=188</guid>
					<description><![CDATA[I got a question recently about my recent Pluralsight REST Fundamentals course. Several times throughout the course, I say something to the effect of &#8220;for more on X, check out the references section at the end of the module&#8221;. The&#160;&#8230; <a href="http://codebetter.com/howarddierking/2012/03/27/rest-resources/">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 got a question recently about <a href="http://www.pluralsight-training.net/microsoft/Courses/TableOfContents?courseName=rest-fundamentals">my recent Pluralsight REST Fundamentals course</a>. Several times throughout the course, I say something to the effect of &#8220;for more on X, check out the references section at the end of the module&#8221;. The question was &#8211; where are the references. The short answer is that each module has a PDF of the slides used &#8211; and the last slide is for references. However, to save you the trouble of going through each of the PDFs to extract the references, I&#8217;ll just provide a consolidated list for the entire course here. Hope this is helpful whether or not you check out the course &#8211; though I would love to get your thoughts on that as well!</p>
<ul>
<li>Fielding, Roy Thomas. <a href="http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm">Architectural Styles and the Design of Network-based Software Architectures</a>. Doctoral dissertation, University of California, Irvine, 2000.</li>
<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">HTTP/1.1 Specification</a></li>
<li>Rotem-Gal-Oz. <a href="http://www.rgoarchitects.com/Files/fallacies.pdf">Fallacies of Distributed Computing Explained</a>.</li>
<li>Amundsen, Mike. <a href="http://www.amazon.com/Building-Hypermedia-APIs-HTML5-Node/dp/1449306578/ref=sr_1_1?ie=UTF8&amp;qid=1332875319&amp;sr=8-1">Building Hypermedia APIs with HTML5 and Node</a>. O’Reilly Media, 2011.</li>
<li><a href="http://tools.ietf.org/html/draft-gregorio-uritemplate-08">URI Template Specification Draft</a></li>
<li><a href="http://www.fiddler2.com/fiddler2/">Fiddler</a></li>
<li><a href="http://curl.haxx.se/">cURL </a></li>
<li><a href="http://stateless.co/hal_specification.html">HAL Media Type Specification</a></li>
<li><a href="https://github.com/howarddierking/RestBugs">RESTBugs Sample Application</a></li>
<li><a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven">http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven</a></li>
<li>Varia, Jinesh. <a href="http://d36cz9buwru1tt.cloudfront.net/AWS_Cloud_Best_Practices.pdf">Architecting for the Cloud: Best Practices</a>.</li>
</ul>
<div class="shr-publisher-188"></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%2Fhowarddierking%2F2012%2F03%2F27%2Frest-resources%2F' data-shr_title='REST+Resources'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fhowarddierking%2F2012%2F03%2F27%2Frest-resources%2F' data-shr_title='REST+Resources'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fhowarddierking%2F2012%2F03%2F27%2Frest-resources%2F' data-shr_title='REST+Resources'></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/m3owRcR70BQ" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/howarddierking/2012/03/27/rest-resources/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
					<feedburner:origLink>http://codebetter.com/howarddierking/2012/03/27/rest-resources/</feedburner:origLink></item>
	      
    	<item>
		<title>Charge for bad code?</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/lHKVj-hqhlA/</link>
		<comments>http://codebetter.com/gregyoung/2012/03/27/charge-for-bad-code/#comments</comments>
		<pubDate>Tue, 27 Mar 2012 12:14:04 +0000</pubDate>
		<dc:creator>gregyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Mighty Moose]]></category>
			<guid isPermaLink="false">http://codebetter.com/gregyoung/?p=280</guid>
					<description><![CDATA[So let&#8217;s throw out a quick idea that we have batted around a bit internally. What if Mighty Moose were to be free? What if we were only to charge you for two features inside of the software that are&#160;&#8230; <a href="http://codebetter.com/gregyoung/2012/03/27/charge-for-bad-code/">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 let&#8217;s throw out a quick idea that we have batted around a bit internally. What if Mighty Moose were to be free? What if we were only to charge you for two features inside of the software that are not needed if you are maintaining a decent code base?</p>
<p>The basic idea is if you write good code, you will never need these features and thus Mighty Moose will be free for you (We will even throw in support!). If however you need these two areas you will pay for them.</p>
<p>The two areas in question are the minimizer (the thing that figures out which tests to run) and the cascading + incremental compilation build providers. If your tests are fast and your builds small, mighty moose is painless to use without these features. You would still get graphs, sequence diagrams, all the unit testing frameworks, gary etc. Its just it would build your solution and run &#8220;all&#8221; your tests (you could still use ignore + ignore categories etc)</p>
<p>We could look at this as being similar to a cigarette tax (cost shifting). We provide people with good code the tool for free by charging people who need the features that help them in bad situations. There is also a large support cost difference we have measured (quite similar to smokers using up more medical resources). We would be helping push you towards doing the right thing. We would of course also provide you guidance about how to fix these issues in your system. If however you choose to take the easy way out and have the tool alleviate your pain, there would be a cost associated with that decision.</p>
<p>From a managerial perspective we are also giving you a bit of ammunition. I can make the case very easily as to why these two problems are very expensive within an organization. This would provide setting a cost to one solution that can then be used in further decision making. From an options pricing model perspective we are pricing the option of not resolving the issues now.</p>
<p>I understand that this is a fairly innovative idea and may seem odd to some people at first so I wanted to drop it up here as a RFC to get some feedback.</p>
<div class="shr-publisher-280"></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%2Fgregyoung%2F2012%2F03%2F27%2Fcharge-for-bad-code%2F' data-shr_title='Charge+for+bad+code%3F'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fgregyoung%2F2012%2F03%2F27%2Fcharge-for-bad-code%2F' data-shr_title='Charge+for+bad+code%3F'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fgregyoung%2F2012%2F03%2F27%2Fcharge-for-bad-code%2F' data-shr_title='Charge+for+bad+code%3F'></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/lHKVj-hqhlA" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/gregyoung/2012/03/27/charge-for-bad-code/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
					<feedburner:origLink>http://codebetter.com/gregyoung/2012/03/27/charge-for-bad-code/</feedburner:origLink></item>
	      
    	<item>
		<title>How to make your build faster</title>
		<link>http://feedproxy.google.com/~r/CodeBetter/~3/iRWsPk48tdE/</link>
		<comments>http://codebetter.com/gregyoung/2012/03/26/how-to-make-your-build-faster/#comments</comments>
		<pubDate>Mon, 26 Mar 2012 13:59:43 +0000</pubDate>
		<dc:creator>gregyoung</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Builds]]></category>
		<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Mighty Moose]]></category>
			<guid isPermaLink="false">http://codebetter.com/gregyoung/?p=277</guid>
					<description><![CDATA[I did an informal survey a while ago and the results were frankly abysmal. I cannot understand how people work in such environments. I am ADD, if I have a feedback cycle more than a few seconds I have already&#160;&#8230; <a href="http://codebetter.com/gregyoung/2012/03/26/how-to-make-your-build-faster/">Continue&#160;reading&#160;<span class="meta-nav">&#8594;</span></a>]]></description>
							<content:encoded><![CDATA[<!-- Start Shareaholic LikeButtonSetTop Automatic --><!-- End Shareaholic LikeButtonSetTop Automatic --><p><img src="http://gregfyoung.files.wordpress.com/2012/03/screen-shot-2012-03-26-at-5-47-40-pm.png" alt="Screen Shot 2012 03 26 at 5 47 40 PM" border="0" width="292" height="359" style="float:left" /><br />
I did an <a href="http://goodenoughsoftware.net/2012/02/25/build-times-2/">informal survey a while ago</a> and the results were frankly abysmal. I cannot understand how people work in such environments. I am ADD, if I have a feedback cycle more than a few seconds I have already hit ctrl+right arrow and am reading my email or sitting in twitter. This however has a very serious affect on my work. I am constantly pushing and popping my mental stack of what was going on (more often than not having cache misses as well). The sample size was pretty decent as well with over 700 respondents. </p>
<p>This post is going to look at some ways we can make our build times faster. There are loads of ways aside from buying SSDs. I work in a VM on a non-SSD drive on a laptop and rarely see a build over 5 seconds mostly because I focus very heavily on not having solutions with 20,000 projects in them but there are some other ways as well.</p>
<h3>Project Structures</h3>
<p>To start with we can use smarter project layouts. Patrick Smacchia has some good posts on it:</p>
<p><a href="http://codebetter.com/patricksmacchia/2008/12/08/advices-on-partitioning-code-through-net-assemblies/">Advices on partitioning code through .NET assemblies</a></p>
<p><a href="http://codebetter.com/patricksmacchia/2007/12/16/hints-on-how-to-componentize-existing-code/">Hints on how to componentize existing code<br />
</a></p>
<p>Keeping well factored projects can go a long way and making a larger project will be faster than building many smaller ones (why? as an example they have a tendency of reusing many of the same references etc that need to be loaded repeatedly causing far more i/o).</p>
<h3>Parallel Builds</h3>
<p>These are good reading to start but there are many more options that are available. Let&#8217;s start with one of the comments from Ben &#8220;I think unless you go down the parallel build/test route (like NCrunch) then this issue of build times is not going to go away.&#8221;</p>
<p>What a great selling point. Luckily for builds everyone can already do this. Did you know that Visual Studio and MSBuild already do parallel builds? All you have to do is drop into your configuration and you will see an options screen like the one here </p>
<p><img src="http://gregfyoung.files.wordpress.com/2012/03/screen-shot-2012-03-26-at-4-39-49-pm.png" alt="Screen Shot 2012 03 26 at 4 39 49 PM" border="0" width="600" height="357" /></p>
<p>Put in your max number of cores that you want. Work with msbuild? just use <a href="http://msdn.microsoft.com/en-us/library/ms164311.aspx">/maxcpucount:4</a>. Of course this is still rather limiting as if you have project 1 that references project 2 which references project 3 you are in a serial situation anyways. The maxcpucount represents the number of projects that can be built concurrently (e.g.: providing no dependencies). Both MM and nCrunch support this option as well. This can get your build times to be quicker in some scenarios though I tend to see only a +- 20-25% increase on average.</p>
<h3>Mighty Moose</h3>
<p>We did a quick survey on Mighty Moose users about a week ago and I was amazed to see that very few people were using this feature (about 10% of a survey size +- 100-150 people). Mighty Moose has a smart build system inside of it that is actually much better than what msbuild can do because it has more information. I know dotnetdemon from red gate has something similar to it. </p>
<p>Basically since I know what is changing and I know how that affects the dependency graph I can be much more intelligent with my builds. I also have further knowledge through static analysis about what the affects of that change was (are public contracts changed etc?). Of course its a bit more complicated than this in practice (lots of edge cases) but it can make a huge difference in your build times for your typical builds in your TDD cycle.</p>
<p><iframe width="640" height="360" src="http://www.youtube.com/embed/05Z5sPrGEeo?fs=1&#038;feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p>[youtube: 05Z5sPrGEeo]</p>
<p>You can see the difference in the video above. MSBuild on an incremental build in AutoTest.Net about 4.5 seconds. MM for the same build + locate tests to run + run the tests about 2.5-3 seconds. AutoTest.Net itself is not a tiny piece of code either. It has a reasonable amount of code in it, even the incremental build is doing pretty well when you consider my dev machine is a VM on a non-SSD drive. This is because we have more information than msbuild does as we stay running compared to it running then dying. You can enable the setting on the first screen in config (Build Setup) here. </p>
<p><img src="http://gregfyoung.files.wordpress.com/2012/03/screen-shot-2012-03-26-at-6-17-23-pm.png" alt="Screen Shot 2012 03 26 at 6 17 23 PM" border="0" width="412" height="374" /></p>
<p>Some people have asked if its so much faster why do we make you opt in to using it? There are a few reasons for this. The largest is compatibility mode. Most people do not generally build their projects directly and often have reasons why they don&#8217;t actually build successfully. Building the solution gives the highest level of compatibility with existing VS projects. As such we make you opt in for it, but its worth opting in for!</p>
<div class="shr-publisher-277"></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%2Fgregyoung%2F2012%2F03%2F26%2Fhow-to-make-your-build-faster%2F' data-shr_title='How+to+make+your+build+faster'></a><a class='shareaholic-googleplusone' data-shr_size='medium' data-shr_count='true' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fgregyoung%2F2012%2F03%2F26%2Fhow-to-make-your-build-faster%2F' data-shr_title='How+to+make+your+build+faster'></a><a class='shareaholic-tweetbutton' data-shr_count='none' data-shr_href='http%3A%2F%2Fcodebetter.com%2Fgregyoung%2F2012%2F03%2F26%2Fhow-to-make-your-build-faster%2F' data-shr_title='How+to+make+your+build+faster'></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/iRWsPk48tdE" height="1" width="1"/>]]></content:encoded>
							<wfw:commentRss>http://codebetter.com/gregyoung/2012/03/26/how-to-make-your-build-faster/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
					<feedburner:origLink>http://codebetter.com/gregyoung/2012/03/26/how-to-make-your-build-faster/</feedburner:origLink></item>
	  </channel>
</rss><!-- Dynamic page generated in 3.542 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-05-16 12:17:34 --><!-- Compression = gzip -->

