<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devlicio.us/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Sergio Pereira</title><subtitle type="html">There are no half-solutions because there isn&amp;#39;t half a problem</subtitle><id>http://devlicio.us/blogs/sergio_pereira/atom.aspx</id><link rel="alternate" type="text/html" href="http://devlicio.us/blogs/sergio_pereira/default.aspx" /><link rel="self" type="application/atom+xml" href="http://devlicio.us/blogs/sergio_pereira/atom.aspx" /><generator uri="http://communityserver.org" version="4.1.31106.3070">Community Server</generator><updated>2010-01-19T14:42:00Z</updated><entry><title>Android App From Idea to Market In a Few Hours</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/12/06/android-app-from-idea-to-market-in-a-few-hours.aspx" /><id>/blogs/sergio_pereira/archive/2010/12/06/android-app-from-idea-to-market-in-a-few-hours.aspx</id><published>2010-12-07T04:11:00Z</published><updated>2010-12-07T04:11:00Z</updated><content type="html">&lt;p&gt;I had been playing a little bit with Android development but
  not really worried about creating any useful or commercially 
  viable application yet. I believe I&amp;#39;ll end up creating a handful
  of small apps, some for personal use and some for fun. It will not
  hurt if a fraction of those yield some profit, but that isn&amp;#39;t a
  realistic goal for now.&lt;/p&gt;

  &lt;p&gt;Maybe I&amp;#39;m wrong, but judging from what I&amp;#39;ve done professionally up
  to this date, I think any money that I eventually make with mobile
  apps will come from custom built LOB apps.&lt;/p&gt;

  &lt;p&gt;Nevertheless, the app I&amp;#39;m going to walk us through in this post is
  a free and for-fun project. You can find the complete source code at the bottom.&lt;/p&gt;

  &lt;h3&gt;The Idea&lt;/h3&gt;
	Just the other day on Twitter I was poking fun at  
	&lt;a href="http://geekswithblogs.net/dlussier/Default.aspx"&gt;D&amp;#39;Arcy Lussier&lt;/a&gt;, then
	 &lt;a href="http://www.igloocoder.com"&gt;Don Belcham&lt;/a&gt; came up with a
	 funny comment that triggered this colossal waste of code.

	 &lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.12/android1_5F00_1.png"&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.12/android1_5F00_1_5F00_small.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

	 Fast forward to later that day, the app was ready for download.

	 &lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.12/android1_5F00_2.png"&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.12/android1_5F00_2_5F00_small.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

     &lt;h3&gt;The Lessons&lt;/h3&gt;

	 &lt;p&gt;
		Since this app is really a glorified &lt;i&gt;Hello World&lt;/i&gt; 
		and I had never let any other Android app leave the confines of my emulator, 
		that&amp;#39;s the perspective I&amp;#39;m hoping to share.
	&lt;/p&gt;
	&lt;p&gt;
		I&amp;#39;ll try to show what&amp;#39;s involved from when your first app is ready to fly to when
		it&amp;#39;s finally available for download in the Android Market.
	 &lt;/p&gt;

  &lt;h3&gt;The Prerequisites&lt;/h3&gt;
  &lt;p&gt;
	There are tons of 
	&lt;a href="http://www.barebonescoder.com/2010/04/a-simple-android-splash-screen/"&gt;compentent&lt;/a&gt; 
	&lt;a href="http://www.getsolved.com/mobile/android/google-android-hello-world-with-eclipse/"&gt;introductory&lt;/a&gt; 
	&lt;a href="http://hackaday.com/2010/07/15/android-dev-101-%E2%80%93-part-1hello-world/"&gt;articles&lt;/a&gt; 
	to Android development, and
	I&amp;#39;ll do everybody a favor and not rehash all that here. Suffice to say 
	you can assume I went through some of those articles and have my development machine
	ready to go, with:
  &lt;/p&gt;
	&lt;ul&gt;
		&lt;li&gt;JDK (not just the JRE)&lt;/li&gt;
		&lt;li&gt;Android &lt;a href="http://developer.android.com/sdk/index.html"&gt;SDK&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Eclipse IDE&lt;/li&gt;
		&lt;li&gt;Android Development Tools for Eclipse (&lt;a href="http://developer.android.com/guide/developing/eclipse-adt.html"&gt;ADT&lt;/a&gt;)&lt;/li&gt;
		&lt;li&gt;At least one virtual device (AVD) created (the emulator)&lt;/li&gt;
	&lt;/ul&gt;
	&lt;p&gt;
		As you probably know, you don&amp;#39;t need to use Eclipse but I think it makes
		your life easier if you&amp;#39;re a total Java n00b like myself; most
		of the Android tutorials and Q&amp;amp;A out there refer to Eclipse.
	&lt;/p&gt;
	
  &lt;h3&gt;The Code&lt;/h3&gt;

  &lt;p&gt;In case I haven&amp;#39;t said it enough, this is a very simple application, so 
  I chose to target the lowest SDK version that I could, which in my case is the
  absolute lowest one available: SDK version 3 for Android 1.5 (Cupcake.)&lt;/p&gt;

  &lt;p&gt;To create the blinking 12:00 text I figured the easiest way would
	be to use two separate image files and alternate between them using a
	very basic animation. The animation is 
	&lt;a href="http://developer.android.com/guide/topics/graphics/2d-graphics.html"&gt;preferred 
	over (animated) GIFs&lt;/a&gt;.
  &lt;/p&gt;

  &lt;p&gt;
	Images are embedded in your application as resources, under your project&amp;#39;s
	&lt;code&gt;res/drawable&lt;/code&gt; directory.
  &lt;p&gt;

  	 &lt;p&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.12/android1_5F00_3.png" alt="" /&gt;&lt;/p&gt;

	&lt;p&gt;I used a pair of PNG images with transparent backgrounds. One of them is seen below.&lt;/p&gt;

  	 &lt;p&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.12/android1_5F00_4.png" alt="" /&gt;&lt;/p&gt;

	&lt;p&gt;Animations are defined in another type of resource. They are XML files with
	the animation specification. They support a nice range of &lt;i&gt;tweening&lt;/i&gt; parameters but
	we&amp;#39;ll only need a straight forward frame-by-frame animation. Here&amp;#39;s the &lt;code&gt;clock.xml&lt;/code&gt;
	file that I created inside that same &lt;code&gt;drawable&lt;/code&gt; directory. Note the 
	two image files drawable resource names that are the file names minus the extension.&lt;/p&gt;

	&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;animation-list xmlns:android=&amp;quot;http://schemas.android.com/apk/res/android&amp;quot;
  android:oneshot=&amp;quot;false&amp;quot;&amp;gt;
  &amp;lt;item 
    android:drawable=&amp;quot;@drawable/dashes_red_alpha&amp;quot; 
    android:duration=&amp;quot;500&amp;quot; /&amp;gt;
  &amp;lt;item 
    android:drawable=&amp;quot;@drawable/numbers_red_alpha&amp;quot; 
    android:duration=&amp;quot;500&amp;quot; /&amp;gt;
&amp;lt;/animation-list&amp;gt;&lt;/pre&gt;

	&lt;p&gt;Now we need to make that animation show up in the
	center of the screen. The application has only one
	activity (activities are the Android term for screens, windows, dialogs, etc.)
	That appearance of that screen is defined by the layout file &lt;code&gt;main.xml&lt;/code&gt;, in the
	project&amp;#39;s &lt;code&gt;res/layout&lt;/code&gt; directory. If you&amp;#39;re familiar with other
	XML based GUI layout formats like XAML or XUL (and even XHTML and ASP.NET 
	webforms to some extend,) Android layout syntax is fairly reasonable. The
	sad part is that there isn&amp;#39;t a good editor for them (there are some
	attempts out there but nothing worth praising yet.)&lt;/p&gt;

	&lt;p&gt;Anyway, here&amp;#39;s the layout I used in &lt;code&gt;main.xml&lt;/code&gt;. The animation
	will be displayed by that &lt;code&gt;ImageView&lt;/code&gt; view (views are the individual
	elements or controls like textboxes and buttons, etc.) You can see 
	that the image is centered in the layout (the &lt;code&gt;layout_centerInParent&lt;/code&gt;
	attribute.)&lt;/p&gt;

	&lt;pre name="code" class="xml"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;
&amp;lt;RelativeLayout 
    ...
  &amp;gt;  
  &amp;lt;ImageView android:id=&amp;quot;@+id/digits&amp;quot;
    ...
    android:layout_centerInParent=&amp;quot;true&amp;quot;
    android:background=&amp;quot;@drawable/clock&amp;quot;
    /&amp;gt;  
&amp;lt;/RelativeLayout&amp;gt;&lt;/pre&gt;

	&lt;p&gt;All that&amp;#39;s left now is telling our activity to use the above layout
	and start the animation when the app gains focus (we need to wait until
	the app gets focus otherwise it might be too early to start and it will
	not do anything). The main activity class in this project is called Home, seen
	below&lt;/p&gt;

&lt;pre name="code" class="java"&gt;public class Home extends Activity {
  /* snip */

  @Override
  public void onWindowFocusChanged(boolean hasFocus) {
    AnimationDrawable frameAnimation = 
	  (AnimationDrawable) findViewById(R.id.digits).getBackground();

    if (hasFocus) {
      frameAnimation.start();
    } else {
      frameAnimation.stop();
    }
  }
}&lt;/pre&gt;

	&lt;p&gt;And that&amp;#39;s all there&amp;#39;s to this application. We can start it in the AVD
	emulator and see it in all its blinktastic glory.&lt;/p&gt;

	&lt;p&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.12/android1_5F00_5.gif" alt="" /&gt;&lt;/p&gt;

  &lt;h3&gt;Package it up&lt;/h3&gt;
	
	&lt;p&gt;Having an app running on the emulator or in your own phone is
	nice but it doesn&amp;#39;t make the world a better place. We must push this
	application to the Android Market so everyone can have it.&lt;/p&gt;

	&lt;p&gt;At this point I should be telling you how a responsible developer
	would test his app in different AVDs, maybe different real devices,
	screen orientations, etc. But guess what? No siree, Bob. 
	&amp;lt;sarcasm&amp;gt;In true Android developer fashion,&amp;lt;/sarcasm&amp;gt; we&amp;#39;re 
	going straight to
	the Market and there&amp;#39;s no stopping us.&lt;/p&gt;

	&lt;h4&gt;Build it&lt;/h4&gt;

	&lt;p&gt;The first step in packaging the app is to simply build the release binaries.
	Yo can do that in Eclipse by right-clicking the project in the Package Explorer and
	choosing &lt;i&gt;Android Tools -&amp;gt; Export Unsigned Application Package&lt;/i&gt; and
	choose a directory to save it. You application .apk file will be created there.&lt;/p&gt;

	&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.12/android1_5F00_6.png"&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.12/android1_5F00_6_5F00_small.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

	&lt;h4&gt;Sign it&lt;/h4&gt;

	&lt;p&gt;We can&amp;#39;t simply send that file as-is to the market. To be accepted in the market,
	our application needs to be &lt;i&gt;stamped&lt;/i&gt; with something that tells everyone who
	built it. This is akin to the strong naming keys that are used in .NET.&lt;/p&gt;

	&lt;p&gt;To stamp, or sign, our app we first need to create our own private key and
	certificate, which will live in a &lt;i&gt;keystore&lt;/i&gt; file. If you already have one such file,
	you can obviously use the existing one instead. We can use the &lt;b&gt;keytool.exe&lt;/b&gt;
	utility to do create it. In my box I have keytool in the JDK installation directory, so I&amp;#39;ll 
	run this command (one line):&lt;/p&gt;

	&lt;pre&gt;C:\[JDKHOME]\bin\keytool.exe -genkey -v 
  -keystore your_secret_file.keystore -alias YourAliasHere -keyalg RSA 
  -keysize 2048 -validity 10000&lt;/pre&gt;

	&lt;p&gt;When you run it, it&amp;#39;ll ask you for a few identification parameters for the certificate and
	also a password that you&amp;#39;ll need to remember later. Just like the SN key files in .NET, 
	make sure you keep the produced keystore file in a safe place.&lt;/p&gt;

	&lt;p&gt;Time to use another tool to sign our .apk file with the information
	in the keystore file. Use this command.&lt;/p&gt;

	&lt;pre&gt;C:\[JDKHOME]\bin\jarsigner.exe -keystore 
  your_secret_file.keystore YourApp.apk YourAliasHere&lt;/pre&gt;

	&lt;p&gt;The above command will prompt you for the password again.&lt;/p&gt;

	&lt;h4&gt;Optimize it&lt;/h4&gt;

	&lt;p&gt;The last step in the .apk preparation is an optimization process to realign bytes 
	in the file for faster reads on the device. You&amp;#39;d be surprised to know that there&amp;#39;s
	another tool to do that. Not surprised? I thought so. Here&amp;#39;s the command. You&amp;#39;ll
	find the utility in your Android SDK installation directory. It will write
	the optimized version to another .apk file, which I&amp;#39;m choosing to name with the
	version number 1.0.&lt;/p&gt;

	&lt;pre&gt;C:\[ANDROID_SDK_HOME]\tools\zipalign.exe -v 4 YourApp.apk YourApp_1_0.apk&lt;/pre&gt;

	&lt;p&gt;Now to the market we go.&lt;/p&gt;

	&lt;h3&gt;Publishing an app&lt;/h3&gt;

	&lt;p&gt;The &lt;a href="http://market.android.com/"&gt;Android Market&lt;/a&gt; is 
		where the vast majority of Android users go to find apps for
		their devices. You definitely want to have your application
		listed in there.
	&lt;/p&gt;
	
	&lt;p&gt;In order to upload an app to the market, you&amp;#39;ll need to purchase a
	developer account, which at the time of this writing will cost
	you USD 25.00.&lt;/p&gt;

	&lt;p&gt;We&amp;#39;re almost done here, I promise. Next we only need to logon to
	the market with our newly minted account and upload the application.
	The upload form will ask you for a couple of screenshots, a 512x512
	high-res icon (?) and a bunch of other unsurprising fields.&lt;/p&gt;

	&lt;p&gt;Hit &lt;b&gt;Publish&lt;/b&gt; and pat yourself on the back. You&amp;#39;re officially
	an Android developer. I hope your first app isn&amp;#39;t as lame as mine and
	that I could have helped you go through the process quicker than I.&lt;/p&gt;

  &lt;h3&gt;Money flows in. Oh, wait&lt;/h3&gt;

  &lt;p&gt;Okay, I can&amp;#39;t promise an early retirement to anyone. That&amp;#39;s on you to 
  create the next viral app. But I can leave you with some good examples
  of successful apps.&lt;/p&gt;

  &lt;ul&gt;
	  &lt;li&gt;&lt;a href="http://www.develop-online.net/news/36155/Paper-Toss-dev-makes-500k-per-month-with-ads"&gt;Paper Toss dev makes $500k per month&lt;/a&gt;&lt;/li&gt;
	  &lt;li&gt;&lt;a href="http://www.androidcentral.com/angry-birds-android-expected-generate-1-million-month-video"&gt;Angry Birds for Android expected to generate $1 million per month&lt;/a&gt;&lt;/li&gt;
	  &lt;li&gt;&lt;a href="http://eddiekim.posterous.com/an-android-success-story-13000month-sales-0"&gt;An Android Success Story: $13,000/month App Sales&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3&gt;Source code&lt;/h3&gt;
  &lt;p&gt;Although there isn&amp;#39;t really much to it, you can also download &lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.12/midnight_2D00_flasher_2D00_src.zip"&gt;the
  source code of this app&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=63789" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term="Development" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Development/default.aspx" /><category term="Mobile" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Mobile/default.aspx" /><category term="Android" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Android/default.aspx" /></entry><entry><title>Have you met arguments.callee?</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/09/10/have-you-met-arguments-callee.aspx" /><id>/blogs/sergio_pereira/archive/2010/09/10/have-you-met-arguments-callee.aspx</id><published>2010-09-10T23:36:00Z</published><updated>2010-09-10T23:36:00Z</updated><content type="html">&lt;p&gt;
  Just the other day I had a need to use &lt;code&gt;arguments.callee&lt;/code&gt; and I realized that&amp;#39;s
  not something you really see every day in JavaScript. Maybe I could talk about it a bit.
 &lt;/p&gt;

 &lt;h3&gt;Anonymous functions everywhere&lt;/h3&gt;
 &lt;p&gt;
  It&amp;#39;s not news to anyone reading this blog that one of JavaScript&amp;#39;s workhorses are
  anonymous functions. Callbacks, strategies, deferred execution, event handlers, etc. 
  They just seem to be all over the place &amp;mdash; and for a good reason; they can
  be convenient and reduce the pollution of a bunch functions that are only called
  from a single spot. 
 &lt;/p&gt;
 &lt;p&gt;
  Another nice thing is that, once your eyes are trained to ignore the little bit
  of noise that they add to the code, the code is really readable and, dare I
  say it, expressive.
 &lt;/p&gt;

 &lt;h3&gt;Yet another contrived example&lt;/h3&gt;
 &lt;p&gt;
  Let&amp;#39;s say we are really into reinventing the wheel and with our understanding
  of anonymous functions we create a revolutionary &lt;code&gt;map&lt;/code&gt; function:

 &lt;/p&gt; 

 &lt;pre name="code" class="js:nogutter"&gt;function map(array, compute){
  var result = [ ];
  for(var i=0; i &amp;lt; array.length; i++){
    result.push( compute(array[i]) );
  }
  return result;
}&lt;/pre&gt;

&lt;p&gt;
	This function, as you can hopefully see, transforms each element of
	the given array into something else and returns the array of the
	transformed elements. Two simple uses are shown below.
&lt;/p&gt;

 &lt;pre name="code" class="js:nogutter"&gt;//apply discount
var prices = [1, 2, 3, 4];
var discount = 0.1; // 10% off today, w00t!
var newPrices = map(prices, function(price){ return (1-discount)*price; } );
//==&amp;gt; [0.9, 1.8, 2.7, 3.6]

//compute areas
var squareSides = [1, 2, 3, 4];
var squareAreas = map(squareSides, function(side){ return side*side; } );
//==&amp;gt; [1, 4, 9, 16]&lt;/pre&gt;

&lt;p&gt;I warned you the examples would be contrived, didn&amp;#39;t I?&lt;/p&gt;

&lt;p&gt;
	Now your product manager comes and asks for a page where the users
	can enter a list of numbers and get the factorials for each of them.
	You immediately think your friend the &lt;code&gt;map&lt;/code&gt; function will
	save the day. You start and...
&lt;/p&gt;

 &lt;pre name="code" class="js:nogutter"&gt;//return the factorials
var userNumbers = [1, 2, 3, 4];
var factorials = map(userNumbers, function(number){ 
  if(number &amp;lt;= 1) { return 1; }
  return number * ????????(number - 1); // ooops! I need to recurse here.
} );&lt;/pre&gt;

 &lt;p&gt;You see, there&amp;#39;s this thing with anonymous functions. 
 &lt;b&gt;They don&amp;#39;t have a name&lt;/b&gt;, d&amp;#39;oh. As I said in the beginning, we
 typically use them in situations where they are called only once so
 we can inline them and forego the need fora name. But now we&amp;#39;re kind of
 wishing they had a name. 

 &lt;h3&gt;Anonymity won&amp;#39;t hide you from me&lt;/h3&gt;
 &lt;p&gt;
	Well, if the post tittle didn&amp;#39;t already give it away, we can achieve that
	with 
	&lt;a href="https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments/callee"&gt;&lt;code&gt;arguments.callee&lt;/code&gt;&lt;/a&gt;. Using &lt;code&gt;arguments.callee&lt;/code&gt; inside a function gives 
	us a reference to the function itself. So now we can finish our code.
 &lt;/p&gt;
 &lt;pre name="code" class="js:nogutter"&gt;//return the factorials
var userNumbers = [1, 2, 3, 4];
var factorials = map(userNumbers, function(number){ 
  if(number &amp;lt;= 1) { return 1; }
  return number * arguments.callee(number - 1);
  //or if you were using &amp;quot;this&amp;quot; in the function you&amp;#39;ll probably want to:
  // return number * arguments.callee.apply(this, [number - 1]);
} );
//==&amp;gt; [1, 2, 6, 24]&lt;/pre&gt;

&lt;h3&gt;A more real world scenario&lt;/h3&gt;
&lt;p&gt;
I won&amp;#39;t leave you without at least a reference to a real use
case for this feature. The example I&amp;#39;ll show comes
from &lt;a href="http://www.nczonline.net/"&gt;Nicholas Zakas&lt;/a&gt;. In
&lt;a href="http://www.nczonline.net/blog/2009/08/11/timed-array-processing-in-javascript/"&gt;a blog post a while ago&lt;/a&gt; he showed how we can
break up long running tasks with smaller timed/deferred chunks,
improving the browser&amp;#39;s responsiveness.
&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s the function from his blog post, which process chunks of
an array for 50ms, then stops and call itself back to process
the remaining items soon after that &amp;mdash; giving the browser
a chance to breathe and take care of its interaction with the 
user&lt;p&gt;

&lt;pre name="code" class="js:nogutter"&gt;//Copyright 2009 Nicholas C. Zakas. All rights reserved.
//MIT Licensed
function timedChunk(items, process, context, callback){
   var todo = items.concat();   //create a clone of the original

  setTimeout(function(){

    var start = +new Date();

    do {
       process.call(context, todo.shift());
    } while (todo.length &amp;gt; 0 &amp;amp;&amp;amp; (+new Date() - start &amp;lt; 50));

    if (todo.length &amp;gt; 0){
      setTimeout(arguments.callee, 25);
    } else {
      callback(items);
    }
  }, 25);
}&lt;/pre&gt;

 &lt;p&gt;I hope this shows you a little new trick.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=62061" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term="Tips-and-Tricks" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Tips-and-Tricks/default.aspx" /><category term="JavaScript" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/JavaScript/default.aspx" /><category term="JavaScript-Demystified" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/JavaScript-Demystified/default.aspx" /></entry><entry><title>Chrome Extension Development</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/06/28/chrome-extension-development.aspx" /><id>/blogs/sergio_pereira/archive/2010/06/28/chrome-extension-development.aspx</id><published>2010-06-29T03:20:00Z</published><updated>2010-06-29T03:20:00Z</updated><content type="html">&lt;p&gt;Do you like JavaScript? Have you been looking for a reaon or an idea to learn and start using
HTML5? Google Chrome extesions are a great way to get into HTML5 and all its new APIs
with bite sized applications.&lt;/p&gt;

&lt;h3&gt;Anatomy of a Chrome Extension&lt;/h3&gt;

&lt;p&gt;A Chrome extesion is nothing more than a tiny website that runs hosted inside Chrome. Like
any website, it consists of regular web components. Grossly simplifying it is just a directory
full of files, such as JavaScript, CSS, images, HTML5, and anything else you usually add to
a web page.&lt;/p&gt;

&lt;p&gt;Because it runs inside the browser, you have access to things like browser events, browsing
history, and open tabs.&lt;/p&gt;

&lt;p&gt;Essentially, your extension gets loaded as an HTML page called &lt;b&gt;background.html&lt;/b&gt; where
you can put any common/global functions and variables. This page is never visible and
even if you don&amp;#39;t provide a background.html in your extension, Chrome will load an
empty one for you. All other pages in your extension can access the background page&amp;#39;s
functions.&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s a diagram of a common scenario.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.06/chrome_2D00_ext_2D00_diag1.png" border="0" alt="" /&gt;&lt;/p&gt;

&lt;h3&gt;Today&amp;#39;s Brew&lt;/h3&gt;

&lt;p&gt;Our sample extension will be something simple but that at the same time
will let us explore interesting aspects of extensions development, namely
local storage and cross-domain requests.&lt;/p&gt;

&lt;p&gt;The sample is also a hat tip to the valuable work &lt;a href="http://twitter.com/calcock"&gt;Chris Alcock&lt;/a&gt; does
with his &lt;a href="http://themorningbrew.net/"&gt;The Morning Brew&lt;/a&gt;, collecting some of the best links for all of us.&lt;/p&gt;

&lt;p&gt;What we will do here is create an extension that will show us his latests links at the click of a button.&lt;/p&gt;

&lt;h3&gt;Introduce yourself&lt;/h3&gt;

&lt;p&gt;The extension needs to inform Chrome a few details about itself, such as name, default icons, along with any 
permissions it requests to access privileged browser features. This is done through the &lt;b&gt;manifest file&lt;/b&gt;, which is
just a JSON document. Here&amp;#39;s our manifest file, aptly named &lt;b&gt;manifest.json&lt;/b&gt;.&lt;/p&gt;

&lt;pre name="code" class="js"&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;Today&amp;#39;s Brew&amp;quot;,
  &amp;quot;version&amp;quot;: &amp;quot;1.0&amp;quot;,
  &amp;quot;description&amp;quot;: &amp;quot;Latest links from The Morning Brew.&amp;quot;,
  &amp;quot;icons&amp;quot;: { 
    &amp;quot;48&amp;quot;: &amp;quot;icon48.png&amp;quot;,
    &amp;quot;128&amp;quot;: &amp;quot;icon128.png&amp;quot; 
  },
  &amp;quot;browser_action&amp;quot;: {
    &amp;quot;default_icon&amp;quot;: &amp;quot;icon.png&amp;quot;,
    &amp;quot;default_popup&amp;quot;: &amp;quot;popup.html&amp;quot;
  },
  &amp;quot;permissions&amp;quot;: [
    &amp;quot;http://feeds.feedburner.com/&amp;quot;,
    &amp;quot;tabs&amp;quot;
  ]
}&lt;/pre&gt;

&lt;h3&gt;What you can do&lt;/h3&gt;

&lt;p&gt;Extensions can perform several different jobs, like showing notifications, providing new themes, changing
some of the default Chrome pages, etc. One other thing they can do are the browser actions, which basically 
means adding a button to the toolbar that acts independent of what page is being shown, as if it were
just another browser feature.&lt;/p&gt;

&lt;p&gt;If you look at our manifest file you&amp;#39;ll notice we declared a &lt;b&gt;browser_action&lt;/b&gt;, with its icon and the page it
opens wen clicked. &lt;/p&gt;

&lt;p&gt;Our extension does not have a custom background page, we will just rely on the default one Chrome will
give us and put all of our logic in the popup page that we will open.&lt;/p&gt;

&lt;h3&gt;What you need to do that&lt;/h3&gt;


&lt;p&gt;Here&amp;#39;s how our extension will look like when we&amp;#39;re done.
&lt;/p&gt;
&lt;p&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.06/todaysbrew.png" border="0" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;In our extension, other than manipulating our own extension&amp;#39;s HTML dynamically (which doesn&amp;#39;t require
any special permissions) we will need to fetch the RSS feed from Feedburner and eventually open
new tabs as the user clicks on the links.&lt;/p&gt;

&lt;p&gt;That&amp;#39;s what you can see in the &lt;b&gt;permissions&lt;/b&gt; section of the manifest file above.
&lt;/p&gt;
&lt;h3&gt;Getting down to business&lt;/h3&gt;

&lt;p&gt;To create our extension we start by creating an empty directory and adding our manifest.json file and all
the icon image files that we mentioned in that manifest file.&lt;/p&gt;

&lt;p&gt;Then we create our popup.html file, which will be pretty empty and will be populated with
the content we will retrieve from the RSS feed. Here&amp;#39;s that file.&lt;/p&gt;

&lt;pre name="code" class="html:nogutter"&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;popup.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;div id=&amp;quot;main&amp;quot;&amp;gt;
  &amp;lt;h1&amp;gt;&amp;lt;/h1&amp;gt;
  &amp;lt;div id=&amp;quot;content&amp;quot;&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/pre&gt;

&lt;p&gt;As you can see, we will be using jQuery so we should also add that file to our directory. We will
leave all the beautification of the popup in the popup.css file, which I won&amp;#39;t bother showing here;
you can download it along with the rest of the code at the end of this article.&lt;/p&gt;

&lt;p&gt;The other file referenced by the HTML is popup.js. That&amp;#39;s where all the action happens.
&lt;/p&gt;


&lt;pre name="code" class="js"&gt;$(document).ready(function(){
  SERGIOPEREIRA.samples.todaysBrew.init();
});

var SERGIOPEREIRA = {
  samples: {
    todaysBrew: {
      state: { },
      feedUrl: &amp;#39;http://feeds.feedburner.com/ReflectivePerspective?format=xml&amp;#39;,
      todaysUrl: &amp;#39;&amp;#39;,
      maxAgeHours: 12, // keep it for 12 hours
      
      init: function(){
        $(&amp;#39;#content h3&amp;#39;).live(&amp;#39;click&amp;#39;, function(){
          $(&amp;#39;#content ul:visible&amp;#39;).slideUp();
          $(this).next().slideToggle();
        });

        $(&amp;#39;#content li a&amp;#39;).live(&amp;#39;click&amp;#39;, function(){
          $(&amp;#39;#content ul:visible&amp;#39;).slideUp();
          chrome.tabs.create({url: this.href});
        });

        $(&amp;#39;h1&amp;#39;).click(function(){
          chrome.tabs.create({url: SERGIOPEREIRA.samples.todaysBrew.todaysUrl});
        });
        
        if(typeof chrome != &amp;#39;undefined&amp;#39;) {
          this.state = localStorage.getItem(&amp;#39;latestBrew&amp;#39;);

          if(this.state){
            var now = new Date();
            var minTimestamp = new Date();
            minTimestamp.setHours(minTimestamp.getHours() - this.maxAgeHours);
            minTimestamp = minTimestamp.toJSON();

            if(this.state.timestamp &amp;gt; minTimestamp) {
              this.renderLatest(this.state.latestData);
              return;
            }
          }
          this.refresh();
        }
      },
      refresh: function(){
        console.log(&amp;#39;will get feed data...&amp;#39;);
        $.get(this.feedUrl, function(xml, status, xhr){
          SERGIOPEREIRA.samples.todaysBrew.update(xml);
        });
      },
      update: function(feedXml) {
        var latest = this.getFirstItem(feedXml);
        this.state = { };
        this.state.latestData = latest;
        this.state.timestamp = new Date();
        localStorage[&amp;#39;latestBrew&amp;#39;] = JSON.stringify(this.state);
        this.renderLatest(latest);
      },
      renderLatest: function(latest){
        $(&amp;#39;#main&amp;gt;h1&amp;#39;).text(latest.title);
        $(&amp;#39;#content&amp;#39;).html(latest.content);
        this.todaysUrl = latest.url;
      },      
      getFirstItem: function(feedXml){
        var items = feedXml.evaluate(&amp;quot;//channel/item&amp;quot;, feedXml, 
                                 null, XPathResult.ANY_TYPE, null); 

        var item = items.iterateNext(); 
        if (item) {
          return this.createItem(item);
        }
      },      
      createItem: function(postXml) {
        return { 
          title: this.readElementText(postXml, &amp;#39;title&amp;#39;),
          url: this.readElementText(postXml, &amp;#39;feedburner:origLink&amp;#39;),
          content: this.readElementText(postXml, &amp;#39;content:encoded&amp;#39;)
        };
      },
      mapElements: function(contextElement, path, map){
        var result = [ ];
        var items = contextElement.ownerDocument.evaluate(path, contextElement, 
                                this.namespaceResolver, XPathResult.ANY_TYPE, null); 
        
        var item = items.iterateNext(); 
        var i = 0;
        while (item) {
          result.push( map(item, i++) );
          item = items.iterateNext();
        }

        return result;
      },      
      readElementText: function(contextElement, path){
        var results = contextElement.ownerDocument.evaluate(path, contextElement, 
                                   this.namespaceResolver, XPathResult.ANY_TYPE, null); 
        var first = results.iterateNext(); 

        if (first) {
          return first.textContent;
        }
      },      
      namespaceResolver: function(prefix) {
        if(prefix == &amp;#39;content&amp;#39;) {
          return &amp;#39;http://purl.org/rss/1.0/modules/content/&amp;#39;;
        }
        if(prefix == &amp;#39;feedburner&amp;#39;) {
          return &amp;#39;http://rssnamespace.org/feedburner/ext/1.0&amp;#39;;
        }
      }

    }
  }
};&lt;/pre&gt;

&lt;p&gt;Wow, that&amp;#39;s a lot of JavaScript at once, right? Hopefully you&amp;#39;ll notice that most of it is just
to parse the RSS xml.&lt;/p&gt;

&lt;p&gt;Only a few parts of this code deserve commentary. The &lt;code&gt;refresh&lt;/code&gt; method (line 45) is the one
that retrieves the RSS data. It uses the &lt;code&gt;jQuery.get&lt;/code&gt; method to do so. Once the data arrives, it will
invoke &lt;code&gt;update&lt;/code&gt;, which will use the parsing methods to get an object representing the latest
news item in the data. &lt;/p&gt;

&lt;pre name="code" class="js:nogutter"&gt;      update: function(feedXml) {
        var latest = this.getFirstItem(feedXml);
        this.state = { };
        this.state.latestData = latest;
        this.state.timestamp = new Date();
        localStorage[&amp;#39;latestBrew&amp;#39;] = JSON.stringify(this.state);
        this.renderLatest(latest);
      },&lt;/pre&gt;

&lt;p&gt;The above code also shows the use of two important APIs that Chrome implements. The
&lt;code&gt;localStorage&lt;/code&gt; is a way to persist information that lives in the client 
machine and lasts even after the browser closes. We use it to remeber our last
results and avoid fetching and parsing the RSS each time the popup is opened.&lt;/p&gt;

&lt;p&gt;The other API is the native &lt;code&gt;JSON&lt;/code&gt; object that can replace any dedicated
library we are used to have in cross-browser websites. We need to &lt;code&gt;stringify&lt;/code&gt;
the data because we can only save strings in the local storage.&lt;/p&gt;

&lt;p&gt;With the parsed data at hand we just need to replace the content in those empty html
tags in popup.html with the information we have.&lt;/p&gt;

&lt;h3&gt;Adding some life with events&lt;/h3&gt;

&lt;p&gt;The last piece of this puzzle are the jQuery event handlers that we created in the 
&lt;code&gt;init&lt;/code&gt; method. They make some of the elements clickable, including the
links, which open new tabs using &lt;code&gt;chrome.tabs.create()&lt;/code&gt;. Also note starting on line 
29 that if we find recent local data we use that instead of refreshing 
the content from the RSS feed.&lt;/p&gt;

&lt;h3&gt;Let&amp;#39;s load this thing up&lt;/h3&gt;

&lt;p&gt;Now we just need to run it and see how it goes. Go to the extesions page, expand
the &lt;i&gt;Developer Mode&lt;/i&gt; area and click &lt;i&gt;Load unpacked extension...&lt;/i&gt;. &lt;/p&gt;

&lt;p&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.06/loadext.png" border="0" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;Then simply browse to your extension&amp;#39;s directory and select it. The extension should now be listed
as seen below.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.06/loadedext.png" border="0" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;While you&amp;#39;re developing your extension you can debug it using the developer tools
included in Chrome. To do that, right click the extension button and select 
&lt;i&gt;Inspect popup&lt;/i&gt;.&lt;/p&gt;

&lt;p&gt;You can &lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.06/todaysbrew.zip"&gt;download&lt;/a&gt; 
the code for this extension and play with it all you want. I&amp;#39;m still early into learning this 
so feel free to give me pointers or ask questions.
&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=60801" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term="JavaScript" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/JavaScript/default.aspx" /><category term="jQuery" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/jQuery/default.aspx" /><category term="HTML5" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/HTML5/default.aspx" /></entry><entry><title>More on blocked files</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/06/23/more-on-blocked-files.aspx" /><id>/blogs/sergio_pereira/archive/2010/06/23/more-on-blocked-files.aspx</id><published>2010-06-24T03:26:00Z</published><updated>2010-06-24T03:26:00Z</updated><content type="html">&lt;p&gt;I&amp;#39;ve &lt;a href="http://devlicio.us/blogs/sergio_pereira/archive/2009/04/03/blocked-js-files-keep-biting-me.aspx"&gt;written about this&lt;/a&gt; before.
You download a file to use in your web application, like a JavaScript library or an image file
but the browser just can&amp;#39;t seem to load it. You spend hours looking for a typo or broken link
until you find out about that Unblock button and you realize that it&amp;#39;s IIS that isn&amp;#39;t serving 
the file. The file had been there; you had the correct URL all along; it&amp;#39;s just disallowed.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2008.04/properties_5F00_js.png"&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2008.04/properties_5F00_js_5F00_small.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I actually developed the reflex to right click and unblock each an every file I
download now. It&amp;#39;s stupid, isn&amp;#39;t it? I should have imagined there was a way to 
disable that Windows feature instead of just learning how to live with the problem.
&lt;/p&gt;
&lt;p&gt;Well, no more. Here&amp;#39;s how you can disable it. Credit goes to &lt;a href="http://www.petri.co.il/unblock-files-windows-vista.htm"&gt;this article&lt;/a&gt;.
&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Run &lt;b&gt;gpedit.msc&lt;/b&gt; (the group policy editor)&lt;/li&gt;
	&lt;li&gt;Go to &lt;b&gt;User Configuration/Administrative Templates/Windows Components/Attachment Manager&lt;/b&gt;&lt;/li&gt;
	&lt;li&gt;Find the setting named &lt;b&gt;Do not preserve zone information in file attachments&lt;/b&gt; and &lt;b&gt;enable&lt;/b&gt; it&lt;/li&gt;
	&lt;li&gt;Log off then log back on, or update the current policies with: &lt;b&gt;Gpupdate /force&lt;/b&gt; in any command prompt.
&lt;/ul&gt;

&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.06/unblock.png"&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.06/unblock_2D00_small.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Note:&lt;/b&gt; If you&amp;#39;re using Chrome it looks like &lt;a href="http://codereview.chromium.org/590001"&gt;there&amp;#39;s some bug&lt;/a&gt; that may or may not be
taken care of as you read this. Chrome doesn&amp;#39;t seem to honor the policy setting and always mark the downloaded files as unsafe.&lt;/p&gt;

&lt;p&gt;Now I just need to add this to the list of tasks anytime I get a new machine or repave one of them.&lt;/p&gt;

&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=60722" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term="Development" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Development/default.aspx" /><category term="Tips-and-Tricks" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Tips-and-Tricks/default.aspx" /></entry><entry><title>The Ground is Shaking Again. Get Mobile.</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/06/17/the-ground-is-shaking-again-get-mobile.aspx" /><id>/blogs/sergio_pereira/archive/2010/06/17/the-ground-is-shaking-again-get-mobile.aspx</id><published>2010-06-17T05:08:00Z</published><updated>2010-06-17T05:08:00Z</updated><content type="html">&lt;p&gt;A little over two years ago I commented how surprising it was that
&lt;a href="http://devlicio.us/blogs/sergio_pereira/archive/2008/05/18/and-the-winner-is-vb-net.aspx"&gt;VisualBasic 
was still more popular than C#&lt;/a&gt; in the .Net world. Back 
then I checked the &lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;TIOBE Index&lt;/a&gt; 
and saw that VB (in all its flavors) enjoyed almost 11% of relevance 
while C# wasn&amp;#39;t even at the 4% level.&lt;/p&gt;

&lt;p&gt;When we look at the June 2010 rank below we see that C# has finally
caught up with VB, and it&amp;#39;s safe to say C# is now the
most popular .Net language (remember, the VB index is not made up of just VB.NET.)&lt;/p&gt;

&lt;table&gt;
&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;Java&lt;/td&gt;&lt;td&gt;18.03%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:18.03%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;C&lt;/td&gt;&lt;td&gt;17.81%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:17.81%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;C++&lt;/td&gt;&lt;td&gt;10.76%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:10.76%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;PHP&lt;/td&gt;&lt;td&gt;8.93%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:8.93%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;(Visual) Basic&lt;/td&gt;&lt;td&gt;5.87%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:5.87%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;C#&lt;/td&gt;&lt;td&gt;5.20%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:5.20%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;7&lt;/td&gt;&lt;td&gt;Python&lt;/td&gt;&lt;td&gt;4.27%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:4.27%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;8&lt;/td&gt;&lt;td&gt;Perl&lt;/td&gt;&lt;td&gt;3.20%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:3.20%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;9&lt;/td&gt;&lt;td&gt;Objective-C&lt;/td&gt;&lt;td&gt;2.47%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:2.47%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;Delphi&lt;/td&gt;&lt;td&gt;2.39%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:2.39%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;11&lt;/td&gt;&lt;td&gt;JavaScript&lt;/td&gt;&lt;td&gt;2.19%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:2.19%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;12&lt;/td&gt;&lt;td&gt;Ruby&lt;/td&gt;&lt;td&gt;2.07%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:2.07%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;13&lt;/td&gt;&lt;td&gt;PL/SQL&lt;/td&gt;&lt;td&gt;0.79%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:0.79%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;14&lt;/td&gt;&lt;td&gt;SAS&lt;/td&gt;&lt;td&gt;0.70%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:0.70%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;15&lt;/td&gt;&lt;td&gt;Pascal&lt;/td&gt;&lt;td&gt;0.70%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:0.70%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;16&lt;/td&gt;&lt;td&gt;Lisp/Scheme/Clojure&lt;/td&gt;&lt;td&gt;0.65%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:0.65%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;17&lt;/td&gt;&lt;td&gt;Lua&lt;/td&gt;&lt;td&gt;0.59%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:0.59%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;18&lt;/td&gt;&lt;td&gt;MATLAB&lt;/td&gt;&lt;td&gt;0.59%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:0.59%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;19&lt;/td&gt;&lt;td&gt;ABAP&lt;/td&gt;&lt;td&gt;0.58%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:0.58%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;tr&gt;&lt;td&gt;20&lt;/td&gt;&lt;td&gt;PowerShell&lt;/td&gt;&lt;td&gt;0.53%&lt;/td&gt;&lt;td style="width:300px;"&gt;&lt;div style="background-color:blue;width:0.53%;"&gt;&amp;nbsp;&lt;/div&gt;&lt;/td&gt;
&lt;/table&gt;

&lt;p&gt;Again, anyone can debate the importance of this ranking system, but at least it
has been there for a while and to me it seems to represent the
pulse of software development quite well.&lt;/p&gt;

&lt;h3&gt;Movers and shakers&lt;/h3&gt;

&lt;p&gt;But this post is not about C# vs. VB.NET.&lt;/p&gt;

&lt;p&gt;This time around what caught my attention was the &lt;b&gt;impressive
rise of  Objective-C&lt;/b&gt; (up 36 positions in one year). Now,
no matter how more common Macs have become in the last few years,
no one will convince me this increase in Objective-C is due to
native OSX application development :)&lt;/p&gt;

&lt;p&gt;Of course we all know it&amp;#39;s caused by the surge in mobile and device app
development (iPhone, iPad, and anything that they decide will
run the iOS, like the AppleTV in the future, who knows?)&lt;/p&gt;

&lt;p&gt;If you look at the trending chart on the 
&lt;a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;TIOBE page&lt;/a&gt;
you&amp;#39;ll see that Objective-C started to gain significant steam around June of
last year, coincidentally (maybe not?) when the iPhone 3GS was announced.&lt;/p&gt; 

&lt;h3&gt;Keep your eyes on the ball&lt;/h3&gt; 

&lt;p&gt;Are you playing with Mobile yet? Have you:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Started reading about mobile development?&lt;/li&gt;
&lt;li&gt;Developed a Mobile web site?&lt;/li&gt;
&lt;li&gt;Written and tested a native app against a device emulator/VM (iPhone, Android, WebOS, WP7)?&lt;/li&gt;
&lt;li&gt;Written and deployed an app to your own mobile device?&lt;/li&gt;
&lt;li&gt;Published an app on the market?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It&amp;#39;s not like you will find yourself out of a job if you don&amp;#39;t get into mobile
but for many developers, from software shops to corporate environments, sooner
or later a request for a mobile product or a mobile version of an existing
one will swing by your desk.&lt;/p&gt;

&lt;p&gt;It&amp;#39;s an exciting time. Once again you have the chance of taking the lead
and play an important role in your team by staying ahead of the game. 
Remember when you started seeing request for Ajax and fancy UI&amp;#39;s in
your web applications. Remember how you were one of the few that
knew anything about it in your team? Same thing here. Only much bigger.&lt;/p&gt;

&lt;h3&gt;What I&amp;#39;m looking into&lt;/h3&gt;

&lt;p&gt;There are two different fronts that interest me in mobile development: 
Native Android apps and Mobile Sites. I&amp;#39;ll explain.&lt;/p&gt;

&lt;p&gt;The time I spent in Objective-C and XCode in the past was enough for
me to know I&amp;#39;d be grinding my teeth and blowing off steam every single
day if I wanted to develop for the iPhone (it&amp;#39;s probably just me, I can live with that admission.)
Besides, I don&amp;#39;t like the idea of an approval process before I can give away or sell my apps.&lt;/p&gt;

&lt;p&gt;Windows Phone is something that I&amp;#39;ll have to wait more and see what
kind of traction it gains. It also has the approval process issue. The
big plus will be the development tools, which I think will better than
iPhone and Android.&lt;/p&gt;

&lt;p&gt;All that, combined with the enormous momentum that Android has, made
me start coding for Android when it comes to native apps.&lt;/p&gt;

&lt;h3&gt;Don&amp;#39;t forget Mobile Web&lt;/h3&gt;

&lt;p&gt;Native mobile development is fun and rewarding but let&amp;#39;s not kid ourselves.
History shows that businesses will favor the simplicity of web development.&lt;/p&gt;

&lt;p&gt;I went through that transition period when custom desktop application
development quickly lost market to web applications. And that happened
in a world where Windows was virtually in every workstation that mattered.&lt;/p&gt;

&lt;p&gt;Now imagine the mobile scene, where there&amp;#39;s more than one big player, none
equivalent to what Windows was back in 1998. Do you really think anyone
will want incur the cost of maintaining 3 or 4 different native 
versions of each mobile application that we will start cranking out
like we do web apps today? Native apps will probably be the minority,
for environments where you have the luxury of dictating your end-user&amp;#39;s
choice of mobile device.&lt;/p&gt;

&lt;p&gt;Didn&amp;#39;t we just spend the better part of the last 10 years trying to get out of 
a certain single-browser paradigm? Do we want to repeat that mistake?&lt;/p&gt;

&lt;h3&gt;Moving to HTML5&lt;/h3&gt;

&lt;p&gt;Why is HTML5 so important in Mobile and not as much in the standard Web yet? Well,
for one there is a greater percentage of HTML5-capable browsers in Mobile
than on the desktop browsers. Android, iPhone, WebOS (and soon BlackBerries) 
have WebKit browsers. &lt;/p&gt;

&lt;p&gt;With things like richer forms, offline support, canvas, video and the
Geo-Location API (not really HTML5 but present in those WebKit browsers) we
can build really capable mobile web apps. Not just small screen
versions of the regular web apps.&lt;/p&gt;

&lt;p&gt;To be very straight forward about it, the way I personally see it is
that HTML5 is where the bulk of the mobile development will happen in the Enterprise and
consumer-facing applications.&lt;/p&gt;

&lt;p&gt;Maybe something like Flash, AIR, or Silverlight makes a run for their
mobile money too but with all the bullying from Apple and diverging
opinions everywhere, that&amp;#39;s not something I&amp;#39;m spending time on right now.&lt;/p&gt;

&lt;h3&gt;Native or Web?&lt;/h3&gt;

&lt;p&gt;Both. But definitely much more of the Web kind.
&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=60619" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term="Development" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Development/default.aspx" /><category term="Mobile" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Mobile/default.aspx" /><category term="Android" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Android/default.aspx" /><category term="HTML5" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/HTML5/default.aspx" /></entry><entry><title>Events do not a community make</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/06/15/events-do-not-a-community-make.aspx" /><id>/blogs/sergio_pereira/archive/2010/06/15/events-do-not-a-community-make.aspx</id><published>2010-06-15T13:17:00Z</published><updated>2010-06-15T13:17:00Z</updated><content type="html">&lt;p&gt;It&amp;#39;s a recurring theme. The relationship between the .Net developers community,
the community leaders, Microsoft products, and Microsoft itself is an endless debate.&lt;/p&gt;

&lt;p&gt;These last couple of weeks I&amp;#39;ve seen it come back again, strong, with the usual
rants, departure notices, and rebuttals (which are getting fewer and further between).&lt;/p&gt;

&lt;h3&gt;The Microsoft .Net User Group Leaders&lt;/h3&gt;

&lt;p&gt;I run a small &lt;a href="http://chicagoalt.net"&gt;.Net UG in Chicago&lt;/a&gt; and when I have a chance to talk with other
user group organizers, no matter how truly dedicated and valuable they are, 
I invariably come to the same sad conclusion.&lt;/p&gt;

&lt;p&gt;The majority of the UG&amp;#39;s act as mere outlets for showing off introductory
talks on whatever is the shiny new technology from Microsoft. I wonder 
if all user groups have a clear (or even unclear) mission statement.&lt;/p&gt;

&lt;p&gt;There&amp;#39;s nothing intrinsically wrong with providing 100-level content about new products. 
The problem I see is that this doesn&amp;#39;t really contribute much to build any kind of community
and we can&amp;#39;t make our UGs be restricted to just that.&lt;/p&gt;

&lt;p&gt;In many UGs there&amp;#39;s a lot of emphasis put in &amp;quot;Microsoft&amp;quot; and &amp;quot;.Net&amp;quot; but almost none 
in &amp;quot;User&amp;quot; or &amp;quot;Group.&amp;quot; I think this is completely backwards. The UG leaders should
have their focus on their members 100% of the time, thinking how the UG can be
used to truly benefit their members, making all of us &lt;i&gt;better developers&lt;/i&gt;, not just 
&lt;i&gt;better .Net developers&lt;/i&gt; (Microsoft or ALT) and much less &lt;i&gt;better MS developers&lt;/i&gt;.&lt;/p&gt;

&lt;h3&gt;The .Net Developer Community&lt;/h3&gt;

&lt;p&gt;We all know this community isn&amp;#39;t exactly like other developer communities. I&amp;#39;d even
go out on a limb and say that the use of the word &lt;i&gt;community&lt;/i&gt; is a bit of a stretch,
it&amp;#39;s more like a &lt;i&gt;demographic&lt;/i&gt;.&lt;/p&gt;

&lt;p&gt;We grew up simply waiting what comes out of One Microsoft Way and attended MS-produced events 
and conferences. I think there are very few occurrences of organically formed community 
manifestations in .Net, like the Code Camps and ALT.NET.&lt;/p&gt;

&lt;p&gt;That&amp;#39;s something that can&amp;#39;t be changed by just talking about it. As community members there
are things we could do.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Look for developer events even if you weren&amp;#39;t forwarded one of those MSDN emails (there&amp;#39;s Community Megaphone, Meetup, EventBrite, just to name a few).&lt;/li&gt;
&lt;li&gt;Attend non-MS user group meetings. Seriously. If you&amp;#39;re a web developer, look for a JavaScript or Flash UG. If you&amp;#39;re curious about the Windows Phone, check out the iPhone and Android users groups too. There&amp;#39;s a lot to learn and much networking to be done.&lt;/li&gt;
&lt;li&gt;Attend Code Camps, even if costs you a small road trip. There&amp;#39;s no way you&amp;#39;ll ever regret doing this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will only be a community when we start acting as such.&lt;/p&gt;

&lt;h3&gt;Microsoft&lt;/h3&gt;

&lt;p&gt;At least in my region Microsoft does a very commendable work in trying to connect the .Net developers
with non-.Net ones. More and more I see MS interested in leaving the community organization
to community itself, providing some level of infrastructure, access to good speakers and sponsorship when possible.&lt;/p&gt;

&lt;p&gt;I&amp;#39;m not convinced MS knows how to measure the health of .Net communities. For me, even
looking from MS&amp;#39; standpoint, a successful community is one where a novices have easy
access to experts and where knowledge and opportunities are exchanged. It doesn&amp;#39;t matter
that you have tens of thousands of .Net developers in your region if you don&amp;#39;t know 
where to find them for a question or business proposition.&lt;/p&gt;

&lt;h3&gt;Microsoft Products&lt;/h3&gt;

&lt;p&gt;Like any other technology company, Microsoft releases products that range from tremendously
successful to niche applications to complete failures.&lt;/p&gt;

&lt;p&gt;We can never dispose of critical eyes when analyzing a new product. The community members
invest their time when attending meetings and events. We need to always demand
perspective in addition to purely technical content. &lt;/p&gt;

&lt;p&gt;Here I want to draw the line and separate developer tools from core technologies. As
a developer I&amp;#39;m ok to be seen as a &lt;i&gt;consumer&lt;/i&gt; of developer tools, like Visual
Studio and Blend, but when it comes to the platform technologies, like IIS, SQL Server, 
Azure, Silverlight, etc I much rather be treated as a coworker that is trying
to create high quality software with these products. Forget that there&amp;#39;s money to
be made by both of us in this process when we talk about core technologies.&lt;/p&gt;

&lt;h3&gt;Can we fix this?&lt;/h3&gt;

&lt;p&gt;I used to be more optimistic about this situation. I still hope we
can stir the will to participate, produce, and consume all things .Net.&lt;/p&gt;

&lt;p&gt;The one thing I know for sure is that I won&amp;#39;t sit and watch until it happens.
I try to do the tiny bit I can but I like this stuff too much and 
I have no problem in carrying my energy over to another platform.&lt;/p&gt;

&lt;p&gt;But the question stands &amp;mdash; Is there a way to make it work?&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=60584" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term=".NET" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/.NET/default.aspx" /><category term="Community" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Community/default.aspx" /></entry><entry><title>Careful with those enumerables</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/05/09/careful-with-those-enumerables.aspx" /><id>/blogs/sergio_pereira/archive/2010/05/09/careful-with-those-enumerables.aspx</id><published>2010-05-09T16:20:00Z</published><updated>2010-05-09T16:20:00Z</updated><content type="html">&lt;p&gt;Ever since .Net 2.0 introduced the &lt;code&gt;yield&lt;/code&gt; keyword
for creating enumerators, and even more after the introduction
of LINQ in C# 3.0, I&amp;#39;ve seen more and more APIs return
&lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt; instead of &lt;code&gt;IList&amp;lt;T&amp;gt;&lt;/code&gt;
or &lt;code&gt;ICollection&amp;lt;T&amp;gt;&lt;/code&gt; or their older cousins 
the &lt;code&gt;ArrayList&lt;/code&gt; and the array object.&lt;/p&gt;

&lt;p&gt;That makes sense most of the time, especially for collections
that aren&amp;#39;t meant to be modified, and choosing between those 
different return types is not what I&amp;#39;m about to discuss here. 
You can find endless articles and threads about that.&lt;/p&gt;

&lt;h3&gt;The caller&amp;#39;s perspective&lt;/h3&gt;

&lt;p&gt;What has caused me some trouble recently was being caught
off guard by some unexpected performance penalties when
using one of those &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Not that &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt; has any performance
issue by itself but the way we deliver it can misguide the caller. 
Let me try to make that statement a little clearer with a 
small example.&lt;/p&gt;

&lt;p&gt;Consider this &lt;code&gt;ProductCatalog&lt;/code&gt; class that 
basically wraps a collection of &lt;code&gt;Product&lt;/code&gt;
objects.&lt;/p&gt;

&lt;pre name="code" class="csharp:nogutter"&gt;public class ProductCatalog
{
  private readonly IInventoryService _inventoryService;
  private List&amp;lt;Product&amp;gt; _products;

  public ProductCatalog(IInventoryService inventoryService)
  {
    _inventoryService = inventoryService;
    _products = new List&amp;lt;Product&amp;gt;();
  }

  public void Populate()
  {
    //imagine this will populate from a database
    _products.Add(new Product {Id = 1, Price = 12.34m});
    _products.Add(new Product {Id = 2, Price = 11.22m});
    _products.Add(new Product {Id = 3, Price = 7.99m});
    _products.Add(new Product {Id = 4, Price = 3.49m});
	//...
    _products.Add(new Product {Id = 10000, Price = 75.99m});
  }

  public IEnumerable&amp;lt;Product&amp;gt; Products { get { return _products; } }

  public IEnumerable&amp;lt;Product&amp;gt; AvailableProducts
  {
    get
    {
      return Products
        .Where(product =&amp;gt; _inventoryService.IsProductInStock(product));
    }
  }
}&lt;/pre&gt;

&lt;p&gt;And here&amp;#39;s the code using it.&lt;/p&gt;

&lt;pre name="code" class="csharp:nogutter"&gt;var catalog = new ProductCatalog(new InventoryService());
catalog.Populate();

var available = catalog.AvailableProducts;

foreach (var product in available)
{
  Console.Out.WriteLine(&amp;quot;Product Id &amp;quot; + product.Id + &amp;quot; is available.&amp;quot;);
}

var priceSum = 0m;

priceSum = available.Sum(product =&amp;gt; product.Price);
Console.Out.WriteLine(
  &amp;quot;If I buy one of each product I&amp;#39;ll pay: &amp;quot; + priceSum.ToString(&amp;quot;c&amp;quot;));&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;InventoryService&lt;/code&gt; is something like this:&lt;/p&gt;

&lt;pre name="code" class="csharp:nogutter"&gt;public class InventoryService : IInventoryService
{
  public bool IsProductInStock(Product product)
  {
    Console.Out.WriteLine(&amp;quot;Expensive verification for prod id: &amp;quot; + product.Id);
    //imagine something a little more complex and lengthy is happening here.
    return true;
  }
}&lt;/pre&gt;

&lt;p&gt;It seems trivial enough, but let&amp;#39;s look at what the output gives us:&lt;/p&gt;

&lt;pre name="code" class="nogutter"&gt;Expensive verification for prod id: 1
Product Id 1 is available.
Expensive verification for prod id: 2
Product Id 2 is available.
Expensive verification for prod id: 3
Product Id 3 is available.
Expensive verification for prod id: 4
Product Id 4 is available.
Expensive verification for prod id: 10000
Product Id 10000 is available.
Expensive verification for prod id: 1
Expensive verification for prod id: 2
Expensive verification for prod id: 3
Expensive verification for prod id: 4
Expensive verification for prod id: 10000
If I buy one of each product I&amp;#39;ll pay: $111.03&lt;/pre&gt;

&lt;p&gt;See? If I didn&amp;#39;t know how &lt;code&gt;ProductCatalog.AvailableProducts&lt;/code&gt;
was implemented I would be stumped by this behavior. Looking at
this from the caller&amp;#39;s point of view, I was just trying to use an
object&amp;#39;s collection property twice, probably thinking the return
value would be the same collection of objects each time.&lt;/p&gt;

&lt;p&gt;Well, they were the same individual &lt;code&gt;Product&lt;/code&gt; objects
in each call but they most definitely were not packaged in the
same collection structure, and I don&amp;#39;t know about you but I
would never, in a million years, think that accessing that
property would cause the collection to be rebuilt each time.&lt;/p&gt;

&lt;h3&gt;What&amp;#39;s an API designer to do?&lt;/h3&gt;

&lt;p&gt;My suggestion in situations like the above, where
the collection is closer to an object feed than
a fixed list, is to implement that member as a method,
not a property. Callers are more likely to associate a 
method call to something expensive than in the property access case.&lt;/p&gt;

&lt;p&gt;Properties carry a historical expectation of being
cheap to use and consistent. If your property&amp;#39;s design
includes the chance of not honoring this expectation, like
in my example which depended on an injected &lt;code&gt;IInventoryService&lt;/code&gt;,
then use a method instead.&lt;/p&gt;

&lt;p&gt;If you can&amp;#39;t use a method for whatever reason, try to
at least lazy load or cache the returned collection. &lt;/p&gt;

&lt;p&gt;The last thing you want is requiring your callers to know
implementation details of all your collection-returning members
to decide how they should use the collection.&lt;/p&gt;

&lt;h3&gt;So this is not about the return type, huh?&lt;/h3&gt;

&lt;p&gt;As you may have noticed, the problem I went into had
nothing to do with &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;, it
could have happened with any of the other mentioned types 
&amp;mdash; they&amp;#39;re all &lt;i&gt;enumerable&lt;/i&gt; anyway. I could
certainly convert my example to &lt;code&gt;IList&amp;lt;T&amp;gt;&lt;/code&gt; 
and still have the same problem.&lt;/p&gt;

&lt;p&gt;The reason I called out &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt; more
explicitly is that it seems to happen more with it than the 
other ones. Maybe that&amp;#39;s because the LINQ extension methods
return &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt; or because an
&lt;code&gt;IList&amp;lt;T&amp;gt;&lt;/code&gt; property backed by a fixed
&lt;code&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; collection is a very common implementation
choice. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=58642" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term=".NET" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/.NET/default.aspx" /></entry><entry><title>ANN: The Second Chicago Code Camp</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/03/22/the-second-chicago-code-camp.aspx" /><id>/blogs/sergio_pereira/archive/2010/03/22/the-second-chicago-code-camp.aspx</id><published>2010-03-22T17:26:00Z</published><updated>2010-03-22T17:26:00Z</updated><content type="html">&lt;p&gt;After a successful first Chicago Code Camp last year, we&amp;#39;re back to announce
the second edition of this unique technical event.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://chicagocodecamp.com" title="Chicago Code Camp"&gt;Chicago Code Camp 2&lt;/a&gt;
will happen on &lt;b&gt;May 1&lt;sup&gt;st&lt;/sup&gt;&lt;/b&gt;. In this event we are addressing one obvious and
recurring feedback: &lt;b&gt;Make it closer to the city&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;We&amp;#39;re thrilled to announce that our Code Camp will take place at the 
&lt;a href="http://www.iit.edu/" title="Illinois Institute of Technology"&gt;IIT Campus&lt;/a&gt;,
just South of downtown Chicago, 
&lt;a href="http://www.iit.edu/about/directions_main.html" title="Directions to IIT&amp;#39;s Main Campus"&gt;easily accessible&lt;/a&gt; 
by car and public transportation.&lt;/p&gt;

&lt;h3&gt;What is the Chicago Code Camp?&lt;/h3&gt;

&lt;p&gt;Just like last year, we want to host an event where any platform or
programming language can have its space, as long as there&amp;#39;s community
interest in talking and hearing about it.&lt;/p&gt;

&lt;p&gt;The code camp is a great opportunity to learn about and network with
developers of different walks of life and technologies. Last year we had 
diverse topics such as .NET, Python, iPhone, Ruby, XUL, JavaScript,
Scala, etc. We hope to have even more this time around.&lt;/p&gt;

&lt;p&gt;To ensure the numerous technical communities are fairly represented, we
are inviting all local technical community leaders to get involved and
provide speakers and attendees.&lt;/p&gt;

&lt;p&gt;The event is free to attend but everyone needs to register. &lt;strike&gt;Registration will
open soon&lt;/strike&gt; &lt;a href="http://chicagocodecamp.eventbrite.com/"&gt;Registration is open&lt;/a&gt; and it&amp;#39;s limited 
due to the venue capacity.  
&lt;/p&gt;
&lt;h3&gt;Call for Speakers&lt;/h3&gt;

&lt;p&gt;The &lt;a href="http://chicagocodecamp.com" title="Chicago Code Camp 2"&gt;Chicago Code Camp&lt;/a&gt;
website is up and ready to receive talk proposals.
&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://www.thedevcommunity.org/codecamps/manifesto.aspx" title="Code Camp Manifesto"&gt;Code Camp Manifesto&lt;/a&gt; calls for sessions that privilege code over 
theory or slides, but it doesn&amp;#39;t mean a good presentation will be immediately 
turned down because of that.
&lt;/p&gt;
&lt;h3&gt;Stay tuned&lt;/h3&gt;

&lt;p&gt;We will have more exciting news and announcements to share about 
this event. We will do so as soon are they are confirmed.
&lt;/p&gt;
&lt;p&gt;Keep an eye on the website (or this blog) to learn about &lt;a href="http://chicagocodecamp.eventbrite.com/"&gt;registrations&lt;/a&gt;,
volunteering, and getting involved.
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=56209" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term=".NET" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/.NET/default.aspx" /><category term="Ruby" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Ruby/default.aspx" /><category term="JavaScript" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/JavaScript/default.aspx" /><category term="Announcement" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Announcement/default.aspx" /><category term="Community" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Community/default.aspx" /></entry><entry><title>dotTrace 3.1 64-bit disabled inside Visual Studio 2008</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/03/12/dottrace-3-1-64-bit-disabled-inside-visual-studio-2008.aspx" /><id>/blogs/sergio_pereira/archive/2010/03/12/dottrace-3-1-64-bit-disabled-inside-visual-studio-2008.aspx</id><published>2010-03-12T18:15:00Z</published><updated>2010-03-12T18:15:00Z</updated><content type="html">&lt;p&gt;
I work on a web application and I use &lt;a href="http://www.jetbrains.com/profiler/"&gt;dotTrace&lt;/a&gt; 
when some profiling is needed. The problem is that I cannot fire off doTrace directly from inside Visual
Studio 2008 because the commands and toolbar icons to launch it are permanently disabled. Well, not anymore.
&lt;/p&gt;

&lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;
The web application I work on is a 64-bit application. I use a 64-bit version of Windows (namely, Win2008 x64).
I installed the 64-bit version of dotTrace 3.1 and it does work stand-alone but it never worked integrated with
VS 2008, which is a shame because it contains some neat features like it&amp;#39;s enabling the ReSharper test runner
to run the chosen test(s) directly under dotTrace profiling. The screen shot below shows how it should look like
but on my box these dotTrace commands were simply disabled.
&lt;/p&gt;

&lt;p&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.03/dottrace_2D00_64.png" alt="" /&gt;&lt;/p&gt;

&lt;h3&gt;The fix&lt;/h3&gt;
&lt;p&gt;
After much disappointment with the missing features, my fellow &lt;a href="http://devlicio.us/"&gt;Devlicio.us&lt;/a&gt;
blogger &lt;a href="http://devlicio.us/blogs/hadi_hariri/"&gt;Hadi Hariri&lt;/a&gt; put me in contact with 
&lt;a href="http://blogs.jetbrains.com/nocturne/"&gt;Oleg Stepanov&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
The first suggestion was trying the 32-bit version of dotTrace, which wasn&amp;#39;t an option for
me because, as I said, my application and all the supporting utilities are 64-bit, 
it runs under a 64-bit process, so that&amp;#39;s ultimately how I need to profile it.
&lt;/p&gt;

&lt;p&gt;
Then Oleg explained that the problem is that VS is a 32-bit application and it
was looking for a registry key in the wrong place, not finding it, and then
it was assuming dotTrace wasn&amp;#39;t available.
&lt;/p&gt;

&lt;p&gt;
 Hmmm... That sounded 
 &lt;a href="http://devlicio.us/blogs/sergio_pereira/archive/2009/07/20/resharper-test-runner-in-64-bit-windows.aspx"&gt;eerily familiar&lt;/a&gt;, didn&amp;#39;t it? Once again the little annoyances of developing 64-bit code with
 32-bit tools come to bite us.
&lt;/p&gt;

&lt;p&gt;
To fix the problem, just like 
&lt;a href="http://devlicio.us/blogs/sergio_pereira/archive/2009/07/20/resharper-test-runner-in-64-bit-windows.aspx"&gt;the other time it happened&lt;/a&gt;, we just need to copy the right registry key to its
corresponding place under the Wow6432Node key. 
&lt;/p&gt;

&lt;p&gt;
Open the Registry Editor and go to the
&lt;code&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\&lt;/code&gt; key.
One of its GUID-named subkeys will contain the dotTrace information. Just search for dotTrace 
and find the right subkey. Now just copy (or export/edit/import) that key under 
&lt;code&gt;HKEY_LOCAL_MACHINE\SOFTWARE\&lt;b&gt;&lt;u&gt;Wow6432Node&lt;/u&gt;&lt;/b&gt;\Microsoft\Windows\CurrentVersion\Uninstall\&lt;/code&gt;
and you&amp;#39;re ready to restart Visual Studio and see all the integrated dotTrace features
come alive.
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=55898" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author></entry><entry><title>[ANN] Chicago ALT.NET shows Rake and Albacore</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/03/09/ann-chicago-alt-net-shows-rake-and-albacore.aspx" /><id>/blogs/sergio_pereira/archive/2010/03/09/ann-chicago-alt-net-shows-rake-and-albacore.aspx</id><published>2010-03-09T23:35:00Z</published><updated>2010-03-09T23:35:00Z</updated><content type="html">&lt;p&gt;
I haven&amp;#39;t mentioned our meetings here in a while but our group has been going strong and enthusiastic all this time.
&lt;/p&gt;

&lt;p&gt;
Tomorrow, March 10&lt;sup&gt;th&lt;/sup&gt; our topic will be build scripts for .Net projects using Rake and Albacore. I&amp;#39;ve been 
using Rake and a little bit of Albacore in my own projects and I&amp;#39;m ready to say that it will take a very serious 
event to make me go back to NAnt or MSBuild.
&lt;/p&gt;

&lt;h3&gt;Introduction to Rake with Albacore.NET&lt;/h3&gt;
&lt;p&gt;
		&lt;span style="font-size:x-small;"&gt;6:00 pm&lt;/span&gt; 
		&lt;br /&gt;

		Pizza and networking time
&lt;/p&gt;
&lt;p&gt;
		&lt;span style="font-size:x-small;"&gt;6:30 pm&lt;/span&gt; 
&lt;/p&gt;
&lt;p&gt;
	How would you to write your build &lt;em&gt;scripts&lt;/em&gt; using a
	&lt;em&gt;scripting&lt;/em&gt; language instead of XML? In this month&amp;#39;s meeting
	we will see how the ease of programming in Ruby can be used
	to create a much more pleasant and extensible build script.

&lt;/p&gt;
&lt;p&gt;&lt;a href="http://rake.rubyforge.org/"&gt;Rake&lt;/a&gt; isn&amp;#39;t just for Rubyists or 
Alphageeks anymore. &lt;a href="http://albacorebuild.net/"&gt;Albacore&lt;/a&gt; helps bring 
the power and expresiveness of the Ruby language to the world of .NET build 
automation. Using Rake it&amp;#39;s never been easier to handle build automation, 
test execution, continuous integration and just about any task you need to 
automate for your build.&lt;/p&gt;
&lt;p&gt;
&lt;img style="margin-right:5px;" src="http://chicagoalt.net/content/images/events/michael-d-hall.jpg" alt="" align="left" /&gt;
&lt;a href="http://www.just3ws.com/%20"&gt;Michael D. Hall&lt;/a&gt; has been developing software 
on the Microsoft platform for over a decade. He&amp;#39;s been an Alt.NETter for years 
and is really enjoying the exposure to different ideas and concepts beyond the 
safe confines of the .NET world. Currently he&amp;#39;s a consultant working with Obtiva 
and has started a &lt;a href="http://www.clouddevelopersgroup.com/"&gt;Cloud Developer&amp;#39;s Group&lt;/a&gt; 
that meets monthly in McHenry county.&lt;/p&gt;

&lt;a href="http://altnetchicago.eventbrite.com" target="_blank"&gt;&lt;img border="0" src="http://www.eventbrite.com/registerbutton?eid=588872333" alt="Register for Introduction to Rake with Albacore.NET in Chicago, IL  on Eventbrite" /&gt;&lt;/a&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=55811" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term="Ruby" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Ruby/default.aspx" /><category term="Automation" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Automation/default.aspx" /><category term="alt.net" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/alt.net/default.aspx" /><category term="Announcement" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Announcement/default.aspx" /><category term="Community" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Community/default.aspx" /></entry><entry><title>Rule "Previous releases of Microsoft Visual Studio 2008" failed</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/03/07/rule-quot-previous-releases-of-microsoft-visual-studio-2008-quot-failed.aspx" /><id>/blogs/sergio_pereira/archive/2010/03/07/rule-quot-previous-releases-of-microsoft-visual-studio-2008-quot-failed.aspx</id><published>2010-03-07T10:43:00Z</published><updated>2010-03-07T10:43:00Z</updated><content type="html">&lt;p&gt;
 Today I was trying to install SQL 2008 on my box and the setup stopped after checking a bunch of
rules. The error message was the title of this post.
&lt;/p&gt;

&lt;p&gt;
A quick search on the internet revealed that somehow the installer didn&amp;#39;t believe I had VS 2008 &lt;b&gt;SP1&lt;/b&gt;
installed, which I did. The recommendations in &lt;a href="http://support.microsoft.com/kb/956139"&gt;the KB article&lt;/a&gt;
were kind of insulting. There&amp;#39;s no way I&amp;#39;d spend hours of my day uninstalling and reinstalling VS and SQL &amp;mdash; sorry, no chance. I
also could not accept not installing the Management Tools, for example. I also did not have any Express version of VS or SQL installed in this box.
&lt;/p&gt;

&lt;p&gt;
A little snooping around with &lt;a href="http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx"&gt;ProcMon&lt;/a&gt;
led me to the following registry key: 
&lt;/p&gt;

&lt;pre&gt;HKLM\SOFTWARE\Wow6432Node\Microsoft\DevDiv\VS\Servicing\9.0\IDE\1033&lt;/pre&gt;

&lt;p&gt;
In that key I noticed the suspicious values:
&lt;/p&gt;

&lt;pre&gt;&amp;quot;SP&amp;quot;=dword:00000000
&amp;quot;SPIndex&amp;quot;=dword:00000000
&amp;quot;SPName&amp;quot;=&amp;quot;RTM&amp;quot;
&lt;/pre&gt;

&lt;p&gt;
Without quitting the SQL server installer validaton screen, I changed these values to what you see below, crossed my fingers 
and rerun the installer validation, &lt;b&gt;which passed!&lt;/b&gt;
&lt;/p&gt;

&lt;pre&gt;&amp;quot;SP&amp;quot;=dword:00000001
&amp;quot;SPIndex&amp;quot;=dword:00000001
&amp;quot;SPName&amp;quot;=&amp;quot;SP1&amp;quot;
&lt;/pre&gt;

&lt;p&gt;
Now, I didn&amp;#39;t really guess those values. I looked in a sibling registry key (...Servicing\9.0\PRO\1033) and saw
that it contained those new values, then I copied them. 
&lt;/p&gt;

&lt;p&gt;
I think I didn&amp;#39;t break anything. So far all seems to be working. But, as usual with anything related
to manual registry hacking, you have to be really insane to change your settings because you
read on a random blog on the &amp;#39;net. I&amp;#39;m just saying... Don&amp;#39;t come crying if your house burns down because of this.
&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=55695" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term="Tips-and-Tricks" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Tips-and-Tricks/default.aspx" /><category term="SQLServer" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/SQLServer/default.aspx" /></entry><entry><title>jQuery Custom Element and Global Events</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/02/21/jquery-custom-element-and-global-events.aspx" /><id>/blogs/sergio_pereira/archive/2010/02/21/jquery-custom-element-and-global-events.aspx</id><published>2010-02-21T18:09:00Z</published><updated>2010-02-21T18:09:00Z</updated><content type="html">&lt;p&gt;This last week I learned a new thing about jQuery custom events, particularly the ones of global nature.
There&amp;#39;s good &lt;a href="http://api.jquery.com/trigger/"&gt;documentation&lt;/a&gt; 
and examples about custom element events, but
not much for the &lt;i&gt;global&lt;/i&gt; ones.&lt;/p&gt;

&lt;h3&gt;Why do we need custom events?&lt;/h3&gt;

&lt;p&gt;Custom events make it easier to keep complex pages under control. They
are a pillar for loosely-coupled UI scripts. Let&amp;#39;s start with a
simple example.&lt;/p&gt;

&lt;p&gt;Suppose we have a fairly complex and dynamic page where many elements
are Ajax-editable, using in-place editors or any other approach that 
posts updates to the server. Depending on how quickly the server 
responds to the request, there&amp;#39;s a chance the user can start another
simultaneous request before the first one finishes, maybe even seeing
inconsistent results, by clicking a button too soon.&lt;/p&gt;

&lt;p&gt;In our example &amp;mdash; a fraction of what a real complex page would be &amp;mdash; 
what we want to do is disable some of these buttons while
the data is being changed, and re-enable them once we hear back from the server.&lt;/p&gt;

&lt;pre name="code" class="html:nogutter"&gt;Click the field to edit it:&amp;lt;br&amp;gt;

&amp;lt;input type=&amp;quot;text&amp;quot; readonly=&amp;quot;readonly&amp;quot; id=&amp;quot;email&amp;quot; name=&amp;quot;email&amp;quot;
   value=&amp;quot;joe@doe.com&amp;quot; style=&amp;quot;background-color: #eee;&amp;quot;/&amp;gt; 

&amp;lt;input type=&amp;quot;button&amp;quot; class=&amp;quot;userOperation&amp;quot; id=&amp;quot;sendButton&amp;quot; value=&amp;quot;Send Message&amp;quot;&amp;gt;
&amp;lt;input type=&amp;quot;button&amp;quot; class=&amp;quot;userOperation&amp;quot; id=&amp;quot;summaryButton&amp;quot; value=&amp;quot;Summary&amp;quot;&amp;gt;&lt;/pre&gt;

&lt;h3&gt;Custom Element Events&lt;/h3&gt;

&lt;p&gt;Let&amp;#39;s tackle this problem first with the custom element events. Below is a 
summary of how these custom events are used.&lt;/p&gt;

&lt;pre name="code" class="js:nogutter"&gt;$(&amp;#39;#publisher&amp;#39;).trigger(&amp;#39;eventName&amp;#39;);

$(&amp;#39;#publisher1&amp;#39;).bind(&amp;#39;eventName&amp;#39;, function() {
   //eventName happened. React here.
   $(&amp;#39;#subscriber1&amp;#39;).doStuff();
   $(&amp;#39;#subscriber2&amp;#39;).doOtherStuff();
   // more...
});&lt;/pre&gt;

&lt;p&gt;In this case we will make the elements being edited announce that they entered edit mode
so that any other element can act on that announcement.&lt;/p&gt;

&lt;pre name="code" class="js:nogutter"&gt;$(&amp;#39;#email&amp;#39;).
click(function(){
	$(this).removeAttr(&amp;#39;readonly&amp;#39;).css({backgroundColor: &amp;#39;&amp;#39;});
	$(this).trigger(&amp;#39;editStart&amp;#39;);
}).
blur(function(){
	$(this).attr(&amp;#39;readonly&amp;#39;, &amp;#39;readonly&amp;#39;).css({backgroundColor: &amp;#39;#eee&amp;#39;});
	$.post(&amp;#39;/updateEmail&amp;#39;, $(&amp;#39;#email&amp;#39;).serialize(), function() {
		$(this).trigger(&amp;#39;editComplete&amp;#39;);
	});
}).
bind(&amp;#39;editStart&amp;#39;, function(){
	// &amp;quot;this&amp;quot; is the #email element
	console.log(&amp;#39;edit started, this =  &amp;#39; + this.id);
	$(&amp;#39;.userOperation&amp;#39;).attr(&amp;#39;disabled&amp;#39;, &amp;#39;disabled&amp;#39;);
}).
bind(&amp;#39;editComplete&amp;#39;, function(){
	// &amp;quot;this&amp;quot; is the #email element
	console.log(&amp;#39;edit complete, this =  &amp;#39; + this.id);
	$(&amp;#39;.userOperation&amp;#39;).removeAttr(&amp;#39;disabled&amp;#39;);		
});

$(&amp;#39;#sendButton&amp;#39;).click(function(){
	//code to send a message
	alert(&amp;#39;Message sent&amp;#39;);
});

$(&amp;#39;#summaryButton&amp;#39;).click(function(){
	//code to generate summary
	alert(&amp;#39;Summary created&amp;#39;);
});&lt;/pre&gt;


&lt;p&gt;This approach works well in the beginning but gets really ugly as
more elements need to publish their own similar events or when
other new elements need to do somethings with these events too. We
will need to bind handlers to all these element&amp;#39;s events and the code 
inside these handlers will start getting longer and probably too
far from the rest of the code that relates to it.&lt;/p&gt;

&lt;h3&gt;One step forward with page level events&lt;/h3&gt;

&lt;p&gt;Since the events we are producing here really reflect the document
state more than any individual field&amp;#39;s state, let&amp;#39;s move that event
to a more top level element, namely the &lt;code&gt;body&lt;/code&gt; element:&lt;/p&gt;

&lt;pre name="code" class="js:nogutter"&gt;$(&amp;#39;#email&amp;#39;).
click(function(){
	$(this).removeAttr(&amp;#39;readonly&amp;#39;).css({backgroundColor: &amp;#39;&amp;#39;});
	$(&amp;#39;body&amp;#39;).trigger(&amp;#39;editStart&amp;#39;);
}).
blur(function(){
	$(this).attr(&amp;#39;readonly&amp;#39;, &amp;#39;readonly&amp;#39;).css({backgroundColor: &amp;#39;#eee&amp;#39;});
	$.post(&amp;#39;/updateEmail&amp;#39;, $(&amp;#39;#email&amp;#39;).serialize(), function() {
		$(&amp;#39;body&amp;#39;).trigger(&amp;#39;editComplete&amp;#39;);
	});
});

$(&amp;#39;body&amp;#39;).
bind(&amp;#39;editStart&amp;#39;, function(){
	// &amp;quot;this&amp;quot; is the body element
	console.log(&amp;#39;edit started, this =  &amp;#39; + this.tagName);
	$(&amp;#39;.userOperation&amp;#39;).attr(&amp;#39;disabled&amp;#39;, &amp;#39;disabled&amp;#39;);
}).
bind(&amp;#39;editComplete&amp;#39;, function(){
	// &amp;quot;this&amp;quot; is the body element
	console.log(&amp;#39;edit complete, this =  &amp;#39; + this.tagName);
	$(&amp;#39;.userOperation&amp;#39;).removeAttr(&amp;#39;disabled&amp;#39;);		
});

$(&amp;#39;#sendButton&amp;#39;).click(function(){
	//code to send a message
	alert(&amp;#39;Message sent&amp;#39;);
});

$(&amp;#39;#summaryButton&amp;#39;).click(function(){
	//code to generate summary
	alert(&amp;#39;Summary created&amp;#39;);
});&lt;/pre&gt;


&lt;p&gt;Now we&amp;#39;re getting somewhere. We reduced the number of event sources to
just one, so guaranteed less duplication. But it still has some shortcomings.&lt;/p&gt;

&lt;p&gt;The code is still bound to a different element than the one we want to operate on.
What I mean by that is that the event handlers are in the context of the elements
publishing the event and the code in the handlers is typically geared towards the
elements that need to react to that event, that is, the &lt;code&gt;this&lt;/code&gt; keyword
is less useful than in most of your common event handlers.&lt;/p&gt;

&lt;p&gt;The pattern of these page-level events is:&lt;/p&gt;

&lt;pre name="code" class="js:nogutter"&gt;$(&amp;#39;body&amp;#39;).trigger(&amp;#39;eventName&amp;#39;);

$(&amp;#39;body&amp;#39;).bind(&amp;#39;eventName&amp;#39;, function() {
   //eventName happened. React here.
   $(&amp;#39;#subscriber1&amp;#39;).doStuff();
   $(&amp;#39;#subscriber2&amp;#39;).doOtherStuff();
   // more...
});&lt;/pre&gt;


&lt;h3&gt;But wait, jQuery has real global events too&lt;/h3&gt;

&lt;p&gt;I had settled down with using the above style of global events until
someone at work pointed out that there&amp;#39;s another way of doing this, which
unfortunately isn&amp;#39;t as well discussed: the &lt;b&gt;custom global events&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;Here&amp;#39;s our code using global custom events:&lt;/p&gt;

&lt;pre name="code" class="js:nogutter"&gt;$(&amp;#39;#email&amp;#39;).click(function(){
	$(this).removeAttr(&amp;#39;readonly&amp;#39;).css({backgroundColor: &amp;#39;&amp;#39;});
	$.event.trigger(&amp;#39;editStart&amp;#39;);
}).blur(function(){
	$(this).attr(&amp;#39;readonly&amp;#39;, &amp;#39;readonly&amp;#39;).css({backgroundColor: &amp;#39;#eee&amp;#39;});
	$.post(&amp;#39;/updateEmail&amp;#39;, $(&amp;#39;#email&amp;#39;).serialize(), function() {
		$.event.trigger(&amp;#39;editComplete&amp;#39;);
	});
});

$(&amp;#39;.userOperation&amp;#39;).bind(&amp;#39;editStart&amp;#39;, function(){
	// &amp;quot;this&amp;quot; is a .userOperation button
	console.log(&amp;#39;edit started, button: &amp;#39; + this.id);
	$(&amp;#39;.userOperation&amp;#39;).attr(&amp;#39;disabled&amp;#39;, &amp;#39;disabled&amp;#39;);
}).bind(&amp;#39;editComplete&amp;#39;, function(){
	// &amp;quot;this&amp;quot; is a .userOperation button
	console.log(&amp;#39;edit complete, button: &amp;#39; + this.id);
	$(&amp;#39;.userOperation&amp;#39;).removeAttr(&amp;#39;disabled&amp;#39;);		
});

$(&amp;#39;#sendButton&amp;#39;).click(function(){
	//code to send a message
	alert(&amp;#39;Message sent&amp;#39;);
});

$(&amp;#39;#summaryButton&amp;#39;).click(function(){
	//code to generate summary
	alert(&amp;#39;Summary created&amp;#39;);
});&lt;/pre&gt;


&lt;p&gt;What is great about this type of event is that they are in the context
of the subscribing elements, as if these elements were the publishers of
the event, much like the majority of the event handling code we write.&lt;/p&gt;

&lt;p&gt;They also allow us to move more code next to the other event handler for
the subscribing elements, and even chain them all together. As an example,
let&amp;#39;s modify the event handlers of the &lt;code&gt;#sendButton&lt;/code&gt; element
to add some different behavior when the &lt;i&gt;editStart&lt;/i&gt; event happens.&lt;/p&gt;

&lt;pre name="code" class="js:nogutter"&gt;$(&amp;#39;#sendButton&amp;#39;).click(function(){
	//code to send a message
	alert(&amp;#39;Message sent&amp;#39;);
}).bind(&amp;#39;editStart&amp;#39;, function(){
	// &amp;quot;this&amp;quot; is the #sendButton button
	this.value = &amp;#39;Send message (please refresh)&amp;#39;;
	// change the click event handler.
	$(this).unbind(&amp;#39;click&amp;#39;).click(function(){
		alert(&amp;#39;Sorry, refresh page before sending message&amp;#39;);
	});
});&lt;/pre&gt;

&lt;p&gt;And here is the simplified representation of the global events code.&lt;/p&gt;

&lt;pre name="code" class="js:nogutter"&gt;$.event.trigger(&amp;#39;eventName&amp;#39;);

$(&amp;#39;#subscriber1&amp;#39;).bind(&amp;#39;eventName&amp;#39;, function() {
   //eventName happened. React here.
   $(this).doStuff();
});

$(&amp;#39;#subscriber2&amp;#39;).bind(&amp;#39;eventName&amp;#39;, function() {
   //eventName happened. React here.
   $(this).doOtherStuff();
});
//more...&lt;/pre&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Event-based programming is the usual way we write UI code. By understanding 
the different types of events that jQuery provides we can allow
our UI to grow without getting into a messy nightmare of 
event handling code scattered all over the place.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=55475" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term="JavaScript" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/JavaScript/default.aspx" /><category term="jQuery" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/jQuery/default.aspx" /></entry><entry><title>Code coverage reports with NCover and MSBuild</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/02/09/code-coverage-reports-with-ncover-and-msbuild.aspx" /><id>/blogs/sergio_pereira/archive/2010/02/09/code-coverage-reports-with-ncover-and-msbuild.aspx</id><published>2010-02-09T18:11:00Z</published><updated>2010-02-09T18:11:00Z</updated><content type="html">&lt;p&gt;
I&amp;#39;ve been doing a lot of static analysis on our projects at work lately. As 
part of that task we added &lt;a href="http://www.ncover.com/"&gt;NCover&lt;/a&gt; to our automated build process. Our
build runs on Team Build (TFS) and is specified in an MSBuild file.

&lt;/p&gt;
&lt;p&gt;
We wanted to take code metrics very seriously and we purchased the 
complete version of the product to take full advantage of its 
capabilities.

&lt;/p&gt;
&lt;p&gt;
Getting NCover to run in your build is very simple and the online 
documentation will be enough to figure it out. The problem comes
when you begin needing to create more and more variations of the
reports. The online documentation is a little short on this aspect,
especially on how to use the MSBuild or NAnt custom tasks. I hear
they plan to update the site with better docs for the next version 
of the product.

&lt;/p&gt;
&lt;p&gt;
NCover Complete comes with 23 different types of reports and 
a ton of parameters that can be configured to produce far
more helpful reports than just sticking to the defaults.

&lt;/p&gt;
&lt;p&gt;
For example, we are working on a new release of our product and
we are pushing ourselves to produce more testable code and
write more unit tests for all the new code. The problem is
that the new code is a just tiny fraction of the existing code and
the metrics get averaged down by the older code.

&lt;/p&gt;
&lt;p&gt;
The key is to separate the code coverage profiling (which is
done by NCover while it runs all the unit tests with NUnit) from
the rendering of the reports. That way we only run the code coverage once; and that
can sometimes take a good chunk of time to produce the coverage data. 
Rendering the reports is much quicker since the NCover reporting engine can feed off the
coverage data as many times as we need, very quickly.

&lt;/p&gt;
&lt;p&gt;
Once we have the coverage data we can choose which report types we want 
to create, the thresholds for sufficient coverage (or to fail the build), which assemblies/types/methods
we want to include/exclude from each report and where to save each of them.

&lt;h3&gt;Example&lt;/h3&gt;

&lt;p&gt;
To demonstrate what I just described in practice, I decided to take
an existing open source project and add NCover reporting to it. The
project I selected was &lt;a href="http://www.codeplex.com/AutoMapper"&gt;AutoMapper&lt;/a&gt; mostly because it&amp;#39;s not very big
and has decent test coverage.
&lt;/p&gt;
&lt;p&gt;
I downloaded the project&amp;#39;s source code from the repository and
added a file named AutoMapper.msbuild to its root directory. You
can &lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.02/automapper.msbuild.zip"&gt;download 
this entire file&lt;/a&gt; but I&amp;#39;ll go over it piece by piece.
&lt;/p&gt;

&lt;p&gt;We start by just importing the MSBuild tasks that ship with NCover into our script and
declaring a few targets, including one to collect coverage data and one to generate the reports.
I added the NCover tasks dll to the project directory &lt;b&gt;tools/NCoverComplete&lt;/b&gt;.&lt;/p&gt;

&lt;pre name="code" class="xml:nogutter"&gt;&amp;lt;Project DefaultTargets=&amp;quot;RebuildReports&amp;quot; 
  xmlns=&amp;quot;http://schemas.microsoft.com/developer/msbuild/2003&amp;quot; &amp;gt;
  &amp;lt;UsingTask  TaskName=&amp;quot;NCover.MSBuildTasks.NCover&amp;quot; 
        AssemblyFile=&amp;quot;$(ProjectDir)tools\NCoverComplete\NCover.MSBuildTasks.dll&amp;quot;/&amp;gt;
  &amp;lt;UsingTask  TaskName=&amp;quot;NCover.MSBuildTasks.NCoverReporting&amp;quot; 
        AssemblyFile=&amp;quot;$(ProjectDir)tools\NCoverComplete\NCover.MSBuildTasks.dll&amp;quot;/&amp;gt;

  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;Configuration Condition=&amp;quot; &amp;#39;$(Configuration)&amp;#39; == &amp;#39;&amp;#39; &amp;quot;&amp;gt;Debug&amp;lt;/Configuration&amp;gt;
    &amp;lt;BuildDir&amp;gt;$(MSBuildProjectDirectory)\build\$(Configuration)&amp;lt;/BuildDir&amp;gt;
    &amp;lt;NUnitBinDirectoryPath&amp;gt;$(MSBuildProjectDirectory)\tools\NUnit&amp;lt;/NUnitBinDirectoryPath&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;Target Name=&amp;quot;RebuildReports&amp;quot; DependsOnTargets=&amp;quot;RunCoverage;ExportReports&amp;quot; &amp;gt;
    &amp;lt;Message Text=&amp;quot;We will rebuild the coverage data than refresh the reports.&amp;quot; 
          Importance=&amp;quot;High&amp;quot; /&amp;gt;
  &amp;lt;/Target&amp;gt;

  &amp;lt;Target Name=&amp;quot;RunCoverage&amp;quot; &amp;gt;
    &amp;lt;!-- snip --&amp;gt;
  &amp;lt;/Target&amp;gt;

  &amp;lt;Target Name=&amp;quot;ExportReports&amp;quot; &amp;gt;
    &amp;lt;!-- snip --&amp;gt;
  &amp;lt;/Target&amp;gt;
&amp;lt;/Project&amp;gt;&lt;/pre&gt;


&lt;p&gt;
	Now let&amp;#39;s look closely at the target that gathers the coverage data. All it
	does is tell NCover (NCover console, really) to run NUnit over the
	AutoMapper.UnitTests.dll and save all the output to well-known locations.
&lt;/p&gt;

&lt;pre name="code" class="xml:nogutter"&gt;&amp;lt;Target Name=&amp;quot;RunCoverage&amp;quot; &amp;gt;
  &amp;lt;Message Text=&amp;quot;Starting Code Coverage Analysis (NCover) ...&amp;quot; Importance=&amp;quot;High&amp;quot; /&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;NCoverOutDir&amp;gt;$(MSBuildProjectDirectory)\build\NCoverOut&amp;lt;/NCoverOutDir&amp;gt;
    &amp;lt;NUnitResultsFile&amp;gt;build\NCoverOut\automapper-nunit-result.xml&amp;lt;/NUnitResultsFile&amp;gt;
    &amp;lt;NUnitOutFile&amp;gt;build\NCoverOut\automapper-nunit-Out.txt&amp;lt;/NUnitOutFile&amp;gt;
    &amp;lt;InputFile&amp;gt;$(BuildDir)\UnitTests\AutoMapper.UnitTests.dll&amp;lt;/InputFile&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;NCover ToolPath=&amp;quot;$(ProgramFiles)\NCover&amp;quot;
    ProjectName=&amp;quot;$(Scenario)&amp;quot;
    WorkingDirectory=&amp;quot;$(MSBuildProjectDirectory)&amp;quot;   
    TestRunnerExe=&amp;quot;$(NUnitBinDirectoryPath)\nunit-console.exe&amp;quot;

    TestRunnerArgs=&amp;quot;$(InputFile) /xml=$(NUnitResultsFile) /out=$(NUnitOutFile)&amp;quot;

    AppendTrendTo=&amp;quot;$(NCoverOutDir)\automapper-coverage.trend&amp;quot;
    CoverageFile=&amp;quot;$(NCoverOutDir)\automapper-coverage.xml&amp;quot;
    LogFile=&amp;quot;$(NCoverOutDir)\automapper-coverage.log&amp;quot;
    IncludeTypes=&amp;quot;AutoMapper\..*&amp;quot;
    ExcludeTypes=&amp;quot;AutoMapper\.UnitTests\..*;AutoMapper\.Tests\..*&amp;quot;
    SymbolSearchLocations=&amp;quot;Registry, SymbolServer, BuildPath, ExecutingDir&amp;quot;
  /&amp;gt;
&amp;lt;/Target&amp;gt;&lt;/pre&gt;

&lt;p&gt;
	Of special interest in the NCover task above are the output files named
	&lt;b&gt;automapper)-coverage.xml&lt;/b&gt; and &lt;b&gt;automapper-coverage.trend&lt;/b&gt;, which
	contain the precious coverage data and historical trending respectively. In case
	you&amp;#39;re curious, the trend file is actually a SQLite3 database file that you
	can report directly from or export to other database formats if you want.
&lt;/p&gt;
&lt;p&gt;
	Also note the &lt;code&gt;IncludeTypes&lt;/code&gt; and &lt;code&gt;ExcludeTypes&lt;/code&gt; parameters,
	which guarantee that we are not tracking coverage on code that we don&amp;#39;t care about.
&lt;/p&gt;

&lt;p&gt;
	Now that we have our coverage and trend data collected and saved to
	files we know, we can run as many reports as we want without needing
	to execute the whole set of tests again. That&amp;#39;s in the next target.
&lt;/p&gt;


&lt;pre name="code" class="xml:nogutter"&gt;&amp;lt;Target Name=&amp;quot;ExportReports&amp;quot; &amp;gt;
  &amp;lt;Message Text=&amp;quot;Starting Producing NCover Reports...&amp;quot; Importance=&amp;quot;High&amp;quot; /&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;Scenario&amp;gt;AutoMapper-Full&amp;lt;/Scenario&amp;gt;
    &amp;lt;NCoverOutDir&amp;gt;$(MSBuildProjectDirectory)\build\NCoverOut&amp;lt;/NCoverOutDir&amp;gt;
    &amp;lt;RptOutFolder&amp;gt;$(NCoverOutDir)\$(Scenario)Coverage&amp;lt;/RptOutFolder&amp;gt;
    &amp;lt;Reports&amp;gt;
      &amp;lt;Report&amp;gt;
        &amp;lt;ReportType&amp;gt;FullCoverageReport&amp;lt;/ReportType&amp;gt;
        &amp;lt;OutputPath&amp;gt;$(RptOutFolder)\Full\index.html&amp;lt;/OutputPath&amp;gt;
        &amp;lt;Format&amp;gt;Html&amp;lt;/Format&amp;gt;
      &amp;lt;/Report&amp;gt;
      &amp;lt;Report&amp;gt;
        &amp;lt;ReportType&amp;gt;SymbolModuleNamespaceClass&amp;lt;/ReportType&amp;gt;
        &amp;lt;OutputPath&amp;gt;$(RptOutFolder)\ClassCoverage\index.html&amp;lt;/OutputPath&amp;gt;
        &amp;lt;Format&amp;gt;Html&amp;lt;/Format&amp;gt;
      &amp;lt;/Report&amp;gt;
      &amp;lt;Report&amp;gt;
        &amp;lt;ReportType&amp;gt;Trends&amp;lt;/ReportType&amp;gt;
        &amp;lt;OutputPath&amp;gt;$(RptOutFolder)\Trends\index.html&amp;lt;/OutputPath&amp;gt;
        &amp;lt;Format&amp;gt;Html&amp;lt;/Format&amp;gt;
      &amp;lt;/Report&amp;gt;
    &amp;lt;/Reports&amp;gt;
    &amp;lt;SatisfactoryCoverage&amp;gt;
      &amp;lt;Threshold&amp;gt;
        &amp;lt;CoverageMetric&amp;gt;MethodCoverage&amp;lt;/CoverageMetric&amp;gt;
        &amp;lt;Type&amp;gt;View&amp;lt;/Type&amp;gt;
        &amp;lt;Value&amp;gt;80.0&amp;lt;/Value&amp;gt;
      &amp;lt;/Threshold&amp;gt;
      &amp;lt;Threshold&amp;gt;
        &amp;lt;CoverageMetric&amp;gt;SymbolCoverage&amp;lt;/CoverageMetric&amp;gt;
        &amp;lt;Value&amp;gt;80.0&amp;lt;/Value&amp;gt;
      &amp;lt;/Threshold&amp;gt;
      &amp;lt;Threshold&amp;gt;
        &amp;lt;CoverageMetric&amp;gt;BranchCoverage&amp;lt;/CoverageMetric&amp;gt;
        &amp;lt;Value&amp;gt;80.0&amp;lt;/Value&amp;gt;
      &amp;lt;/Threshold&amp;gt;
      &amp;lt;Threshold&amp;gt;
        &amp;lt;CoverageMetric&amp;gt;CyclomaticComplexity&amp;lt;/CoverageMetric&amp;gt;
        &amp;lt;Value&amp;gt;8&amp;lt;/Value&amp;gt;
      &amp;lt;/Threshold&amp;gt;
    &amp;lt;/SatisfactoryCoverage&amp;gt;

  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;NCoverReporting 
    ToolPath=&amp;quot;$(ProgramFiles)\NCover&amp;quot;
    CoverageDataPaths=&amp;quot;$(NCoverOutDir)\automapper-coverage.xml&amp;quot;
    LoadTrendPath=&amp;quot;$(NCoverOutDir)\automapper-coverage.trend&amp;quot;
    ProjectName=&amp;quot;$(Scenario) Code&amp;quot;
    OutputReport=&amp;quot;$(Reports)&amp;quot;
    SatisfactoryCoverage=&amp;quot;$(SatisfactoryCoverage)&amp;quot;
  /&amp;gt;
&amp;lt;/Target&amp;gt;&lt;/pre&gt;

&lt;p&gt;
	What you can see in this target is that we are creating three different
	reports, represented by the &lt;code&gt;Report&lt;/code&gt; elements and that
	we are changing the satisfactory threshold to 80% code coverage 
	(down from the default of 95%) and the maximum cyclomatic complexity 
	to 8. These two blocks of configuration are passer to the NCoverReporting
	task via the parameters &lt;code&gt;OutputReport&lt;/code&gt; and &lt;code&gt;SatisfactoryCoverage&lt;/code&gt;, 
	respectively.
&lt;/p&gt;

&lt;p&gt;
	The above reports are shown in the images below.
&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.02/ncover_2D00_full.png"&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.02/ncover_2D00_full_2D00_small.png" border="0" alt="" /&gt;&lt;/a&gt;

&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.02/ncover_2D00_class.png"&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.02/ncover_2D00_class_2D00_small.png" border="0" alt="" /&gt;&lt;/a&gt;
&lt;br /&gt;
&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.02/ncover_2D00_trend.png"&gt;&lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/sergio_5F00_pereira.2010.02/ncover_2D00_trend_2D00_small.png" border="0" alt="" /&gt;&lt;/a&gt;
&lt;/p&gt;


&lt;h3&gt;Focus on specific areas&lt;/h3&gt;

&lt;p&gt;
	Let&amp;#39;s now say that, in addition to the reports for the entire source code, we
	also want to keep a closer eye on the classes under the &lt;code&gt;AutoMapper.Mappers&lt;/code&gt;
	namespace. We can get that going with another reporting target, filtering the reported
	data down to just the code we are interested in:
&lt;/p&gt;

&lt;pre name="code" class="xml:nogutter"&gt;&amp;lt;Target Name=&amp;quot;ExportReportsMappers&amp;quot; &amp;gt;
  &amp;lt;Message Text=&amp;quot;Reports just for the Mappers&amp;quot; Importance=&amp;quot;High&amp;quot; /&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;Scenario&amp;gt;AutoMapper-OnlyMappers&amp;lt;/Scenario&amp;gt;
    &amp;lt;NCoverOutDir&amp;gt;$(MSBuildProjectDirectory)\build\NCoverOut&amp;lt;/NCoverOutDir&amp;gt;
    &amp;lt;RptOutFolder&amp;gt;$(NCoverOutDir)\$(Scenario)Coverage&amp;lt;/RptOutFolder&amp;gt;
    &amp;lt;Reports&amp;gt;
      &amp;lt;Report&amp;gt;
        &amp;lt;ReportType&amp;gt;SymbolModuleNamespaceClass&amp;lt;/ReportType&amp;gt;
        &amp;lt;OutputPath&amp;gt;$(RptOutFolder)\ClassCoverage\index.html&amp;lt;/OutputPath&amp;gt;
        &amp;lt;Format&amp;gt;Html&amp;lt;/Format&amp;gt;
      &amp;lt;/Report&amp;gt;
      &amp;lt;!-- add more Report elements as desired --&amp;gt;
    &amp;lt;/Reports&amp;gt;
    &amp;lt;CoverageFilters&amp;gt;
      &amp;lt;Filter&amp;gt;
        &amp;lt;Pattern&amp;gt;AutoMapper\.Mappers\..*&amp;lt;/Pattern&amp;gt;
        &amp;lt;Type&amp;gt;Class&amp;lt;/Type&amp;gt;
        &amp;lt;IsRegex&amp;gt;True&amp;lt;/IsRegex&amp;gt;
        &amp;lt;IsInclude&amp;gt;True&amp;lt;/IsInclude&amp;gt;
      &amp;lt;/Filter&amp;gt;
      &amp;lt;!-- include/exclude more classes, assemblies, namespaces, 
      methods, files as desired --&amp;gt;
    &amp;lt;/CoverageFilters&amp;gt;

  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;NCoverReporting 
    ToolPath=&amp;quot;$(ProgramFiles)\NCover&amp;quot;
    CoverageDataPaths=&amp;quot;$(NCoverOutDir)\automapper-coverage.xml&amp;quot;
    ClearCoverageFilters=&amp;quot;true&amp;quot;
    CoverageFilters=&amp;quot;$(CoverageFilters)&amp;quot;
    LoadTrendPath=&amp;quot;$(NCoverOutDir)\automapper-coverage.trend&amp;quot;
    ProjectName=&amp;quot;$(Scenario) Code&amp;quot;
    OutputReport=&amp;quot;$(Reports)&amp;quot;
  /&amp;gt;
&amp;lt;/Target/&amp;gt;&lt;/pre&gt;

&lt;p&gt;
	Now that we have this basic template our plan is to identify
	problem areas in the code and create reports aimed at them.
	The URLs of the reports will be included in the CI build reports 
	and notification emails.
&lt;/p&gt;
&lt;p&gt;
	It&amp;#39;s so easy to add more reports that we will have reports
	that will live for a single release cycle or even less if
	we need it.
&lt;/p&gt;
&lt;p&gt;
	I hope this was helpful for more people because it did take
	a good amount of time to get it all sorted out. Even if
	you&amp;#39;re using NAnt instead of MSBuild, the syntax is
	similar and I&amp;#39;m sure you can port the idea easily.
&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=55327" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term=".NET" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/.NET/default.aspx" /><category term="Tips-and-Tricks" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Tips-and-Tricks/default.aspx" /><category term="Automation" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Automation/default.aspx" /><category term="UnitTesting" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/UnitTesting/default.aspx" /></entry><entry><title>How to detect the text encoding of a file</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/01/26/how-to-detect-the-text-encoding-of-a-file.aspx" /><id>/blogs/sergio_pereira/archive/2010/01/26/how-to-detect-the-text-encoding-of-a-file.aspx</id><published>2010-01-27T01:18:00Z</published><updated>2010-01-27T01:18:00Z</updated><content type="html">&lt;p&gt;
Today I needed a way to identify ANSI (Windows-1252) and UTF-8 files in a directory filled with files of
these two types. I was surprised to not find a simple way of doing this via a property of method somewhere
under the &lt;code&gt;System.IO&lt;/code&gt; namespace.
&lt;/p&gt;
&lt;p&gt;
Not that it&amp;#39;s that hard to identify the encoding programmatically, but it&amp;#39;s always better when you
don&amp;#39;t need to write a method yourself. Anyway, here&amp;#39;s what I came up with. It detects UTF-8 encoding
based on the encoding signature added to the beginning of the file.
&lt;/p&gt;
&lt;p&gt;
The code below is specific to UTF-8 but shouldn&amp;#39;t be too hard to extend the example to
detect more encodings.
&lt;/p&gt;
&lt;pre name="code" class="csharp:nogutter"&gt;public static bool IsUtf8(string fname){
  using(var f = File.Open(fname, FileMode.Open)){
    var sig = new byte[Encoding.UTF8.GetPreamble().Length];
    f.Read(sig, 0, sig.Length);
    return sig.SequenceEqual(Encoding.UTF8.GetPreamble());
  }
}&lt;/pre&gt;

&lt;p&gt;
Maybe I just looked in the wrong places. Does anyone know a simpler way in the framework to accomplish this?
&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=55142" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term=".NET" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/.NET/default.aspx" /><category term="Tips-and-Tricks" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Tips-and-Tricks/default.aspx" /></entry><entry><title>On ALT.NET and patience</title><link rel="alternate" type="text/html" href="/blogs/sergio_pereira/archive/2010/01/19/on-alt-net-and-patience.aspx" /><id>/blogs/sergio_pereira/archive/2010/01/19/on-alt-net-and-patience.aspx</id><published>2010-01-19T20:42:00Z</published><updated>2010-01-19T20:42:00Z</updated><content type="html">&lt;p&gt;
There ALT.NET bashing season is on full steam. Ian Cooper has a &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2010/01/19/whither-alt-net.aspx"&gt;thorough post&lt;/a&gt; about it.
&lt;/p&gt;
&lt;p&gt;
To my recollection, ALT.NET was formed by people that shared very similar tastes on what 
represents good development tools, practices, and methodologies. This group of people, 
just by the simple fact that they decided to get together under one roof to discuss these 
ideas, showed that they are constantly and decidedly trying to become better at what 
they do.

&lt;/p&gt;

&lt;p&gt;But when you take the step to form a new community or movement (or whatever else you
want to call it) you can&amp;#39;t easily control who jumps on board or who jumps ship - and 
you shouldn&amp;#39;t even try to.
&lt;/p&gt;
&lt;p&gt;Inevitably the original idea started to attract many different kinds of participants, 
which I&amp;#39;m going to roughly distribute in the below four categories (I was tempted to 
use the term personas, but … never mind.)
&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;
		&lt;b&gt;I&amp;#39;m here to help&lt;/b&gt;&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;I like to teach,&lt;/li&gt;
			&lt;li&gt;to write,&lt;/li&gt;
			&lt;li&gt;to contribute to OSS,&lt;/li&gt;
			&lt;li&gt;coordinating UGs and events&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;b&gt;Those who like to complain&lt;/b&gt;&lt;br /&gt;
		A very minor percentage of those know how to externalize their criticism in a constructive way. Unfortunately 
		the majority limit their contributions to rants and trolling. &lt;br /&gt;
		That&amp;#39;s probably the only group of people that I&amp;#39;d try to weed out if I could (but I can&amp;#39;t; and we shouldn&amp;#39;t).
	&lt;/li&gt;
	&lt;li&gt;
		&lt;b&gt;Those who want to learn&lt;/b&gt;&lt;br /&gt;
		&lt;ul&gt;
			&lt;li&gt;They want to hear about other ideas,&lt;/li&gt;
			&lt;li&gt;to figure out how to bring better practices to their work,&lt;/li&gt;
			&lt;li&gt;they have a specific problem and they&amp;#39;re seeking opinions or answers.&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/li&gt;
	&lt;li&gt;
		&lt;b&gt;Heliotropic migrants&lt;/b&gt;&lt;br /&gt;
		The ones who want to be linked to (and hops on) every new, shiny thing for commercial 
		reasons. There&amp;#39;s always this type of people. They need to latch on to what 
		could be the next big thing for the sake of their own livelihood. There&amp;#39;s 
		nothing wrong with that, by the way.
	&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some people just can&amp;#39;t put up with the other types. Some folks go ballistic with 
people on &lt;b&gt;#4&lt;/b&gt;, others can&amp;#39;t stand the whiners in &lt;b&gt;#2&lt;/b&gt;. Some don&amp;#39;t tolerate repeated or trivial questions 
from folks that are just trying to learn.
&lt;/p&gt;

&lt;p&gt;In the midst of all this, it becomes hard to connect &lt;b&gt;#1&lt;/b&gt; and &lt;b&gt;#3&lt;/b&gt;, which I think is 
the ultimate reason for ALT.NET existence.
&lt;/p&gt;

&lt;p&gt;Frankly speaking, I think I&amp;#39;ve personally danced around in all these four categories 
but I find myself most of the time in &lt;b&gt;#3&lt;/b&gt; and some other times in &lt;b&gt;#1&lt;/b&gt;. I do apologize 
for my ventures in &lt;b&gt;#2&lt;/b&gt; – it&amp;#39;s hard to avoid.
&lt;/p&gt;

&lt;p&gt;So, if you dabble in the ALT.NET waters, let me just ask you to exercise a little 
bit of patience. We all still have a lot to learn and there&amp;#39;s very good indications that 
some of those lessons are permeating the .NET development community &amp;mdash;
from the individual developer to the big Enterprise, Inc.
&lt;/p&gt;

&lt;p&gt;Let&amp;#39;s no try to change the world with a single swing of the bat. Changing one 
constructor method at a time will get us further. In the end, the idea is simply to 
more efficiently produce more maintainable and reliable software.
&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=55063" width="1" height="1"&gt;</content><author><name>sergiopereira</name><uri>http://devlicio.us/members/sergiopereira/default.aspx</uri></author><category term="alt.net" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/alt.net/default.aspx" /><category term="Community" scheme="http://devlicio.us/blogs/sergio_pereira/archive/tags/Community/default.aspx" /></entry></feed>
