<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Vineet Gupta</title> <link>http://www.vineetgupta.com</link> <description>Cloud computing, distributed systems, high scalable systems, mobile-web, real-time web, functional programming, concurrency, algorithms and data structures</description> <lastBuildDate>Thu, 05 Apr 2012 20:29:06 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.0.1</generator> <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/VineetGupta" /><feedburner:info uri="vineetgupta" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>12.56</geo:lat><geo:long>77.38</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by-sa/3.0/</creativeCommons:license><image><link>http://creativecommons.org/licenses/by-sa/3.0/</link><url>http://creativecommons.org/images/public/somerights20.gif</url><title>Some Rights Reserved</title></image><feedburner:emailServiceId>VineetGupta</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2FVineetGupta" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FVineetGupta" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2FVineetGupta" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/VineetGupta" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FVineetGupta" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FVineetGupta" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FVineetGupta" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Ffeeds.feedburner.com%2FVineetGupta" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2FVineetGupta" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><item><title>Product Design and the Paradox of Choice</title><link>http://feedproxy.google.com/~r/VineetGupta/~3/ByvSbPrL42A/</link> <comments>http://www.vineetgupta.com/2012/04/product-design-and-the-paradox-of-choice/#comments</comments> <pubDate>Thu, 05 Apr 2012 20:29:06 +0000</pubDate> <dc:creator>Vineet Gupta</dc:creator> <category><![CDATA[Product Design]]></category><guid isPermaLink="false">http://www.vineetgupta.com/?p=10112</guid> <description>Last Sunday my wife finally managed to drag me to get a new pair of jeans. We went to a Levi&amp;#8217;s store where they had choices differing in: Size Color Fit &amp;#8211; slim, skinny, comfort, relaxed Cut &amp;#8211; straight, taper Wash &amp;#8211; stone, acid, something else I cant recall Artificial creases / seams Torn / &lt;a
href='http://www.vineetgupta.com/2012/04/product-design-and-the-paradox-of-choice/'&gt;[...]&lt;/a&gt;</description> <content:encoded><![CDATA[<p>Last Sunday my wife finally managed to drag me to get a new pair of jeans. We went to a Levi&#8217;s store where they had choices differing in:</p><ul><li>Size</li><li>Color</li><li>Fit &#8211; slim, skinny, comfort, relaxed</li><li>Cut &#8211; straight, taper</li><li>Wash &#8211; stone, acid, something else I cant recall</li><li>Artificial creases / seams</li><li>Torn / damaged material</li></ul><p>After 30 minutes of trying, I figured out my type (it&#8217;s a 501, and never will I forget!), but since I could not get the color I wanted (deep blue), I did not end up buying at all.</p><p>This reminded me of Barry Schwartz&#8217; Paradox of Choice (it&#8217;s a 2 min clip &#8211; go on):</p><p><iframe
width="420" height="315" src="http://www.youtube.com/embed/4matGzkYN0w?rel=0" frameborder="0" allowfullscreen></iframe></p><p>As Schwartz said, he has written an entire <a
href="http://www.amazon.com/The-Paradox-Choice-More-Less/dp/0060005688">book</a> on the subject &#8211; it is a brilliant book and should be mandatory reading for marketers and product designers. Here&#8217;s a quick summary:</p><p>1) Too many choices cause decision paralysis</p><ul><li>employee participation in 401(k) pension plan reduced as number of plan options were increased (2% drop for every extra plan option), thus losing out on the equal contribution their employer would have made (upto $ 5,000) &#8211; completely irrational behavior</li><li>multiple other case studies in different areas leading to the same conclusion</li><li>closer home &#8211; almost everyone from my generation has a LIC policy since that was the only choice for a long time, but how many of us have put off picking a SIP plan / mutual fund plan / health insurance plan just because the complexity of choices is so overwhelming?</li></ul><p>2) Too many choices lead to bad decisions</p><ul><li>even if you do manage to get out of paralysis and make a choice, you are likely going to make a bad choice</li><li>people typically make a simpler choice, not the best choice &#8211; it is just too hard to make a good, informed choice</li></ul><p>3) Too many choices cause anxiety</p><ul><li>assuming you made a good choice, you would still not be happy<li>during the decision making you will wonder if you are losing out on a better choice by making this choice</li><li>post-decision &#8211; in case your choice is not satisfactory in any respect, you will regret your decision &#8211; perhaps the other choice would have been better</li></ul><p>4) Too many choices are good if:</p><ul><li>you know exactly what you want &#8211; then you can go and pattern match</li><li>choices are on the same dimension (only one variable is changing)</li></ul><p>(BTW, the book has a lot more to offer than my little summary here, so don&#8217;t judge the book by my writing)</p><p>Now while too much choice would be a poor thing, perhaps a little bit of choice would not be too bad? Turns out that the amount of time required to make a decision is directly related to the number of choices. This is called <a
href="http://en.wikipedia.org/wiki/Hick%27s_law">Hick&#8217;s Law</a>. So the best case scenario is to provide a single choice at any given point in time.</p><p>The implications for product design are obvious. A typical consumer software product is a means to an end, and not the end in itself. The product should get out of the way to let the user accomplish his task. To a designer, each carefully thought thru feature of the product means a lot. A user couldn&#8217;t care less. He will start your app for a specific task, do the task and switch out. If we provide choices, we create cognitive load for the user, slowing him down. Worse, the user may not even understand the choices and end up making a bad decision.</p><p>Two years back, when my father was to be operated upon for a heart-valve replacement, the cardiac surgeon offered us a set of choices for the kind of valves that could be put in:</p><ul><li>mechanical valves would have longer life (so no replacement required), have no allergic effects, but would require blood thinners</li><li>biological valves would have lesser life, could cause allergic reactions, but would not require blood thinners</li></ul><p>It does not stop here &#8211; each of these types have multiple sub-types, and the impact of the type of valve also depends on other aspects of the patient&#8217;s health, for example in my dad&#8217;s case his blood has a tendency to not clot quickly, which means that blood thinners can create complications in the event of an injury. Now how does one make a decision in the face of these choices whose consequences are really hard for a lay person to understand? I wish the doctor had made one for us, but even on pressing, he wouldn&#8217;t give a clear recommendation. This was hugely frustrating, and scary to an extent &#8211; we did not want to make a wrong choice.</p><p>As product designers, our role is like that of the cardiac surgeon &#8211; we understand nuances and complexities of the software that the user cannot fathom and does not want to understand. It is our job to choose for the user. Yet product upon product offers choices whose consequences are not understood by the user. And I am talking not just about settings. Every menu option, every tab offering a different view, every sorting option, every new filter, every additional use-case we try to satisfy &#8211; it all adds up to the set of choices in front of the user at a given point in time. It is overwhelming!</p><p>Besides, the smartphone is introducing software to a lot of people who have no prior experience of software. They do not even understand the medium &#8211; software with its infinite malleability can present some very abstract models for the end user. Decision paralysis is inevitable. Making poor choices is inevitable. Dissatisfaction and regret arising out of those choices is inevitable. An unhappy user is inevitable.</p><p>Products designed by engineers are particularly susceptible to drowning their users in a sea of choices. As an engineer, I like to keep my design flexible to accommodate potential future use-cases. But my user does not care for the flexibility &#8211; his requirements are met by 20% of the features I am offering. The rest is just cruft he has to wade thru in order to get his task done. Why expose the flexibility of my design to my user? Why not give him a simpler model with lesser flexibility and lesser choice?</p><p>I am a geek, and feel quite comfortable digesting a lot of information to make a decision. So my tendency is to surface information to the user if it is available. However, my user &#8211; a teenager in the middle of a conversation, or a busines-woman on the move &#8211; is not the same. She has started my app for a specific task, would do it in under a minute and then switch out. She may not even realize that there is information there, and if she does, it is likely that her eyes would glaze over because of all the clutter and she would switch out of my app!</p><p>So what is the solution? I am not sure, but here is what may work:</p><ul><li>Choose for the user &#8211; make him follow a path instead of opening up multiple paths</li><li>Give the user ONE thing to focus on at a given point in time</li><li>If you absolutely have to provide a choice (and remember this is not just about settings), then minimize the number of choices and communicate the consequences clearly</li><li>Model the product on well-established metaphors from daily life &#8211; desk, shelf, book, paper, etc. &#8211; so that the user can anticipate the result of his choices based on a familiar mental model</li><li>Keep it familiar for the user &#8211; follow the conventions of the platform instead of inventing your own</li></ul><p>Easier said than done of course. One fear that stops me from making a choice on behalf of the user is the fear of making the wrong choice &#8211; what if it does not work for the user? But here is the deal &#8211; if I do not make a choice, I will force the user to make one, which in itself is bad enough. Worse, the choice made by the user is likely to be a poor one as compared to even a sub-optimal choice on the part of the designer, since the designer has way more context and makes the choice after careful thought, while the user makes the choice based on very little context, in a state of rush, distracted by the task he is trying to accomplish.</p><p>The larger issue is that as a society, our value system is based on &#8220;more.&#8221; The incentive is to add, not subtract. Consequently, every product gathers cruft over a period of time, as feature requests and market pressure lead to bells and whistles getting added. So even if you started off with a product that worked well for the user, over a period of time it would cease to do so. Almost every single IM product out there &#8211; Yahoo, MSN, AOL, ICQ &#8211; is a victim of this tendency. Ditto for social networking &#8211; MySpace is a shining example. Even Google Search has gathered cruft &#8211; it first picked up search result previews from Bing and has now integrated the Google+ bar under pressure from Facebook. Has this improved Google Search? No! But if you are working for the Search group at Google and tasked with improving Google Search &#8211; a near perfect product &#8211; would you be thinking about adding stuff or removing stuff? It is very hard to beat social conditioning and think about creating value by subtraction.</p> <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ByvSbPrL42A:5FrCPQBc4x8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ByvSbPrL42A:5FrCPQBc4x8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=ByvSbPrL42A:5FrCPQBc4x8:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ByvSbPrL42A:5FrCPQBc4x8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=ByvSbPrL42A:5FrCPQBc4x8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ByvSbPrL42A:5FrCPQBc4x8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=ByvSbPrL42A:5FrCPQBc4x8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ByvSbPrL42A:5FrCPQBc4x8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VineetGupta/~4/ByvSbPrL42A" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.vineetgupta.com/2012/04/product-design-and-the-paradox-of-choice/feed/</wfw:commentRss> <slash:comments>0</slash:comments> <feedburner:origLink>http://www.vineetgupta.com/2012/04/product-design-and-the-paradox-of-choice/</feedburner:origLink></item> <item><title>We all owe big to Dennis Ritchie</title><link>http://feedproxy.google.com/~r/VineetGupta/~3/ER3LQLrIUtQ/</link> <comments>http://www.vineetgupta.com/2011/10/we-all-owe-big-to-dennis-ritchie/#comments</comments> <pubDate>Thu, 13 Oct 2011 21:27:11 +0000</pubDate> <dc:creator>Vineet Gupta</dc:creator> <category><![CDATA[Personal]]></category><guid isPermaLink="false">http://www.vineetgupta.com/?p=10108</guid> <description>I just came back from IIT Guwahati and discovered that Dennis Ritchie has passed away Most people would know of Dennis Ritchie as the person who invented C and Unix. What most folks do not realize is how profound C and Unix were when they were created and what amazing impact they have had on &lt;a
href='http://www.vineetgupta.com/2011/10/we-all-owe-big-to-dennis-ritchie/'&gt;[...]&lt;/a&gt;</description> <content:encoded><![CDATA[<p>I just came back from IIT Guwahati and discovered that Dennis Ritchie has passed away</p><p>Most people would know of Dennis Ritchie as the person who invented C and Unix. What most folks do not realize is how profound C and Unix were when they were created and what amazing impact they have had on the industry.</p><p>Consider this &#8211; before C, you had to program directly to the instruction set of the machine you were programming on. Today when most hardware happens to be x86 or ARM, this seems simple, but back then, the variety of hardware was far more. And this hardware was different not just in terms of instruction sets, but also in terms of information representation, memory addressing, etc. Sure enough there were languages like Fortran and COBOL which could do math and data, but there was no general purpose language which could produce programs that could compete in terms of performance with custom code written for the hardware. Writing a portable program, much less a portable operating system was un-imaginable.</p><p>And yet, Dennis Ritchie imagined just such a world and invented a highly performant, high level programming language and then used that to write an operating system which could be ported to any hardware. This one change meant that programmers did not have to create a new OS for every new piece of hardware that got thrown at them &#8211; they could take for granted a set of tools, calls and programs, as being available and could spend time going up the value chain and doing more interesting things than just re-inventing the wheel. The result was a spurt of innovation and growth which allowed the industry to grow exponentially into a myriad different directions leading to the world we are in.</p><p>If you are a programmer, you owe a lot to Ritchie, whether you have ever programmed in C or worked on Unix or not.</p><p>[Edit: Bjarne Stroustrup expresses the same sentiment way more eloquently: <a
href="http://herbsutter.com/2011/10/12/dennis-ritchie/">http://herbsutter.com/2011/10/12/dennis-ritchie/</a></p><p>Most of us are happy to settle for incremental change. People like Ritchie don’t, and that’s what sets them apart.]</p> <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ER3LQLrIUtQ:_DBykPKFuT4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ER3LQLrIUtQ:_DBykPKFuT4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=ER3LQLrIUtQ:_DBykPKFuT4:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ER3LQLrIUtQ:_DBykPKFuT4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=ER3LQLrIUtQ:_DBykPKFuT4:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ER3LQLrIUtQ:_DBykPKFuT4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=ER3LQLrIUtQ:_DBykPKFuT4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ER3LQLrIUtQ:_DBykPKFuT4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VineetGupta/~4/ER3LQLrIUtQ" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.vineetgupta.com/2011/10/we-all-owe-big-to-dennis-ritchie/feed/</wfw:commentRss> <slash:comments>8</slash:comments> <feedburner:origLink>http://www.vineetgupta.com/2011/10/we-all-owe-big-to-dennis-ritchie/</feedburner:origLink></item> <item><title>The True Legacy of Steve Jobs</title><link>http://feedproxy.google.com/~r/VineetGupta/~3/-yIeHSX_4nY/</link> <comments>http://www.vineetgupta.com/2011/10/the-true-legacy-of-steve-jobs/#comments</comments> <pubDate>Thu, 06 Oct 2011 03:46:25 +0000</pubDate> <dc:creator>Vineet Gupta</dc:creator> <category><![CDATA[Personal]]></category><guid isPermaLink="false">http://www.vineetgupta.com/?p=10102</guid> <description>Steve Jobs passed away today &amp;#8211; I woke up and read the news on my iPhone, like much of the world. I never thought I would be so affected by the passing away of someone I never knew personally. But if you are in the world of tech and developing consumer products, it is not &lt;a
href='http://www.vineetgupta.com/2011/10/the-true-legacy-of-steve-jobs/'&gt;[...]&lt;/a&gt;</description> <content:encoded><![CDATA[<p>Steve Jobs passed away today &#8211; I woke up and read the news on my iPhone, like much of the world.</p><p>I never thought I would be so affected by the passing away of someone I never knew personally. But if you are in the world of tech and developing consumer products, it is not possible to have not thought about life as Steve Jobs &#8211; how his brain functions, how he figures out what should be built, how he sets the bar, how he hires and build teams, how he delves upon every aspect of the product, &#8230; you wish you had 0.1% of his ability, you wish you could be more like him, since being him means creating profound impact, and that is what you are really here for.</p><p>And this I believe is his true legacy. The products he helped create would have a shelf life of maybe a decade, Apple as a company would be perhaps super successful for another 2-3 decades, but what would inspire generations of current and future entrepreneurs, programmers and designers is the way he set about building products:</p><ul><li>leapfrogging the current state of the art, not incremental change</li><li>relentless focus on the user</li><li>not settling for less than perfection</li></ul><p>This approach to building products is his true legacy, and for that, the world would be a better place.</p><div></div> <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VineetGupta?a=-yIeHSX_4nY:lm3HinE0fls:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=-yIeHSX_4nY:lm3HinE0fls:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=-yIeHSX_4nY:lm3HinE0fls:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=-yIeHSX_4nY:lm3HinE0fls:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=-yIeHSX_4nY:lm3HinE0fls:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=-yIeHSX_4nY:lm3HinE0fls:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=-yIeHSX_4nY:lm3HinE0fls:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=-yIeHSX_4nY:lm3HinE0fls:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VineetGupta/~4/-yIeHSX_4nY" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.vineetgupta.com/2011/10/the-true-legacy-of-steve-jobs/feed/</wfw:commentRss> <slash:comments>4</slash:comments> <feedburner:origLink>http://www.vineetgupta.com/2011/10/the-true-legacy-of-steve-jobs/</feedburner:origLink></item> <item><title>Deciphering Complex C Declarations</title><link>http://feedproxy.google.com/~r/VineetGupta/~3/SoclXVUdbk4/</link> <comments>http://www.vineetgupta.com/2011/03/deciphering-complex-c-declarations/#comments</comments> <pubDate>Thu, 17 Mar 2011 12:47:40 +0000</pubDate> <dc:creator>Vineet Gupta</dc:creator> <category><![CDATA[Languages]]></category> <category><![CDATA[C declarations]]></category><guid isPermaLink="false">http://www.vineetgupta.com/?p=10094</guid> <description>As I have mentioned in earlier posts, we are building a x-platform mobile chat client. One of the platforms is iPhone and that means that the team is having to learn Objective C, and therefore C. Last couple of days, I have been spending time  helping my team understand and appreciate C better. Yesterday, we &lt;a
href='http://www.vineetgupta.com/2011/03/deciphering-complex-c-declarations/'&gt;[...]&lt;/a&gt;</description> <content:encoded><![CDATA[<p>As I have mentioned in <a
href="http://www.vineetgupta.com/2011/03/mobile-platforms-part-1-android/"> earlier</a> <a
href="http://www.vineetgupta.com/2011/03/mobile-platforms-part-2-blackberry/"> posts</a>, we are building a x-platform mobile chat client. One of the platforms  is iPhone and that means that the team is having to learn Objective C, and  therefore C. Last couple of days, I have been spending time  helping my team understand and appreciate C better. Yesterday, we  got really deep on figuring out how to read a C declaration and it was a lot of  fun taking people thru the rules and examples of how to read some complex C  declarations. I am summarizing the key aspects over here.</p><p>PS: Could not cross link to references since there is no authoritative version  of the <a
href="http://en.wikipedia.org/wiki/C99">C-99</a> standard in an HTML  form &#8211; the <a
href="http://www.open-std.org/jtc1/sc22/wg14/www/standards">standard docs</a> are all in <a
href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf"> PDF</a>.</p><h3>C Declaration Grammar</h3><p>Understanding a C declaration requires that we understand what elements can a  C declaration have. While I will describe the overall syntax over here, I will  not go into semantics:</p><pre><em>declaration:
	declaration-specifiers init-declarator-list<sub>opt</sub> ;
declaration-specifiers:
	storage-class-specifier declaration-specifiers<sub>opt</sub>
	type-specifier declaration-specifiers<sub>opt</sub>
	type-qualifier declaration-specifiers<sub>opt</sub>
	function-specifier declaration-specifiers<sub>opt</sub>
init-declarator-list:
	init-declarator
	init-declarator-list , init-declarator
init-declarator:
	declarator
	declarator = initializer</em></pre><p>This is what the above grammar is saying:</p><ul><li>A declaration is:<ul><li>declaration-specifiers followed by an optional list of  		init-declarators</li></ul></li><li>The declaration-specifiers are:<ul><li>A storage-class specifier, followed by other optional declaration  		specifiers</li><li>A type-specifier, followed by other optional declaration specifiers</li><li>A type-qualifier, followed by other optional declaration specifiers</li><li>A function-specifier, followed by other optional declaration  		specifiers</li></ul></li><li>List of init-declarators is:<ul><li>An init-declarator</li><li>An init-declarator list, followed by a comma, followed by an  		init-declarator</li></ul></li><li>An init-declarator is:<ul><li>A declarator</li><li>A declarator followed by an assignment operator (=),  followed  		by an initializer</li></ul></li></ul><h3>Declaration Specifiers</h3><p>As per the grammar defined  above, a declaration starts with a declaration specifier. A  declaration-specifier can be:</p><ul><li><strong>Storage-class specifier:</strong> These are: <code>auto</code>, <code>static</code>, <code>extern</code>, <code>register</code> and <code>typedef</code>. Default is <code>auto</code>, so if nothing is specified, <code>auto</code> is assumed.</li><li><strong>Type-specifier:</strong> A type-specifier is one of the following. Default is <code>int</code><ul><li><code>void</code></li><li><code>char</code></li><li><code>signed char</code></li><li><code>unsigned char</code></li><li><code>short</code>, <code>signed short</code>, <code>short int</code>, or <code>signed short int</code></li><li><code>unsigned short</code> or <code>unsigned short int</code></li><li><code>int</code>, <code>signed</code> or <code>signed int</code></li><li><code>unsigned</code> or <code>unsigned int</code></li><li><code>long</code>, <code>signed long</code>, <code>long int</code> or <code>signed long int</code></li><li><code>unsigned long</code> or <code>unsigned long int</code></li><li><code>long long</code>, <code>signed long long</code>, <code>long long int</code>, or <code>signed long long int</code></li><li><code>unsigned long long</code> or <code>unsigned long long int</code></li><li><code>float</code></li><li><code>double</code></li><li><code>long double</code></li><li><code>_Bool</code></li><li><code>float _Complex</code></li><li><code>double _Complex</code></li><li><code>long double _Complex</code></li><li><em>struct-or-union-specifier</em></li><li><em>enum-specifier</em></li><li><em>typedef-name</em></li></ul></li><li><strong>Type-Qualifer:</strong> Applicable only to <a
href="http://en.wikipedia.org/wiki/Value_(computer_science)">l-values</a>: <code>const</code>, <code>volatile</code>, <code>restrict</code></li><li><strong>Function-specifier:</strong> There is only one function specifier: <code>inline</code></li></ul><h3>Declarators</h3><p>What follows a declaration-specifier is a init-declarator-list &#8211; a comma  separated sequence of declarators that may optionally be initialized. A declarator [2] is defined as:</p><pre><em>declarator:
	pointer<sub>opt</sub> direct-declarator
direct-declarator:
	identifier
	( declarator )
	direct-declarator [ type-qualifier-list<sub>opt</sub> assignment-expression<sub>opt</sub> ]
	direct-declarator [ static type-qualifier-list<sub>opt</sub> assignment-expression ]
	direct-declarator [ type-qualifier-list static assignment-expression ]
	direct-declarator [ type-qualifier-list<sub>opt</sub> * ]
	direct-declarator ( parameter-type-list )
	direct-declarator ( identifier-list<sub>opt</sub> )
pointer:
	* type-qualifier-list<sub>opt</sub>
	* type-qualifier-list<sub>opt</sub> pointer
type-qualifier-list:
	type-qualifier
	type-qualifier-list type-qualifier
parameter-type-list:
	parameter-list
	parameter-list , ...
parameter-list:
	parameter-declaration
	parameter-list , parameter-declaration
parameter-declaration:
	declaration-specifiers declarator
	declaration-specifiers abstract-declarator<sub>opt</sub>
identifier-list:
	identifier
	identifier-list , identifier</em></pre><p>We can break down the above grammar the same way we did for the grammar of a  declaration, but I&#8217;m gonna skip that and give some examples of declarators, just  to give an idea of what declarators are supposed to be:</p><ul><li><code>i</code> &#8211; An identifier (and hence a direct-declarator)</li><li><code>i, j</code> &#8211; A list of identifiers</li><li><code>i = 10</code> &#8211; An Identifer followed by an assignment expression</li><li><code>*p</code> &#8211; A pointer declarator</li><li><code>* const p</code> &#8211; A pointer declarator with a type-qualifer (<code>const</code>)</li><li><code>a[10]</code> &#8211; An array declarator with a constant size</li><li><code>a[*]</code> &#8211; An array declarator with a variable size</li><li><code>a[]</code> &#8211; An array declarator with an unspecified size &#8211; the size will need to be defined somewhere else</li><li><code>f()</code> &#8211; A function declarator</li><li><code>f(void)</code> &#8211; A function declarator with no parameters</li><li><code>f(int i)</code> &#8211; A function declarator with a parameter</li><li><code>f(int i, int j)</code> &#8211; A function declarator with a parameter-list</li></ul><h3>Structure of a Declaration</h3><p>Now that we have developed an idea of declaration-specifiers and declarators,  we can see that the overall structure of a declaration is of the following form:</p><ol><li>One or more declaration-specifiers followed by</li><li>One or more declarators (separated by commas)</li></ol><p>However, not all combinations are valid. The following are not allowed:</p><pre>f()[] // function can't return an array
f()() // function can't return a function
a[]() // array can't hold a function</pre><p>The following, however, are allowed:</p><pre>(* f())[] // function returning pointer to an array
(* f())() // function returning pointer to a function
(* a[])() // array holding pointers to functions</pre><p>If you are flummoxed by the last three examples of combining pointers,  functions and arrays, you are not alone. Such declarations can look scary till  you develop a technique to start deciphering them. In order to do that however,  we need to know the basic order of precedence</p><h3>Operator Precedence</h3><ol><li>Parentheses grouping together parts of a declaration</li><li>Postfix operators: parentheses (for a function), square brackets (for an  	array)</li><li>Prefix operator: Asterisk (for a pointer)</li></ol><p>Here are some examples of how this order applies:</p><table
style="width: 100%;"><tbody><tr><td>Declaration</td><td>Same as</td><td>Not Same as</td></tr><tr><td><code>int * f();</code></td><td><code>int * (f());</code></td><td><code>int (* f());</code></td></tr><tr><td><code>int * a[];</code></td><td><code>int * (a[]);</code></td><td><code>int (* a[]);</code></td></tr></tbody></table><p>Now the way to use these rules is as follows:</p><ol><li>Read from left to right</li><li>For the first identifier you encounter (or if there is no identifier,  	then look for the inner-most construct), look to the immediate right<ul><li>If there is nothing, or if you have a closing parenthesis, go to 3</li><li>Otherwise you have a function declarator indicated by () or an array  		declarator indicated by [] to the right of the identifier</li><li>Read left to right &#8211; you will have a &#8220;function returning&#8221; or &#8220;array  		of&#8221;</li><li>This would typically end with a right parenthesis, or the end of the  		declarator (semi-colon or assignment)</li></ul></li><li>Look to the left<ul><li>If you find nothing on the left, or if you find an opening  		parenthesis, go to 4</li><li>Otherwise you have a pointer declarator indicated by an asterisk to  		the left of the identifier. Read right to left &#8211; you will get a &#8220;pointer  		to&#8221;</li><li>This would end with a left parenthesis, or start of declarator</li></ul></li><li>At this point you have either<ul><li>A complete declarator &#8211; then you are done</li><li>Or an expression in parenthesis &#8211; go back to step 2.</li></ul></li></ol><p>If you did not realize this on reading the above description, what we are  really doing in steps 2 and 3 is to convert the C declaration into a postfix  expression by taking into account the lower predence of the asterisk. This same  approach is used in the <a
href="http://www.cdecl.org/">cdecl</a> program given in K&amp;R.</p><p>This will become clear with a few examples:</p><pre>int * f();</pre><ul><li>Start with identifer &#8211; f</li><li>Parenthesis to the right &#8211; &#8220;function returning&#8221;</li><li>Asterisk to the left &#8211; &#8220;pointer to&#8221;</li><li>int</li></ul><p>The postfix expression is:</p><pre>f () * int // "f is" "a function returning" "pointer to int"</pre><p>Here are a few more examples:</p><pre>int * a[10];
// postfix expression: a [10] * int
// "a is" "array of 10" "pointers to int"</pre><pre>int (* a)[10]
// postfix: a * [10] int
// "a is" "pointer to" "array of 10" "int"</pre><pre>int **p;
// postfix: p * * int
// "p is" "pointer to" "pointer to" int</pre><pre>int **p[10];
// postfix: p [10] * * int
// "p is" "array of 10" "pointer to" "pointer to" int</pre><pre>int *f();
// postfix: f () * int
// "f is" "function returning" "pointer to" int</pre><pre>int (*f)();
// postfix: f * () int
// "f is" "a pointer to" "function returning" int</pre><pre>int (* vtable[])();
// postfix: vtable [] * () int
// vtable is an array of pointer to function returning int</pre><pre>int (* a[])(int, int);
// postfix: a [] * (int, int) int
// a is an array of pointer to function returning int
// and taking (int, int) as parameters</pre><h3>Applying Type-Qualifiers</h3><p>The way you apply a type-qualifier (<code>const</code>, <code>volatile</code>) is that:</p><ol><li>If next to a type-specifer, it applies to the type-specifier</li><li>Otherwise applies to the asterisk (pointer) on its immediate left</li></ol><p>Examples:</p><pre>const int * p;
// postfix: p * const int
// p is a pointer to a const int</pre><pre>int const * p;
// postfix: p * const int
// p is a pointer to a const int</pre><pre>int * const p;
// postfix: p const * int
// p is a const pointer to int</pre><pre>int * const * p;
// postfix: p * const * int
// p is a pointer to a const pointer to int</pre><pre>int * const * (* p)();
// postfix: p * () * const * int
// p is a pointer to a function returning a
// pointer to const-pointer-to-int</pre><h3>Abstract Declarators</h3><p>An abstract declarator is a declarator without an identifer. However, lack of  an identifier does not mean that we can&#8217;t interpret such declarators, since the  missing identifier&#8217;s position can be determined by the placement of (), [] and *  Some examples will help clarify this:</p><pre>int *
// pointer to int</pre><pre>int * [10]
// array of 10 pointers to int</pre><pre>int * (*)
// function returing a pointer to int and taking no arguments</pre><pre>int (*) [10]
// pointer to array of 10 int</pre><pre>int (*) (*)
// pointer to a function returning an int and taking no arguments</pre><p>With this background, lets tackle this gem from Andrew Koenig&#8217;s C Traps and  Pitfalls (<a
href="http://www.literateprogramming.com/ctraps.pdf">PDF</a>):</p><pre>(*(void(*)())0)();</pre><p>Clearly, we are casting 0 to some type here. The type being:</p><pre>void(*)()</pre><p>We know this type:</p><pre>// postifx: * () void
// pointer to function returning void</pre><p>In the next step, this pointer is de-referenced and then called. So what is  happening here is that zero is being cast to a pointer to a function returning  void, then dereferenced and called!</p> <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VineetGupta?a=SoclXVUdbk4:sflFZcBsr4g:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=SoclXVUdbk4:sflFZcBsr4g:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=SoclXVUdbk4:sflFZcBsr4g:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=SoclXVUdbk4:sflFZcBsr4g:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=SoclXVUdbk4:sflFZcBsr4g:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=SoclXVUdbk4:sflFZcBsr4g:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=SoclXVUdbk4:sflFZcBsr4g:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=SoclXVUdbk4:sflFZcBsr4g:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VineetGupta/~4/SoclXVUdbk4" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.vineetgupta.com/2011/03/deciphering-complex-c-declarations/feed/</wfw:commentRss> <slash:comments>4</slash:comments> <feedburner:origLink>http://www.vineetgupta.com/2011/03/deciphering-complex-c-declarations/</feedburner:origLink></item> <item><title>Mobile Platforms – Part 2 – Blackberry</title><link>http://feedproxy.google.com/~r/VineetGupta/~3/q3t068xNfHc/</link> <comments>http://www.vineetgupta.com/2011/03/mobile-platforms-part-2-blackberry/#comments</comments> <pubDate>Sat, 12 Mar 2011 13:56:34 +0000</pubDate> <dc:creator>Vineet Gupta</dc:creator> <category><![CDATA[Mobile]]></category> <category><![CDATA[Blackberry Java Development]]></category><guid isPermaLink="false">http://www.vineetgupta.com/?p=10081</guid> <description>As I mentioned on my previous post, we are building a x-platform native mobile chat client for Android, iPhone and Blackberry. The earlier post was about the Android platform, this one is on Blackberry. After having gone thru the Android documentation and videos from Google IO, I found the documentation on Blackberry to be somewhat &lt;a
href='http://www.vineetgupta.com/2011/03/mobile-platforms-part-2-blackberry/'&gt;[...]&lt;/a&gt;</description> <content:encoded><![CDATA[<p>As I mentioned on my <a
href="http://www.vineetgupta.com/2011/03/mobile-platforms-part-1-android/"> previous post</a>, we are building a x-platform native mobile chat client  for Android, iPhone and Blackberry. The earlier post was about the Android  platform, this one is on Blackberry.</p><p>After having gone thru the Android  documentation and videos from Google IO, I found the <a
href="http://us.blackberry.com/developers">documentation</a> on Blackberry to  be somewhat disorganized &#8211; it is not easy to get the big picture and grasp key  concepts. You need to go thru a lot of documentation to figure out how things works  together as a system. I also tried to access the materials from <a
href="http://www.blackberrydevcon.com/2010-on-demand"> http://www.blackberrydevcon.com/2010-on-demand</a> but it turned out that it would  require a registration for $ 20. That was a bit of a WTF moment &#8230; I mean, you  want to make money by selling conference materials? Who does that?? Anyway I  proceeded to register on <a
href="https://www.eventreg.com/pls/pg_rim/reg_rim.reg_login?icpid=&amp;ipr_code=ONDNON"> https://www.eventreg.com/pls/pg_rim/reg_rim.reg_login?icpid=&amp;ipr_code=ONDNON</a> and after filling two lengthy forms, was unable to make a payment despite  getting a registration id. I wrote to <a
href="mailto:BlackBerryDEVCON@eventreg.com">BlackBerryDEVCON@eventreg.com</a> with my registration id (this was on 3rd Mar),  but am yet to hear from them. Rather discourgaing for somene starting off on a  new platform.</p><h2>The Blackberry Platform</h2><p>The Blackberry platform consists of the following key components:</p><ul><li><a
href="http://us.blackberry.com/developers/started/">Phone</a>:  	Blackberry phones support two kind of applications:<ul><li><a
href="http://us.blackberry.com/developers/javaappdev/">Java Apps</a>:  		These are native Blackberry apps which can take full advantages of all  		the features available in a Blackberry phone, for example the <a
href="http://us.blackberry.com/developers/blackberrymessenger/">BBM  		API</a>.</li><li><a
href="http://us.blackberry.com/developers/browserdev/index.jsp"> WebWorks Apps</a>: Browser based apps built using HTML, CSS, JS and capable  		of accessing native APIs thru the <a
href="http://us.blackberry.com/developers/browserdev/widgetsdk.jsp"> WebWorks SDK</a>.</li></ul></li><li><a
href="http://us.blackberry.com/developers/tablet/">Tablet</a>:  	One can build playbook tablet applications in two ways:<ul><li><a
href="http://us.blackberry.com/developers/tablet/adobe.jsp">Adobe  		AIR apps</a>: Based on Action Script 3 with a bunch of Blackberry  		specific APIs. Use this to build apps with a <a
href="http://docs.blackberry.com/en/developers/deliverables/24075/UI_APIs_for_Tablet_OS_look_and_feel_1354896_11.jsp"> native look and feel</a>.</li><li><a
href="http://us.blackberry.com/developers/tablet/webworks.jsp"> WebWorks apps</a>: Similar to WebWorks apps for the Blackberry phone.</li></ul></li><li><a
href="http://us.blackberry.com/developers/platform/">Platform Services</a>:  	Bunch of services provided by RIM including <a
href="http://us.blackberry.com/developers/platform/pushapi.jsp">Push</a>, <a
href="http://us.blackberry.com/developers/platform/locateservice/"> Location</a>, <a
href="http://us.blackberry.com/developers/platform/adservices/"> Advertising</a> and <a
href="http://us.blackberry.com/developers/platform/paymentservice.jsp"> Payment</a> services</li><li>Connectivity Services: RIM also provides a couple of connectivity  	services:<ul><li><a
href="http://us.blackberry.com/apps-software/server/">Blackberry  		Enterprise Server (BES)</a>: Enterprises can make their mail  		infrastructure available over the Blackberry network using BES which  		acts as a relay between the mail server and Blackberry&#8217;s NOC co-located  		with a carrier providing Blackberry services. One of the components of  		BES called the <a
href="http://docs.blackberry.com/en/admin/deliverables/7335/BB_MDS_267706_11.jsp"> Mobile Data System (MDS)</a> provides  HTTP and TCP proxies for a  		Blackberry application. This allows a Blackberry device to communicate  		with app / web-servers behind a corporate firewall without using VPN.</li><li><a
href="http://us.blackberry.com/support/software/internet.jsp"> Blackberry Internet Services (BIS)</a>: For individuals, the alternative  		to BES is the BIS. This provides the ability to access mail over POP and  		IMAP email without going thru BES. The service is provided in  		partnership with a carrier.</li></ul></li><li><a
href="http://us.blackberry.com/developers/appworld/distribution.jsp"> AppWorld</a>: The blackberry application store front, similar to the iPhone  	App Store</li></ul><p>This post is specific to Java development for the Blackberry phones.  Moreover, it is specific to Blackberry 5 since <a
href="http://us.blackberry.com/developers/choosingtargetos.jsp">75-85% of app  downloads from the App World are from Blackberry 5 devices</a>.</p><h2>Java ME</h2><p>Native apps on the Blackberry phone are Java apps that run on RIM&#8217;s JVM  implementation. This Java API is based on Java ME with Blackberry adding its own  extensions. If you are new to Java ME like I am, here is a quick review:</p><p>Java ME (Micro Edition) is Java targeted for small devices. It is a  collection of specs and technologies to address the needs of providing a  programming interface to small devices. Since there is a large variety in the  types of devices and their capabilities, it is quite likely that a device  manufacturer would implement some specs and not others, leading to API  fragmentation and hence non-portable code. To address this, Java ME defines  capabilities for devices which are organized into  Configurations, Profiles and Optional APIs:</p><p><img
src="http://developers.sun.com/mobility/getstart/articles/survey/fig1.jpg" alt="Organization of the Java ME technologies" /></p><p>(Organization of the Java ME technologies &#8211; source: <a
href="http://developers.sun.com/mobility/getstart/articles/survey"> http://developers.sun.com/mobility/getstart/articles/survey/</a>)</p><ul><li><strong>Configurations</strong>: A configuration is a specification for  	a virtual machine + some base APIs designed for a specific kind of device,  	based on memory constraints and processor power.<ul><li><a
href="http://jcp.org/en/jsr/detail?id=139">Connected Limited   		Device Configuration (CLDC)</a>: The CLDC is meant for small wireless  		devices with intermittent network connections, like pagers, mobile  		phones and PDAs</li><li><a
href="http://jcp.org/en/jsr/detail?id=218">Connected Device  		Configuration (CDC)</a>:  The CDC is a superset of the CLDC meant for larger devices with  		robust connections, like Set-top boxes and internet appliances.</li></ul></li><li><strong>Profiles:</strong> A profile is more specific than a  	configuration. A profile is based on a configuration and adds APIs for UI,  	Storage, or whatever else is required to develop apps. For CLDC, a profile called <a
href="http://jcp.org/en/jsr/detail?id=118">Mobile Information  		Device Profile (MIDP)</a> is specified. For CDC, there is a hierarchy of profiles:<ul><li><a
href="http://jcp.org/en/jsr/detail?id=219">Foundation Profile</a></li><li><a
href="http://jcp.org/en/jsr/detail?id=217">Personal Basis Profile</a></li><li><a
href="http://jcp.org/en/jsr/detail?id=215">Personal Profile</a></li><li><a
href="http://jcp.org/en/jsr/detail?id=228">Information Module Profile</a></li></ul></li><li><strong>Optional APIs:</strong> A device implementing Java ME may define  	additional optional APIs besides the ones that are defined as a part of a  	Java ME profile.</li></ul><p>Based on the configurations, profiles and optional APIs, Java ME is able to  address a wide variety of small devices including Handsets, Smart-cards and  embedded devices:</p><p><img
src="http://developers.sun.com/mobility/getstart/articles/survey/fig2.jpg" alt="Java ME technologies by device type" width="600" height="242" /></p><p>(Map of the Java ME Universe &#8211; source: <a
href="http://developers.sun.com/mobility/getstart/articles/survey/"> http://developers.sun.com/mobility/getstart/articles/survey/</a>)</p><p>A device implements a stack consisting of a Configuration, Profile and  Optional APIs. For wireless devices like mobile phones, the stack is based on  CLDC, MIDP and some optional APIs. An application targeting the MIDP profile is  called a MIDlet.</p><p><img
src="http://www.oracle.com/ocom/groups/public/@otn/documents/digitalasset/148676.jpg" alt="Stack for Wireless devices" width="358" height="277" /></p><p>(Stack for wireless devices. Source: <a
href="http://www.oracle.com/technetwork/java/javame/tech/technology-139316.html"> http://www.oracle.com/technetwork/java/javame/tech/technology-139316.html</a>)</p><p>As one can imagine, despite the CLDC and MIDP being defined, a lot of  commonly required functionality and the way it is provided remains un-defined,  thus introducing scope for API fragmentation and un-portable code. This was  addressed thru <a
href="http://jcp.org/en/jsr/detail?id=185">JSR 185 &#8211; Java  Technology for the Wireless Industry</a> &#8211; a specification that addresses  fragmentation by defining key APIs and code portability issues by clarifying  spces and providing a suite of compliance tests. JSR 185 consists of CLDC 1.0 or  1.1, MIDP 2.0 and WMA (Windows Messaging API &#8211; <a
href="http://jcp.org/en/jsr/detail?id=120">JSR 120</a> and <a
href="http://jcp.org/en/jsr/detail?id=205">JSR 205</a>), with support for  MMAPI (Mobile Media API &#8211; <a
href="http://jcp.org/en/jsr/detail?id=135">JSR 135</a>)  being optional:</p><p><img
src="http://developers.sun.com/mobility/getstart/images/stack2.jpg" alt="JSR 185 - JTWI Stack" width="330" height="208" /></p><p>(JSR 185 &#8211; JTWI Stack. Source: <a
href="http://developers.sun.com/mobility/getstart/"> http://developers.sun.com/mobility/getstart/</a>)</p><p>This was superseded by the <a
href="http://developers.sun.com/mobility/midp/articles/msaintro/">MSA (Mobile  Services Architecture) specification</a> which defined two stacks: a full stack  of 16 JSRs and a subset of 8 JSRs:</p><p><img
src="http://developers.sun.com/mobility/midp/articles/msaintro/fig1.gif" alt="MSA Stacks" width="359" height="320" /></p><p>(MSA Stacks. Source: <a
href="http://developers.sun.com/mobility/midp/articles/msaintro/"> http://developers.sun.com/mobility/midp/articles/msaintro/</a>)</p><p>Blackberry 5 <a
href="http://docs.blackberry.com/en/developers/deliverables/9095/Java_ME_and_Java_APIs_for_BB_446980_11.jsp"> is based on</a> <a
href="http://jcp.org/en/jsr/detail?id=139">CLDC 1.1</a>, <a
href="http://jcp.org/en/jsr/detail?id=118">MIDP 2.0</a> and is JSR-185 compliant. It also supports the full MSA stack except for JSR 184  (3-D graphics), JSR 180 (SIP) and JSR 229 (Payment). For other JSRs supported by  Blackberry 5, see <a
href="http://docs.blackberry.com/en/developers/deliverables/9095/Support_for_standard_Java_APIs_446981_11.jsp"> http://docs.blackberry.com/en/developers/deliverables/9095/Support_for_standard_Java_APIs_446981_11.jsp</a></p><h2>Blackberry Applications</h2><p>Blackberry applications are of two types:</p><ul><li> <a
href="http://docs.blackberry.com/en/developers/deliverables/9095/MIDlet_applications_446987_11.jsp">MIDlet  	Application</a>: A MIDlet is an application targeting MIDP  	(javax.microedition namespace). Such an app can run on other MIDP 2.0  	compliant phones from other vendors</li><li> <a
href="http://docs.blackberry.com/en/developers/deliverables/9095/BlackBerry_API_applications_647766_11.jsp">Blackberry Java Application</a>:  	A Blackberry Java Application (also called a RIMlet) targets the CLDC, but  	uses Blackberry specific APIs (from the net.rim namespace). Such an app can  	run only on a Blackberry device.</li></ul><p>Unless your code is targeting mulitple Java ME platforms, it makes sense to  build Blackberry Java applications since they tend to be a lot <a
href="http://docs.blackberry.com/en/developers/deliverables/9095/BlackBerry_API_applications_647766_11.jsp">richer</a> than  MIDlets. Specifically, if you want the look and feel of applications that RIM  ships with a Blackberry (also called &#8220;native apps&#8221;), then you should build a  Blackberry Java application by using <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/package-summary.html"> net.rim.device.api.ui</a> and not use <a
href="http://www.blackberry.com/developers/docs/5.0.0api/javax/microedition/lcdui/package-summary.html"> javax.microedition.lcdui</a>. More differences on the UI capabilities of both  frameworks are given on <a
href="http://www.blackberry.com/developers/docs/5.0.0api/UI-summary.html"> http://www.blackberry.com/developers/docs/5.0.0api/UI-summary.html</a>.</p><p>Note that all APIs are always available to all apps. So if your app is using  the Blackberry UI, you can always invoke MIDP APIs. If your app is using the MIDP UI, you can always  invoke Blackberry APIs, but of course doing so would render the application  non-portable. The only exception to this is on mixing UI. The MIDP UI model  allows concurrent access while the Blackberry UI model does not and hence mixing  UI library calls is unsupported.</p><p>In the rest of this post, I would be focussing mostly on the Blackberry Java  Application.</p><h3>Startup</h3><p>A Blackberry application can start in one of the following ways:</p><ol><li>Use clicking an icon on the Home screen</li><li>By another app</li><li>OS starting an app automatically when the device starts</li><li>OS starting an app at a scheduled time</li></ol><p>This startup is managed by an entity called the <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/ApplicationManager.html"> Application Manager</a>. An running application can obtain a reference to the  Application Manager by calling <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/ApplicationManager.html#getApplicationManager()"> getApplicationManager()</a>, and then, can use this to:</p><ul><li> <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/ApplicationManager.html#runApplication(net.rim.device.api.system.ApplicationDescriptor, boolean)"> Run</a> or <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/ApplicationManager.html#launchApplication(java.lang.String)"> Launch</a> another application</li><li> <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/ApplicationDescriptor.html"> Schedule</a> an application to run at a specific time</li><li> <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/ApplicationManager.html#postGlobalEvent(int, long, int, int, java.lang.Object, java.lang.Object)"> Post</a> a global event to the OS</li><li> <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/ApplicationManager.html#lockSystem(boolean)"> Lock</a> and <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/ApplicationManager.html#unlockSystem()"> Unlock</a> the system</li></ul><p>To start an application, the App Manager creates a new process and a thread  within that process and then starts the main() function on that thread with a  set of input parameters. The parameters are specified in the <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/ApplicationDescriptor.html"> application descriptor</a>. It is possible to create multiple descriptors for  the same app and associate them with different icons on the screen, This allows  the <a
href="http://www.blackberry.com/knowledgecenterpublic/livelink.exe/fetch/2000/348583/800901/How_To_-_Setup_an_alternate_entry_point_for_my_application.html?nodeid=800820&amp;vernum=0"> creation of multiple entry points</a> for the same app.</p><h3>Event Processing</h3><p>Once started, an application can choose to do a series of operations and then  quit, never showing a UI. However, most applications want to stay around and  respond to system events, including UI events. For this, one of the threads of  the application needs to acquire what is called the Event Lock by calling <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/Application.html#getEventLock()"> Application.getEventLock()</a>. Only one thread in the application can acquire  this lock &#8211; this thread is then called the <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/Application.html#isEventThread()"> Event Thread</a>. Typically, the first thread acquires this lock by calling <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/Application.html#enterEventDispatcher()"> enterEventDispatcher()</a>. Once this method is called, the application starts  receiving system events. Note that this does not mean that the application is  showing a UI &#8211; just that is it receiving all system events, including UI events.  So as of now, the application is still running in the background. An application  can control whether it wants to continue processing systems events by toggling <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/Application.html#setAcceptEvents(boolean)"> setAcceptEvents()</a>.</p><h3>Showing a UI</h3><p>All the visible elements in a Blackberry Java Application are of three types:</p><ul><li> <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Field.html"> Fields</a>: A building block element that is used to work with a particular  	kind of data for which it draws the UI and if required handles user-input.  	It typically corresponds to a control like a <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/component/ButtonField.html"> button</a> / <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/component/TextField.html"> text-field</a>, etc. You can create custom Fields by sub-classing the Field  	class, implementing the <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Field.html#layout(int, int)"> layout()</a> and <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Field.html#paint(net.rim.device.api.ui.Graphics)"> paint()</a> abstract methods and optionally overriding <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Field.html#getPreferredHeight()"> getPreferredHeight()</a> and <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Field.html#getPreferredWidth()"> getPreferredWidth()</a> methods.</li><li> <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Manager.html"> Managers</a>: Responsible for arranging fields. Each field must belong to  	only one manager. Since a manager is also a field, managers are composable,  	making it possible to build complex, rich, UI layouts. There are several  	types of managers provided: <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/container/HorizontalFieldManager.html"> Horizontal</a>, <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/container/VerticalFieldManager.html"> Vertical</a>, <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/container/GridFieldManager.html"> Grid</a>, <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/container/FlowFieldManager.html"> Flow</a>, <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/container/AbsoluteFieldManager.html"> Absolute</a>, etc., and you can also build your own by sub-classing the  	Manager class and implementing <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Manager.html#sublayout(int, int)"> sublayout()</a>, <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Field.html#getPreferredHeight()"> getPreferredHeight()</a> and <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Field.html#getPreferredWidth()"> getPreferredWidth()</a> methods and optionally overriding <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Manager.html#subpaint(net.rim.device.api.ui.Graphics)"> subpaint()</a> method.</li><li> <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Screen.html"> Screens</a>: A screen is a window that is active at any given time. There  	are two types of screens: <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/container/PopupScreen.html"> PopupScreen</a> and a <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/container/FullScreen.html"> FullScreen</a>.</li></ul><p><img
src="http://www.blackberry.com/developers/docs/5.0.0api/images/UI_BB.jpg" alt="Blackberry UI Framework" width="564" height="315" /></p><p>(Blackberry UI Framework. Source: <a
href="http://www.blackberry.com/developers/docs/5.0.0api/UI-summary.html"> http://www.blackberry.com/developers/docs/5.0.0api/UI-summary.html</a>)</p><p>The way the system works is that the <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/UiEngine.html"> UI Engine</a> maintains a stack of Screen objects. As new screens are created,  they are <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/UiApplication.html#pushScreen(net.rim.device.api.ui.Screen)"> pushed</a> on the display stack. Only the screen at the top receives input  events. When a screen is <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/UiApplication.html#popScreen(net.rim.device.api.ui.Screen)"> popped</a> from the stack, the underlying screens are drawn as necessary. Note  that the Blackberry display stack is not the same as the Android back-stack. The  Android back-stack is a system-managed structure, scoped to a task with  acitivities from different processes getting interleaved. The Blackberry display  stack is a per-process application-managed stack of Screens.</p><p>To show a UI, the application extends the <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/package-summary.html"> net.rim.device.api.ui.UiApplication</a> class (which implements <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/UiEngine.html"> UiEngine</a> and extends the <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/Application.html"> Application</a> class), creates an instance of <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/container/MainScreen.html"> MainScreen</a> (which is of type <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/container/FullScreen.html"> FullScreen</a>) and then pushes this instance on the display stack.</p><pre>
class MyApp extends UiApplication {
	MyApp() {
		MyAppScreen myAppScreen = new MyAppScreen();
		pushScreen(myAppScreen);
	}

	public static void main(String[] args) {
		MyApp app = new MyApp();
		app.enterEventDispatcher();
	}
}

class MyAppScreen extends MainScreen {
	MyAppScreen() {
		// add fields etc.
	}
}
</pre><h3>Termination</h3><p>An application terminates when <a
href="http://www.blackberry.com/developers/docs/5.0.0api/java/lang/System.html#exit(int)"> System.exit()</a> is called. This method causes the Blackberry JVM to terminate  the process of the caller. For applications that show a UI, the typical way of  quitting is that when the <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Screen.html#close()"> close()</a> method is called on a screen, it pops the screen from the display  stack, and if the display stack is empty, calls <a
href="http://www.blackberry.com/developers/docs/5.0.0api/java/lang/System.html#exit(int)"> System.exit()</a>. So if the user keeps pressing back and hits the first screen  of your application, pressing back once again would by default exit the app. To  avoid this, one needs to override the close() method.</p><h2>Doing Long Running Work</h2><p>As described in the Event-Processing section above, the Blackberry UI model  is a single threaded one. That means that you cannot do long-running work on it,  and instead need to launch a worker thread. This worker thread can update the UI  in two ways:</p><ol><li><strong>Acquire and synchronize on the event lock:</strong> To do this, the  	worker  	thread invokes <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/Application.html#getEventLock()"> Application.getEventLock()</a> and then synchronizes this object to access  	the UI. While this is being done the Event Thread is paused, so the lock  	should be held for a really short period of time.<pre>// on the background thread
synchronized(Application.getEventLock()) {
    // update the UI
}</pre></li><li><strong>Inject an event in the UI message queue:</strong> To inject an event, you model it  	as a class that implements <a
href="http://www.blackberry.com/developers/docs/5.0.0api/java/lang/Runnable.html"> Runnable</a> and inject it into the Event Thread message queue by calling <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/Application.html#invokeAndWait(java.lang.Runnable)"> invokeAndWait()</a> or <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/Application.html#invokeLater(java.lang.Runnable)"> invokeLater()</a>. The event thread would then call the runnable&#8217;s <a
href="http://www.blackberry.com/developers/docs/5.0.0api/java/lang/Runnable.html#run()"> run()</a> method at the next available opportunity. While for  	invokeAndWait(), the worker thread would block till run() returns,  	invokeLater does not block and returns immediately.<pre>// on the background thread:
UiApplication.getUiApplication().invokeLater (new  Runnable() {
    public void run()
    {
        // update the UI - runs on the Event thread
    }
});</pre></li></ol><h2>Interprocess Communication</h2><p>There are two ways in which Blackberry applications can communicate with each  other:</p><ol><li>Using the <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/RuntimeStore.html">RuntimeStore</a>:  	The RuntimeStore is a system-wide volatile storage where applications can  	place data to share with other applications.</li><li>Using Global Events: Use <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/Application.html#addGlobalEventListener(net.rim.device.api.system.GlobalEventListener)"> Application.addGlobalEventListener()</a> to add a <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/GlobalEventListener.html"> GlobalEventListener</a> to listen to global events. Post a Global Event by  	calling <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/system/ApplicationManager.html#postGlobalEvent(long, int, int)"> ApplicationManager.postGlobalEvent()</a>.</li></ol><h2>Security Model</h2><p>Blackberry has a complex security model, owing to its roots in enterprise  software. When businesses issue their employees Blackberry devices, they also  expect to able to exercise control over what the user is able to do on the  device. This is made possible thru a <a
href="http://docs.blackberry.com/en/developers/deliverables/9095/Application_control_447165_11.jsp"> policy</a> which is pushed to the device using BES or the Blackberry Desktop  Manager. Such policies can limit the resources available to an  application, and to handle that gracefully, applications should:</p><ol><li>Find out what permissions they have: By calling <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/applicationcontrol/ApplicationPermissionsManager.html#getApplicationPermissions()"> ApplicationPermissionsManager.getApplicationPermissions()</a>. This returns  	an instance of <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/applicationcontrol/ApplicationPermissions.html"> ApplicationPermissions</a> class which gives all the permissions that are  	set.</li><li>Ask for permissions they need: By calling <a
href="http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/applicationcontrol/ApplicationPermissionsManager.html#invokePermissionsRequest(net.rim.device.api.applicationcontrol.ApplicationPermissions)"> ApplicationPermissionsManager.invokePermissionsRequest()</a> and passing it  	an instance of ApplicationPermissions with the requested permissions set.</li></ol><p>Besides this, RIM has marked a <a
href="http://docs.blackberry.com/en/developers/deliverables/9095/Java_APIs_with_controlled_access_447163_11.jsp"> number of APIs</a> as <a
href="http://docs.blackberry.com/en/developers/deliverables/9095/Controlled_APIs_and_code_signing_447162_11.jsp"> controlled APIs</a>. To access these APIs on the device, you must sign your  application using a key or signature obtained from RIM. For details, see <a
href="http://us.blackberry.com/developers/javaappdev/codekeys.jsp"> http://us.blackberry.com/developers/javaappdev/codekeys.jsp</a>. On the  simulators, these APIs are accessible without code-signing.</p><h2>Packaging</h2><p>When you build your app, you create a JAR, alongwith a manifest. Java ME <a
href="http://developers.sun.com/mobility/midp/ttips/getAppProperty/index.html"> defines certain mandatory and optional attributes</a> that applications should  include in the JAR manifest, besides any other app-specific info that maybe  present.</p><p>However, a Blackberry device cannot directly execute a JAR. It first needs to  be converted into a proprietary format file called a <a
href="http://drbolsen.wordpress.com/2006/07/26/blackberry-cod-file-format/"> .COD</a> file which is essentially RIM&#8217;s own version of the JAR. So if you want  to run a MIDlet on a Blackberry device, you first need to convert the JAR into a  COD file which can be done using the Eclipse plugin or by using the <a
href="http://supportforums.blackberry.com/t5/Java-Development/Use-the-RAPC-compiler/ta-p/444879"> RAPC compiler</a> on the command line. Some more details on using the RAPC  compiler are given <a
href="http://codeforfun.wordpress.com/2008/09/09/how-to-use-rapc-from-rim-dirty-details/"> here</a>.</p><p>However, the max size of a COD file is 128 kb with a 64 kb limit on compiled  code and 64-kb limit on resource data. In case the compiled code produced is  larger than these limits, the compiler breaks the code into mulitple COD files,  naming them in increasing numerical order like this:</p><ul><li>HelloWorld.cod</li><li>HelloWorld-1.cod</li><li>HelloWorld-2.cod</li><li>HelloWorld-3.cod</li><li>&#8230;</li></ul><p>The compiler then takes the numbered files (called sibling COD files), zips  them and names the zip as a COD file (HelloWorld.cod above) &#8211; this is called the  main COD file. There is a max limit to the main COD file too &#8211; it can contain up  to 127 sibling COD files, thus imposing a theoretical size limit. For more  details, see <a
href="http://supportforums.blackberry.com/t5/Java-Development/The-maximum-size-of-a-BlackBerry-smartphone-application/ta-p/502534"> http://supportforums.blackberry.com/t5/Java-Development/The-maximum-size-of-a-BlackBerry-smartphone-application/ta-p/502534</a>.</p><p>Packaging the application for Wireless or Over-the-Air (OTA) distribution requires more work. For this, Java ME defines an additional manifest called  a JAD (Java Application Descriptor) that Java ME applications should provide for  OTA distribution. The main purpose of a JAD is for locating a JAR and figuring  out its size. Besides the JAR URL and JAR size, the JAD must also contain  certain other attributes that are also required in a JAR manifest and may  contain any attribute that is in a JAR manifest. For details, see <a
href="http://developers.sun.com/mobility/midp/ttips/getAppProperty/index.html"> here</a>. Blackberry specific attributes for a JAD are given <a
href="http://docs.blackberry.com/en/developers/deliverables/7693/Attributes_for_jad_files_513047_11.jsp"> here</a>. Also, for OTA distribution, you need to extract the sibling COD files  from the main COD file. For details see <a
href="http://docs.blackberry.com/en/developers/deliverables/7693/Extract_sibling_cod_files_512523_11.jsp"> here</a>.</p><h2>Distribution</h2><p>Blackberry applications can be distributed in two ways:</p><ol><li> <a
href="http://docs.blackberry.com/en/developers/deliverables/7693/App_distribution_through_a_computer_connection_447181_11.jsp"> Direct Connection</a>: Connect the device to your computer and install the  	app. There are two possibilities here:<ul><li> <a
href="http://docs.blackberry.com/en/developers/deliverables/7693/Distribute_an_application_from_a_computer_447182_11.jsp"> Using the Blackberry Desktop Manager</a>: The application needs to have  		a COD file alongwith an additional manifest file called the<a
href="http://docs.blackberry.com/en/developers/deliverables/7693/Elements_and_attributes_for_alx_files_513046_11.jsp"> ALX file</a>.</li><li> <a
href="http://docs.blackberry.com/en/developers/deliverables/7693/Distribute_an_application_from_a_web_page_447183_11.jsp"> Using a Web Page</a>: For this, you need to put up an ActiveX control  		called a  <a
href="http://docs.blackberry.com/en/developers/subcategories/?userType=21&amp;category=BlackBerry+Application+Web+Loader"> Web Loader</a> on the web-page from where you want the installation to  		happen. The user browses to a web-page on his desktop using IE and the  		control starts an installer. In case the user visits the page using a  		Blackberry device, the user is prompted to connect the device to a  		desktop.</li></ul></li><li> <a
href="http://docs.blackberry.com/en/developers/deliverables/7693/Distributing_BB_Java_Apps_over_wireless_network_512513_11.jsp"> OTA</a>: There are two ways in which OTA distribution may happen:<ul><li><strong>BES Push:</strong> An organization with a Blackberry  		Enterprise server deployment can push notifications to Blackberry  		devices for applications based on policies defined by an administrator.</li><li> <a
href="http://docs.blackberry.com/en/developers/subcategories/?userType=21&amp;category=BlackBerry+App+World+storefront"> Blackberry App-World</a>: The process is described <a
href="http://docs.blackberry.com/en/developers/deliverables/24398/Process_flow_title_647894_11.jsp"> here</a>.</li></ul></li></ol> <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VineetGupta?a=q3t068xNfHc:gyFLeT9eaE0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=q3t068xNfHc:gyFLeT9eaE0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=q3t068xNfHc:gyFLeT9eaE0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=q3t068xNfHc:gyFLeT9eaE0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=q3t068xNfHc:gyFLeT9eaE0:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=q3t068xNfHc:gyFLeT9eaE0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=q3t068xNfHc:gyFLeT9eaE0:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=q3t068xNfHc:gyFLeT9eaE0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VineetGupta/~4/q3t068xNfHc" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.vineetgupta.com/2011/03/mobile-platforms-part-2-blackberry/feed/</wfw:commentRss> <slash:comments>5</slash:comments> <feedburner:origLink>http://www.vineetgupta.com/2011/03/mobile-platforms-part-2-blackberry/</feedburner:origLink></item> <item><title>Mobile Platforms – Part 1 – Android</title><link>http://feedproxy.google.com/~r/VineetGupta/~3/mQvRIRIZH1U/</link> <comments>http://www.vineetgupta.com/2011/03/mobile-platforms-part-1-android/#comments</comments> <pubDate>Sun, 06 Mar 2011 19:36:38 +0000</pubDate> <dc:creator>Vineet Gupta</dc:creator> <category><![CDATA[Mobile]]></category> <category><![CDATA[Android]]></category><guid isPermaLink="false">http://www.vineetgupta.com/?p=10071</guid> <description>One of the products we are building at Directi is a x-platform mobile chat client. Developing it has been arduous &amp;#8211; we experimented with Phonegap and then Titanium and found both lacking (see this Quora thread for details). So now we are building this as three native apps, targeting iPhone, Android and Blackberry. In this &lt;a
href='http://www.vineetgupta.com/2011/03/mobile-platforms-part-1-android/'&gt;[...]&lt;/a&gt;</description> <content:encoded><![CDATA[<p>One of the products we are building at Directi is a x-platform mobile chat client.     Developing it has been arduous &#8211; we experimented with Phonegap and then Titanium     and found both lacking (see this <a
href="http://www.quora.com/How-do-you-decide-whether-to-go-with-a-native-iPhone-Android-app-or-a-web-app-that-pretends-to-be-an-iPhone-Android-app/answer/Vineet-Gupta?srid=Ysz"> Quora thread</a> for details). So now we are building this as three native apps,     targeting iPhone, Android and Blackberry. In this post I am going to cover the Android platform, and would follow up with iOS and Blackberry.</p><h2>Android Architecture</h2><p>The following diagram (from <a
href="http://developer.android.com/guide/basics/what-is-android.html"> http://developer.android.com/guide/basics/what-is-android.html</a>) gives the     overall architecture of the Android OS:</p><p><img
src="http://developer.android.com/images/system-architecture.jpg" alt="Android Architecture" /></p><p>The Android OS is basically a Linux 2.6.4 kernel fork. The Linux kernel is used     for memory management, process management, security, driver model, shared lib model.     Google has added Android specific enhancements: Power management, Kernel debugger,     Logger, Low Memory killer, Shared Memory Driver, IPC Driver, etc.</p><p>Above the kernel, in the user space, sits the Hardware abstraction layer &#8211; this     deals with stuff like Radio, Wifi, GPS, Graphics, Audio, Camera, Bluetooth, etc.     Basically this defines a set of interfaces that drivers need to implement. These     libaries are loaded by the system at runtime on a need basis.</p><p>Above the HAL, sit a bunch of libraries &#8211; the most important of course is libc &#8211;     Google has written a port called Bionic libc which is optimized for embedded use     &#8211; in terms of being small in size (since it is loaded in every process) and fast     (since CPU is limited), but also because libc is GPL and Google wanted to protect     apps from being GPLed. Besides there is webkit of course and SQLite. Google also     provides a Media Framework, OpenGL library, and libraries for UI rendering and audio.</p><p>The Android programming environment is based on Java. For this, the OS ships with     Dalvik &#8211; a custom implementation of the JVM optimized for the embedded environment.     Dalivk does not run the Java bytecode, but its own custom bytecode called Dex &#8211;     Dalvix Executable. It uses runtime memory very efficiently, the bytecode interpreter     is highly CPU optimized, and because of this low footprint, the VM can be run in     multiple processes &#8211; basically each app gets its own Linux process with its own     instance of a Dalvik VM. The VM is exposed by a set of core Java APIs which provide     the familiar Java library.</p><p>All of the above is wrapped in a set of platform services called the Android Application     Framework &#8211; these services work behind the scenes to provide abstractions like Activities,     Packages, Windows, Resources, Content Providers, View System, hardware access, etc.</p><h2>Startup</h2><p>Like a typical Linux system, in Android, the bootstrapper loads the Linux kernel     and starts the init process, which in turn starts various daemons like Android Debug     Bridge (adbd), Radio Interface Layer Daemon (rild), etc. After this, init starts     what is called the Zygote process. The purpose of this process is to kick off the     rest of the Android system and later help in the instantiation of apps. The Zygote     process initializes a Dalvik VM instance and loads a bunch of libraries and starts     listening on a socket for requests to spawn more processes (with VM instances).     As requests come in, it forks to create new processes with VM instances. Copy-on-write     is used to maximize reuse and minimize footprint.</p><p><img
class="alignnone" alt="Android Startup Sequence" src="http://farm6.static.flickr.com/5291/5502863911_40f78966b5_z.jpg" /></p><p>(Android Startup Sequence &#8211; source: <a
href="http://sites.google.com/site/io/anatomy--physiology-of-an-android"> http://sites.google.com/site/io/anatomy&#8211;physiology-of-an-android</a>)</p><p>Once Zygote is in place, the init process starts what is called the Runtime process.     This basically does two things:</p><ol><li>Start the Service Manager &#8211; this is responsible for managing IPC and all services         are required to register with it. It acts like a local DNS providing a way to bind         to a service given its name.</li><li>Ask Zygote to fork what is called the System Server. This is the first process (besides         Zygote) that has a running VM instance. The System server starts services for display         (Surface Flinger) and audio (Audio Flinger). These services register with the service         manager like all services are expected to. Now other apps can start using display         and audio. After this, the System server starts up all the core platform services         &#8211; Window manager, Telephony manager, Power manager, Activity manager, etc. Each         one of these services also registers with the Service Manager, so that apps can         use these services.</li></ol><p>At this stage, we have the following processes in place:</p><ol><li>Init &#8211; the original init process started by the bootstrapper</li><li>Daemons &#8211; started by init</li><li>Runtime &#8211; also started by init</li><li>Zygote &#8211; the original zygote which will continually get forked as new apps get launched</li><li>System Server &#8211; the first managed process which contains all the core services and         platform components.</li></ol><p>After this, the Home Screen or the Idle screen is launched &#8211; basically the Activity     Manager (which is inside the System Server) sends a message to Zygote to start the     &#8220;Home&#8221; Activity, which causes Zygote to fork into a new process with a     Dalvik VM and the Home activity. Now depending on the action carried out by the     user, the appropriate app would be launched with the Zygote forlking each time to     create a new VM instance inside a new process. So for example, if the user starts     the Contacts app, the apt process would be setup:</p><p><img
class="alignnone" alt="Android Startup Processes" src="http://farm6.static.flickr.com/5171/5503452198_4f8d649c05_z.jpg" /></p><p>(Startup processes in Android -  source: <a
href="http://sites.google.com/site/io/anatomy--physiology-of-an-android"> http://sites.google.com/site/io/anatomy&#8211;physiology-of-an-android</a>)</p><p>Each new app gets a unique user Id which is opaque to the app, and the system sets     permissions for all files in the app so that only the user id assigned to the app     can access those files.This makes the system secure since the app only has access     to the components that it needs to do its work and nothing else. However,      apps may need to communicate with each other and the system services, which are     all running in separate processes. This is accomplished thru Inter Process Communication</p><h2>IPC</h2><p>With its emphasis on isolating apps and services in process boundaries, it is clear     that Android requries a lightweight IPC. The IPC mechanism in Android is called     Binder and is based on shared memory. Recall that when a process starts it registers     itself with the Service Manager. This happens behind the scenes, and on registeration,     each process gets what is called a <a
href="http://developer.android.com/reference/android/content/Context.html"> Context</a> object &#8211; a reference to the Service manager. Now lets say app A     needs to communicate with service B, and the two are running in two separate processes.     To do this, app A asks the Context for the Service B by passing the well known name     of the service. The Context returns a reference to the service to A, on which A     can call a method &#8211; say foo. This method call is intercepted by the Binder driver.     The driver marshals the object and passes a reference of it to the receiver &#8211; B.     Note that this is passing by reference, not passing by value, in which the object     is serialized. On the side of the service B, the Binder maintains a thread-pool     (transparent to the service). One of the threads in this pool receives the incoming     call, locates the actual object in the service B and make the call. The return value     is then similarly passed back to the caller. The following diagram (from <a
href="http://sites.google.com/site/io/anatomy--physiology-of-an-android"> http://sites.google.com/site/io/anatomy&#8211;physiology-of-an-android</a>) illustrates     this:</p><p><img
alt="Android IPC - Binder" src="http://farm6.static.flickr.com/5015/5503451932_08abdba708_z.jpg" /></p><p>The entire operation is synchronous, and the objects are reference counted so that     when they are no longer in use, they can be deleted. Since there is no serialization     / de-serialization, there is no overhead and therefore this model can also be used     to communicate with services that run in your own process without any penalty.</p><h2>Applications</h2><p>An application in Android is a collection of components. There are four types of     components:</p><ul><li><a
href="http://developer.android.com/guide/topics/fundamentals/activities.html"> Activity</a>: An Activity is a UI component corresponding to one screen with which         a user interacts in order to do something.</li><li><a
href="http://developer.android.com/guide/topics/fundamentals/services.html">Service</a>:         A Service is an application component without a UI used to perform long running         operations in the background.</li><li><a
href="http://developer.android.com/reference/android/content/BroadcastReceiver.html"> Broadcast Receiver</a>: A broadcast receiver is a component that responds to system-wide         broadcasts (for example screen turned off, battery low, etc.)</li><li><a
href="http://developer.android.com/guide/topics/providers/content-providers.html"> Content Provider</a>: A content provider is a component that stores and retrieves         data and makes it available to all applications. There are different types of content         providers: audio, video, contacts, etc. and you can create your own custom provider         also.</li></ul><p>As mentioned earlier, each application runs in its own process. By default, all     components used by that app also run in the same process, and on the main thread.     However, it is possible to make a component of your app run in a separate process     thru the manifest file. Thus, an application in Android may span multiple processes.</p><h2>Application Startup</h2><p>Android follows a fairly unique model in that there is no single entry point for     an application &#8211; there is no main() function. Instead, a component in one application     can start another application&#8217;s component, thus bringing the application to life.     This communication across apps happens thru the IPC mechanism descibed above. So     while an Activity is owned by an application, it is possible for another application     to start it (if the owning application allows it). An example is clicking on a hyperlink     in an app opening up the browser. This applies for not just Activities, but other     types of components also. In order for this to happen, there are two steps required:</p><ol><li>In case the application is not already running, the Android system would bring the         application to life in a new process forked from Zygote.</li><li>The desired component inside the app would need to be activated.</li></ol><p>Note that in case the application is already running, the new component would be     by default instantiated in the same process.</p><p>As mentioned above, IPC happens thru a <a
href="http://developer.android.com/reference/android/content/Context.html"> Context</a> object. So when a component A inside one app needs to activate another     component B in a different app, or give it something new to do, it basically uses     the Context object to send a message to the other component. In the case of an Activity,     Service or a BroadcastReceiver, this takes the form of a what is called an <a
href="http://developer.android.com/guide/topics/intents/intents-filters.html"> Intent</a> &#8211; a passive data structure that defines the operation to be performed     for an Activity and a Service, and for a Broadcast Receiver, a defintion of the     announcement being broadcast.</p><p>Content Providers however are not activated thru Intents. Instead, activation happens     on a request from a <a
href="http://developer.android.com/reference/android/content/ContentResolver.html"> ContentResolver</a>, which acts as a mediator between the requesting component     and the Content Provider.</p><h2>The Activity Back-Stack</h2><p>Consider the following scenario:</p><ol><li>You are on the Home Screen. This is Activity 1</li><li>You click on the Mail app icon, and that activates the main activity in the Mail         app which comes to the foreground. This is Activity 2</li><li>You now click on Compose and that activates the Compose activity in the Mail app.         This is Activity 3</li><li>You decide to cancel out of composing a new message and press the back button. You         come back to Activity 2</li></ol><p>Here is what happens in the background:</p><ul><li>When one activity starts another activity, it stops and its state is saved. So when         Activity 1 starts activity 2, activity 1 is stopped, its state saved and so on</li><li>The system maintains a stack (called a back-stack) with the latest activity on top         and the oldest activity at the bottom.</li><li>When the user presses the back-key, Activity 3 is popped and Activity 2 is started         from its saved state</li></ul><p><img
src="http://developer.android.com/images/fundamentals/diagram_backstack.png" alt="Activity Back Stack" width="700" height="300" /></p><p>(The Activity Back Stack &#8211; source: <a
href="http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html"> http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html</a>)</p><p>This approach allows Android to seamlessly transition from one app to the other     in a consistent way.</p><h2>Tasks</h2><p>In the scenario described above, assume that when the user was in Compose mail (Activity     3), he decided to call someone and pressed the Home key. This would not unwind the     back-stack, but start a new stack. In order to do this, the collection of Activities     in the first stack needs to go into the background. This is achieved thru the notion     of a Task &#8211; a cohesive unit of Acitivities. When a task moves to the background,     all activities in the Task are stopped but the back-stack for the task remains intact,     so that when the user returns back to the Task, she can resume where she left off.     However, to save memory, the back-stack for a background Task is not retained for     a very long period and if the user does not go back to the task, the back-stack     is cleared except for the root activity.</p><p><img
src="http://developer.android.com/images/fundamentals/diagram_multitasking.png" alt="Tasks" width="331" height="202" /></p><p>(Background and Foreground Tasks &#8211; source: <a
href="http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html"> http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html</a>)</p><h2>Activity Life Cycle</h2><p>The lifecycle of an activity is affected by its association with other activities,     its task and its back-stack. There are three states in which an activity can exist:</p><ul><li><strong>Resumed / Running:</strong> Activity is in the foreground and has user focus.         Such an activity is never killed by the system,</li><li><strong>Paused:</strong> Activity is visible, but another activity is in the foreground         and has user focus. This could happen if the other activity is at the top, but is         translucent, or because it does not cover the entire screen. In the paused state,         the Activity object is retained in memory, maintains all state and member info and         remains attached to the Window manager. However it can be killed in extremely low         memory conditions.</li><li><strong>Stopped:</strong> The Activity is not visible to the user.While the Activity         object is retained in memory, maintains all state and member info, it does not remain         attached to the Window manager. The activity can be killed by the system to reclaim         memory if required.</li></ul><p><img
src="http://developer.android.com/images/activity_lifecycle.png" alt="Activity State Transitions" width="545" height="711" /></p><p>(Activity Lifecycle &#8211; source: <a
href="http://developer.android.com/guide/topics/fundamentals/activities.html#Lifecycle"> http://developer.android.com/guide/topics/fundamentals/activities.html#Lifecycle</a>)</p><h2>Saving Activity State</h2><p>Note that it is entirely possible that the system, in order to reclaim memory, may     destroy an Activity, or even the process in which the Activity was running. However,     when the user comes back to the activity (thru the back-stack), you still want to     resume at the point the user left. To do this, an activity must save its state.     This happens thru the <a
href="http://developer.android.com/reference/android/app/Activity.html#onSaveInstanceState(android.os.Bundle)"> Activity.onSaveInstanceState()</a> method.</p><p><img
src="http://developer.android.com/images/fundamentals/restore_instance.png" alt="Saving Activity State" width="612" height="400" /></p><p>(Saving and restoring Activity State &#8211; source: <a
href="http://developer.android.com/guide/topics/fundamentals/activities.html#SavingActivityState"> http://developer.android.com/guide/topics/fundamentals/activities.html#SavingActivityState</a>)</p><h2>Process Lifecycle</h2><p>The Android system may need to kill a process in order to reclaim memory. To ensure     that this creates minimal impact on the user expereince, Android ranks processes     in a priority order:</p><ul><li><strong>Foreground Process</strong>: A process that is required for what the user         is currently doing. Such a process is killed only as a last resort</li><li><strong>Visible Process</strong>: This process is not in the foreground but can         affect what the user is seeing on the screen. For example it may host a paused Activity.         Such a process is not killed unless doing so is required to keep all foreground         processes running</li><li><strong>Service Procress</strong>: A process that is running a service and is not         one of the two types above. For example the service may be playing music or downloading         something. The system would keep such a process running unless there is not enough         memory to keep Foreground and Visible processes running.</li><li><strong>Background Process</strong>: A process that is holding an activity not currently         visible to the user (the activity is stopped). Such a process has no impact on the         user experience (if the activity lifecycle is correctly implemented and the activity         state is being properly saved and restored) The system can kill such a process any         time. Typically there are mulitple background processes running and the system maintains         a LRU list which is used to kill such processes.</li><li><strong>Empty Process</strong>: An empty process does not hold any active component.         The only reason such a process is kept alive in the first place is for caching and         to improve startup time. The system often kills such processes to maintain the balance         between process caches and underlying kernel caches.</li></ul><p>Of course it can so happen that a higher priority process is dependent on a lower     priority process. In such a case the ranking of the serving process is increased     to the same level as that of the dependent process.</p><p>A situation where this ranking has a direct impact is this:</p><ul><li>Your app needs to download something big which may take time and the user is likely         to move out of the app&#8217;s activity to something else.</li><li>If you spawn a worker thread for this task and the user moves out, the process would         become a background process.</li><li>However, if you instead spawn a service, the process would be a service process         and be less likely to be killed</li></ul><h2>Main / UI Thread</h2><p>When an application is launched and a new process created to host it, the application     gets a single thread called the main thread or the UI thread since this thread is     responsible for servicing the UI. The way this works is mostly the same for almost     any UI implementation &#8211; be it desktop operating systems or mobile OS. Basically,     the UI thread runs an infinite loop which checks a queue to see if there are any     pending UI events. In the case of Android, this concept is formalized in the form     of a <a
href="http://developer.android.com/reference/android/os/Looper.html">Looper</a>.      The looper loops over a <a
href="http://developer.android.com/reference/android/os/MessageQueue.html"> MessageQueue</a> which contains the <a
href="http://developer.android.com/reference/android/os/Message.html"> messages</a> to be dispatched. The actual task of managing the queue is     done by a <a
href="http://developer.android.com/reference/android/os/Handler.html">Handler</a> which is responsible for handling (adding, removing, dispatching) messages in the     message queue.</p><p><img
src="http://farm6.static.flickr.com/5295/5502982451_1f78830c9e_z.jpg" alt="Android Threading"  /></p><p>(Android Threading &#8211; source: <a
href="http://sites.google.com/site/io/inside-the-android-application-framework">http://sites.google.com/site/io/inside-the-android-application-framework</a>)</p><p>For the main thread, a Looper is setup by the system. However, you can also associate     a Looper with your own thread. Note that the Looper can be associated only with     one thread and that association cannot be changed. The way Android ensures this     is by putting the Looper on the <a
href="http://developer.android.com/reference/java/lang/ThreadLocal.html"> thread local storage</a> of the thread and not exposing a constructor for the     Looper. You get a Looper by calling the static <a
href="http://developer.android.com/reference/android/os/Looper.html#prepare"> prepare</a> method which first checks the TLS to see if there is already a Looper,     and if not creates one. You then call the <a
href="http://developer.android.com/reference/android/os/Looper.html#loop"> loop</a> method on it to start pumping messages. Unlike a Looper, mulitple handlers     can be associated with a message queue.</p><p>So quite obviously, one should not run a blocking operation on the UI thread. If     you do, messages would stop getting processed from the Message Queue and your app     would become unresponsive. This is what leads to the famous <a
href="http://developer.android.com/guide/practices/design/responsiveness.html"> Application Not Responding (ANR) dialog</a>. One solution is decsribed <a
href="http://developer.android.com/guide/appendix/faq/commontasks.html#threading"> here</a>: create a handler, spawn a worker thread, post results back from     the worker thread to the handler, update the UI. But this is a bit cumbersome to     do. A simpler solution is to use a <a
href="http://developer.android.com/reference/android/os/AsyncTask.html"> AysncTask</a> which takes care of the underlying plumbing.</p><h2>Service</h2><p>As mentioned earlier, a Service is a type of component that is used to carry out     a background operation, and does not provide a UI. An app component can start a     service, and even if the user switches out of the application, the service would     keep running. Typical use cases include playing music and downloading a file. Android     ensures that a process running a Service is not killed as far as possible (see Process     lifecycle above).</p><p>Note that a service by default runs on the main UI thread in the same process. This     means that if it carries out a blocking operation, your UI would become unresponsive     since the thread would not be available to run the Activity. To circumvent this,     you should launch a worker thread inside the service.</p> <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VineetGupta?a=mQvRIRIZH1U:X1QMVJUfXwM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=mQvRIRIZH1U:X1QMVJUfXwM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=mQvRIRIZH1U:X1QMVJUfXwM:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=mQvRIRIZH1U:X1QMVJUfXwM:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=mQvRIRIZH1U:X1QMVJUfXwM:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=mQvRIRIZH1U:X1QMVJUfXwM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=mQvRIRIZH1U:X1QMVJUfXwM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=mQvRIRIZH1U:X1QMVJUfXwM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VineetGupta/~4/mQvRIRIZH1U" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.vineetgupta.com/2011/03/mobile-platforms-part-1-android/feed/</wfw:commentRss> <slash:comments>10</slash:comments> <feedburner:origLink>http://www.vineetgupta.com/2011/03/mobile-platforms-part-1-android/</feedburner:origLink></item> <item><title>How Browsers Work – Part 1 – Architecture</title><link>http://feedproxy.google.com/~r/VineetGupta/~3/fQrhrL-Kr-U/</link> <comments>http://www.vineetgupta.com/2010/11/how-browsers-work-part-1-architecture/#comments</comments> <pubDate>Sun, 07 Nov 2010 19:23:55 +0000</pubDate> <dc:creator>Vineet Gupta</dc:creator> <category><![CDATA[Web]]></category> <category><![CDATA[Browser Architecture]]></category> <category><![CDATA[Browser Internals]]></category><guid isPermaLink="false">http://www.vineetgupta.com/?p=10065</guid> <description>The web-browser is not an easy platform to program against. I realized this in Dec 2008 when we decided to change the architecture of one of our products at Directi to a pure JavaScript client talking to a REST API, and even more so in Apr 2009 when we decided to build our desktop product &lt;a
href='http://www.vineetgupta.com/2010/11/how-browsers-work-part-1-architecture/'&gt;[...]&lt;/a&gt;</description> <content:encoded><![CDATA[<p>The web-browser is not an easy platform to program against. I realized this in Dec 2008 when we decided to change the architecture of one of our products at Directi to a pure JavaScript client talking to a REST API, and even more so in Apr 2009 when we decided to build our <a
href="http://Chat.pw">desktop product</a> on webkit. However, despite all the issues, the decision of betting the client on web technologies has paid off handsomely and since then our investments in using web-technologies on the client have increased manifold. Over the last two years, multiple teams at Directi have discovered the pains and joy of programming the browser, and almost everyday we learn something interesting about how browsers behave. As we kept learning stuff, I kept notes and thought it would be a good idea to annotate them and share them more widely. This is the first in a series of posts, in which I intend to cover (not necessarily in this order or with this breakup):</p><ul><li>Architecture</li><li>HTTP</li><li>Security Model</li><li>Content and Rendering</li><li>JavaScript</li><li>Apps</li></ul><p>Having said that, I have <a
href="http://www.vineetgupta.com/2009/06/notes-on-xmpp-part-i-fundamentals/">a</a> <a
href="http://www.vineetgupta.com/2008/12/usability-part-1-research-findings/">few</a> <a
href="http://www.vineetgupta.com/2010/01/nosql-databases-part-1-landscape">posts</a> lying around where I have never gotten around to writing part 2. Let&#8217;s hope it does not happen in this case <img
src='http://www.vineetgupta.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><h3>1. Rendering Process</h3><p>The job of a browser is to fetch and display a web-page. At a high level, most modern browsers carry out the following steps to render an HTML page:</p><p><img
title="Rendering Process" src="https://developer.mozilla.org/@api/deki/files/236/=Gecko_Overview_9.png" alt="" /></p><p>(Source: <a
href="https://developer.mozilla.org/en/Introduction_to_Layout_in_Mozilla">https://developer.mozilla.org/en/Introduction_to_Layout_in_Mozilla</a>)</p><ul><li>Load the HTML</li><li>Parse it</li><li>Apply styles</li><li>Build frames</li><li>Layout the frames (flow)</li><li>Paint the frames</li></ul><ol><li><strong>Load:</strong> The browser tries to fetch the page from the specified location. Typically this would be thru a HTTP client. However, a HTML page may also be loaded from a filesystem. Irrespective, the loader fetches the HTML page from its location. The super important concept of Browser Cache comes into play over here &#8211; but more on this later. The way the HTML page gets loaded is different from the way the resources get loaded. In WebKit there are two different pipelines &#8211; one for loading the page and another for loading resources:</li><p>(source: <a
href="http://webkit.org/blog/1188/how-webkit-loads-a-web-page/">http://webkit.org/blog/1188/how-webkit-loads-a-web-page/</a>)</p><li><strong>Parse:</strong> As the stream comes thru from the loader, an HTML parser starts building the DOM (also called a &#8220;Content Tree&#8221;) &#8211; each node here is an HTML element. Now a lot of HTML on the net is broken, and each browser has had to implement its own quirks to parse HTML leading to subtle incompatibilities. HTML 5 however specifies the <a
href="http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html">parsing algorithm</a>. As this gets adopted, the x-browser incompatibilities because of parsing should go away.	While parsing, the engine may come across resources (JS, CSS, images, fonts, etc.) When that happens the particular resource is queued for loading and parsing continues. Again, there is more to this, which we&#8217;ll tackle later.</li><li><strong>Compute Styles:</strong> The browser provides a default stylesheet. Often the HTML page also has a set of styles specified. These styles need to be applied to the Content Tree. For this purpose, a &#8220;Rendering Tree&#8221; is built &#8211; this essentially consists of elements that are to be rendered. For example an element with display set to none would not appear in this tree (nor would its descendants). Nor would elements like HEAD and SCRIPT. Nodes in the Render Tree represent style information: CSS box model, z-order, opacity are all specified here</li><li><strong>Construct Frames:</strong> Most render-able elements follow the <a
href="http://www.w3.org/TR/CSS21/box.html">CSS box model</a>: They have height, width, border, spacing, padding, margin and position. For these objects, a rectangular box &#8211; called a Frame &#8211; is  created. Not all objects have a frame &#8211; for example the SVG image above does not have a frame. It is put inside an iframe, which has a frame. A frame has all the information on how the object itself is going to be rendered. What is not known however, is how is the element going to be placed w.r.t other elements.</li><li><strong>Compute Flow:</strong> Flow Computation or Layout Computation is about how elements are placed w.r.t each other and is mostly controlled by the <a
href="http://www.w3.org/TR/CSS21/visuren.html">CSS Visual Rendering Model</a>. This is typically a recursive process from the root of the tree to leafs. Also, this is typically a lazy process &#8211; it is done on a need-basis. Basically when the layout engine determines that an element needs to be laid out (for example a newly added Node), it marks it as such by setting a dirty bit. The actual layout is done only when some method is called which requires the new information. A visual representation of the layout process can be seen in these videos:<ul><li><a
href="http://video.google.com/videoplay?docid=-1471976166301235697">Gecko reflow for Google homepage</a></li><li><a
href="http://video.google.com/videoplay?docid=-5863446593724321515">Gecko reflow for Wikipedia homepage</a></li><li><a
href="http://video.google.com/videoplay?docid=1020647662203348823">Gecko reflow for Mozilla.org homepage</a></li></ul><p>Most browsers do flow calculation at a higher resolution than what any display would have. This is to support zooming &#8211; when the user zooms in or out, the objects can be drawn correctly on the screen without requiring any extra steps other than mapping the coordinates to real pixels.</li><li><strong>Paint:</strong> Once the engine knows exactly where the objects need to be drawn, comes the process of actually rendering the objects on the screen. This process &#8211; called Painting &#8211; is described in agonizing detail in <a
href="http://www.w3.org/TR/CSS21/zindex.html">Appendix E of the CSS 2.1 Spec</a>. This is basically a Tree walk from the root of the Rendering tree, where each node is asked to paint itself. The actual rendering is abstracted out thru a Graphics Engine which is responsible for actually turning on the pixels and things like hardware acceleration.</li></ol><h3>2. Rendering Modes</h3><p>The actual execution of the rendering process described above can change completely based upon the rendering mode the browser decides to use for a particular page. The reason browsers have different rendering modes is because of the history of the web, and understanding rendering modes is very important to understanding how browsers behave. However, I would not touch upon it here since <a
href="http://hsivonen.iki.fi/doctype/">http://hsivonen.iki.fi/doctype/</a> does an excellent job of capturing all the details. If you are just interested in the background, read <a
href="http://en.wikipedia.org/wiki/Quirks_mode">http://en.wikipedia.org/wiki/Quirks_mode</a>.</p><h3>3. Dynamic Pages</h3><p>Pages can change because of JavaScript or because of user interaction which triggers parts of the rendering process:</p><p><img
title="Incremental Rendering" src="https://developer.mozilla.org/@api/deki/files/235/=Gecko_Overview_34.png" alt="" /></p><p>(Source: <a
href="https://developer.mozilla.org/en/Introduction_to_Layout_in_Mozilla">https://developer.mozilla.org/en/Introduction_to_Layout_in_Mozilla</a>)</p><ul><li>If DOM elements are added or removed, the typical response of the browser is to follow the rendering process described earlier in almost serial order</li><li>If the Style attribute on an element is changed, the style for the element needs to be recomputed, the page re-flown and re-painted<ul><li>Browsers may optimize this by batching style re-computes by queuing them</li><li>However, scripts often read back changes that they have just made which requires the re-styling queue to be flushed</li><li>For better performance, make style changes as a batch and then read them in a batch so that the queue is flushed less frequently</li></ul></li><li>Some style changes are cheaper:<ul><li>Changing size / location would not require style re-compute but only re-flowing and re-painting</li><li>Color change does not require re-flowing, but only re-painting</li><li>Scrolling also does not require re-computation, but only re-painting &#8211; this is typically done incrementally and may not even require full repainting (but things like fixed background images would necessitate full repainting). So moving elements by scrolling programmatically can be faster than moving elements by modifying their style attribute</li></ul></li><li>Re-Flow &#8211; because of position or size changes &#8211; is typically recursive (root to leafs)<ul><li>Some attribute changes in a child can trigger changes in the entire ancestry all the way up to the root. Example: Height changes</li><li>Some attribute changes in a parent can trigger changes in all the descendants right down to leaves. Example: Width changes</li><li>Browsers can detect that only a section of the tree may change and do re-flow only on that sub-tree</li></ul></li></ul><h3>4. Resource Loading</h3><p>As the Parser goes over the Content Tree, it may see an element referring an external resource (image, CSS, JS, font, etc), which needs to be loaded. This loading happens as follows:</p><h4>Order of Loading</h4><p>While typically resources get loaded in the order of appearance in the document, browsers optimize this by prioritizing stylesheets and JavaScript files ahead of images. It is also recommended that stylesheets be put at the top. This is because:</p><ul><li>Stylesheets are required to build the Rendering Tree, but have no impact on Content Tree, so HTML parsing and JS execution can continue while CSS is downloaded and loaded.</li><li>A script could ask for style information even as the stylesheet is being downloaded and the rendering tree is being built. If this happens, you get an error. So you want to load styles before JS starts executing</li></ul><h4>Parallel Loading</h4><p>Modern browsers maintain multiple persistent connections to a server. This allows parallel loading. Parallel loading is a good thing because it reduces the overall latency of the page getting delivered to the end-user. However, out of consideration for the load factor on web-servers, The HTTP 1.1 RFC <a
href="http://tools.ietf.org/html/rfc2616#section-8.1.4">recommends</a> that &#8220;Clients that use persistent connections SHOULD limit the number of simultaneous connections that they maintain to a given server. A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy&#8221;.</p><p>Note that there is a trade-off here between the overhead of number of open sockets vs. the overhead of opening new sockets, and its impact on latency. With the number of external resources being fetched by a page going up, it makes sense to optimize for reducing the number of times a new connection has to be setup, to reduce the latency and improve the user experience. Indeed, most browsers these days allow more than 2 simultaneous connections per host. Steve Souders summarizes the current situation nicely in his <a
href="http://www.stevesouders.com/blog/2008/03/20/roundup-on-parallel-connections/">Roundup on Parallel Connections</a>.</p><h4>Blocking Loads</h4><p>Since a script can call document.write(), parsing can&#8217;t proceed before the script is fully loaded, executed (if there is any inline script in the script block) and document.write() has been inserted. This means that a script load blocks parsing, and that means that further loading is blocked, preventing the parallelism mentioned above from being exploited. Modern browsers do help a bit. For example, in WebKit, when the main parser gets blocked because of a script load, it starts a side parser that figures out other resources to load in the rest of the HTML. However, that is WebKit &#8211; for other browsers, there are a couple of ways out:</p><ol><li>Put script blocks at the end &#8211; that way they do not pause any further parsing</li><li>Use a hack to download scripts asynchronously &#8211; Souders sums these up in his post on <a
href="http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/">Loading Scripts Without Blocking</a></li><li>HTML 5 specifies the <a
href="http://dev.w3.org/html5/spec/Overview.html#attr-script-async">async attribute on the script tag</a> which tells the browser that the script does not require synchronous execution and the parser can continue. WebKit <a
href="http://webkit.org/blog/1395/running-scripts-in-webkit/">recently</a> started supporting this attribute and Firefox has supported this since 3.6.</li></ol><h3>5. Physical Architecture</h3><p>Web browsers started off with a single process, single thread model. This was acceptable since web-pages were just documents that had to be rendered. However, the web has evolved from being document-centric to becoming application-centric &#8211; a lot of sites these days are applications, with a lot of active code, a far-cry from the static content browsers were designed to render. This gives rise to problems of stability, performance and security. To address these, most browsers have moved (or are in the process of moving) to a multi-process architecture. There are three drivers behind this trend:</p><ul><li><strong>Performance:</strong> Multiple processes exploit multiple cores</li><li><strong>Security:</strong> The browser can spin up a new process in a lower privilege mode, reducing / removing the impact of malicious code</li><li><strong>Stability:</strong> A badly behaved page / script / plugin does not impact others since it is isolated in a process.</li></ul><h4>Firefox</h4><p>Firefox uses a single thread, single process model. This means that in Firefox <a
href="http://www.mail-archive.com/mozilla-layout@mozilla.org/msg03579.html">a single UI thread is shared by all windows</a>. The reason for that apparently is to allow X-DOM blocking calls from diff pages of the same origin. More details on <a
href="http://www.mail-archive.com/mozilla-layout@mozilla.org/msg03580.html">http://www.mail-archive.com/mozilla-layout@mozilla.org/msg03580.html</a>. Network calls and web-worker requests are handled on different threads.</p><p>To provide better isolation and reliablility Firefox will move to a multi-process model with its <a
href="https://wiki.mozilla.org/Electrolysis">Electrolysis</a> project. However, this seems to be for plugins alone and pages would continue to be served from a single process.</p><h4>IE</h4><p>The first browser to ship with multiple process support was IE 7, with each browser window running in its own process:</p><p><img
title="IE 7 Process Model" src="http://ieblog.members.winisp.net/images/IE.Process.Model3.png" alt="" /></p><p>(source: <a
href="http://blogs.msdn.com/b/ie/archive/2008/03/11/ie8-and-loosely-coupled-ie-lcie.aspx">http://blogs.msdn.com/b/ie/archive/2008/03/11/ie8-and-loosely-coupled-ie-lcie.aspx</a>)</p><p>IE 8 improved upon this model by putting each tab in its own process, but moving the frame and the broker into a common process for improving startup time. Microsoft calls this architecture Loosely Coupled Internet Explorer (LCIE):</p><p><img
title="IE 8 Process Model" src="http://ieblog.members.winisp.net/images/IE8.Process.Model2.png" alt="" /></p><p>(source: <a
href="http://blogs.msdn.com/b/ie/archive/2008/03/11/ie8-and-loosely-coupled-ie-lcie.aspx">http://blogs.msdn.com/b/ie/archive/2008/03/11/ie8-and-loosely-coupled-ie-lcie.aspx</a>)</p><p>The actual model is however more sophisticated than what the diagram above suggests since IE 8 tries to balance the benefits of more processes with the extra overhead, without compromising on security. The actual process model is:</p><ul><li><strong>Protected Mode processes:</strong> Irrespective of memory overhead, sites with different levels of configured security open in different processes. This approach called <a
href="http://msdn.microsoft.com/en-us/library/bb250462(VS.85).aspx">Protected Mode</a> is based on <a
href="http://en.wikipedia.org/wiki/Mandatory_Integrity_Control">Mandatory Integrity Control</a></li><li><strong>Context-based tab-processes:</strong> The decision on whether to create a new tab-process or not is made depending upon the amount of memory available</li><li><strong>Max tab-processes:</strong> A specific value of maximum tab processes that can be created for a single isolated session at specific MIC</li></ul><p>More details: <a
href="http://blogs.msdn.com/b/askie/archive/2009/03/09/opening-a-new-tab-may-launch-a-new-process-with-internet-explorer-8-0.aspx">http://blogs.msdn.com/b/askie/archive/2009/03/09/opening-a-new-tab-may-launch-a-new-process-with-internet-explorer-8-0.aspx</a></p><h4>Chrome</h4><p>Chrome follows an approach similar to that of IE 8 &#8211; the host process for a tab is called a Renderer and the broker process is called Browser:</p><p><img
title="Google Chrome Process Model" src="http://dev.chromium.org/_/rsrc/1220197832277/developers/design-documents/multi-process-architecture/arch.png" alt="" /></p><p>(source: <a
href="http://dev.chromium.org/developers/design-documents/multi-process-architecture">http://dev.chromium.org/developers/design-documents/multi-process-architecture</a>)</p><p>Chrome supports four <a
href="http://dev.chromium.org/developers/design-documents/process-models">process models</a>:</p><ul><li><strong>Process per site-instance:</strong> Different visits to a site are in separate processes. Provides the highest level of isolation but also creates more overhead.</li><li><strong>Process per site:</strong> Different sites are isolated from each other, but visits to the same site run in the same process. Reduces overall memory overhead, but if you have several pages from a site open, the size of a single Renderer would be quite large, perhaps slowing it down.</li><li><strong>Process per tab:</strong> While the previous models consider source of origin, the process per tab model is based on the choice a user makes. One process is used for rendering one tab, and if in the same tab you switch to a different site, the process would continue.</li><li><strong>Single process:</strong> This is the simplest process with no isolation.</li></ul><p>In both Chrome and IE, a frame runs in the same process as its parent page. Also, separate process may prevent legal interactions between two pages from the same origin. Chrome&#8217;s solution to this is to not permit a x-process call even if it is legal. What IE does is to proxy these specific calls and convert them behind the scenes into some sort of IPC. This may also be supported by Chrome at some later stage.</p> <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VineetGupta?a=fQrhrL-Kr-U:0T0DsTdlxm4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=fQrhrL-Kr-U:0T0DsTdlxm4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=fQrhrL-Kr-U:0T0DsTdlxm4:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=fQrhrL-Kr-U:0T0DsTdlxm4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=fQrhrL-Kr-U:0T0DsTdlxm4:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=fQrhrL-Kr-U:0T0DsTdlxm4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=fQrhrL-Kr-U:0T0DsTdlxm4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=fQrhrL-Kr-U:0T0DsTdlxm4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VineetGupta/~4/fQrhrL-Kr-U" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.vineetgupta.com/2010/11/how-browsers-work-part-1-architecture/feed/</wfw:commentRss> <slash:comments>21</slash:comments> <feedburner:origLink>http://www.vineetgupta.com/2010/11/how-browsers-work-part-1-architecture/</feedburner:origLink></item> <item><title>PDC 2010 Announcements</title><link>http://feedproxy.google.com/~r/VineetGupta/~3/394TwO3UZdo/</link> <comments>http://www.vineetgupta.com/2010/11/pdc-2010-announcements/#comments</comments> <pubDate>Tue, 02 Nov 2010 17:35:14 +0000</pubDate> <dc:creator>Vineet Gupta</dc:creator> <category><![CDATA[.Net]]></category> <category><![CDATA[Cloud]]></category> <category><![CDATA[Mobile]]></category> <category><![CDATA[Web]]></category> <category><![CDATA[Azure]]></category> <category><![CDATA[IE 9]]></category> <category><![CDATA[PDC 2010]]></category> <category><![CDATA[Windows Phone 7]]></category><guid isPermaLink="false">http://www.vineetgupta.com/?p=10061</guid> <description>The PDC 2010 got over last weekend and there seems to be some interesting stuff that has come out of Redmond. While most of the big changes are on the Cloud side, the roadmap on the web and mobile platform is much clearer now with some important changes in strategy. Cloud Ok, I&amp;#8217;m gonna stick &lt;a
href='http://www.vineetgupta.com/2010/11/pdc-2010-announcements/'&gt;[...]&lt;/a&gt;</description> <content:encoded><![CDATA[<h1><span
style="font-weight: normal; font-size: 13px;">The <a
href="http://www.microsoftpdc.com">PDC 2010</a> got over last weekend and there seems to be some interesting stuff that has come out of Redmond. While most of the big changes are on the Cloud side, the roadmap on the web and mobile platform is  much clearer now with some important changes in strategy.</span></h1><h2>Cloud</h2><p>Ok, I&#8217;m gonna stick my neck out on this &#8211; IMHO, post PDC 2010, Microsoft has the most comprehensive offering among all the Cloud vendors when it comes to Windows. They are doing what everyone else is doing, and more. Besides, they are making it far simpler to move existing apps to the cloud and integrating your on-premise apps + infra with the cloud. The big problem is that they are only doing this for Windows, and there is nothing on the Linux side. So if you are a pure Microsoft shop, choosing Azure for the Cloud is a no-brainer. However, if you have a mixed environment, you would need to host your Linux workloads somewhere else, which may / may not work for you.</p><p><strong>VM Role:</strong> Azure now offers a <a
href="http://www.microsoft.com/windowsazure/compute/default.aspx">hypervisor in the sky</a> to host your Windows VMs. This is interesting since with the VM Role, Azure now provides both models &#8211; a auto-scalable, compute service exposed thru CLR and Win32, that competes with Google App Engine&#8217;s Python / JVM fabric, as well as the your-own-box-in-the-sky VPS model that competes with Amazon EC2, Rackspace and others. Jargon hungry analysts call the former PaaS (Platform as a Service) and the latter IaaS (Infrastructure as a Service). Both are useful &#8211; the former model works where you need agility of deployment, infinite scalability, and where your app and deployment architecture can be accommodated on top of the primitives provided by the service. The latter is useful if you need more flexibility in your architecture, or if you want to do a quick migration of an existing app without modifying stuff. The VM role would initially be available thru a invite-only beta program starting next year.</p><p><strong>Enhancements to Windows Azure:</strong> While the VM role certainly creates more flexibility, the PaaS version has become more flexible too:</p><ul><li><strong>Full IIS and Elevated Privilege:</strong> So far an Azure deployment could have a web-role, a worker-role or both, with the web-role mapping to a IIS website. What changes is that the web-role would now start mapping to an IIS instance, allowing you to run multiple websites under a single web-role, not to mention the ability to install IIS modules (or configure the APS.net pipeline). Also, the web and worker roles in Azure can now run in an elevated privilege mode. This would again help people migrate their existing apps.</li><li><strong>Azure Connect:</strong> A <a
href="http://www.microsoft.com/windowsazure/virtualnetwork/default.aspx">virtual network</a> that enables direct IP-based connectivity of app instances to and from on-premise infra. Basically sets up a IpSec based tunnel. Very helpful for sysads and devs who need to bring cloud instances under the org AD, or where cloud apps need to access on-premise data.</li><li><strong>Remote Desktop:</strong> Right now the way to manage your Azure deployment is to use the <a
href="http://code.msdn.microsoft.com/azurecmdlets">Powershell Cmdlets for Azure</a>. Most people like them since they are bandwidth friendly and scriptable. But now there is help for the command-line challenged. You can now &#8220;see&#8221; your application host over remote desktop. Not sure if this exposes any new functionality beyond what was already available thru the <a
href="http://msdn.microsoft.com/en-us/library/ee460799.aspx">Management API</a>.</li><li><strong>Better Java Support:</strong> I am not sure if people are aware of this, but it has been possible to run Java apps on Azure since around an year, including the ability to run Tomcat (thru the <a
href="http://code.msdn.microsoft.com/winazuretomcat">Tomcat Acclerator</a>), ability to access Windows Azure services thru the open source <a
href="http://www.windowsazure4j.org/">Azure SDK for Java</a> and a JDBC driver for SQL Azure. What&#8217;s new is an <a
href="http://www.windowsazure4e.org/">Eclipse plugin</a> and <a
href="http://www.jdotnetservices.com/">App Fabric SDK</a> to access App-Fabric (see below) from Java.</li><li><strong>Better PHP Support:</strong> Similar to Java, it is possible to run PHP apps on Azure. And similarly, there is a <a
href="http://phpazure.codeplex.com/">Windows Azure SDK</a>, an <a
href="http://www.windowsazure4e.org/">Eclipse plugin</a> and a PHP driver to talk to SQL Azure. Some extras: <a
href="http://azurephptools.codeplex.com">command-line tools for PHP</a> and a <a
href="http://www.interoperabilitybridges.com/projects/windows-azure-companion">Windows Azure Companion</a> to make it easy to deploy, diagnose and monitor PHP applications.</li></ul><p><strong>Improved App Fabric:</strong> The <a
href="http://www.microsoft.com/en-us/appfabric/azure/">App Fabric</a> is one of the strongest differentiators in the Azure stack. This is some very sophisticated middleware that I think is unique among all the Cloud vendors today:</p><ul><li><strong>Access Control:</strong> Identity integration with AD, Live Id, Facebook, Google and Yahoo. Authorization thru declarative rules that transform incoming security claims into claims understood by app. REST API.</li><li><strong>Service bus:</strong> Allows message exchange across firewalls, NAT gateways, etc. with the same programming model as for WCF or using REST, Pub-Sub system with multiple topics, Full-duplex bi-directional communication, including P2P with NAT traversal. It is now possible to do durable messaging, which increases delivery assurance to mobile devices / 3rd parties. If you have ever tried to do cross network messaging, you know how difficult firewall traversal and NAT traversal can get, and how troublesome DoS attacks can get. The Service Bus addresses all these issues and more.</li><li><strong>Integration:</strong> BizTalk in the sky &#8211; pipelines, transforms, adaptors, BAM, Rules, self-service trading partner community portal and provisioning of B2B pipelines. What, you do not know about BizTalk? Well, think of it as a higher degree of abstraction for the messaging layer, and a lot of pre-built patterns and functionality. If you are running multiple apps in your IT, sooner or later you need something like this. App Fabric Integration brings it to the sky so that you can integrate your on-premise apps and cloud apps using the same model. Not available yet though &#8211; the invite only CTP starts in 2011.</li><li><strong>Caching:</strong> Memcached like distributed in-memory cache, available on the local network. No limits on object size, pre-built ASP.net providers for session state and page output caching (so no app code changes required). Additionally, this can be secured thru Access Control (mentioned above). However, there is no HA yet. Available thru a invite-only CTP.</li><li><a
href="http://www.microsoft.com/en-us/appfabric/azure/composite-apps.aspx">Composite Apps</a>: So you have got your app all nicely written with access control defined, endpoints exposed using Service Bus, message transformation, etc. being handled by the Integration service and frequently used data cached. Is this enough? What about lifetime management? Scale out/scale-in? Deployment automation? Monitoring? Mission critical systems need all this and more. This is where the Composite Apps service comes in. This essentially provides a multi-tenant runtime and tools for handling all of the above thru a declarative model. Again, CTP would be available in 2011</li></ul><p><strong>Improved CDN:</strong> So far Azure CDN was only able to pull content from Azure Storage. Now it can also cache data returned from the app (dynamic caching). Also the CDN is available over SSL/TLS. Besides, they have put up POPs in Middle East and improved the pipe.</p><p><strong>Improved SQL Azure:</strong> SQL Azure would start providing Reporting Services (thru an invite-only CTP to begin with), a Web-based management console (called Database Manager) and ability to <a
href="http://www.microsoft.com/en-us/SQLAzure/datasync/default.aspx">Sync</a> entire databases or specific tables between on-premises SQL Server and SQL Azure, or between SQL Azure datacenters. The data to be synced is declarative defined, and the sync can be scheduled, with conflict handling and logging + monitoring support.</p><p><strong>Azure Marketplace:</strong> The <a
href="http://www.microsoft.com/windowsazure/marketplace/">Azure Marketplace</a> &#8220;is an online marketplace for developers to share, find, buy and sell building block components, training, service templates, premium data sets plus finished services and applications needed to build Windows Azure platform applications.&#8221; The data part (which I think is more interesting) is already available at the <a
href="https://datamarket.azure.com/">Data Market</a>. This includes both public domain data-sets as well as commercial data-sets on a wide variety of topics &#8211; &#8220;everything from demographics, navigation, crime, media, to web services and algorithms for data cleansing.&#8221; Cool stuff!</p><h2>Web and Mobile</h2><p>One good thing that happened at the PDC was that Microsoft came clean on its UI platform strategy, and the strategy is a pretty simple, logical one:</p><ul><li>Web Apps thru HTML 5</li><li>Native apps on Desktop thru WPF</li><li>Native apps on Mobile thru Silverlight</li></ul><p>There is a lot of noise in the media about how Microsoft has dumped Silverlight and is repositioning it for the mobile, etc. There are three aspects to this discussion:</p><p><strong>Why focus on HTML 5 for the Web</strong></p><p>This is a no-brainer:</p><ul><li>HTML 5 already provides most capabilities that required plugins like Flash / SL not so long back, so SL is not adding a ton of value over HTML 5 anymore.</li><li>HTML 5 enjoys tremendous momentum with web-devs</li><li>Firefox and Webkit have better support for HTML 5 than IE, and hence more web-dev mind-share</li><li>IE is losing ground to Chrome, Firefox and Safari</li></ul><p>The choice for Microsoft is obvious &#8211; embrace HTML 5 completely and take a leadership role. And now with this commitment coming right from the top, with SteveB himself vaxing eloquent about HTML 5, you can bet that the IE team will produce the goods. This may not happen in the IE 9 timeframe though, but then this is a long-term play.</p><p><strong>What about SL on the Web</strong></p><p>There are lot of people who think that SL is about to disappear from the web, but that is incorrect. There are lots of things that are still very hard to do in HTML 5, for which developers will continue to rely on plugins like Flash and Silverlight. However, there is no doubt that SL will move into a niche role, being utilized more to fill HTML 5 gaps, at least when it comes to the consumer web. On the enterprise side, SL may enjoy a more mainstream role since x-platform, x-browser and plugin deployment issues are more controllable there, and development on SL is any day simpler than on HTML 5, especially if you have a background in imperative languages.</p><p><strong>Why SL for Mobile</strong></p><p>The vision for CoreCLR &#8211; the version of CLR that powers Silverlight &#8211; has always been to provide the .Net experience on all low footprint environments. If my memory serves me right, a lot of SL core came from .Net Compact Framework which was the version of .Net shipped on Windows Mobile back in 2002-2003. And since SL 2, a team in Hyderabad has been working on making SL available on the mobile. So SL on Mobile is nothing new. It also makes sense as the mainstream platform for the Mobile, since SL is a proper subset of WPF and therefore you can share a lot of code between desktop and mobile. So why not WPF itself? I&#8217;m not very sure, but certainly the lighter footprint of SL as compared to WPF is more suitable for mobile. Also, this would allow Microsoft to optimize SL for the mobile, focussing on issues like reducing power consumption and CPU utilization. Last, but not the least, the developer momentum behind Silverlight is certainly bigger than that behind WPF, and therefore this allows Microsoft to accelerate the app development on Windows Mobile.</p><p><strong>IE 9 HTML 5 Support</strong></p><p>Things are looking better than ever on the <a
href="http://msdn.microsoft.com/en-us/ie/ff468705.aspx">HTML 5 support</a> front. The first <a
href="http://test.w3.org/html/tests/reporting/report.htm">Official HTML5 Test Suite Conformance Results</a> from W3C show that IE 9 is passing most tests, however the coverage of the test itself seems fairly small &#8211; only a few features are being tested. More illuminating are the following comparisons on wikipedia:</p><ul><li><a
href="http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(ECMAScript)">JavaScript</a></li><li><a
href="http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(Cascading_Style_Sheets)">CSS</a></li><li><a
href="http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(Document_Object_Model)">DOM</a></li><li><a
href="http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(HTML5)">HTML 5</a></li><li><a
href="http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(HTML5_Canvas)">HTML 5 Canvas</a></li><li><a
href="http://en.wikipedia.org/wiki/Comparison_of_layout_engines_(HTML5_Media)">HTML 5 Media</a></li></ul><p>After going thru these comparisons, my take is that all browsers are at varying degrees of HTML 5 support and IE 9 is not too far behind. How quickly the various browsers start supporting the major features would be a function of resources deployed and how quickly the release cycles go.</p><p>What should also be obvious from the above comparisons is that it is utterly foolish to do browser detection since the feature set of each browser is going to change very rapidly over the next couple of years. What we should do instead is feature detection and fail gracefully. This is of course done by all the major JS libraries already, the risk is in your own custom code. If you are doing browser detection, you should get rid of it right now to keep it forward compatible.</p><p><strong>Windows Phone 7</strong></p><p>The development model for Windows Phone is clear enough &#8211; Silverlight for apps and XNA for games. Both make sense and provide a ton of power. What Microsoft has done is to provide a bunch of templates, tooling and APIs to make it simpler to do Windows Phone apps. Moreover, this can be done using VS Express, so there is no cost! However, for developing apps, you need to get familiar with the UI, its nothing like iOS or Android. If you do not have a Windows Phone, the simplest way is to run the emulator that ships with VS Express and figure your way around. Finally there is also the <a
href="http://marketplace.windowsphone.com/Default.aspx">Windows Phone Marketplace</a> &#8211; same concept as the App-Store, including an approval process and $ 100 fees for submitting an app. But none of this is really new &#8211; all of this has been in place for a while.</p><p>While we are on this topic, I do want to mention that I am surprised that Microsoft is taking the Apple approach to the marketplace. The real value of a marketplace is in providing consumers and developers a single point for app publication, discovery and access. The approval process and the submission fee are not good for anyone in the long run, including the platform vendor. Especially for Microsoft, who need to steal share from iOS and Android, I think a more open marketplace would have helped:</p><ul><li>Reduced costs for the developer, and therefore for the end consumer</li><li>Less process overhead for the developer</li><li>Freedom of expression &#8211; this counts for a lot in spirit, if not in fact</li><li>Mature content can be marked as such by reviewers or community, same as what happens on sites like YouTube / Facebook</li><li>There is the problem of crapware, but then a rating / popularity / recommendation system would easily address that</li><li>There would be some upfront loss of revenue, but I think right now the real problem is increasing adoption for which you need to drive up the platform value by having more content + functionality available on it.</li></ul><p>A marketplace that requires content approval and a submission fees discourages the developer from building native apps and instead focus on building mobile apps. No platform vendor likes that, since that reduces the tie-in to the platform. Microsoft understands this well enough and despite that we have an Apple like marketplace. Very baffling.</p><h2>Languages and Tools</h2><p>The focus of the next version of C# and VB would be asynchronous programming. There are two motivations for this:</p><ul><li><strong>UI responsiveness:</strong> As apps get more and more connected, the data often comes over a network call, which must not block the UI thread</li><li><strong>Scalability:</strong> Use the thread for doing some useful work and not keep it blocked</li></ul><p>Now at this stage, there is a chance that one would confuse asynchrony with parallelism. That is not the case &#8211; asynchrony is about yielding control while results are awaited, whereas concurrency is about doing two things in parallel. The former is necessarily cooperative, while the latter maybe achieved thru multiple hardware threads or pre-emptive / co-operative scheduling of multiple threds.</p><p>Just to be sure, .Net Framework has provided async support since version 1 via the begin-end pattern. So to appreciate the value of the async support being provided requires us to go a little deeper in terms of semantics, what happens behind the scenes and why the feature has been designed the way it is. These are all involved topics, and I would try and cover async support in a different post. Meanwhile, you can find more details on <a
href="http://msdn.com/vstudio/async">http://msdn.com/vstudio/async</a>.</p> <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VineetGupta?a=394TwO3UZdo:mliIsq_WyB4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=394TwO3UZdo:mliIsq_WyB4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=394TwO3UZdo:mliIsq_WyB4:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=394TwO3UZdo:mliIsq_WyB4:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=394TwO3UZdo:mliIsq_WyB4:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=394TwO3UZdo:mliIsq_WyB4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=394TwO3UZdo:mliIsq_WyB4:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=394TwO3UZdo:mliIsq_WyB4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VineetGupta/~4/394TwO3UZdo" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.vineetgupta.com/2010/11/pdc-2010-announcements/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <feedburner:origLink>http://www.vineetgupta.com/2010/11/pdc-2010-announcements/</feedburner:origLink></item> <item><title>Facebook is the new Microsoft</title><link>http://feedproxy.google.com/~r/VineetGupta/~3/ALDrwlOV11M/</link> <comments>http://www.vineetgupta.com/2010/10/facebook-is-the-new-microsoft/#comments</comments> <pubDate>Sat, 30 Oct 2010 07:47:57 +0000</pubDate> <dc:creator>Vineet Gupta</dc:creator> <category><![CDATA[Web]]></category><guid isPermaLink="false">http://www.vineetgupta.com/?p=10056</guid> <description>Facebook these days reminds me a lot of Microsoft of yore. For one, they are taking a platform approach exactly like Microsoft &amp;#8211;  Facebook Connect is the most powerful and widely used identity platform on the Internet today &amp;#8211; as enticing to developers and businesses as Windows was in its heydays. They have succeeded where &lt;a
href='http://www.vineetgupta.com/2010/10/facebook-is-the-new-microsoft/'&gt;[...]&lt;/a&gt;</description> <content:encoded><![CDATA[<p>Facebook these days reminds me a lot of Microsoft of yore.</p><p>For one, they are taking a platform approach exactly like Microsoft &#8211;  Facebook Connect is the most powerful and widely used identity platform on the Internet today &#8211; as enticing to developers and businesses as Windows was in its heydays. They have succeeded where Microsoft failed (Hailstorm, Passport) as well as the open source community (OpenId). Apparently, <a
href="http://mashable.com/2010/10/26/10000-websites-integrate-with-facebook-every-day/">10,000 websites integrate with Facebook everyday</a> and people are even taking the <a
href="http://techcrunch.com/2010/10/18/likify-qr-code/">Facebook experience offline</a>! This means that as other companies innovative and create value, Facebook gets richer. Exactly like Windows. IIRC, one of the metrics at Microsoft used to be the ratio of ISV revenue to Windows revenue, the idea being that this ratio should keep going up. Facebook today is in a similar position and benefits similarly from their platform.</p><p>Second, they are changing the rules of the game, much like Microsoft did. The model before Microsoft was a single integrated stack and customers had to pay big money for the iron, the software and the services &#8211; all from the same vendor &#8211; IBM. Microsoft changed this by commoditizing software and opening up the vertically integrated stack. In a similar vein, Facebook changes the game by offering an alternative to Google Search, hitherto the de-facto gateway to the web. A lot of content discovery today happens thru the Facebook News-feed. This means that publishers once again need to target their audience and not just the search engine, which is biased for more frequently changing content and can be, and has been gamed by publishers. This helps the small, niche publisher who would otherwise be lost in the long-tail, never landing on the first page of a Google Search. This is not just about stuff you read, but also about what you buy. My wife&#8217;s latest acquisition &#8211; a DSLR camera &#8211; was entirely based on recommendations received from friends and family, mostly on Facebook. An year back, she would have been searching and going thru review sites. Not that we did not search or read reviews, but the decision was mostly based on recommendations.</p><p>Finally, they are using this tremendous leverage to move into markets they find interesting, and much like Microsoft when they decide to move into that market, the incumbents are under threat to becoming irrelevant. This is what happened when they announced the beta of their Q&amp;A system, with Quora and Aardvark coming under threat. This is again happening with Facebook Places and this time Foursquare is under threat. Now one could argue that this is bound to happen anytime the 800 pound gorilla in any industry forays into a market, but this is different. This is about leverage. Google / Apple, despite being larger, would never create the kind of threat that Facebook creates simply because Facebook owns the user like no one else does. Exactly the same as Microsoft owning the PC like no one else. Of course Microsoft was prudent about it &#8211; they focussed only on the software bit (where the margins were highest) and deliberately kept away from the hardware and the services businesses to let the ecosystem thrive and drive the platform forward. Facebook would also need to figure out where they want to pursue opportunities and where they would not go.</p> <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ALDrwlOV11M:nyAwQ_HESB0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ALDrwlOV11M:nyAwQ_HESB0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=ALDrwlOV11M:nyAwQ_HESB0:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ALDrwlOV11M:nyAwQ_HESB0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=ALDrwlOV11M:nyAwQ_HESB0:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ALDrwlOV11M:nyAwQ_HESB0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=ALDrwlOV11M:nyAwQ_HESB0:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=ALDrwlOV11M:nyAwQ_HESB0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VineetGupta/~4/ALDrwlOV11M" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.vineetgupta.com/2010/10/facebook-is-the-new-microsoft/feed/</wfw:commentRss> <slash:comments>1</slash:comments> <feedburner:origLink>http://www.vineetgupta.com/2010/10/facebook-is-the-new-microsoft/</feedburner:origLink></item> <item><title>Moved to WordPress</title><link>http://feedproxy.google.com/~r/VineetGupta/~3/sSVcFj1o9dY/</link> <comments>http://www.vineetgupta.com/2010/10/moved-to-wordpress/#comments</comments> <pubDate>Sat, 30 Oct 2010 04:20:41 +0000</pubDate> <dc:creator>Vineet Gupta</dc:creator> <category><![CDATA[Personal]]></category><guid isPermaLink="false">http://www.vineetgupta.com/?p=10052</guid> <description>Last year, when I moved to Blogger, my decision was influenced by: Staying with a cloud provider for the blog service Ability to install plugins Now WordPress.com does not allow you to install plugins unless you are really big, and therefore Blogger made sense. However, I have found Blogger to be very limiting and every time &lt;a
href='http://www.vineetgupta.com/2010/10/moved-to-wordpress/'&gt;[...]&lt;/a&gt;</description> <content:encoded><![CDATA[<p>Last year, when I moved to Blogger, my decision was influenced by:</p><ul><li>Staying with a cloud provider for the blog service</li><li>Ability to install plugins</li></ul><p>Now WordPress.com does not allow you to install plugins unless you are <a
href="http://vip.wordpress.com/hosting/">really big</a>, and therefore Blogger made sense. However, I have found Blogger to be very limiting and every time I looked at the WordPress plugin ecosystem, I found myself yearning for all that richness. Finally, yesterday evening, I set up a box in the sky, installed WordPress, added the plugins I wanted and imported my blog from Blogger.</p><p>What went well:</p><ul><li>Installation was a breeze &#8211; took me less than 10 minutes to get WP up and running on a bare Ubuntu box (and I am a newbie to LAMP)</li><li>Plugins &#8211; you are spoilt for choice here, and the time taken was mostly in trying out various plugins and selecting which one to use for a specific functionality.</li><li>Import went off without a hitch, except that it kept throwing an error for one of the posts (the migration from Live to Blogger one)</li><li>Bonus was that I was able to bring back all the comments I had lost on my older Live Space blog &#8211; they could not be imported to Blogger, but WordPress worked like a charm.</li></ul><p>The only thing that did not work was that I could not find any simple way of retaining the permalinks &#8211; Blogger appends a random number after each post and short of entering that manually for each post, I can&#8217;t think of any other mechanism to retaining them. This is bad because it will break people&#8217;s bookmarks, but with the new scheme, I don&#8217;t think this will ever need changing hence.</p> <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VineetGupta?a=sSVcFj1o9dY:8j6INd094dQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=sSVcFj1o9dY:8j6INd094dQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=sSVcFj1o9dY:8j6INd094dQ:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=sSVcFj1o9dY:8j6INd094dQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=sSVcFj1o9dY:8j6INd094dQ:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=sSVcFj1o9dY:8j6INd094dQ:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/VineetGupta?i=sSVcFj1o9dY:8j6INd094dQ:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VineetGupta?a=sSVcFj1o9dY:8j6INd094dQ:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/VineetGupta?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VineetGupta/~4/sSVcFj1o9dY" height="1" width="1"/>]]></content:encoded> <wfw:commentRss>http://www.vineetgupta.com/2010/10/moved-to-wordpress/feed/</wfw:commentRss> <slash:comments>0</slash:comments> <feedburner:origLink>http://www.vineetgupta.com/2010/10/moved-to-wordpress/</feedburner:origLink></item> </channel> </rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using apc
Page Caching using apc
Database Caching 2/54 queries in 0.007 seconds using apc
Object Caching 694/865 objects using apc

Served from: www.vineetgupta.com @ 2012-05-02 20:51:20 -->

