<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-137385657526678306</id><updated>2011-07-28T21:46:54.352-07:00</updated><category term='ruby'/><category term='scripting'/><category term='grails groovy'/><category term='scala'/><category term='javascript'/><category term='java'/><category term='programming'/><category term='gwt'/><category term='hacking'/><category term='jvm'/><category term='two phase commit'/><category term='statically typed'/><category term='agile'/><category term='qa'/><category term='groovy'/><category term='DSL'/><category term='ejb3'/><category term='haskell'/><category term='languages'/><category term='mac'/><category term='design'/><category term='agile testing'/><category term='eclipse'/><category term='build tool'/><category term='testing'/><category term='sas'/><category term='Fluent Interface'/><category term='pipes'/><category term='duck typing'/><category term='rant'/><category term='software rewrite'/><title type='text'>Braincasting</title><subtitle type='html'>Stuff about software development, agile and testing</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://nilanjan-braincasting.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>46</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-3515901377221671842</id><published>2010-01-07T20:33:00.000-08:00</published><updated>2010-01-07T21:19:44.992-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Ruby inject in Scala</title><content type='html'>Do you have your favorite line in Ruby. Mine will be&lt;br /&gt;&lt;br /&gt;(1..100).inject(&amp;amp;:+)&lt;br /&gt;&lt;br /&gt;and I first saw that in  &lt;a href="http://weblog.raganwald.com/2008/02/1100inject.html"&gt;Reg Braithwaite blog&lt;/a&gt; (very good read)&lt;br /&gt;&lt;br /&gt;So what's going on here? Here is the explanation from Reg Braithwaite's blog&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;strong style="font-style: italic;"&gt;Explanation&lt;/strong&gt;&lt;span style="font-style: italic;"&gt;: &lt;/span&gt;&lt;code style="font-style: italic;"&gt;(1..100)&lt;/code&gt;&lt;span style="font-style: italic;"&gt; creates a &lt;/span&gt;&lt;em style="font-style: italic;"&gt;Range&lt;/em&gt;&lt;span style="font-style: italic;"&gt;. For our purposes, this is equivalent to a collection of the whole numbers from one to one hundred, inclusive (The major way in which it differs from an array for us is that it doesn’t actually require one hundred spots in memory. Ranges are also useful for matching.) The #inject method is called &lt;/span&gt;&lt;code style="font-style: italic;"&gt;fold&lt;/code&gt;&lt;span style="font-style: italic;"&gt; or &lt;/span&gt;&lt;code style="font-style: italic;"&gt;reduce&lt;/code&gt;&lt;span style="font-style: italic;"&gt; in other languages. Expressed like this, it applies the “+” function to the elements of our range, giving us the sum. &lt;/span&gt;&lt;a style="font-style: italic;" href="http://en.wikipedia.org/wiki/Carl_Friedrich_Gauss"&gt;Primary school students&lt;/a&gt;&lt;span style="font-style: italic;"&gt; could tell you an easier way to obtain the sum, of course, but we will ignore that for now.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Ruby doesn’t actually have a function called &lt;/span&gt;&lt;code style="font-style: italic;"&gt;+&lt;/code&gt;&lt;span style="font-style: italic;"&gt;. What actually happens is that &lt;/span&gt;&lt;code style="font-style: italic;"&gt;#inject&lt;/code&gt;&lt;span style="font-style: italic;"&gt; wants a block. The &lt;/span&gt;&lt;code style="font-style: italic;"&gt;&amp;amp;&lt;/code&gt;&lt;span style="font-style: italic;"&gt; operator converts Proc objects into blocks and block into Proc objects. In this case, it tries to convert the symbol &lt;/span&gt;&lt;code style="font-style: italic;"&gt;:+&lt;/code&gt;&lt;span style="font-style: italic;"&gt; into a block. The conversion uses Ruby’s built-in coercion mechanism. That mechanism checks to see whether we have a Proc object. If not, it sends the &lt;/span&gt;&lt;code style="font-style: italic;"&gt;#to_proc&lt;/code&gt;&lt;span style="font-style: italic;"&gt; method to the argument to make a Proc. If the Symbol &lt;/span&gt;&lt;code style="font-style: italic;"&gt;:+&lt;/code&gt;&lt;span style="font-style: italic;"&gt; has a &lt;/span&gt;&lt;code style="font-style: italic;"&gt;#to_proc&lt;/code&gt;&lt;span style="font-style: italic;"&gt; method, it will be called. In Ruby 1.9 it has a &lt;/span&gt;&lt;code style="font-style: italic;"&gt;#to_proc&lt;/code&gt;&lt;span style="font-style: italic;"&gt; method. That method returns a Proc that takes its first argument and sends the &lt;/span&gt;&lt;code style="font-style: italic;"&gt;+&lt;/code&gt;&lt;span style="font-style: italic;"&gt; method to it along with any other arguments that may be present.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Well even though there are plenty different way you could add entries in collection, this line of code demonstrates the power of the language and what you could do with it.&lt;br /&gt;&lt;br /&gt;Being Scala is my  favorite programming language right now I wanted to implement something very similar in it. By default in Scala if you want some apply some binary operator to a range you could do &lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;(1 until 100).reduceLeft { _ + _}&lt;/span&gt;  and if you want your range to be inclusive then&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;(1 until 100).inclusive.reduceLeft { _ + _} &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But still it is little bit verbose. So with some &lt;a href="http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-6"&gt;implicit&lt;/a&gt; trick  I was able to come quite a bit close to the actual Ruby line above&lt;br /&gt;&lt;br /&gt;1 ⟞ 10 inject '+&lt;br /&gt;&lt;br /&gt;'⟞' is a unicode character and yes you could define method names with unicode characters. '+ is symbol is Scala. And here is rest of the implementation...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;implicit def rich_range(r: Range) = new {&lt;br /&gt;  def inject(s:Symbol) = {&lt;br /&gt;    s match {&lt;br /&gt;      case '+ =&gt; r.reduceLeft { _ + _ }&lt;br /&gt;      case _ =&gt; //not supported yet&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;implicit def rich_int(start: Int) = new { def ⟞(end:Int) = (start until end).inclusive }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Well again point is not about using binary operator on a collection or range. Its about powerful and expressiveness of a programming language.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-3515901377221671842?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3515901377221671842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3515901377221671842'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2010/01/ruby-inject-in-scala.html' title='Ruby inject in Scala'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-2882999473988571262</id><published>2009-10-05T19:54:00.000-07:00</published><updated>2009-10-05T19:58:53.795-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='grails groovy'/><title type='text'>Database Migration in Grails</title><content type='html'>   &lt;meta name="Title" content=""&gt; &lt;meta name="Keywords" content=""&gt; &lt;meta equiv="Content-Type" content="text/html; charset=utf-8"&gt; &lt;meta name="ProgId" content="Word.Document"&gt; &lt;meta name="Generator" content="Microsoft Word 2008"&gt; &lt;meta name="Originator" content="Microsoft Word 2008"&gt; &lt;link rel="File-List" href="file://localhost/Users/nilanjan/Library/Caches/TemporaryItems/msoclip/0/clip_filelist.xml"&gt; &lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;o:documentproperties&gt;   &lt;o:template&gt;Normal.dotm&lt;/o:Template&gt;   &lt;o:revision&gt;0&lt;/o:Revision&gt;   &lt;o:totaltime&gt;0&lt;/o:TotalTime&gt;   &lt;o:pages&gt;1&lt;/o:Pages&gt;   &lt;o:words&gt;742&lt;/o:Words&gt;   &lt;o:characters&gt;4230&lt;/o:Characters&gt;   &lt;o:company&gt;Pillar technology&lt;/o:Company&gt;   &lt;o:lines&gt;35&lt;/o:Lines&gt;   &lt;o:paragraphs&gt;8&lt;/o:Paragraphs&gt;   &lt;o:characterswithspaces&gt;5194&lt;/o:CharactersWithSpaces&gt;   &lt;o:version&gt;12.0&lt;/o:Version&gt;  &lt;/o:DocumentProperties&gt;  &lt;o:officedocumentsettings&gt;   &lt;o:allowpng/&gt;  &lt;/o:OfficeDocumentSettings&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:worddocument&gt;   &lt;w:zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:trackmoves&gt;false&lt;/w:TrackMoves&gt;   &lt;w:trackformatting/&gt;   &lt;w:punctuationkerning/&gt;   &lt;w:drawinggridhorizontalspacing&gt;18 pt&lt;/w:DrawingGridHorizontalSpacing&gt;   &lt;w:drawinggridverticalspacing&gt;18 pt&lt;/w:DrawingGridVerticalSpacing&gt;   &lt;w:displayhorizontaldrawinggridevery&gt;0&lt;/w:DisplayHorizontalDrawingGridEvery&gt;   &lt;w:displayverticaldrawinggridevery&gt;0&lt;/w:DisplayVerticalDrawingGridEvery&gt;   &lt;w:validateagainstschemas/&gt;   &lt;w:saveifxmlinvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:ignoremixedcontent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:alwaysshowplaceholdertext&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:compatibility&gt;    &lt;w:breakwrappedtables/&gt;    &lt;w:dontgrowautofit/&gt;    &lt;w:dontautofitconstrainedtables/&gt;    &lt;w:dontvertalignintxbx/&gt;   &lt;/w:Compatibility&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:latentstyles deflockedstate="false" latentstylecount="276"&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt; &lt;style&gt; &lt;!--  /* Font Definitions */ @font-face 	{font-family:Cambria; 	panose-1:2 4 5 3 5 4 6 3 2 4; 	mso-font-charset:0; 	mso-generic-font-family:auto; 	mso-font-pitch:variable; 	mso-font-signature:3 0 0 0 1 0;} @font-face 	{font-family:Tahoma; 	panose-1:2 11 6 4 3 5 4 4 2 4; 	mso-font-charset:0; 	mso-generic-font-family:auto; 	mso-font-pitch:variable; 	mso-font-signature:3 0 0 0 1 0;}  /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-parent:""; 	margin:0in; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-ascii-font-family:Cambria; 	mso-ascii-theme-font:minor-latin; 	mso-fareast-font-family:Cambria; 	mso-fareast-theme-font:minor-latin; 	mso-hansi-font-family:Cambria; 	mso-hansi-theme-font:minor-latin; 	mso-bidi-font-family:"Times New Roman"; 	mso-bidi-theme-font:minor-bidi;} a:link, span.MsoHyperlink 	{mso-style-noshow:yes; 	color:blue; 	text-decoration:underline; 	text-underline:single;} a:visited, span.MsoHyperlinkFollowed 	{mso-style-noshow:yes; 	color:purple; 	text-decoration:underline; 	text-underline:single;} @page Section1 	{size:8.5in 11.0in; 	margin:1.0in 1.25in 1.0in 1.25in; 	mso-header-margin:.5in; 	mso-footer-margin:.5in; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --&gt; &lt;/style&gt; &lt;!--[if gte mso 10]&gt; &lt;style&gt;  /* Style Definitions */ table.MsoNormalTable 	{mso-style-name:"Table Normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-parent:""; 	mso-padding-alt:0in 5.4pt 0in 5.4pt; 	mso-para-margin:0in; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-ascii-font-family:Cambria; 	mso-ascii-theme-font:minor-latin; 	mso-fareast-font-family:"Times New Roman"; 	mso-fareast-theme-font:minor-fareast; 	mso-hansi-font-family:Cambria; 	mso-hansi-theme-font:minor-latin;} &lt;/style&gt; &lt;![endif]--&gt;  &lt;!--StartFragment--&gt;      &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;span style="font-weight: bold;"&gt;So what is database migration? &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;span style="font-style: italic;"&gt;Managing database schema changes between multiple environments.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br /&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;In most of the agile projects database schema evolves along with the code. Its follows the same incremental change code goes through, we add a table, rename column and so on (&lt;a href="http://martinfowler.com/articles/evodb.html"&gt;Evolutionary database design&lt;/a&gt;). Database by itself doesn’t have any versioning information. One of the great thing about versioning code is if the current version doesn’t work the way we want we can always rollback to the prior version. But what about the database schema changes? Having a tool automate and manage database migration helps teams to address that problem.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;If you have worked with grails then you would know that we don’t necessary deal with database when working with grails domain objects. Instead of creating new table we create new domain object, we don't add column instead we add a new property to an existing domain object. But we still need to deal with database migration issues when make incremental releases. We cannot create/recreate database every time we make release. We have to have a mechanism to version and keep track of all the scheme changes. As of writing grails as 3 viable possible tools to manage database migration and in this blog entry I will discuss about my little playing with them&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;a href="http://code.google.com/p/dbmigrate/wiki/Grails"&gt;DbMigrate&lt;/a&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;Well I didn’t find any descend documentation about how to use dbmigrate with grails. When I installed the plugin it don’t work and gave me a file not found exception. After going into the plugin source code I figured that it is looking for the resource inside my grails project not in the location where plugin is actually install {dbmigratePluginDir}. And on top of that asking to create version table (db_version) manually is not very developer friendly. Let me know if anyone has used dbmigrate and had better experience than me.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;a href="http://grails.org/plugin/liquibase"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;a href="http://grails.org/plugin/liquibase"&gt;Liquibase&lt;/a&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;This is a very matured database migration tool but unfortunately has some gotcha’s when it comes to use it with grails. If you haven’t thought about database migration from beginning of the project it’s becomes harder to start with one. When you will run the liquibase plugin for the first time it will show the entire database as change because none of the changes are logged with liquibase. So to register all the changes with liquibase we had to recreate the database schema. Now if that is not an option, taking backup and reloading the data back again is possibly the only way. Well now is the fun part. My spike involved adding a property to an existing domain object and then removing it again, simple isn’t? We test-drive almost all our changes. So in any typical scenario our test database will change before any other environment. So one of the expectations we had liquibase is to detect that change and propagate that to dev and QA environment.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;Liquibase plugin does ship with a db-diff tool but unfortunately it compares between dev and test environment. I think I need to explain that little bit more. So according to Liquibase db-diff tool dev is more current than test schema. What that means is if we add a property to a domain object(that means a new column is added in test schema) liquibase will think that the column needs to be dropped from test schema and will generate a drop column change log, weird right? So I had to change the plugin source. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;In this case I changed DbDiff.groovy to swap dev and test database between source and target and it worked. But when we tried dropping a property for some reason it got the schema name wrong in it. I had to modify the generated change log. But overall it's a working solution if you are ready to deal with xml.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;a href="http://github.com/RobertFischer/autobase"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;a href="http://github.com/RobertFischer/autobase"&gt;Autobase&lt;/a&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;Autobase is the new and shinny database migration tool for grails. It is actually build over liquibase and has a nice little DSL in groovy. If you have an experience with rails migration you will find this very closely related. The biggest problem with autobase is to make to run successfully over and over again. When I tried to run it first time I got all sort of class not found exception. It turns out that autobase plugin relies on some groovy source that needs to be compiled before using it. And it doesn’t happen automatically. So I basically had to clean the scriptCache (&lt;home&gt;/.grails/scriptCache) and rebuild the entire grails project before running it (I had to do that every time before running grails create-migration). Autobase doesn’t ship with db-diff tool like liquibase so we have to create our own migration scripts. Even though it might sound bad but having little cool groovy dsl is nice and easy.&lt;o:p&gt;&lt;/o:p&gt;&lt;/home&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="font-style: italic;" class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;//Dropping column&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="font-style: italic;" class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;changeSet(id:'DropColumnAddedForTest', author:'Nilanjan') { &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="font-style: italic;" class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;span style=""&gt;  &lt;/span&gt;dropColumn(tableName:'company', columnName:'added_for_test')&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p style="font-style: italic;" class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;} &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;o:p&gt;&lt;br /&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span style="font-family:Tahoma;"&gt;&lt;span style=""&gt;&lt;/span&gt;Looking at all the things I went through so far I like Autobase better than any other database migration tool. Who doesn’t like DSL these days :)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;!--EndFragment--&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-2882999473988571262?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2882999473988571262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2882999473988571262'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2009/10/database-migration-in-grails.html' title='Database Migration in Grails'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-3122906417924383015</id><published>2009-09-22T20:07:00.000-07:00</published><updated>2009-09-22T20:16:07.012-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><category scheme='http://www.blogger.com/atom/ns#' term='gwt'/><title type='text'>Is anyone out there using GWT?</title><content type='html'>   &lt;meta name="Title" content=""&gt; &lt;meta name="Keywords" content=""&gt; &lt;meta equiv="Content-Type" content="text/html; charset=utf-8"&gt; &lt;meta name="ProgId" content="Word.Document"&gt; &lt;meta name="Generator" content="Microsoft Word 2008"&gt; &lt;meta name="Originator" content="Microsoft Word 2008"&gt; &lt;link style="font-family: georgia;" rel="File-List" href="file://localhost/Users/nilanjan/Library/Caches/TemporaryItems/msoclip/0/clip_filelist.xml"&gt; &lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;o:documentproperties&gt;   &lt;o:template&gt;Normal.dotm&lt;/o:Template&gt;   &lt;o:revision&gt;0&lt;/o:Revision&gt;   &lt;o:totaltime&gt;0&lt;/o:TotalTime&gt;   &lt;o:pages&gt;1&lt;/o:Pages&gt;   &lt;o:words&gt;609&lt;/o:Words&gt;   &lt;o:characters&gt;3476&lt;/o:Characters&gt;   &lt;o:company&gt;Pillar technology&lt;/o:Company&gt;   &lt;o:lines&gt;28&lt;/o:Lines&gt;   &lt;o:paragraphs&gt;6&lt;/o:Paragraphs&gt;   &lt;o:characterswithspaces&gt;4268&lt;/o:CharactersWithSpaces&gt;   &lt;o:version&gt;12.0&lt;/o:Version&gt;  &lt;/o:DocumentProperties&gt;  &lt;o:officedocumentsettings&gt;   &lt;o:allowpng/&gt;  &lt;/o:OfficeDocumentSettings&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:worddocument&gt;   &lt;w:zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:trackmoves&gt;false&lt;/w:TrackMoves&gt;   &lt;w:trackformatting/&gt;   &lt;w:punctuationkerning/&gt;   &lt;w:drawinggridhorizontalspacing&gt;18 pt&lt;/w:DrawingGridHorizontalSpacing&gt;   &lt;w:drawinggridverticalspacing&gt;18 pt&lt;/w:DrawingGridVerticalSpacing&gt;   &lt;w:displayhorizontaldrawinggridevery&gt;0&lt;/w:DisplayHorizontalDrawingGridEvery&gt;   &lt;w:displayverticaldrawinggridevery&gt;0&lt;/w:DisplayVerticalDrawingGridEvery&gt;   &lt;w:validateagainstschemas/&gt;   &lt;w:saveifxmlinvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:ignoremixedcontent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:alwaysshowplaceholdertext&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:compatibility&gt;    &lt;w:breakwrappedtables/&gt;    &lt;w:dontgrowautofit/&gt;    &lt;w:dontautofitconstrainedtables/&gt;    &lt;w:dontvertalignintxbx/&gt;   &lt;/w:Compatibility&gt;  &lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:latentstyles deflockedstate="false" latentstylecount="276"&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt; &lt;style&gt; &lt;!--  /* Font Definitions */ @font-face 	{font-family:Cambria; 	panose-1:2 4 5 3 5 4 6 3 2 4; 	mso-font-charset:0; 	mso-generic-font-family:auto; 	mso-font-pitch:variable; 	mso-font-signature:3 0 0 0 1 0;}  /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-parent:""; 	margin:0in; 	margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-ascii-font-family:Cambria; 	mso-ascii-theme-font:minor-latin; 	mso-fareast-font-family:Cambria; 	mso-fareast-theme-font:minor-latin; 	mso-hansi-font-family:Cambria; 	mso-hansi-theme-font:minor-latin; 	mso-bidi-font-family:"Times New Roman"; 	mso-bidi-theme-font:minor-bidi;} @page Section1 	{size:8.5in 11.0in; 	margin:1.0in 1.25in 1.0in 1.25in; 	mso-header-margin:.5in; 	mso-footer-margin:.5in; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --&gt; &lt;/style&gt; &lt;!--[if gte mso 10]&gt; &lt;style&gt;  /* Style Definitions */ table.MsoNormalTable 	{mso-style-name:"Table Normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-parent:""; 	mso-padding-alt:0in 5.4pt 0in 5.4pt; 	mso-para-margin:0in; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:12.0pt; 	font-family:"Times New Roman"; 	mso-ascii-font-family:Cambria; 	mso-ascii-theme-font:minor-latin; 	mso-fareast-font-family:"Times New Roman"; 	mso-fareast-theme-font:minor-fareast; 	mso-hansi-font-family:Cambria; 	mso-hansi-theme-font:minor-latin;} &lt;/style&gt; &lt;![endif]--&gt;  &lt;!--StartFragment--&gt;  &lt;p  class="MsoNormal" style="font-family:georgia;"&gt;I would be surprised if the answer is yes except you are working for Google. For our new project we had a dream. A dream to create a complete testable web based business application for our customer. Now don’t get me wrong, it is possible to test drive standard web apps but it's hard. We have to have some unit testing tool for JavaScript and then something like Selenium or Watir for the actual integration test. It's a mess.&lt;/p&gt;  &lt;p face="georgia" class="MsoNormal"&gt;Now when you take a first look at GWT, it’s like a promise land. You get an integrated development environment to build web application. An environment where your Java code compiles to JavaScript, you get all IDE goodness and above all write unit tests for your GUI code. &lt;span style=""&gt; &lt;/span&gt;And it’s been out for few years now. What could go wrong if we try it out for our new project? At least that’s what we thought…&lt;/p&gt;&lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;span style=""&gt; &lt;/span&gt;&lt;/p&gt;  &lt;p style="font-weight: bold; font-family: georgia;" class="MsoNormal"&gt;Installation&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;Most of our developers use Mac book pro as their development environment. Now GWT has some issues running with Java 6 because of 64-bit mode, we had to use Java 5. Now after Snow Leopard update we had to re-install Java 5 just for GWT. This is entirely Apple’s fault but we had this initial hiccup to make up and running for our developers.&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-weight: bold; font-family: georgia;" class="MsoNormal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-weight: bold; font-family: georgia;" class="MsoNormal"&gt;Creating Project&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;This one was really annoying for us. Now in GWT, project could be created in 2 ways, using the command line &lt;b style=""&gt;webappCreator&lt;/b&gt; or using eclipse plug-in. We kind of needed both. We needed eclipse because we like to use as our development environment and command line scripts for hooking into our CI builds. If you create project-using eclipse, you cannot use it from command line. Now if you create your project using &lt;b style=""&gt;webappCreator&lt;/b&gt; (command line) then it will work from command line but eclipse will not recognize it as GWT project. Come on, this is something really basic. How would a tool like GWT miss something simple like this? But webappCreator does create a .classpath and .project file so that you could import the project to eclipse but that is not good enough. We could have still lived with that but the project that got created had an absolute path dependency specific to the environment. Ok let’s look at this in perspective of a team environment. If you create project and check all the files in your source control, no one else will be able to checkout and run the project as is. They have to go and edit both project and launch configuration files. A big failure for us.&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-weight: bold; font-family: georgia;" class="MsoNormal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-weight: bold; font-family: georgia;" class="MsoNormal"&gt;Testing&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;Being part of an agile team we like to test drive all our design and production code. In fact that was one of the reasons why we choose GWT. To write a unit test we had to use GWTTestCase, which is a wrapper over JUnit. But unfortunately it wraps JUnit 3 not the 4, which is bummer. Every GWT test we created we had to create a launch file at the same time so that we could run it form eclipse and CI box. And did I mention that this launch files will again have an absolute path to the environment it was created. We did tried to use relative path but never worked for us. So again if you are in a team environment how do you scale this? And did I mention that GWT tests ran really slow in hosted mode. A huge failure for us.&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-weight: bold; font-family: georgia;" class="MsoNormal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-weight: bold; font-family: georgia;" class="MsoNormal"&gt;Using 3rd path libraries&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;Could anyone expect a decent size Java project without any 3&lt;sup&gt;rd&lt;/sup&gt; party library? To our surprise GWT doesn’t allow any 3&lt;sup&gt;rd&lt;/sup&gt; party jar, it has its own special requirements. First we had to add 3&lt;sup&gt;rd&lt;/sup&gt; party jars as module and it needs to have source and class files in same location. Now if you want to use apache commons for example you cannot. How many open source projects and tools do you know that follows this special requirement, only very handful of them? I do understand why this requirement is there but at the same time not having access to helpful libraries could slow your team velocity and throughput. Another failure for us.&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-weight: bold; font-family: georgia;" class="MsoNormal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-weight: bold; font-family: georgia;" class="MsoNormal"&gt;So what happened next?&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;Within the second week of the project we scraped GWT and decided to go back to html/JavaScript. Even though we are facing the same testability challenges but our productivity went up. I am sure there are possible workarounds for all the problems I am mentioned up here. And I would like to hear them but if barrier of entry into GWT world is so high, I don’t see anyone using GWT in decent size project.&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;br /&gt;&lt;/p&gt;  &lt;p style="font-family: georgia;" class="MsoNormal"&gt;&lt;o:p&gt; &lt;/o:p&gt;&lt;/p&gt;  &lt;!--EndFragment--&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-3122906417924383015?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3122906417924383015'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3122906417924383015'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2009/09/is-anyone-out-there-using-gwt.html' title='Is anyone out there using GWT?'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-122676814947339521</id><published>2009-04-14T19:34:00.000-07:00</published><updated>2009-04-14T20:23:28.425-07:00</updated><title type='text'>Tracking change in xp project?</title><content type='html'>The project I am in right now is a fixed bid xp project. Now I am sure this might raise few eyebrows but that's how it is in most of the enterprise environment these days. They want to be agile/xp but is not ready to change the way they write contracts with their vendors. There are &lt;a href="http://www.infoq.com/news/2007/12/agile-contracts"&gt;few better alternatives&lt;/a&gt; out there but I am not sure whether that's a starting point for an organization to be agile?&lt;br /&gt;&lt;br /&gt;So given the suituation our team is in right now, we are all puzzled with one question, how to track change?&lt;br /&gt;&lt;br /&gt;This is really hard because I see my customer/product owner changing his mind every hour.&lt;br /&gt;&lt;br /&gt;We don't want to stop that because it is adding more value to the product by making it better. The more customer is able to see the evolving product, more it is helping him to make the right choices. That's why upfront planning doesn't work to begin with. But at the same time we don't want to be in a position where we don't get our product done before a big trade show. We are doing the prioritization of the stories but I am not sure whether that's enough. I guess it helps to know that if you make this change than something else will not get done because other two ends of our pyramid is fixed, time and budget. But I am not sure what is the simple solution to this problem? Maybe &lt;span style="font-weight: bold;"&gt;build trust&lt;/span&gt;....&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-122676814947339521?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/122676814947339521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/122676814947339521'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2009/04/tracking-change-in-xp-project.html' title='Tracking change in xp project?'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-4317564893000357613</id><published>2009-01-31T17:47:00.000-08:00</published><updated>2009-01-31T17:50:29.517-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><title type='text'>Why Scripting languages Matter</title><content type='html'>As far as I can tell, the way they taught me to program in college was all wrong. You should figure out programs as you're writing them, just as writers and painters and architects do. Realizing this has real implications for software design. It means that a programming language should, above all, be malleable. A programming language is for thinking of programs, not for expressing programs you've already thought of. It should be a pencil, not a pen. Static typing would be a fine idea if people actually did write programs the way they taught me to in college. But that's not how any of the hackers I know write programs. We need a language that lets us scribble and smudge and smear, not a language where you have to sit with a teacup of types balanced on your knee and make polite conversation with a strict old aunt of a compiler&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.paulgraham.com/hp.html"&gt;Hackers and Painters&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-4317564893000357613?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4317564893000357613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4317564893000357613'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2009/01/why-scripting-languages-matter.html' title='Why Scripting languages Matter'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-7452793469221537978</id><published>2009-01-13T16:39:00.000-08:00</published><updated>2009-01-13T19:13:39.091-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='qa'/><title type='text'>Quality Assurance versus Quality Control</title><content type='html'>&lt;b&gt;From Jason Yip blog&lt;br /&gt;&lt;br /&gt;Quality Assurance (QA):&lt;/b&gt; The design and implementation of processes (roles + activities) to &lt;i&gt;ensure quality&lt;/i&gt; in a system/product/service.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Quality Control (QC):&lt;/b&gt; The design and implementation of processes (roles + activities) to &lt;i&gt;verify the quality&lt;/i&gt; of a system/product/service.&lt;br /&gt;&lt;br /&gt;QA = prevent defects; QC = detect defects&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-7452793469221537978?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7452793469221537978'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7452793469221537978'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2009/01/quality-assurance-versus-quality.html' title='Quality Assurance versus Quality Control'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-3292084523370571397</id><published>2009-01-12T20:31:00.000-08:00</published><updated>2009-01-12T20:44:38.542-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Testing File upload with Watir</title><content type='html'>For uploading file from watir test we have to do something like following&lt;br /&gt;&lt;br /&gt;@browser.file_field(:name, "fileUploadFieldName").set "path.to.file"&lt;br /&gt;&lt;br /&gt;But when I was running my test(on windows) I was getting the following error&lt;br /&gt;&lt;br /&gt;&lt;a style="font-weight: bold;" title="Search for references of 'Watir'" href="javascript:searchRef('Watir')" class="r"&gt;Watir&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;::&lt;/span&gt;&lt;a style="font-weight: bold;" title="Search for references of 'Exception'" href="javascript:searchRef('Exception')" class="r"&gt;Exception&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;::&lt;/span&gt;&lt;a style="font-weight: bold;" title="Search for references of 'WatirException'" href="javascript:searchRef('WatirException')" class="r"&gt;WatirException&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;, &lt;/span&gt;&lt;span style="font-weight: bold;" class="str"&gt;"The AutoIt dll must be correctly registered for this feature to work properly"&lt;/span&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Apparently what this means is you have to install &lt;a href="http://www.autoitscript.com/autoit3/"&gt;AutoIt&lt;/a&gt; and once you do that everything works as you expected. I kind of discovered it in a hard way but maybe some else will find this little information useful.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-3292084523370571397?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3292084523370571397'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3292084523370571397'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2009/01/testing-file-upload-with-watir.html' title='Testing File upload with Watir'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-1578112426997726182</id><published>2008-12-17T15:32:00.000-08:00</published><updated>2008-12-17T17:10:22.391-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile testing'/><title type='text'>Marick’s Law: When it comes to code, it never pays to rush</title><content type='html'>&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-1578112426997726182?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/1578112426997726182'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/1578112426997726182'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/12/when-it-comes-to-code-it-never-pays-to.html' title='Marick’s Law: When it comes to code, it never pays to rush'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-3984992531445035768</id><published>2008-11-28T20:01:00.000-08:00</published><updated>2008-11-28T20:27:46.007-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Thou shall not access network resources from unit test</title><content type='html'>&lt;p&gt;Currently I am working on a tool called &lt;a href="http://pillartechnology.com/index.php/verde" mce_href="http://pillartechnology.com/index.php/verde"&gt;Verde&lt;/a&gt;, this is an automated characterization testing tool targeted for all Java legacy applications out in the wild.&lt;br /&gt;One of the key feature of this tool is it can generate characterization tests with mocks meaning if we want we can generate Junit test cases by mocking database access or network access. Yeah it is cool.&lt;/p&gt; &lt;p&gt;As part of our integration test suite of Verde we have few end-to-end tests that generate test cases with mocks from sample application and run them to verify that everything is working, as they should be.&lt;/p&gt; &lt;p&gt;Recently one of our developer noticed that generated tests are no longer generating correct mock expectations. This must be because of some changes we made in our code but the crazy part is our integration tests never failed. In spite of wrong expectations our tests are still running fine because without mocks our generated tests are hitting the actual network resource and asserting the result received over the network. So from outside everything looked fine and worked fine too. Now this is an interesting problem, we cannot disable network connection because some tests are expected to use external resources. What do we do?&lt;/p&gt; &lt;p&gt;&lt;b&gt;SecurityManager&lt;/b&gt; is for reuse.&lt;/p&gt; &lt;p&gt;Without going into details of how Security Manager works in Java, java.security.SecurityManager defines quite a few check methods for various operations like file read/write, print job, network access etc. The behavior of these check methods is very simple, if allowed nothing happens but when denied these methods are suppose to throw SecurityException.&lt;br /&gt;So to tackle this problem we created a custom security manager to block network access. First we overridden all the check methods with do nothing implementation. This means that you are allowing all the access or granting all the permissions. Then we did something like following.&lt;br /&gt;&lt;/p&gt; &lt;p&gt;…&lt;br /&gt;&lt;b&gt;&lt;br /&gt;@Override&lt;br /&gt;public void checkConnect(String host, int port) {&lt;br /&gt;throw new SecurityException("Not allowed to access network connection, make sure all the dependencies are mocked out");&lt;br /&gt;}&lt;/b&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;@Override&lt;br /&gt;public void checkConnect(String host, int port, Object context) {&lt;br /&gt;throw new SecurityException("Not allowed to access network connection, make sure all the dependencies are mocked out");&lt;br /&gt;}&lt;/b&gt;&lt;/p&gt; &lt;p&gt;…&lt;/p&gt;&lt;p&gt; We are throwing SecurityException from couple of check methods related to network access. What it means is now when test will try to access network it will get security exception, and the test will fail. That’s it. Maybe oneday you might find this trick useful. &lt;/p&gt;&lt;p&gt;Oh don't forget to specify your custom security manager using –Djava.security.manager when running the tests.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-3984992531445035768?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3984992531445035768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3984992531445035768'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/11/thou-shall-not-access-network-resources.html' title='Thou shall not access network resources from unit test'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-3797925232687749315</id><published>2008-11-15T14:29:00.000-08:00</published><updated>2008-11-15T14:34:04.443-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='haskell'/><title type='text'>Offline website browsing</title><content type='html'>There is nothing like free books, especially when it is really a good one. Recently I have started playing with Haskell; a pure functional programming language and the best book I found so far is http://book.realworldhaskell.org/ (the printed version is not out yet).  Unfortunately this book is only available online and I really wanted to read it on my way to India. While I was feeling disappointed about the lack of internet accessibility on airplanes I found something that is really cool, &lt;a href="http://www.httrack.com/"&gt;HTTrack &lt;/a&gt;&lt;br /&gt;This tool allows you to archive the whole website for offline browsing. If you are unhappy because you didn’t find a Mac version, don’t be, there is a &lt;a href="http://httrack.darwinports.com/"&gt;macport&lt;/a&gt; available. Now I don't have to watch those boring inflight movies anymore, I can now play with something else.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-3797925232687749315?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3797925232687749315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3797925232687749315'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/11/offline-website-browsing.html' title='Offline website browsing'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-5931468920076811770</id><published>2008-11-10T19:55:00.000-08:00</published><updated>2008-11-10T21:02:41.422-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='languages'/><category scheme='http://www.blogger.com/atom/ns#' term='jvm'/><title type='text'>Another programming language for JVM</title><content type='html'>Things are really going crazy in programming language world these days, especially for JVM. Yesterday I noticed the new &lt;a href="http://kenai.com/projects/ioke/"&gt;loke&lt;/a&gt; programming language from Ola bini and today I found &lt;a href="http://clojure.org/"&gt;clojure&lt;/a&gt;.&lt;br /&gt;loke is a prototype based object oriented programming language. I personally think prototype based languages are much more fun to play with compare to class based object oriented languages, the  reason I love JavaScript so much.&lt;br /&gt;On the other hand we have clojure which is a functional programming language with lisp dialect. I haven't looked into it yet but I will definitely play with it very soon. Infact there is already a &lt;a href="http://pragprog.com/titles/shcloj/programming-clojure"&gt;beta book&lt;/a&gt; available for it.&lt;br /&gt;&lt;br /&gt;I am not sure what tomorrow has in store for me?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-5931468920076811770?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/5931468920076811770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/5931468920076811770'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/11/clojure-another-programming-language.html' title='Another programming language for JVM'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-2409738911510056774</id><published>2008-10-09T16:04:00.000-07:00</published><updated>2008-10-09T16:09:08.658-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Trust in team environment</title><content type='html'>The following paragraph kind of sums it up when people ask &lt;a href="http://www.estherderby.com/weblog/2008/10/what-trust-means-for-teams.html"&gt;what trust means for teams&lt;/a&gt;?&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;em&gt;I believe you are competent to do the work&lt;br /&gt;&lt;br /&gt;I believe that if you have an issue with me, you’ll bring it up directly&lt;br /&gt;with me, not talk behind my back.&lt;br /&gt;&lt;br /&gt;I believe will follow through on commitments—or let me know when you need&lt;br /&gt;to renegotiate.&lt;br /&gt;&lt;br /&gt;I believe you have good intentions towards me and the team.&lt;/em&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-2409738911510056774?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2409738911510056774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2409738911510056774'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/10/trust-in-team-environment.html' title='Trust in team environment'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-7958994536681599058</id><published>2008-09-27T17:54:00.000-07:00</published><updated>2008-09-27T20:09:27.544-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rant'/><title type='text'>I give up...mysql</title><content type='html'>Its over with mysql. I hope that I don't see it again. There are things that you love about database and installing them is not one of them, especially when it comes to MySql. No no I am not trying anything fancy, all I want is to get Mysql up and running on my new Mac book pro.&lt;br /&gt;&lt;br /&gt;The installation process goes through fine but when time comes to login, mysql comes back with aceess denied for 'root@localhost.com'. According to the documentation, root user comes with no password...hmmmm, never mind. Lets move on.&lt;br /&gt;&lt;br /&gt;My first reaction was , maybe its using some old my data folder that I migrated from my old mac book pro.&lt;br /&gt;&lt;br /&gt;So I tried running &lt;installation&gt;/bin/mysqld_safe --init-file=reset-root-password-file to reset my root password. The init file contains an update sql statement to update mysql.user table with a new password for root user. To my surprise the situation did not improve at all.&lt;br /&gt;&lt;br /&gt;Next I tried starting the mysql deamon server with -skip-grant-tables option and it worked. No don't start celebrating yet, when I said worked I mean now I was able to connect to the server using my mysql client. And when I looked up the user table I discovered that I don't have any users. Why ? I really don't know. At this point I have already spent 2 hours figuring out the problem but not ready to give up yet. I looked it up on google and as usual I am not alone, some mysql installation doesn't run the post installation script to create users and grant permissions.&lt;br /&gt;&lt;br /&gt;All mysql installation comes with a &lt;span style="font-weight: bold;"&gt;mysql_install_db&lt;/span&gt; script under mysql/scripts folder. Apparently for some installation you have to run it manually. I am not sure why?.&lt;br /&gt;&lt;br /&gt;Anyways, finally I thought I got it. So I went ahead and ran the &lt;span style="font-weight: bold;"&gt;mysql_install_db&lt;/span&gt;, it fails. This time because of 'duplicate entry for localhost-'. Apprently this happens when your hostname is set to localhost. Maybe this it, so as recommened I changed my hostname to my name and hooray the script ran successfully. Now I am ready to build the rails app I was planning (the only reason I want to use mysql in first place is because my pair has that setup) for in the first place. But no...now my mysql server doesn't start up and it doesn't even show any error message.&lt;br /&gt;&lt;br /&gt;I think 3 hours a lot of time to setup a database and  I cannot take it anymore&lt;/installation&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-7958994536681599058?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7958994536681599058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7958994536681599058'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/09/i-give-upmysql.html' title='I give up...mysql'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-5162760571579043292</id><published>2008-09-18T17:22:00.000-07:00</published><updated>2008-09-27T17:53:04.459-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='design'/><title type='text'>What makes design...simple</title><content type='html'>&lt;p&gt;Last weekend in the “&lt;a href="http://sdtconf.com/" mce_href="http://sdtconf.com/"&gt;Simple Design and Testing Conference&lt;/a&gt;” we had a discussion on “&lt;b&gt;What makes Design Simple&lt;/b&gt;” and this is a summary of the discussion we had along with my thoughts.&lt;/p&gt; &lt;p&gt;Well before we go further with in our way of defining simple/complicated design we have to step back and first answer &lt;b&gt;why do we design?&lt;/b&gt;&lt;/p&gt; &lt;p&gt;We design to be productive and I don’t do it if it is below the &lt;a href="http://martinfowler.com/bliki/DesignPayoffLine.html" mce_href="http://martinfowler.com/bliki/DesignPayoffLine.html"&gt;DesignPayoffLine&lt;/a&gt;. Now if you read &lt;a href="http://www.developerdotstar.com/mag/articles/reeves_design.html" mce_href="http://www.developerdotstar.com/mag/articles/reeves_design.html"&gt;What is software design&lt;/a&gt; which I highly recommend you will learn that we design all the time, when customer approves a story he/she makes a design decision (this is interesting, some times we evolve to complicated design when stories are not broken properly), when we write tests (we do test driven development) and programming is also a design activity. So I guess we are always designing with or without knowing it.&lt;/p&gt; &lt;p&gt;Being an agile developer, we don’t focus ourselves on BUFD (Big Up Front Design) but rather we believe in evolutionary design, a design that grows as your system grows and there are benefits of doing that which I will not discuss here (read &lt;a href="http://martinfowler.com/articles/designDead.html" mce_href="http://martinfowler.com/articles/designDead.html"&gt;http://martinfowler.com/articles/designDead.html&lt;/a&gt;). One of the key aspects of the evolutionary design is to do the “simplest thing that could possibly work” nothing less, nothing more. There are couple of things that needs to be noted here, “&lt;b&gt;simplest&lt;/b&gt;” and “&lt;b&gt;possibly&lt;/b&gt;”. Simplest or simplicity is your shortest path to the solution i.e. getting your idea from your head to screen as quickly as possible. And why it is possibly? Because we are not sure whether it will work and that’s why we write test to make sure that our idea works.&lt;/p&gt; &lt;p&gt;But the interesting part is we all start simple (I am totally ignoring the fact that there are teams that start with 200 page design document from day one) and it gets complicated over time because it starts doing more work. But if we could restrict ourselves to keep it simple for tomorrows need tomorrow then I guess we can preserve simplicity and this is where refactoring step fits in. Refactoring is our way to simplify things when it gets complicated. Einstein once said, "As simple as possible, but no simpler." And I think that makes sense here.&lt;/p&gt; &lt;p&gt;Wait a minute &lt;b&gt;we haven’t defined simple design yet&lt;/b&gt;? I don’t think I can define simple in two lines but lets ask the question differently, “&lt;b&gt;How will we know that our application design is simple?&lt;/b&gt;”&lt;/p&gt; &lt;p&gt;Software with simple design will enable team members to quickly respond to change. And as your design deteriorates, so does your ability to respond to change. This is really critical for agile projects (again ignoring rest 70% of teams who don't believe in agile, they really don’t care) because we embrace change and customer satisfaction is important to us. Kent beck calls it “&lt;b&gt;reversibility&lt;/b&gt;” property of software. If we can change our decisions quickly it is not a big deal to get them right in the first place and that means less planning upfront (we are wrong most of the times anyways). There are some really good second order benefits to simple design, we get our work done sooner and it is easier to communicate our work with others (I am not sure about you but I still work as part of a team, collective ownership rings any bells?). Above of all it is &lt;b&gt;less stressful to work &lt;/b&gt;with simple design.&lt;/p&gt; &lt;p&gt;&lt;b&gt;So how can we keep our design simple?  Testability&lt;/b&gt;&lt;/p&gt; &lt;p&gt;I absolutely agree with James Bach on " there are &lt;a href="http://www.satisfice.com/blog/archives/27" mce_href="http://www.satisfice.com/blog/archives/27"&gt;no best practices"&lt;/a&gt; but rather appropriate practices and I think the appropriate practice  to keep your design simple is continue to write tests.&lt;/p&gt; &lt;p&gt;&lt;b&gt;Testability&lt;/b&gt; is a characteristic of software application that provides ability to developers to write tests for their software application. In the world of TDD, we derive our design from tests and having that ability is very important. In fact if it is hard to write test, developers will stop writing tests especially new agile developers. It is very easy to get into “code and fix” mode under agile radar. If you are the only manager reading this article please pay attention to your developers when they say it is hard to test, this could be good indication that application design is deteriorating.&lt;/p&gt; &lt;p&gt;While discussing “What makes design simple” in the conference, &lt;a href="http://www.exampler.com/blog/" mce_href="http://www.exampler.com/blog/"&gt;Brain Marick&lt;/a&gt; raised one interesting point, we should strive for &lt;b&gt;habitability&lt;/b&gt;, “The characteristic of source code that enable developers feel like home and place their hands on any item without having to think deeply about where it is”( read &lt;a href="http://www.wirfs-brock.com/PDFs/DoesBeautifulCodeImply.pdf" mce_href="http://www.wirfs-brock.com/PDFs/DoesBeautifulCodeImply.pdf"&gt;http://www.wirfs-brock.com/PDFs/DoesBeautifulCodeImply.pdf&lt;/a&gt;). We do spend good portion of our time everyday inside the code we are working on and habitability makes working easy. I guess more appropriate answer to the question “&lt;b&gt;How will we know that our application design is simple?&lt;/b&gt;” would be habitability. If it is easy to work with your design, it is simple.&lt;/p&gt; &lt;p&gt;If you are still with me then probably some of these makes sense but if you were looking for top 10 practices for simple design sorry to disappoint. The only take way point is  “&lt;b&gt;Design for today, not for tomorrow”&lt;/b&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-5162760571579043292?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/5162760571579043292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/5162760571579043292'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/09/what-makes-designsimple.html' title='What makes design...simple'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-4062298649761893826</id><published>2008-09-07T10:38:00.001-07:00</published><updated>2008-09-27T17:53:26.808-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>If we have to look at the code to explain the program, are we missing a test?</title><content type='html'>&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-4062298649761893826?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4062298649761893826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4062298649761893826'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/09/if-we-have-to-look-at-code-to-explain.html' title='If we have to look at the code to explain the program, are we missing a test?'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-2832092408836740837</id><published>2008-08-19T21:43:00.001-07:00</published><updated>2008-09-27T17:53:38.419-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>What is the first thing that you know about project before starting it?</title><content type='html'>due date of the project and reality is nothing goes as you plan in this world.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-2832092408836740837?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2832092408836740837'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2832092408836740837'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/08/what-is-first-thing-that-you-know-about.html' title='What is the first thing that you know about project before starting it?'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-8439709660226282068</id><published>2008-08-12T20:32:00.000-07:00</published><updated>2008-08-12T20:34:23.127-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><category scheme='http://www.blogger.com/atom/ns#' term='scripting'/><title type='text'>Using Groovy Script</title><content type='html'>&lt;p&gt;&lt;b&gt;Groovy Script&lt;/b&gt;&lt;/p&gt; &lt;p&gt;Groovy Scripts are different from Groovy classes, in Groovy Scripts you can directly write code without declaring methods or classes (just like your bash or perl scripts). We can use Groovy Scripts from Groovy classes, Java classes or using "java" to run them.&lt;/p&gt; &lt;p&gt;&lt;u&gt;&lt;i&gt;From Java Classes&lt;/i&gt;&lt;/u&gt;&lt;/p&gt; &lt;p align="left"&gt;&lt;span style="font-size:100%;"&gt;ScriptEngineManager manager = new ScriptEngineManager();&lt;br /&gt;ScriptEngine engine = manager.getEngineByName("groovy");&lt;br /&gt;System.out.println("Calling script from Java");&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;engine.eval(new FileReader("MyGroovyScript.groovy"));&lt;br /&gt;}&lt;br /&gt;catch(ScriptException ex)&lt;br /&gt;{&lt;br /&gt;System.out.println(ex);&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;b&gt;&lt;i&gt;Note: Make sure your groovy-engine.jar file is in your classpath&lt;/i&gt;&lt;/b&gt;&lt;/p&gt; &lt;p&gt;&lt;i&gt;&lt;u&gt;From Other Groovy Scripts&lt;/u&gt;&lt;br /&gt;&lt;/i&gt;&lt;/p&gt; &lt;p&gt;def shell = new GroovyShell()&lt;br /&gt;shell.evaluate(new File('MyGroovyScript.groovy'))&lt;/p&gt; &lt;p&gt;&lt;u&gt;&lt;i&gt;From Command line &lt;/i&gt;&lt;/u&gt;&lt;/p&gt; &lt;p&gt;We can compile our Groovy Scripts using groovyc compiler and when you do that it will create a single ".class" file based on name of the script with auto generated main(String[] args) method. Once you have a main method we can clearly run using java command, no tricks there. The auto generated main method creates an instance of the class which extends groovy.lang.Script and invokes run method on it (We will come back to this)&lt;/p&gt; &lt;p&gt;&lt;u&gt;&lt;i&gt;From Groovy Classes&lt;/i&gt;&lt;/u&gt;&lt;/p&gt; &lt;p&gt;def runSomeScript() {&lt;/p&gt; &lt;p&gt;...&lt;/p&gt; &lt;p&gt;run(MyGroovyScript)&lt;/p&gt; &lt;p&gt;...&lt;/p&gt; &lt;p&gt;}&lt;/p&gt; &lt;p&gt;What the heck is this? Are we missing something?&lt;/p&gt; &lt;p&gt;No we are not. In Groovy (like Ruby) class names are constant and in Groovy this constant points to java.lang.Class class of the class created by the groovyc compiler. So now if I have a method like following I would be able to run the script&lt;/p&gt; &lt;p&gt;def run(Class scriptClass) {//You don't have to specify type, I did for clarity&lt;/p&gt; &lt;p&gt;Script script = InvokerHelper.createScript(scriptClass, new Binding()) //Binding is a way to share variables and context info with Script&lt;/p&gt; &lt;p&gt;script.run()&lt;/p&gt; &lt;p&gt;}&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-8439709660226282068?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/8439709660226282068'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/8439709660226282068'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/08/using-groovy-script.html' title='Using Groovy Script'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-7556057228927096487</id><published>2008-08-11T19:11:00.000-07:00</published><updated>2008-08-11T19:12:02.542-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>View hidden files in Finder</title><content type='html'>&lt;p&gt;Lately I am having stupid merging issues with .classpath (eclipse) file because of subversion. Anyways that's not what I want to discuss here. In Mac dot files are hidden and you cannot view them in finder by default and my windows friends find that bit annoying while pairing. So I looked up and found that we could use "defaults" command from terminal to change some of these behavior. For example if you want to view hidden files in finder, the following command will enable it&lt;/p&gt; &lt;p&gt;&lt;b&gt;defaults write com.apple.Finder.AppleShowAllFiles YES&lt;/b&gt;&lt;/p&gt; &lt;p&gt;To make the above command work you have to restart your finder from your dock though.&lt;/p&gt; &lt;p&gt;Not only that , you have other &lt;a href="http://www.macosxtips.co.uk/index_files/terminal-commands-for-hidden-mac-os-x-settings.html" mce_href="http://www.macosxtips.co.uk/index_files/terminal-commands-for-hidden-mac-os-x-settings.html"&gt;hidden features&lt;/a&gt; that you could enable, especially I liked the one where you could drag widgets from dash board to your desktop.&lt;/p&gt; &lt;p&gt;Even better you have &lt;a href="http://www.bresink.com/osx/TinkerTool.html" mce_href="http://www.bresink.com/osx/TinkerTool.html"&gt;TinkerTool &lt;/a&gt; which allows you to play with these hidden defaults from a nice gui...Sweet.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-7556057228927096487?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7556057228927096487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7556057228927096487'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/08/view-hidden-files-in-finder.html' title='View hidden files in Finder'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-1794514455776998460</id><published>2008-08-07T16:26:00.000-07:00</published><updated>2008-09-27T17:54:04.012-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Understanding The Misunderstood, JavaScript Part 1</title><content type='html'>&lt;span style=";font-family:verdana;font-size:85%;"  &gt;&lt;span style="font-style: italic;"&gt;Many of us work with JavaScript in daily basis but only few actually consider JavaScript as a powerful programming language. But new renaissance of JavaScript frameworks prove that there is something about this language that we haven't learned yet.  This mini part series of blog posts will give another shot at JavaScript.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 0, 0);font-family:verdana;" &gt;So what went wrong?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;JavaScript was developed by &lt;a href="http://en.wikipedia.org/wiki/Brendan_Eich"&gt;Brendan Eich&lt;/a&gt; at Netscape as the in-page scripting language and most often used for client-side web development. It is a remarkably expressive dynamic programming language. JavaScript, despite the name, is essentially unrelated to the Java programming language. This language was renamed from &lt;a href="http://www.computerhope.com/jargon/l/livescri.htm"&gt;LiveScript&lt;/a&gt; in a co-marketing deal between Netscape and Sun in exchange for Netscape bundling Sun's Java runtime with their then dominant browser. I think this is the main contributor to the misunderstanding we had about this language.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Most programmers never realized the true power of this language. The reason being most of the people writing JavaScript in early days were not programmers and they lacked the training and discipline to write good programs hence finding good JavaScript materials or examples were hard. Along with those browser incompatibilities, bugging implementation gave an impression that this language is not ready for professional programming. This is simply not true anymore, in many ways we can say that suddenly the bar was put much higher in front of us as we started to see some smart JavaScript programs and applications. And as the web is becoming target platform for Web 2.0 applications, scripting languages and other dynamic languages are currently experiencing a renaissance. JavaScript is becoming the only scripting language of the web and its clearly becoming important to understand this language, its paradigms, and its semantics.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-weight: bold;font-family:verdana;" &gt;Re-introducing JavaScript&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;JavaScript is prototype based object oriented dynamic language descendant from Self. Quite a mouthful! right? Lets explore.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;If you are familiar with prototype design pattern, you know that in this creational pattern objects are created from a prototypical instance. JavaScript uses the same concept to create new instances, by cloning existing objects that serves as prototype (more about this later). This is quite different from class based languages in which objects comes in two distinctive taste, classes as collection of behavior and instances as state holder.&lt;br /&gt;In JavaScript, objects hold both the behavior and state. This language semantic enables the programmer to focus on behavior without worrying about the abstractions and relationships upfront. Here is nice comparison of prototype-based language with class-based language from &lt;span style="font-weight: bold;"&gt;wikipedia&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;Traditional class-based OO languages are based on a deep-rooted duality:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;     1. Classes define the basic qualities and behaviors of objects.&lt;/span&gt;&lt;br /&gt;    &lt;span style="font-style: italic;font-family:verdana;" &gt;2. Object instances are particular manifestations of a class.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;For example, suppose objects of the Vehicle class have a name and the ability to perform various actions, such as drive to work and deliver construction materials. Porsche 911 is a particular object (in-stance) of the class Vehicle, with the name "Porsche 911". In theory one can then send a message to Porsche 911, telling it to deliver construction materials.&lt;/span&gt;  &lt;span style="font-style: italic;font-family:verdana;" &gt;&lt;br /&gt;&lt;br /&gt;This example shows one of the problems with this approach: Porsches are not able to carry and deliver construction materials (in any meaningful sense), but this is a capability that Vehicles are modeled to have. One way to create a more useful model is to use subclassing to create specializations of Vehicle; for example Sports Car and Flatbed Truck. Only objects of the class Flatbed Truck need provide a mechanism to deliver construction materials; sports cars, which are ill suited to that sort of work, need only drive fast.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;This issue is one of the motivating factors behind prototypes. Unless one can predict with certainty what qualities a set of objects and classes will have in the distant future, one cannot design a class hierarchy properly. All too often the program would eventually need added behaviors, and sections of the system would need to be re-designed (or refactored) to break out the objects in a different way.[citation needed]&lt;br /&gt;&lt;br /&gt;Experience with early OO languages like Smalltalk showed that this sort of issue came up again and again. Systems would tend to grow to a point and then become very rigid, as the basic classes deep below the programmer's code grew to be simply "wrong". Without some way to easily change the original class, serious problems could arise.[citation needed]&lt;/span&gt;  &lt;span style="font-style: italic;font-family:verdana;" &gt;&lt;br /&gt;&lt;br /&gt;Dynamic languages such as Smalltalk allowed for this sort of change via well-known methods in the classes; by changing the class, the objects based on it would change their behavior. But in other languages like C++ no such ability exists, and making such changes can actually break other code, a problem known as the fragile base class problem. In general, such changes had to be done very carefully, as other objects based on the same class might be expecting this "wrong" behavior: "wrong" is often dependent on the context.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;In Self, and other prototype-based languages, the duality between classes and object instances is eliminated.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:verdana;" &gt;Instead of having an "instance" of an object that is based on some "class", in Self one makes a copy of an existing object, and changes it. So Porsche 911 would be created by making a copy of an existing "Vehicle" object, and then adding the drive very fast method. Basic objects that are used primarily to make copies are known as prototypes. This technique is claimed to greatly simplify dynamism. If an existing object (or set of objects) proves to be an inadequate model, a programmer may simply create a modified object with the correct behavior, and use that instead. Code which uses the existing objects is not changed.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Like most programming languages JavaScript has a type system but its dynamically determined by the runtime environment, its types are associated with value not with variables.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-family:verdana;" &gt;Some examples would be handy right about now&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Since essentially everything in JavaScript is an object it would be nice to have some familiarity to it. &lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;var myJSONObject =  {"ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*"};&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-style: italic;font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Here in the above &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt; example, object is created using object literal syntax, which is comma-separated list of property/value pairs within curly braces. The variable name in JavaScript could be any valid identifier or string and value could be constant or JavaScript expression. Since JavaScript is dynamically typed, variables are declared using var keyword(see above example). You could also declare variables without the var keyword but that would mean that scope of the variable is global.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:verdana;font-size:85%;"  &gt;&lt;span style="font-weight: bold;"&gt;Note&lt;/span&gt;: &lt;span style="font-style: italic;"&gt;This post will not look into scoping and namespace but it’s really important to have that knowledge especially when building frameworks. &lt;/span&gt;&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Here is another example from &lt;span style="font-weight: bold;"&gt;Prototype.js&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;var Prototype = {&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;Version: '1.6.0', &lt;span style="color: rgb(0, 0, 0);"&gt;//Constant value&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: italic;"&gt;Browser: {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;IE: !!(window.attachEvent &amp;amp;&amp;amp; !window.opera), &lt;span style="color: rgb(0, 0, 0);"&gt;//javascript expression&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Opera: !!window.opera,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;WebKit: navigator.userAgent.indexOf('AppleWebKit/') &gt; -1,&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;Gecko: navigator.userAgent.indexOf('Gecko') &gt; -1 &amp;amp;&amp;amp; naviga&lt;/span&gt;&lt;span style="font-style: italic;"&gt;tor.userAgent.indexOf('KHTML') == -1,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;},&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;...&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Here in this example we are creating Prototype object using object literal syntax and "Version" is one of the property of the Prototype object with value of "1.6.0".&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Objects are created when JavaScript interpreter evaluates the object literals. Once the object is created you can access its properties using the "." operator.&lt;br /&gt;For Example&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;myJSONObject.ircEvent&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt; (produces: "PRIVMSG")&lt;/span&gt;&lt;span style="font-style: italic;font-size:85%;" &gt; &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;&lt;br /&gt;Prototype.IE (produces: true or false based on browser)&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;We should note that object properties doesn't have to be boolean or string, it could be another object as well. In the case of &lt;span style="font-weight: bold;"&gt;Prototype&lt;/span&gt;, "Browser" is a property and it is also an object with properties like IE, Opera, Webkit etc.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;In the re-introduction section we discussed about the nature of the prototype based languages and how it encourages programmers to evolve their existing objects. In JavaScript we can create properties when we need them by simply assigning value to it.&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Example from &lt;span style="font-weight: bold;"&gt;scriptaculous/unittest.js&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;var Test = {} //creating a empty object&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;Test.Unit = {}; //creating a new Unit property to Test object&lt;br /&gt;&lt;/span&gt;  &lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;// security exception workaround&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;Test.Unit.inspect = Object.inspect; //adding a new property to Unit object&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;In the above example we are creating an empty Test object without any property but moment we do Test.Unit = {}, it is creating a new property called Unit inside the Test object. We could also delete prop-erties from object on the fly using "delete" operator.&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Earlier we looked how objects are created and how to access object properties using "." operator but we haven't formally defined JavaScript object yet. &lt;/span&gt; &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;In JavaScript, object is an unordered collection of properties. What it means is, we can loop through the object properties and access them as associative array using [] operator. This was very confusing to me before I understood how JavaScript objects are defined.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:verdana;"&gt;Example from &lt;span style="font-weight: bold;"&gt;scriptaculous/effect.js&lt;/span&gt;&lt;/span&gt;  &lt;span style="font-style: italic;font-family:verdana;" &gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;//inspect property inside some object&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;  inspect: function() {&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;var data = $H(); //some function, yes $ is allowed&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;     //looping through all the properties defined inside this object&lt;/span&gt;&lt;span style="font-size:85%;"&gt; &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;&lt;br /&gt;for(property in this)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;if (!Object.isFunction(this[property])) &lt;/span&gt; &lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;         //here object property is accessed as an array.               &lt;/span&gt; &lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;    &lt;br /&gt;     data.set(property, this[property]);&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;    return ...&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;  }&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Using "[]" operator has one advantage over the "." operator because the name of the property is expressed as string and could be manipulated in runtime.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;someObject["someProperty" + "_en"]&lt;/span&gt;  &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Before we leave associative arrays, I like to mention that JavaScript also has a concept of array and it is defined as an ordered collection of values. Since JavaScript is dynamically typed we could create array with many different types, here is an example&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;var someArray = [ "this", "is", [1], way] &lt;/span&gt;&lt;span style="font-family:verdana;"&gt;&lt;span style="font-size:85%;"&gt;//way is some variable already defined&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:verdana;"&gt;JavaScript also defines additional methods like reverse, sort, slice, push, pop and others (complete list of methods and properties) for ar-ray. If we take a look at the list of methods it could be surprising to see methods like push and pop as if we are using stack instead of ar-ray. JavaScript arrays could be used as stack by pushing an element and popping an element.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:verdana;"&gt;Example from &lt;span style="font-weight: bold;"&gt;prototype.js&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;…&lt;/span&gt; &lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;  keys: function(object) {&lt;/span&gt;&lt;span style="font-size:85%;"&gt; &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;&lt;br /&gt; var keys = [];&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;  &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;for (var property in object)&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;&lt;br /&gt;  keys.push(property);&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt; &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;return keys;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;  },&lt;/span&gt;&lt;span style="font-size:85%;"&gt;  &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;&lt;br /&gt;values: function(object) {&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;       var values = [];&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;for (var property in object)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;      &lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;values.push(object[property]);&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;       return values;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;  }&lt;br /&gt;&lt;/span&gt; &lt;span style="font-style: italic;font-family:verdana;font-size:85%;"  &gt;  …&lt;/span&gt;&lt;span style="font-size:85%;"&gt;  &lt;/span&gt;&lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;In this code snippet we are pushing property names to keys array and pushing property values to values array.&lt;/span&gt; &lt;span style="font-family:verdana;"&gt;&lt;br /&gt;&lt;br /&gt;Its quite similar to Ruby where array could also be used a stack but unlike Java where there is separate class for Array and Stack. It al-most feels like dynamic languages have their own design principles separate from other languages. Advocates of &lt;/span&gt;&lt;a style="font-family: verdana;" href="http://www.blogger.com/%28http://martinfowler.com/bliki/HumaneInterface.%20html"&gt;Humane interface&lt;/a&gt;&lt;span style="font-family:verdana;"&gt;s would argue that there could be multiple usage of an array, as an array or as a stack and hence we see methods like push and pop.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-1794514455776998460?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/1794514455776998460'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/1794514455776998460'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/08/understanding-misunderstood-javascript.html' title='Understanding The Misunderstood, JavaScript Part 1'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-6949108822121880791</id><published>2008-08-05T19:32:00.000-07:00</published><updated>2008-08-06T21:41:52.592-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><title type='text'>Learning is your bottleneck</title><content type='html'>"Our civilization runs on software." It is therefore a tremendous privilege as well as a deep responsibility to be a software developer&lt;br /&gt;Bjarne Stroustrup&lt;br /&gt;&lt;br /&gt;I just started reading about  &lt;a href="http://www.amazon.com/Agile-Adoption-Patterns-Roadmap-Organizational/dp/0321514521"&gt;“Agile Adoption Patterns”&lt;/a&gt; book and I must say I am already impressed. It starts with “Learning is the bottleneck” chapter that example how that is main problem with any project and how agile helps mitigate that risk.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Why learning is important?&lt;/span&gt; Because we cannot know everything about a project even you are doing software development for 20 years and unknowns are risk in projects. No two projects are same. Even if you end up using same technology set, your teammates are different or maybe it is a new organization. So we have to learn things as we go (no assumptions doesn’t help) by iterations.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Why it’s a bottleneck?&lt;/span&gt; Software project failures have a lot in common with airplane crashes. Just as pilots never intend to crash, software developers don't aim to fail. It is amazing to look at history of &lt;a href="http://www.codinghorror.com/blog/archives/000588.html"&gt;software&lt;/a&gt; &lt;a href="http://www.spectrum.ieee.org/sep05/1685"&gt;failures&lt;/a&gt;, here are some reasons why software project fails&lt;br /&gt;&lt;br /&gt;•    Unrealistic or unarticulated project goals&lt;br /&gt;•    Inaccurate estimates of needed resources&lt;br /&gt;•    Badly defined system requirements&lt;br /&gt;•    Poor reporting of the project's status&lt;br /&gt;•    Unmanaged risks&lt;br /&gt;•    Poor communication among customers, developers, and users&lt;br /&gt;•    Use of immature technology&lt;br /&gt;•    Inability to handle the project's complexity&lt;br /&gt;•    Sloppy development practices&lt;br /&gt;•    Poor project management&lt;br /&gt;•    Stakeholder politics&lt;br /&gt;•    Commercial pressures&lt;br /&gt;&lt;br /&gt;And it is quite interesting how all these reasons are somehow tied to not having a negative feedback cycle so that teams can make smaller mistakes and learn from them.&lt;br /&gt;Only if we could have opportunity to rectify our oversights sooner!&lt;br /&gt;&lt;br /&gt;Yes we can, we need a software development process that allows to us learn from our mistakes. The iterative nature of an agile process helps us to make small mistakes and fail fast helps us to make necessary corrections. And if we don’t pay enough attention to them we might end up as another failed project in the list. But wait is it only process that could save us from the misery? No it is always “people over process”. If we are not paying attention to our mistakes no process can help. We need people who are adaptive and ready to learn, &lt;a href="http://www.agileadvice.com/2008/05/13/miscellaneous/stonecutters-paycheck-earners-or-cathedral-builders/"&gt;“we need Cathedral builders not stonecutters”&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-6949108822121880791?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/6949108822121880791'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/6949108822121880791'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/08/learning-is-your-bottleneck.html' title='Learning is your bottleneck'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-4817036106848851459</id><published>2008-06-13T09:39:00.000-07:00</published><updated>2008-06-14T06:46:38.608-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='testing'/><title type='text'>Code Coverage is a negative metrics tool</title><content type='html'>This is something we forgot on our way with coverage tools over the years and I think, needs to be restated. Its really not important how much code is covered by your unit tests(assuming they are good) but rather which parts of code is not been covered by your tests.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-4817036106848851459?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4817036106848851459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4817036106848851459'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/06/code-coverage-is-negative-metric-tool.html' title='Code Coverage is a negative metrics tool'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-2808057120043775027</id><published>2008-05-01T13:05:00.000-07:00</published><updated>2008-05-05T10:34:16.063-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><title type='text'>Literate Programming to DSL</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Literate programming&lt;/span&gt; is phrase coined by Donald Knuth to describe a certain approach of developing computer programs from the perspective of a report or prose. The basic idea is to create self-documenting code. The programmer should write code as if he or she is explaining to another programmer how the code will be executed by the machine, like a literature. Knuth implemented literate programming through the &lt;span style="font-weight: bold;"&gt;WEB&lt;/span&gt; system of structured documentation. It uses Tex for documentation and C for executable code.&lt;br /&gt;&lt;br /&gt;Sounds like a awesome idea but I wonder why it didn't take world by storm like DSL. According to the &lt;a href="http://www.informit.com/articles/article.aspx?p=1193856"&gt;interview&lt;/a&gt; recently published, Knuth thinks only small percentage of programmers are good at writing, hence never been adopted that well. What do you guys think? Now it keeps me wondering how good are we going to be with DSL, doesn't it requires same skill. It is not easy to come up with good succinct, well readable DSL. Do we need new skills to be good at it?&lt;br /&gt;&lt;br /&gt;One beauty of DSL is, its domain specific and sometimes its really small and succinct, so no need to have extra documentation. Sometimes its important to have documentation if you allow your business users to play with your DSL but having them integrated part of the code could make it bit clumsy and verbose. And like any other type documentation it still have the same inherited problem of keeping up with code changes (maybe having them integrated might help). Now with languages like Ruby and Groovy its possible to write human readable executable code without any additional documentation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Update: Nice blog entry from PragDave. Addresses few core issues associated with DSLs&lt;br /&gt;&lt;a href="http://pragdave.blogs.pragprog.com/pragdave/2008/03/the-language-in.html"&gt;http://pragdave.blogs.pragprog.com/pragdave/2008/03/the-language-in.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-2808057120043775027?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2808057120043775027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2808057120043775027'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/05/literate-programming-to-dsl.html' title='Literate Programming to DSL'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-3748155454550209087</id><published>2008-03-27T20:24:00.001-07:00</published><updated>2008-03-27T20:24:39.262-07:00</updated><title type='text'>Big enterpise deal going bad</title><content type='html'>http://www.itworld.com/App/670/waste-management-sues-sap-080327/&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-3748155454550209087?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3748155454550209087'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3748155454550209087'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/03/big-enterpise-deal-going-bad.html' title='Big enterpise deal going bad'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-242166072142618587</id><published>2008-03-11T17:36:00.000-07:00</published><updated>2008-03-11T17:48:54.994-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><title type='text'>autotest for java</title><content type='html'>I just hacked out a java version of autotest plugin for eclipse (of course inspired by the ZenTest).&lt;br /&gt;&lt;br /&gt;No more running JUnit tests manually, this plugin will detect code changes and run JUnit tests of that Java project. You can download and install this plugin from &lt;a href="http://code.google.com/p/autotest4j/"&gt;http://code.google.com/p/autotest4j/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Current version of plugin only runs with eclipse 3.3 and I need to do some clean up and fixes before I can checkin my source code. Watch out for some changes I am planning for next version.&lt;br /&gt;&lt;br /&gt;Enjoy...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-242166072142618587?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/242166072142618587'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/242166072142618587'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/03/autotest-for-java.html' title='autotest for java'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-4672053169596931380</id><published>2008-03-05T13:22:00.000-08:00</published><updated>2008-03-05T13:24:12.344-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='pipes'/><title type='text'>rss to json</title><content type='html'>Here is a nice yahoo pipe if you want to process rss feed from you web pages&lt;br /&gt;&lt;a href="http://pipes.yahoo.com/pipes/pipe.info?_id=2FV68p9G3BGVbc7IdLq02Q"&gt;rss to json&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-4672053169596931380?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4672053169596931380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4672053169596931380'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/03/rss-to-json.html' title='rss to json'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-6203632437420908931</id><published>2008-01-14T12:15:00.000-08:00</published><updated>2008-01-15T22:25:51.439-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>Scala: Surprise Part oNe</title><content type='html'>Ruby is a language of least surprises but I am not sure whether I can say that for Scala yet. I have already encountered some of them, here is one example&lt;br /&gt;&lt;br /&gt;You can define method without '()'&lt;br /&gt;&lt;br /&gt;def height: Int = 0  //This is a valid method&lt;br /&gt;&lt;br /&gt;def width(): Int = 0 //This is valid too&lt;br /&gt;&lt;br /&gt;Now you can invoke 'width' method with and without parenthesis but you cannot do that for height method.&lt;br /&gt;&lt;br /&gt;SURPRISED&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Update:&lt;/span&gt; The Scala convention is, use '()' for parameter less method if it has side effects otherwise don't&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-6203632437420908931?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/6203632437420908931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/6203632437420908931'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2008/01/scala-surprises-one.html' title='Scala: Surprise Part oNe'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-2459299872321186143</id><published>2007-12-13T20:31:00.000-08:00</published><updated>2007-12-13T20:37:00.887-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='scala'/><title type='text'>scala book is out</title><content type='html'>Its now an open secret that Scala doesn't have good documentation/reference to help any developer to try their programming skills. But finally &lt;a href="http://www.artima.com/shop/forsale"&gt;Scala book is out&lt;/a&gt; (pre-print edition) and I got my copy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-2459299872321186143?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2459299872321186143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2459299872321186143'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/12/scala-book-is-out.html' title='scala book is out'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-8934895852189723390</id><published>2007-11-29T19:39:00.000-08:00</published><updated>2007-11-29T19:46:54.022-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>jruby closure decompiled</title><content type='html'>Its quite interesting to look into the compiled class file generated by JRuby. Following is the sample java code generated for a closure (1.times { puts 'in closure' }) .   &lt;br /&gt;&lt;br /&gt;private static ByteList __18 = ByteList.create("in closure");&lt;br /&gt;.....&lt;br /&gt;.....&lt;br /&gt; public IRubyObject closure0(ThreadContext threadcontext, IRubyObject irubyobject, IRubyObject airubyobject[])&lt;br /&gt;    {&lt;br /&gt;        Ruby ruby;&lt;br /&gt;        IRubyObject irubyobject1 = (ruby = threadcontext.getRuntime()).getNil();&lt;br /&gt;        DynamicScope dynamicscope = threadcontext.getCurrentScope();&lt;br /&gt;        IRubyObject _tmp = irubyobject1;&lt;br /&gt;        do&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                threadcontext.setPosition(__15);&lt;br /&gt;                return _17.call(threadcontext, irubyobject, RuntimeHelpers.constructObjectArray(ruby.newStringShared(__18)));&lt;br /&gt;            }&lt;br /&gt;            catch(org.jruby.exceptions.JumpException.RedoJump _ex) { }&lt;br /&gt;        } while(true);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;RedoJump exception is used to simulate ruby redo&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-8934895852189723390?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/8934895852189723390'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/8934895852189723390'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/11/jruby-closure-decompiled.html' title='jruby closure decompiled'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-2329390178513339555</id><published>2007-11-27T19:22:00.000-08:00</published><updated>2007-11-27T19:26:10.052-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>inpsect gem file</title><content type='html'>Playing around with RubyGems source code. So first thing I wanted to know is the gemspec.&lt;br /&gt;&lt;br /&gt;Here is a small script to inspect any gem file&lt;br /&gt;&lt;br /&gt;require 'yaml'&lt;br /&gt;require 'rubygems/source_info_cache'&lt;br /&gt;&lt;br /&gt;Gem::SourceInfoCache.cache&lt;br /&gt;spec = Gem::SourceInfoCache.search('#{gem}')&lt;br /&gt;p spec.to_yaml&lt;br /&gt;&lt;br /&gt;You could also use Gem::SourceIndex to spec out locally installed gems&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-2329390178513339555?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2329390178513339555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/2329390178513339555'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/11/inpsect-gem-file.html' title='inpsect gem file'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-4644988612279296740</id><published>2007-11-11T09:22:00.000-08:00</published><updated>2007-11-11T09:42:46.901-08:00</updated><title type='text'>My new X</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm3.static.flickr.com/2099/1968423455_5817975c23_o.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px;" src="http://farm3.static.flickr.com/2099/1968423455_5817975c23_o.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Finally I got Leopard installed in my Mac..... :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-4644988612279296740?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4644988612279296740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4644988612279296740'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/11/my-new-x.html' title='My new X'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-1819882869945586029</id><published>2007-10-23T18:59:00.000-07:00</published><updated>2007-10-23T19:22:25.314-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='build tool'/><title type='text'>hudson rules</title><content type='html'>Gone those days when we were promised that copying a war file to web server will bring your  application.  I thought that's a myth in Java world(what happened to webstart anayway?). But when I looked into &lt;a href="http://hudson.gotdns.com/wiki/display/HUDSON/Home"&gt;Hudson&lt;/a&gt; today my eyes were wide open, its possible..all j2ee developers out there close your xml editors and take a pick.&lt;br /&gt;&lt;br /&gt;We use Anthill Pro for our continuous integration build and it has all the bells and whistles   you  expect from big CI tool these days.  But Hudson has only those basic things that you need to setup a continuous build environment. I was able to setup within 15 mins using my existing ant build file. Now when I compare with other tools they seemed to be over-engineered and difficult to setup and use(Let me know if I am wrong). Did I mention it has some cool plugins.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-1819882869945586029?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/1819882869945586029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/1819882869945586029'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/10/hudson-rules.html' title='hudson rules'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-1217376079500883284</id><published>2007-09-12T16:33:00.000-07:00</published><updated>2007-09-12T16:37:44.901-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ejb3'/><title type='text'>ejb 3</title><content type='html'>After ranting about Xml and j2ee development pain, I have to agree that ejb3 is really awesome. I was able to develop an entity and session bean without any deployment descriptor apart from persistence.xml file. Its really cool to see power of annotations in practice. Having a reflection of field experience really helps any framework to be more developer friendly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-1217376079500883284?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/1217376079500883284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/1217376079500883284'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/09/ejb-3.html' title='ejb 3'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-810209580762904611</id><published>2007-09-07T13:54:00.000-07:00</published><updated>2007-09-07T14:28:31.217-07:00</updated><title type='text'>xml bites again</title><content type='html'>Have you seen anybody who actually like doing j2ee/xml work?&lt;br /&gt;&lt;br /&gt;I haven't and just because 90% of java work is j2ee stuff they are tied to it in spite of the dislike.  If you have &lt;a href="http://www.infoq.com/articles/agile-kanban-boards"&gt;noko niko&lt;/a&gt; calendar of your team all you will see is :( . Apparently it took 1 day for me to integrate one external ejb with our module.  I don't consider myself a j2ee expert but honestly how good are collection of xml configurations when every time you change something you have to redeploy. All I want is to compile and run my tests, is it too much to ask? . If you have a big project like us then you are screwed because every XML change requires jaring, redeploy and restart of your application. Its quite a big cycle when you have no compiler watching for your deployment  descriptor errors. I am not sure whether Websphere application developer or Weblogic workshop  have any sophisticated logic to validate your DD's before even deploying it.&lt;br /&gt;Anyways do we really need all these descriptors to deploy some manage beans? Introspection and clever defaults could solve all the problem and it doesn't need a CS degree to figure that out, maybe some practical experience.&lt;br /&gt;Honestly have anyone used any 3rd party ejb components or followed all the j2ee roles?  If  Java at all wants to  make  a component market a reality make it easy for developers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-810209580762904611?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/810209580762904611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/810209580762904611'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/09/xml-bites-again.html' title='xml bites again'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-4540564095418633184</id><published>2007-09-06T18:18:00.000-07:00</published><updated>2008-11-28T20:44:07.711-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fluent Interface'/><category scheme='http://www.blogger.com/atom/ns#' term='DSL'/><title type='text'>Fluent Interface</title><content type='html'>Like most other projects out there we are using fit/fitnesse to write our acceptance tests. But to be honest I am not very big fan of fitnesse. It doesn't scale very well with project size and having fixture tables through out fitnesse pages doesn't help readability and maintainability.&lt;br /&gt;&lt;br /&gt;Especially if you are building web application you leave the UI part out of the test unless you integrate your UI test tool like selenium with fitnesse but you still miss the readability for tabular test structures. When we get story in BDD(Behaviour driven development) format and acceptance criteria in Given-Then-When style I expect to see my test in following pattern.&lt;br /&gt;&lt;br /&gt;"Given products exists when I search product by name then user expect to see all matching products" do&lt;br /&gt;&lt;br /&gt;test "goto product page and search for product code '100'&lt;br /&gt;now number of matching products found is '10' "&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;Doing something like this Ruby is possible and in fact &lt;a href="http://dust.rubyforge.org/"&gt;Dust&lt;/a&gt; is doing something very similar. But achieving something like this in Java is a challenge.&lt;a href="http://www.martinfowler.com/bliki/FluentInterface.html"&gt; Fluent Interface&lt;/a&gt; is one of the easiest way to do achieve DSL like look in Java and its quite easy to implement too. Lets consider the following selenium unit test&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;public void testGivenProductsExistsWhenISearchProductByNameThenUserExpectToSeeAllMatchingProducts() {&lt;br /&gt;&lt;br /&gt;goToProductPage().andSearchForProductCode("100);&lt;br /&gt;assertThat(now().numberOfMatchingProductsFoundIs("10"));&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Its not cool as ruby DSL's but its close and quite readable. Some of our test now looks like this and rest of the team loves it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-4540564095418633184?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4540564095418633184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/4540564095418633184'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/09/fluent-interface.html' title='Fluent Interface'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-9164643252709327407</id><published>2007-08-26T13:10:00.000-07:00</published><updated>2007-08-27T08:04:05.695-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Five different ways to test equality</title><content type='html'>It's bit confusing when it comes to test equality of objects  in Ruby.  It has five different ways to do it and each one has a different purpose and context in which it should be used.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;equal?&lt;/span&gt; returns true if receiver and the parameter object have same object_id.  Object ids are unique and its not shared among the objects. This method should not be overridden&lt;br /&gt;&lt;br /&gt;&lt;span&gt;==&lt;/span&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;returns true if the receiver and parameter object has same values. This is most intuitive and should be overridden in your sub-classes&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;eq? &lt;/span&gt;Like == it compares objects but is more strict about type. Only reason this exists is to compare Hash keys&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;=== &lt;/span&gt;This is used for Switch Case statement.  It compares target in case statement with each selectors. You can override it to control the way case statements are matched inside the switch block&lt;br /&gt;&lt;br /&gt;&lt;span&gt;=~&lt;/span&gt; Pattern matching (Side note: In Erlang = does the pattern matching)&lt;br /&gt;&lt;br /&gt;== and =~ does have a negated version and since ruby is a great language if you implement == you != for free, isn't that great.&lt;br /&gt;&lt;br /&gt;Next time when you have to equate objects you know which one to use&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-9164643252709327407?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/9164643252709327407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/9164643252709327407'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/08/five-different-ways-to-test-equality.html' title='Five different ways to test equality'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-3681825365061833788</id><published>2007-08-21T18:57:00.000-07:00</published><updated>2007-08-21T19:17:18.251-07:00</updated><title type='text'>Ruby open classes</title><content type='html'>This issue have been flamed in many blogs and Java programmers are not very comfortable with open classes that includes me. But its really powerful there is not doubt about it, like &lt;a href="http://memeagora.blogspot.com/2007/05/are-open-classes-evil.html"&gt;Neal ford&lt;/a&gt; said how many times did we created StringUtils class in our java project. But I guess re-opened classes should be organized in some way where everyone knows where to find it. When  I say "1.hour.from_now" example in the rails book for the first time. I was really shocked, does it makes sense to have hour method in Fixnum and to add more confusion if you open irb and look at fixnum methods you will not see it at all.&lt;br /&gt;&lt;br /&gt;One of the thing that Java programmers should get over is you cannot know a class in Ruby completely. In Java we could say that I know the String class, I know how many methods are there and what are those methods etc but in the world of open classes you never know. There is no replacement of communications, in ruby world its more important talk about your work with other teammates and unit testing of course.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-3681825365061833788?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3681825365061833788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3681825365061833788'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/08/ruby-open-classes.html' title='Ruby open classes'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-7262123813488023308</id><published>2007-08-14T20:24:00.000-07:00</published><updated>2007-08-14T20:36:43.243-07:00</updated><title type='text'>netbeans ruby support</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://farm2.static.flickr.com/1170/1121445317_c2873c3ee1_b.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px;" src="http://farm2.static.flickr.com/1170/1121445317_c2873c3ee1_b.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;If you are used to eclipse or intellij, you know how hard is to live without auto-completion, debugging and refactoring. Textmate is cool and simple but netbeans ruby support is probably best right now. It actually uses string pattern matching to list out all the options and its pretty fast. To download ruby only version go to &lt;a href="http://deadlock.netbeans.org/hudson/job/ruby/"&gt;link&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-7262123813488023308?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7262123813488023308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7262123813488023308'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/08/netbeans-ruby-support.html' title='netbeans ruby support'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm2.static.flickr.com/1170/1121445317_c2873c3ee1_t.jpg' height='72' width='72'/></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-7009354394692483997</id><published>2007-07-20T09:05:00.000-07:00</published><updated>2007-08-21T18:37:11.792-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>eval vs define_method</title><content type='html'>There are many ways you could dynamically define methods and eval should be your last option. I really don't care how many variations of eval ruby provides but don't use it.  Writing code inside string cannot help anyone not even you.&lt;br /&gt;Please remember "with more power comes more responsibility".&lt;br /&gt;define_method is much cleaner way of defining methods in meta world and gives much more readability.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-7009354394692483997?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7009354394692483997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7009354394692483997'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/07/eval-vs-definemethod.html' title='eval vs define_method'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-1526852435396650277</id><published>2007-07-17T21:22:00.000-07:00</published><updated>2007-07-17T21:54:26.873-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='two phase commit'/><title type='text'>Starbucks does not use two-phase commit</title><content type='html'>As a consultant I do fly a lot. Its sucks to do that but at the same time I do get time to read through some of my pending list of books. Right now I am reading  "Best of software writing 1"  by Joel  Spolsky . Anyways, the  "Starbucks does not use two-phase commit" is an awesome article.  In the synchronous world where most of us leave in, its fascinating how effective asynchronous solutions could be.&lt;br /&gt;&lt;br /&gt;Based on my previous experience I could say that messaging solutions is not straightforward to implement especially if you haven't done it before. Its a exotic world of xml messages, its has its own patterns and challenges.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-1526852435396650277?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/1526852435396650277'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/1526852435396650277'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/07/starbucks-does-not-use-two-phase-commit.html' title='Starbucks does not use two-phase commit'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-5465828576745945345</id><published>2007-07-13T18:36:00.000-07:00</published><updated>2007-07-13T20:30:18.580-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sas'/><category scheme='http://www.blogger.com/atom/ns#' term='software rewrite'/><title type='text'>Software rewrite and big bang theory</title><content type='html'>&lt;p class="MsoNormal"&gt;Managing multiple version of any product is tough and intricate and if the product is poorly written, you have a mess in your hand. Refactor or rewrite is a debate we participate in all the time. Let’s not go into that again right now. Let’s pretend that we have decided to rewrite our product….hoooray.  But rewriting the whole product in a one bang is not only ill-advised but a project doomed to be failure.&lt;br /&gt;&lt;br /&gt;So what should we do then? Take small steps. If you have a big, unmanageable product in your hand, figure out the core/important services/components that need to be rewritten (maybe in different technology). Integrate those components with your existing product as soon as possible and release it. If you have many existing clients, releasing quite often could be an issue.  Maybe hosting your new solution as a service (SaaS) with data centers might solve that problem. This could also be very lucrative to customers because they don’t have worry about any infrastructure/administration issues any more. This might cost you more money but you know what! you will always have a working software.&lt;br /&gt;&lt;br /&gt;Sometimes you cannot avoid having multiple version of same product, especially when you are transitioning from old messing mud ball architecture to something more manageable. But rewriting in one big bang is an illusion which results in a 200 member team project with no end date (I am serious).&lt;br /&gt;&lt;!--[if !supportLineBreakNewLine]--&gt;&lt;br /&gt;&lt;!--[endif]--&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-5465828576745945345?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/5465828576745945345'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/5465828576745945345'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/07/software-rewrite-and-big-bang-theory.html' title='Software rewrite and big bang theory'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-6205992530732858580</id><published>2007-07-10T17:22:00.000-07:00</published><updated>2007-07-10T17:30:40.690-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='statically typed'/><category scheme='http://www.blogger.com/atom/ns#' term='duck typing'/><title type='text'>Duck Typing</title><content type='html'>I was reading a blog by Bill Venners about &lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=209353"&gt;duck typing&lt;/a&gt; and kind of liked the following extract&lt;br /&gt;&lt;br /&gt;...Don't check whether it IS-a duck: check whether it QUACKS-like-a duck, WALKS-like-a duck, etc, etc, depending on exactly what subset of duck-like behaviour you need...&lt;br /&gt;&lt;br /&gt;Its funny how we advocate the same thing in Java in spite of being statically typed , when we talk about programming to interface not to implementation. As long as it QUACKS, WALKS like a duck, we shouldn't care about its type.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-6205992530732858580?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/6205992530732858580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/6205992530732858580'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/07/duck-typing.html' title='Duck Typing'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-3731177652894270213</id><published>2007-07-08T18:09:00.000-07:00</published><updated>2007-07-08T18:30:55.024-07:00</updated><title type='text'>To do list</title><content type='html'>I find it really hard to keep my focus on one thing for very long. There are so many stuff to do. I guess its a trademark problem with any software developer.  Anyways I have decided to give another shot to organize myself, create my own  personal project plan.  I found &lt;a href="http://voo2do.com/"&gt;voo2do&lt;/a&gt; to be good place to start. This site allows you to create project, tasks with time line and organize them. One of the cool feature of voo2do is , you can add new tasks just by sending a email.&lt;br /&gt;&lt;br /&gt;Now I need to out-source all my tasks :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-3731177652894270213?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3731177652894270213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3731177652894270213'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/07/to-do-list.html' title='To do list'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-9198327271894791635</id><published>2007-06-28T15:39:00.000-07:00</published><updated>2007-06-28T16:04:35.250-07:00</updated><title type='text'>Web UI prototyping</title><content type='html'>I guess we all agree to the fact that developers are not very good UI designers, atleast I am not.  5 pixel here, 10 pixel there is not my cup of tea.  So we have UI analysts, designers, usability experts to bother about them. But how helpful is your UI prototype if developers can't even use it. I hear some people use photoshop for prototyping. Now whats wrong with this picture.&lt;br /&gt;&lt;br /&gt;Let me guess,&lt;br /&gt;&lt;ul&gt;&lt;li&gt;we don't know what color code you are using?&lt;/li&gt;&lt;li&gt;no html code to start with? &lt;/li&gt;&lt;li&gt;fonts, borders other style sheet properties are up for  interpretations&lt;/li&gt;&lt;li&gt;and any more...&lt;/li&gt;&lt;/ul&gt;if you as a designer don't get the feeling of how it works in html or how long it going to take, how good that could be for the project?&lt;br /&gt;&lt;br /&gt;I think its very important to see that developers get a cleanly built static html page to start with.  So that they can plug-in their dynamic parts to it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-9198327271894791635?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/9198327271894791635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/9198327271894791635'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/06/web-ui-prototyping.html' title='Web UI prototyping'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-7365511306798619299</id><published>2007-06-27T18:50:00.001-07:00</published><updated>2007-06-27T19:10:05.978-07:00</updated><title type='text'>Ever wondered how virtualization works</title><content type='html'>I am planning to run windows on my mac book pro, so I recently brought parallels which I heard is really amazing and resource hog. Anyways and the end of the installation I realized that I need to have Windows XP or Vista installer to install on top of parallels. Urrrrg... what I was thinking?&lt;br /&gt;&lt;br /&gt;Check out this video. Its really cool&lt;br /&gt;&lt;br /&gt;&lt;a href="http://channel9.msdn.com/showpost.aspx?postid=163022"&gt;http://channel9.msdn.com/showpost.aspx?postid=163022&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-7365511306798619299?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7365511306798619299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/7365511306798619299'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/06/ever-wondered-how-virtualization-works.html' title='Ever wondered how virtualization works'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-9184777150975664686</id><published>2007-06-27T17:28:00.000-07:00</published><updated>2007-06-27T19:31:06.575-07:00</updated><title type='text'>Ritual vs Standups</title><content type='html'>As an agile team we are terribly affectionate about lots of things and Standups is one amongst them. We do it everyday religiously and discuss our last day’s activity, plan for today and hurdles one needs to over come.&lt;br /&gt;&lt;br /&gt;I feel like ritual when I attend the meeting every morning. I could feel very subtle differences between this type Standups and Status meeting. The bigger and better benefit of it is to have a shared commitment across the team and to get a positive feeling. If some pair is having a problem it becomes teams problem and the whole team should try to solve it.&lt;br /&gt;Unfortunately umpteen times it remains as status meeting. I believe we should be proactive enough to say NO to such meetings because if it is just about status we have card wall.&lt;br /&gt;&lt;br /&gt;I am working on how to make my team more insightful and proactive about standups rather than just one morning ritual.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-9184777150975664686?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/9184777150975664686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/9184777150975664686'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/06/ritual-vs-standups.html' title='Ritual vs Standups'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry><entry><id>tag:blogger.com,1999:blog-137385657526678306.post-3238671466841317240</id><published>2007-06-26T18:45:00.000-07:00</published><updated>2007-06-26T19:08:55.828-07:00</updated><title type='text'>Conway's Law</title><content type='html'>Have you ever wondered why big organizations end up developing software having multiple sub-modules/layers which doesn't interact very well with each other. Hummmm... sounds like a project you are working on! according to &lt;a href="http://en.wikipedia.org/wiki/Conway%27s_Law"&gt;Conway's law&lt;/a&gt;&lt;br /&gt;&lt;blockquote&gt;Any piece of software reflects the organizational structure that produced it.&lt;/blockquote&gt;The reality is, it doesn't matter what methodology you are using to develop your software, without communication and organizational overhead, its a ship sailing nowhere.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/137385657526678306-3238671466841317240?l=nilanjan-braincasting.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3238671466841317240'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/137385657526678306/posts/default/3238671466841317240'/><link rel='alternate' type='text/html' href='http://nilanjan-braincasting.blogspot.com/2007/06/have-you-ever-wondered-why-big.html' title='Conway&apos;s Law'/><author><name>Nilanjan Raychaudhuri</name><uri>http://www.blogger.com/profile/02162193549733305130</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://4.bp.blogspot.com/_JclCagta9AU/SrmSsSj_bOI/AAAAAAAAABU/mTeQvuJxZ4g/S220/Photo+2.jpg'/></author></entry></feed>
