<?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-13243193</id><updated>2011-12-01T14:45:39.914-08:00</updated><category term='Mule'/><category term='SD West 2008'/><category term='My OSS'/><category term='Pragmatic ESB'/><category term='Slides'/><category term='Writings'/><category term='Craftsmanship'/><category term='REST'/><category term='Statistics'/><category term='Review'/><category term='Corporate'/><category term='Caching'/><category term='MS'/><category term='Fun'/><category term='Science'/><category term='SOA'/><category term='Google'/><category term='Testing'/><category term='Platform'/><category term='Scala'/><category term='Readings'/><category term='SD West 2007'/><category term='Multi-threading'/><category term='Conferences'/><category term='Data'/><category term='World'/><category term='DDJ'/><category term='agile'/><category term='Ruby'/><category term='Tools'/><category term='QCon'/><category term='Hardware'/><category term='operations'/><category term='Hiring'/><category term='Off-topic'/><category term='devops'/><category term='Monitoring'/><category term='Cloud'/><category term='R'/><category term='Erlang'/><title type='text'>Just Do I.T.</title><subtitle type='html'>Software As If It Matters</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.dossot.net/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default?start-index=101&amp;max-results=100'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>309</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-13243193.post-6271373803811306477</id><published>2011-11-19T10:44:00.001-08:00</published><updated>2011-11-19T10:47:30.436-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QCon'/><category scheme='http://www.blogger.com/atom/ns#' term='Conferences'/><title type='text'>QCon San Francisco - Day 3</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;i&gt;QCon San Francisco 2011 is a wrap. I have mixed feelings about the conference and I believe I'm not the only one. Feedback forms will speak... Here are the last &lt;a href="http://twitter.com/ddossot/favorites"&gt;tweets that I favorited&lt;/a&gt; and that represent the ideas I grabbed from the sessions I&amp;nbsp;attended. Thank you to all the twitter users I've shamelessly re-used :)&lt;/i&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-GdmY_o2fmyE/Tsf4-GsHv8I/AAAAAAAAA3U/rd5BqQqoQ_Y/s1600/qconsf-day3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-GdmY_o2fmyE/Tsf4-GsHv8I/AAAAAAAAA3U/rd5BqQqoQ_Y/s1600/qconsf-day3.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6271373803811306477?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6271373803811306477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6271373803811306477' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6271373803811306477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6271373803811306477'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/11/qcon-san-francisco-day-3.html' title='QCon San Francisco - Day 3'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-GdmY_o2fmyE/Tsf4-GsHv8I/AAAAAAAAA3U/rd5BqQqoQ_Y/s72-c/qconsf-day3.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3779204945344498618</id><published>2011-11-18T08:27:00.001-08:00</published><updated>2011-11-18T08:28:23.490-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QCon'/><category scheme='http://www.blogger.com/atom/ns#' term='Conferences'/><title type='text'>QCon San Francisco - Day 2</title><content type='html'>&lt;i&gt;My &lt;a href="https://twitter.com/#!/ddossot/favorites"&gt;second-hand conference tweeting&lt;/a&gt; continues...&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-wefraP_wYyw/TsaHlf52RmI/AAAAAAAAA3M/O-TCfYDVWSg/s1600/qconsf-day2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-wefraP_wYyw/TsaHlf52RmI/AAAAAAAAA3M/O-TCfYDVWSg/s1600/qconsf-day2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3779204945344498618?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3779204945344498618/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3779204945344498618' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3779204945344498618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3779204945344498618'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/11/qcon-san-francisco-day-2.html' title='QCon San Francisco - Day 2'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-wefraP_wYyw/TsaHlf52RmI/AAAAAAAAA3M/O-TCfYDVWSg/s72-c/qconsf-day2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3431935923337924639</id><published>2011-11-16T18:19:00.001-08:00</published><updated>2011-11-16T18:20:54.218-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QCon'/><category scheme='http://www.blogger.com/atom/ns#' term='Conferences'/><title type='text'>QCon San Francisco - Day 1</title><content type='html'>&lt;i&gt;As I'm getting old and lazy, I've decided to cover QCon by &lt;a href="https://twitter.com/#!/ddossot/favorites"&gt;favoriting other people's tweets&lt;/a&gt; on sessions I attended and post the result as a daily chunk...&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-ins4RyIJzQc/TsRvbe_BE7I/AAAAAAAAA3E/RaEqRinMEHQ/s1600/qcon_day1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-ins4RyIJzQc/TsRvbe_BE7I/AAAAAAAAA3E/RaEqRinMEHQ/s1600/qcon_day1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3431935923337924639?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3431935923337924639/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3431935923337924639' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3431935923337924639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3431935923337924639'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/11/qcon-san-francisco-day-1.html' title='QCon San Francisco - Day 1'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-ins4RyIJzQc/TsRvbe_BE7I/AAAAAAAAA3E/RaEqRinMEHQ/s72-c/qcon_day1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-7176264405015606890</id><published>2011-11-05T18:53:00.000-07:00</published><updated>2011-11-07T14:03:12.227-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>API-First Development</title><content type='html'>&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;A while back, REST advocate &lt;a href="http://brendel.com/"&gt;Juergen Brendel&lt;/a&gt; twitted:&lt;/span&gt;&lt;br /&gt;&lt;blockquote class="tr_bq"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;API-first development: Modern dev. must consider multiple clients. Think about your REST API first, then add front end.&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;I &lt;a href="http://twitter.com/#!/ddossot/statuses/11835286686277632"&gt;retwited him&lt;/a&gt; because I can't agree more. In fact, even if there is a single client I'm convinced API-First development is a winning approach.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;I've been involved in &lt;strike&gt;two&lt;/strike&gt;&amp;nbsp;three&amp;nbsp;API-first projects, all very different in term of domain, size and technology. But in all cases, things turned out pretty well, and, in fact, way better than with traditional approaches to web development.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;b&gt;Clear responsibility delineation&lt;/b&gt; - When an API gets defined, client and server&amp;nbsp;responsibilities&amp;nbsp;become easier to define. The API becomes the guardian of this separation of concerns, as any temptation to make concerns of one side permeate to the other will either be impossible or at least extremely cumbersome. The API will resist almost naturally to desires to pervert it.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;Better&amp;nbsp;&lt;/span&gt;maintainability&lt;/b&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&amp;nbsp;- Server-side front-end generation usually ends up in a pretty ugly mess where&amp;nbsp;&lt;/span&gt;presentation concerns get mixed with service concerns. Even when following the MVC pattern, the sheer fact all artifacts are contained within the same project space opens the door to nasty transfers of responsibility between layers. An API is a contract around which clients and server can evolve&amp;nbsp;harmoniously.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;Client liberated&lt;/b&gt;&amp;nbsp;- Front-end developers can use rich internet application frameworks and work on a clear interface with the back-end instead of getting constrained by a particular technology and having to deal with data transfer objects they don't fully control and which may change&amp;nbsp;unexpectedly.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;b&gt;Test what matters most&lt;/b&gt; - This revolves around my &lt;a href="http://blog.dossot.net/search/label/Testing"&gt;previous rants about what's really important to test&lt;/a&gt;. When you expose an API, you can fully test your system as it is experienced by its different clients. There is no need for in-browser testing gimmicks. A simple HTTP client allows you to guarantee that the back-end is performing its duty and offering the front-end the features it needs. And that's what matters most.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;Ninjas only&lt;/b&gt; - This point is a little harsh but here we go: API-first tolls the bell of &lt;i&gt;tag soup developers&lt;/i&gt;. This category of developers, not skilled (or experienced) enough to be doing pure server-side development nor pure front-end one, is not needed anymore. Developers building clients for a server API are experts in their domain, be it HTML5, JavaScript, Flex, Android, iOS, Phonegap or whatnot. They can't rely on "the back-end guys" to pre-chew their job and are fully in charge of what they do.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;In API-First development, the time you reach the point of trying a&amp;nbsp;&lt;/span&gt;first&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&amp;nbsp;connection between an actual client and the server is an&amp;nbsp;&lt;/span&gt;exhilarating&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&amp;nbsp;moment. Sure you've been testing the back-end for a while with a simulated front-end, but when they both connect for the first time, it's party time! And amazingly, things work very well right away, all thanks to a well defined API.&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Before closing I should mention a downside for which I haven't found a satisfactory answer yet: &lt;i&gt;against what back-end should client developers work&lt;/i&gt;? It is sure easy enough to expose a development-grade server to use while developing the front-end. But it's not always practical. A local server is an option, a client-specific stub is another one. Or maybe a state machine simulating the server API and allowing the front-end developer to change its state at will to easily simulate test scenarios?&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;So, what's your experience with API-first development? Any blazing success or horror story to share?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-7176264405015606890?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/7176264405015606890/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=7176264405015606890' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7176264405015606890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7176264405015606890'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/11/api-first-development.html' title='API-First Development'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-5925548209734903979</id><published>2011-10-29T16:55:00.002-07:00</published><updated>2011-10-29T16:55:57.960-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='Corporate'/><title type='text'>Service Oriented Organizations</title><content type='html'>Earlier this year, I twitted this:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://twitter.com/#!/ddossot/statuses/78597979384188928"&gt;&lt;img border="0" height="130" src="http://1.bp.blogspot.com/-_WqQebnAt-k/Tqx7tx5WPUI/AAAAAAAAAzg/Wf3CXLvIE7U/s320/78597979384188928.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;and that:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;img border="0" height="115" src="http://2.bp.blogspot.com/-PdGCCN662YU/Tqx74rFCOPI/AAAAAAAAAzo/S-RAhgDEV9k/s320/78847402123075585.png" width="320" /&gt;&lt;/div&gt;&lt;br /&gt;Though&amp;nbsp;seemingly&amp;nbsp;disconnected these tweets are actually related. So here we are, in the blink of an eye, almost five months later and I can finally find some time to circle back to these ideas and expand them a little.&lt;br /&gt;&lt;br /&gt;Both these tweets are related to the problem of growth and the pains a software company goes through when it expands.&lt;br /&gt;&lt;br /&gt;At the beginning of a company, life is good, sharing code is easy. Whether everybody sits in the same room or not, the number of people involved in coding the product is so limited that synchronization is easy. Friction is limited, things go fast. Conflicts can be resolved with beer and pizza.&lt;br /&gt;&lt;br /&gt;If by accident (!) the company ends up being successful, things change, sometimes very quickly and most of the time not for the best. So&amp;nbsp;the team grows, divides into groups, and once the 150 persons mark gets passed, people start losing track of who's who.&lt;br /&gt;&lt;br /&gt;The traditional path to a graceful handling of growth consists in adding layers of management. Whether the control this approach brings is actual or illusionary, the fact of the matter is that it&amp;nbsp;increases the distance between teams. Here I'm not talking about physical distance, though it may be the case, but really about the &lt;i&gt;perceived&lt;/i&gt; distance, the kind of distance from which the "us versus them" mindset stems.&lt;br /&gt;&lt;br /&gt;Independently of all that, code still gets written. As the business has grown, so did the code base. Teams are sharing code. But&amp;nbsp;now any code change must go through several layers of management, both up and down for each team. Fluidity has been lost in favor of process, which protects the business stability by doing what process does best: slowing things down, if possible to the point nothing happens thus preventing anything bad to happen.&lt;br /&gt;&lt;br /&gt;At this point, the sheer fact of sharing code becomes a heavy burden. In software companies, shared code doesn't typically consist of pure libraries, like Apache Commons. Shared code more often than not involves shared dependencies on enterprise resources, like databases. High level of coupling, if not tangling, exists in the shared codebase. The mismatch between the boundaries that have been cut across teams and the actual&amp;nbsp;software artifacts'&amp;nbsp;delineation becomes an impediment to progress.&lt;br /&gt;&lt;br /&gt;This is where the idea for a Service Oriented Organization comes from (notice how I avoided &lt;i&gt;Service Oriented Business&lt;/i&gt; for obvious "acronymistic" reasons). It is not about getting rid of management or meetings. It is about &lt;b&gt;organizing teams around tangible boundaries that fit the needs of sustainable software development&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;In a Service Oriented Organization teams interact around well defined contracts: APIs and SLAs are the promises teams make to each other. And they fully define the actual extent of their commitments to each other. Teams do not share code but services.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Having clear objectives in order to achieve common goals without exposing any gory details is&amp;nbsp;beneficial both for people management and software development. Whether APIs expose fine-grained technical methods or coarse-grained business ones, teams will have the&amp;nbsp;rabid desire to provide the best service possible for what they're responsible of, and this for functional and non-functional qualities.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;Of course, all this sounds nice and rosy and quite possibly the wishful thinking of an utopian. The quest that many people have embarked upon is to find ways for corporates not to succumb to the illusion of control and grow themselves into dumbness.&lt;br /&gt;&lt;br /&gt;Service Oriented Organizations have been &lt;a href="http://www.duperrin.com/english/2008/06/20/what-if-the-future-of-organizations-was-soo-or-spo/"&gt;discussed&lt;/a&gt; &lt;a href="http://www.castlepointe.com/20110225432/IT-Strategy-and-Innovation/Innovation-and-the-Service-Oriented-Organization-SOO-Business-Value-Through-IT-Innovation-Is-it-right-under-your-nose.html"&gt;before&lt;/a&gt;. This is just my two cents about the concept.&amp;nbsp;Please share yours.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-5925548209734903979?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/5925548209734903979/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=5925548209734903979' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5925548209734903979'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5925548209734903979'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/10/service-oriented-organizations.html' title='Service Oriented Organizations'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-_WqQebnAt-k/Tqx7tx5WPUI/AAAAAAAAAzg/Wf3CXLvIE7U/s72-c/78597979384188928.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8323965992162829593</id><published>2011-10-22T18:11:00.002-07:00</published><updated>2011-10-22T18:16:39.043-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='My OSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Monitoring'/><title type='text'>SNMP Monitoring for Scout</title><content type='html'>Half a year ago, I created a JMX plug-in for the &lt;a href="https://www.scoutapp.com/"&gt;Scout&lt;/a&gt; monitoring platform in the cloud. This time, I've created a plug-in for reading values from SNMP-enabled applications or systems.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The plug-in is &lt;a href="https://github.com/ddossot/scout-snmp-plugin"&gt;available on GitHub&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's capable of reading multiple values or walking the tree and gather all read values.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let me know what you think of it: post bugs or feature requests here or directly in GitHub.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8323965992162829593?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8323965992162829593/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8323965992162829593' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8323965992162829593'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8323965992162829593'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/10/snmp-monitoring-for-scout.html' title='SNMP Monitoring for Scout'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-1224538096733564517</id><published>2011-09-15T20:01:00.001-07:00</published><updated>2011-09-15T20:03:00.952-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Slides'/><category scheme='http://www.blogger.com/atom/ns#' term='My OSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Statistics'/><category scheme='http://www.blogger.com/atom/ns#' term='R'/><title type='text'>RSB (R Service Bus) at the Vancouver R Users Group</title><content type='html'>&lt;div style="width:425px" id="__ss_9276574"&gt; &lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/ddossot/r-service-bus" title="R Service Bus" target="_blank"&gt;R Service Bus&lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/9276574" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt; &lt;div style="padding:5px 0 12px"&gt; View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/ddossot" target="_blank"&gt;David Dossot&lt;/a&gt; &lt;/div&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-1224538096733564517?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/1224538096733564517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=1224538096733564517' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1224538096733564517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1224538096733564517'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/09/rsb-r-service-bus-at-vancouver-r-users.html' title='RSB (R Service Bus) at the Vancouver R Users Group'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2858465899518590014</id><published>2011-09-03T12:58:00.005-07:00</published><updated>2011-09-03T13:58:04.515-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='My OSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>The loggr Erlang Client is out!</title><content type='html'>I've just released &lt;a href="https://github.com/ddossot/loggErL/tree/v1.0.0"&gt;the very first version of &lt;b&gt;loggErL&lt;/b&gt;&lt;/a&gt;, my Erlang client for &lt;a href="http://loggr.net/"&gt;&lt;b&gt;loggr&lt;/b&gt;&lt;/a&gt;. In case you do not know, &lt;a href="http://loggr.net/"&gt;&lt;b&gt;loggr&lt;/b&gt;&lt;/a&gt; is a sweet piece of SaaS that offers &lt;a href="http://docs.loggr.net/overview"&gt;a great deal of compelling log-related features wrapped in beautiful UI&lt;/a&gt;.&lt;div&gt;&lt;b&gt;loggErL&lt;/b&gt; offers direct API calls to the &lt;b&gt;loggr&lt;/b&gt; API, including support for optional fields:&lt;/div&gt;&lt;script src="https://gist.github.com/1191767.js"&gt; &lt;/script&gt;&lt;div&gt;&lt;b&gt;loggErL&lt;/b&gt; comes complete with a &lt;a href="https://github.com/ahmednawras/log4erl"&gt;Log4Erl&lt;/a&gt; appender that allows sending log events to &lt;b&gt;loggr&lt;/b&gt;, again optionally supporting extra fields:&lt;/div&gt;&lt;script src="https://gist.github.com/1191772.js"&gt; &lt;/script&gt;&lt;div&gt;Feel free to fork this project on GitHub: &lt;a href="https://github.com/ddossot/loggErL"&gt;https://github.com/ddossot/loggErL&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2858465899518590014?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2858465899518590014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2858465899518590014' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2858465899518590014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2858465899518590014'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/09/loggr-erlang-client-is-out.html' title='The loggr Erlang Client is out!'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-9199380927576209299</id><published>2011-07-29T15:09:00.002-07:00</published><updated>2011-07-29T15:15:28.552-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><title type='text'>Mounting Resque Web Server in Ruby on Rails 3</title><content type='html'>If you want to load Resque's web server on a URL path alongside your main Ruby on Rails 3 application, no need to mess with config.ru or Rack::URLMap, as shown in different places.&lt;br /&gt;&lt;br /&gt;The solution is way simpler and consists in using the RoR3's capacity to mount Rack applications directly in the routes table, as shown here:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1114855.js"&gt; &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Yep, it's that simple. Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-9199380927576209299?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/9199380927576209299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=9199380927576209299' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/9199380927576209299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/9199380927576209299'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/07/mounting-resque-web-server-in-ruby-on.html' title='Mounting Resque Web Server in Ruby on Rails 3'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3756897030505462082</id><published>2011-05-26T21:55:00.002-07:00</published><updated>2011-05-26T22:19:05.478-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>Erlang Monads FTW!</title><content type='html'>&lt;blockquote&gt;&lt;/blockquote&gt;A few days ago, the big brains at RabbitMQ have released &lt;a href="http://www.rabbitmq.com/blog/2011/05/17/can-you-hear-the-drums-erlando/"&gt;Erlando&lt;/a&gt;, a nifty pair of parse transformers that add support for cuts and do-syntax monads in Erlang. Like many others I'm sure, I've quickly started to use these new language constructs.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;Here is a quick demonstration of how the Maybe monad and the do keyword can simplify the chaining of methods. The following shows a succession of condition evaluations which must all succeed for the final function (&lt;span class="Apple-style-span" &gt;process_json_entities&lt;/span&gt;) to be called:&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 12px; line-height: 16px; white-space: pre; "&gt;&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;script src="https://gist.github.com/994663.js"&gt; &lt;/script&gt;&lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;For those of you who wonder, yes I know that &lt;a href="http://webmachine.basho.com/"&gt;WebMachine&lt;/a&gt; could do most of this stuff for me: using this awesome REST framework is not an option for my project.&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;Without the help of the maybe monad, I would have add to either nest case clauses (yuck!) or chain methods, each of them calling the next one in case of success of its condition.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are two problems with the latter approach:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;the most obvious problem is that the overall sequence of calls would not be in one place but buried deeper and deeper in the succession of functions,&lt;/li&gt;&lt;li&gt;the least obvious problem pertains to the classic issue of naming things: finding good names for a chain of methods, each of them testing a condition and calling the next one is very hard.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;So what's inside each of these method? Let's look into the first, which is basically a blueprint for most of them:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;script src="https://gist.github.com/994665.js"&gt; &lt;/script&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Notice on line 4 and 7 how the &lt;span class="Apple-style-span" &gt;return/1&lt;/span&gt; and &lt;span class="Apple-style-span" &gt;fail/1&lt;/span&gt; method of the Maybe monad are used to influence the flow of the sequence in the encapsulating do. The values I'm passing to these two functions are purely arbitrary but it is not always the case. In the first example above, on line 5 the value passed to &lt;span class="Apple-style-span" &gt;return/1&lt;/span&gt; &lt;span&gt;&lt;span&gt;in &lt;span class="Apple-style-span" &gt;extract_json_entities&lt;/span&gt; is assigned to &lt;span class="Apple-style-span" &gt;JsonEntities&lt;/span&gt;, eventually passed to the actual processing function.&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: 'Bitstream Vera Sans Mono', 'Courier New', monospace; font-size: 12px; line-height: 16px; white-space: pre; "&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To make this work, besides a Rebar dependency, not much is needed besides the following directives:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;script src="https://gist.github.com/994661.js"&gt; &lt;/script&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Hopefully, this will whet your appetite and decide you to &lt;a href="https://github.com/rabbitmq/erlando"&gt;give Erlando a try&lt;/a&gt;!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3756897030505462082?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3756897030505462082/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3756897030505462082' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3756897030505462082'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3756897030505462082'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/05/erlang-monads-ftw.html' title='Erlang Monads FTW!'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2852396432246234698</id><published>2011-04-20T08:05:00.002-07:00</published><updated>2011-04-20T08:09:06.898-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='My OSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Monitoring'/><title type='text'>JMX Monitoring for Scout</title><content type='html'>&lt;a href="https://www.scoutapp.com/"&gt;Scout&lt;/a&gt; is a very convenient monitoring platform in the cloud that I have started to use recently. I needed to monitor JMX data point, something that Scout doesn't do by default.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One of the many shiny things about Scout is its extensibility: it is super trivial to write a Ruby plug-in and have start use it to report custom data points.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Therefore, I've created a JMX plug-in which, after some QA from the awesome team at Scout, just ended up in their repository of supported plug-ins.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Read more about this &lt;a href="http://blog.scoutapp.com/articles/2011/04/20/jmx-monitoring"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2852396432246234698?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2852396432246234698/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2852396432246234698' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2852396432246234698'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2852396432246234698'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/04/jmx-monitoring-for-scout.html' title='JMX Monitoring for Scout'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3455832207207525664</id><published>2011-02-28T22:16:00.003-08:00</published><updated>2011-02-28T22:21:02.736-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='My OSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>Put a rabbit in your HTTP</title><content type='html'>I'm pleased to announce the release of &lt;span style="font-weight:bold;"&gt;&lt;a href="https://github.com/ddossot/rabbitmq-http-safe"&gt;http-safe&lt;/a&gt;&lt;/span&gt;, a store-and-forward HTTP gateway plugin for RabbitMQ.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Its goal is to simplify the integration and communication of services over HTTP by relieving systems from the chore of resending requests when something went wrong with "the other side".&lt;br /&gt;&lt;br /&gt;&lt;b&gt;http-safe&lt;/b&gt; goes beyond the fire and forget paradigm as it supports the notion of delivery callback in order to inform the originating system of the success or failure of its dispatch request.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Read more on GitHub: &lt;a href="https://github.com/ddossot/rabbitmq-http-safe"&gt;https://github.com/ddossot/rabbitmq-http-safe&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3455832207207525664?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3455832207207525664/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3455832207207525664' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3455832207207525664'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3455832207207525664'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2011/02/put-rabbit-in-your-http.html' title='Put a rabbit in your HTTP'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3357462374114884886</id><published>2010-10-26T12:17:00.006-07:00</published><updated>2010-10-26T15:05:34.105-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='operations'/><category scheme='http://www.blogger.com/atom/ns#' term='Monitoring'/><title type='text'>Listen to Your Applications</title><content type='html'>&lt;div&gt;&lt;i&gt;Applications have lots to say. Here's how I've learned to listen to them.&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have recently been involved in the development of a highly distributed cloud application. We were a small team and wanted to remain agile all the way through. We had extensive testing and continuous integration in place from day one giving us plenty of feedback during development, a feedback that is essential for building the right thing and building it well.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But what about production time?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We wanted to get feedback from this part of the application life cycle too, therefore we've decided to build and configure many different feedback sources so our application could speak to us.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And speaking it did. It actually provided us precious feedback on three very different aspects of itself: &lt;b&gt;user experience&lt;/b&gt;, &lt;b&gt;design&lt;/b&gt; and &lt;b&gt;implementation&lt;/b&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I have tried to represent the different feedback sources we've baked into our application and to what domain they belong to on this lovely triangular diagram:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_wgiUOehXWyI/TMcqTL_1swI/AAAAAAAAAn0/uo-23cxBHbg/s1600/ApplicationFeebackTriangle.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 239px;" src="http://3.bp.blogspot.com/_wgiUOehXWyI/TMcqTL_1swI/AAAAAAAAAn0/uo-23cxBHbg/s400/ApplicationFeebackTriangle.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5532437176374375170" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;Let me detail each feedback source:&lt;br /&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Activity Log&lt;/b&gt; - This is a detailed audit trail of each and every user action you can capture. It provides detailed feedback on your features and how you've made them usable or not. Storing this data in a &lt;a href="http://www.postgresql.org/docs/8.4/static/ddl-partitioning.html"&gt;PostgreSQL partitioned table&lt;/a&gt; did well for us. With higher volumes, you may want to &lt;a href="http://www.gonosql.com/"&gt;go NoSQL&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Error Log&lt;/b&gt; - An embarrassing stack festival that may or may not have direct impact on the end user. No need to mention that this log is best kept empty. A service like &lt;a href="http://hoptoadapp.com/"&gt;Hoptoad&lt;/a&gt; can help you with that by putting errors in your face until you resolve them.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Trace Log&lt;/b&gt; - This is where you take the true measure of what your application is actually doing, which is less than obvious in highly distributed applications. Logging correlation IDs and aggregating logs in a central place via &lt;i&gt;syslog&lt;/i&gt; or &lt;a href="http://github.com/facebook/scribe"&gt;Scribe&lt;/a&gt; is a good approach. You'll need searching capacities in these logs: think &lt;a href="http://github.com/tobi/clarity"&gt;Clarity&lt;/a&gt; or &lt;a href="http://www.splunk.com/"&gt;Splunk&lt;/a&gt;, depending on your constraints and budget.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Response Time&lt;/b&gt; - This is an obvious metric that will shed some light on your design and implementation. Just be sure you're logging it and paying attention to it.&lt;/li&gt;&lt;li&gt;&lt;b&gt;DB TPS&lt;/b&gt; - Though outside of the pure realm of your application feedback loop, this metric gives you a good measure on how DB intensive is your application and if it needs some redesign, like for example some low hanging fruits where caching could help.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Cache Hit/Miss&lt;/b&gt; - Caching brings as much problems as it solves: a cache-happy application doesn't come for free, especially if it is distributed. Measuring the hit/miss ratio on each cache can help validate their usefulness or lack thereof.&lt;/li&gt;&lt;li&gt;&lt;b&gt;MQ Throughput&lt;/b&gt; - Monitoring of queues for high watermark thresholds is commonly done outside of the application's realm. An interesting MQ-related data an application can log is the time a message has been in-flight, including, or not, the processing time of the message after it's been consumed.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Activity Intensity&lt;/b&gt; - This last one is a fun one: by representing the number of active application sessions and the current database activity, you can get a great idea of how active (or bored) are your users.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Let me mention a single benefit of this approach: thanks to the detailed activity log, we've been able to spot design issues that were preventing users to make full use of some features. And we've been able to fix these issues not based on assumptions or wild guesses but on measured data.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;div style="text-align: left;"&gt;Your applications want to talk to you: do you listen to them? How do you do it?&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3357462374114884886?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3357462374114884886/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3357462374114884886' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3357462374114884886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3357462374114884886'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/10/listen-to-your-applications-feedback.html' title='Listen to Your Applications'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_wgiUOehXWyI/TMcqTL_1swI/AAAAAAAAAn0/uo-23cxBHbg/s72-c/ApplicationFeebackTriangle.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3030843993550788233</id><published>2010-10-12T21:47:00.001-07:00</published><updated>2010-10-12T21:50:13.373-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><category scheme='http://www.blogger.com/atom/ns#' term='Slides'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>Shamelessly Plugged: cferl &amp; Mule Erlang Transport</title><content type='html'>&lt;div style="width:425px" id="__ss_5429434"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/ddossot/cferl-erlang-transportplugs" title="Vancouver Erlang Meetup cferl &amp;amp; Mule Transport Plug"&gt;Vancouver Erlang Meetup cferl &amp;amp; Mule Transport Plug&lt;/a&gt;&lt;/strong&gt;&lt;object id="__sse5429434" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cferlerlangtransportplugs-101012234419-phpapp01&amp;stripped_title=cferl-erlang-transportplugs&amp;userName=ddossot" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse5429434" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cferlerlangtransportplugs-101012234419-phpapp01&amp;stripped_title=cferl-erlang-transportplugs&amp;userName=ddossot" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/ddossot"&gt;David Dossot&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3030843993550788233?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3030843993550788233/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3030843993550788233' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3030843993550788233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3030843993550788233'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/10/shamelessly-plugged-cferl-mule-erlang.html' title='Shamelessly Plugged: cferl &amp; Mule Erlang Transport'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-4688840407825992551</id><published>2010-09-15T20:15:00.003-07:00</published><updated>2010-09-15T20:19:17.442-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='devops'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='operations'/><title type='text'>DevOps: Time for Agile Operations!</title><content type='html'>I've made a little &lt;span style="font-style: italic;"&gt;xtranormal&lt;/span&gt; movie to introduce DevOps on the blog of AgilePartner.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://blog.agilepartner.net/devops-time-for-agile-operations/"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 320px; height: 241px;" src="http://3.bp.blogspot.com/_wgiUOehXWyI/TJGMaz6AmPI/AAAAAAAAAng/Np45JH2i_jo/s320/Picture+2.png" alt="" id="BLOGGER_PHOTO_ID_5517345410743572722" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blog.agilepartner.net/devops-time-for-agile-operations/"&gt;Go check it out&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-4688840407825992551?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/4688840407825992551/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=4688840407825992551' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4688840407825992551'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4688840407825992551'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/09/devops-time-for-agile-operations.html' title='DevOps: Time for Agile Operations!'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_wgiUOehXWyI/TJGMaz6AmPI/AAAAAAAAAng/Np45JH2i_jo/s72-c/Picture+2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8699595823296205795</id><published>2010-09-10T19:57:00.004-07:00</published><updated>2010-09-11T22:33:59.264-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cloud'/><category scheme='http://www.blogger.com/atom/ns#' term='My OSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>Erlang + Cloud Files = cferl</title><content type='html'>&lt;div style="text-align: left;"&gt;To celebrate the return of &lt;a href="http://www.cloudcamp.org/vancouver/2010-09-13"&gt;CloudCamp in Vancouver&lt;/a&gt;, I'm happy to announce the very first release of &lt;b&gt;cferl&lt;/b&gt;, the Erlang API for &lt;a href="http://www.rackspacecloud.com/cloud_hosting_products/files"&gt;Rackspace Cloud Files&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;img src="http://1.bp.blogspot.com/_wgiUOehXWyI/TIvY6VyC2WI/AAAAAAAAAm4/PHFwI9YpHoY/s320/cferl.png" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 171px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5515740665436363106" /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;cferl&lt;/b&gt; fully implements the current version of the &lt;a href="http://www.rackspacecloud.com/cloud_hosting_products/files/api"&gt;Cloud Files API&lt;/a&gt;. With it, you can very easily create and manage storage containers and the data objects they contain. You also have full control over the publication of your data objects on Rackspace's CDN.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is a short example that demonstrates a few operations using &lt;b&gt;cferl&lt;/b&gt;:&lt;/div&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/574747.js?file=gistfile1.hrl"&gt;&lt;/script&gt;&lt;br /&gt;&lt;div&gt;That's all it takes to create a container, add an XML document into it and make it available to the rest of the world over CDN!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To probe further, you can:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://github.com/ddossot/cferl/blob/master/README.md"&gt;Browse the readme document&lt;/a&gt; that contains many more syntax examples.&lt;/li&gt;&lt;li&gt;&lt;a href="http://github.com/ddossot/cferl/downloads"&gt;Download &lt;b&gt;cferl&lt;/b&gt; 1.0&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://github.com/ddossot/cferl"&gt;Fork the project&lt;/a&gt; or &lt;a href="http://github.com/ddossot/cferl/issues"&gt;report issues&lt;/a&gt; on github.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Enjoy &lt;b&gt;cferl&lt;/b&gt;!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8699595823296205795?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8699595823296205795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8699595823296205795' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8699595823296205795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8699595823296205795'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/09/erlang-cloud-files-cferl.html' title='Erlang + Cloud Files = cferl'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_wgiUOehXWyI/TIvY6VyC2WI/AAAAAAAAAm4/PHFwI9YpHoY/s72-c/cferl.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-7314187232441317863</id><published>2010-09-05T09:54:00.004-07:00</published><updated>2010-09-05T10:34:39.912-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Review'/><title type='text'>Recently Reviewed: Patterns-Based Engineering</title><content type='html'>&lt;div&gt;&lt;i&gt;From time to time, I participate in technical book reviews. Here is my account for a book I've recently reviewed.&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.amazon.com/Patterns-Based-Engineering-Successfully-Delivering-Solutions/dp/0321574281"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.amazon.com/Patterns-Based-Engineering-Successfully-Delivering-Solutions/dp/0321574281"&gt;&lt;img style="text-align: left;display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; cursor: pointer; width: 300px; height: 300px; " src="http://ecx.images-amazon.com/images/I/51tt1X-H5PL._BO2,204,203,35,-76_AA300_SH20_OU01_.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;Pattern galore&lt;/i&gt;, a term that aptly describes one of the worst nightmare of software craftsmen. No-one wants to come close to a system that has been dragged into a design hell created by pattern-overenthusiastic programmers. A craftsman wants his design to be constrained by requirements and his code to be written by hand.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Alas not all code is born equal. Some languages and platforms insist on the creation of tedious scaffolding code before starting to tackle the real meat of the problem. And large projects imply the repetition of this code &lt;i&gt;ad nauseam&lt;/i&gt;. Moreover, many have been lost in the quest for the long sought holy grail of code re-use.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Not deterred by this difficult context and heavy history, Ackerman and Gonzalez have decided to present a pragmatic approach to using patterns in software engineering. And they did great. In truth, &lt;b&gt;&lt;a href="http://www.amazon.com/Patterns-Based-Engineering-Successfully-Delivering-Solutions/dp/0321574281"&gt;Patterns-Based Engineering&lt;/a&gt;&lt;/b&gt; is faithful to its tagline: &lt;i&gt;Successfully Delivering Solutions via Patterns&lt;/i&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Rest assured that snake-oil is not in the catalog of the authors: the book is as concrete as possible, organized as a manual for kick-starting a rational approach to using patterns. The authors took time to debunk pattern-related misconceptions and, this, for a reason: there is a lot to do to polish the image of design patterns. I believe this book is an essential first step in the right direction.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-7314187232441317863?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/7314187232441317863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=7314187232441317863' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7314187232441317863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7314187232441317863'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/09/recently-reviewed-patterns-based.html' title='Recently Reviewed: Patterns-Based Engineering'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8972591442995700079</id><published>2010-08-27T08:53:00.002-07:00</published><updated>2010-08-27T08:54:44.889-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Multi-threading'/><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>Watch These Threads</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lh4.ggpht.com/_wgiUOehXWyI/THffXGX0rnI/AAAAAAAAAmo/OK6cPb888Qk/thread-cat.jpg"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 450px; height: 338px;" src="http://lh4.ggpht.com/_wgiUOehXWyI/THffXGX0rnI/AAAAAAAAAmo/OK6cPb888Qk/thread-cat.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;You've been warned...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8972591442995700079?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8972591442995700079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8972591442995700079' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8972591442995700079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8972591442995700079'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/08/watch-these-threads.html' title='Watch These Threads'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_wgiUOehXWyI/THffXGX0rnI/AAAAAAAAAmo/OK6cPb888Qk/s72-c/thread-cat.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8180724586211204725</id><published>2010-05-24T16:26:00.003-07:00</published><updated>2010-05-24T19:46:03.790-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Data'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='Caching'/><title type='text'>Data Interaction Patterns</title><content type='html'>Throughout my experience with working on back-end systems for anything from big governmental to online gaming, I have came to develop a particular appreciation of the interactions that happen between data consumers and data producers. The following is a non-exhaustive and non-authoritative review of the different data interaction patterns that I've came up to play with. These are mostly unstructured notes from my experience in the field that I hope may turn useful to others.&lt;p&gt;As you know, when data is involved caching comes into play when performance and scalability are sought. In the coming diagrams, cache is represented as a vertical rectangle. The persistent storage is represented as a vertical blue cylinder, while horizontal cylinders represent some form of reliable and asynchronous message delivery channels. The data interactions are represented with curvy arrows: they can represent reading or writing.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Direct [R/W]&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_wgiUOehXWyI/S_s4W1Cv1XI/AAAAAAAAAkU/0lqumESe1qU/s1600/direct.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 119px; height: 71px;" src="http://4.bp.blogspot.com/_wgiUOehXWyI/S_s4W1Cv1XI/AAAAAAAAAkU/0lqumESe1qU/s320/direct.png" alt="" id="BLOGGER_PHOTO_ID_5475031736845849970" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Besides the obvious drawbacks coming from the temporal coupling with the persistent storage mechanism, the interesting thing to note in such a trivial data access pattern is that there is often some form of request-scoped caching happening without the need to explicitly do anything. This first level of cache you get from data access layers help in optimizing operations provided they occur in the same request (to which is bound the transaction, if one exists).&lt;/p&gt;&lt;p&gt;Being short lived, this kind of caching is free from the problem of expired cache entries eviction: it can kick in transparently without the application being aware of it.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Through Cache [R/W]&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_wgiUOehXWyI/S_s4XdF2XhI/AAAAAAAAAkc/9Na55FfWQjM/s1600/thru_cache.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 178px; height: 62px;" src="http://1.bp.blogspot.com/_wgiUOehXWyI/S_s4XdF2XhI/AAAAAAAAAkc/9Na55FfWQjM/s320/thru_cache.png" alt="" id="BLOGGER_PHOTO_ID_5475031747596279314" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Reading through cache is a simple and powerful mechanism where an application tries first to read from a long lived cache (a very cheap operation) and, if the requested data can't be found, proceeds with a read in the persistent storage (a way more expensive operation).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;It's interesting to note that write operations don't necessarily happen the same way, ie. it is well possible that a write to the persistent storage doesn't perform a similar write in the cache. Why is that? Cached data is often a specific representation of the data available in the storage: it can be for example an aggregation of different data points that correspond to a particular cache key. The same persistent data can lead to the creation of several different cache entries. In the case, a write can simply lead to an immediate cache flush, waiting for subsequent read operations to repopulate these entries with new data.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Conversely, it's possible to have write operations update the cache, which opens the interesting problem of consistency. In the current scenario, the persistent storage remains the absolute truth of consistency: the application must handle the case when the cache was inconsistent and led to an invalid data operation in the persistent storage. I've found that localized cache evictions work well: the system goes through a little hiccup but quickly restores its data sanity.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Though some data access technologies allow the automatic management of this kind of second level of caching, I personally prefer that my applications have an explicit interaction with the caching technology they use, and this at the service layer. This is especially true when considering distributed caching and the need to address the inherent idiosyncrasies of such a caching model.&lt;br /&gt;&lt;/p&gt;Cache distribution or clustering is not compulsory though: you can reap the benefits of reading through cache with localized caches but at the expense of needing to establish some form of stickiness between the data consumers and the providers (for example, by keeping a user sticky to a particular server based on its IP or session ID).&lt;br /&gt;&lt;br /&gt;This said, stickiness skews load balancing and doesn't play well when you alter a pool of servers: I've really became convinced that you get better applications by preventing stickiness and letting requests hit any server. In that case, cache distribution or clustering becomes necessary: the former presents some challenges (like getting stale data after a repartition of the caching continuum) but scales better than the latter.&lt;br /&gt;&lt;p&gt;&lt;b&gt;Write Behind [W]&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_wgiUOehXWyI/S_s4Xlrc7nI/AAAAAAAAAkk/4GgGIja0AGU/s1600/write_behind.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 178px; height: 57px;" src="http://4.bp.blogspot.com/_wgiUOehXWyI/S_s4Xlrc7nI/AAAAAAAAAkk/4GgGIja0AGU/s320/write_behind.png" alt="" id="BLOGGER_PHOTO_ID_5475031749901479538" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Writing behind consists in updating the data cache synchronously and then defer the writing to the persistent storage to an asynchronous process, through a reliable messaging channel.&lt;/p&gt;&lt;p&gt;This is possible with regular caching technologies if there is no strong integrity constraints or if it's acceptable to present temporarily wrong data to the data consumer. In case the application has strong integrity constraints, the caching technology must be able to become the primary source of integrity truth: consistent distributed cached that supports some form of transactional data manipulation becomes necessary.&lt;/p&gt;&lt;p&gt;In this scenario, the persistent storage doesn't enforce any form of data constraint, mostly because it is too hard to propagate violation issues back to the upstream layers in any meaningful form. One could wonder what is the point of using such a persistent storage if it is dumbed down to such a mundane role: if this storage is an RDBMS, there is still value in writing to it because external systems like a back-office or business intelligence tools often require to access a standard data store.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Cache Push [R]&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_wgiUOehXWyI/S_s4YME6flI/AAAAAAAAAks/kMEOO8ArNXg/s1600/cache_push.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 178px; height: 62px;" src="http://4.bp.blogspot.com/_wgiUOehXWyI/S_s4YME6flI/AAAAAAAAAks/kMEOO8ArNXg/s320/cache_push.png" alt="" id="BLOGGER_PHOTO_ID_5475031760208821842" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Pushing to cache is very useful for data whose lifecycle is not related to the interactions with its consumers. This is valid for feeds or the result of expensive computations not triggered by client requests.&lt;/p&gt;&lt;p&gt;The mechanism that pushes to cache can be something like a scheduled task or a process consuming asynchronous message channels.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;Future Read [R]&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_wgiUOehXWyI/S_s4YW_bvTI/AAAAAAAAAk0/eMM26pDsxXQ/s1600/future_read.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 178px; height: 81px;" src="http://2.bp.blogspot.com/_wgiUOehXWyI/S_s4YW_bvTI/AAAAAAAAAk0/eMM26pDsxXQ/s320/future_read.png" alt="" id="BLOGGER_PHOTO_ID_5475031763138624818" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;In this scenario, the data producers synchronously answers the consumers with the promise of the future delivery of the requested data. When available, this data is delivered to the client via some sort of server push mechanism (see next section).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This approach works very well for expensive computations triggered by client requests.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Server Push [R]&lt;/b&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e)  {}" href="http://2.bp.blogspot.com/_wgiUOehXWyI/S_s4YW_bvTI/AAAAAAAAAk0/eMM26pDsxXQ/s1600/future_read.png"&gt;&lt;img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 178px; height: 57px;" src="http://lh5.ggpht.com/_wgiUOehXWyI/S_s5iyM-KWI/AAAAAAAAAlU/ZkKLh9aBexk/server_push.png" alt="" id="BLOGGER_PHOTO_ID_5475031763138624818" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Server push can be used to complement any of the previous interactions: in that case, a process prepares some data and delivers it directly to the consumer. There are many well known technological approaches for this, including HTTP long-polling, AJAX/CometD, web sockets or AMQP. Enabling server push in an application opens the door to very interesting data interactions as it allows to decouple the activities of the data consumers and producers.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8180724586211204725?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8180724586211204725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8180724586211204725' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8180724586211204725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8180724586211204725'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/05/data-interaction-patterns.html' title='Data Interaction Patterns'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_wgiUOehXWyI/S_s4W1Cv1XI/AAAAAAAAAkU/0lqumESe1qU/s72-c/direct.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6537173628615021780</id><published>2010-05-17T19:29:00.002-07:00</published><updated>2010-05-17T19:32:04.293-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Infected but not driven</title><content type='html'>&lt;span class="Apple-style-span"  style=" ;font-family:Verdana;"&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;The least I can say is that I'm test infected: when a coverage report shows lines of code that are not exercised by any test, I can't help but freak out a little (unless it appears that this code is truly useless and can be mercilessly pruned). This quasi obsession for testing is not vain at all: time and again I have experienced the quality, stability and freedom of move a high test coverage gives me. Things work, regressions are rare and refactoring is a bliss thanks to the safety net tests provide.&lt;/div&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;b&gt;So what's with TDD... and me?&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;There are some interesting discussions going on around &lt;a href="http://coderoom.wordpress.com/2010/04/27/tdd-without-the-t/" id="dszb" title="TDD" style="color: rgb(85, 26, 139); "&gt;TDD&lt;/a&gt; and its applicability, which I think are mostly fueled by the heavy insistence of TDD advocates on their particular way of approaching software development in general and testing in particular. The more time I spend thinking about these discussions, the more it becomes clear to me that as far as testing is concerned, the usual rule of precaution of our industry applies: ie. &lt;i&gt;it depends&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;To be frank, I'm having a hard time with the middle D in TDD: as I said, I'm test infected, low test coverage gives me the creeps, but my process of building software is not &lt;i&gt;driven&lt;/i&gt; by tests. From an external viewpoint, it is driven by features so that would make it FDD. From my personal viewpoint, it is driven by gratification, which makes it GDD.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;Being gratified when writing software is what has driven me since I'm a kid: I didn't spend countless hours hurting my fingers on a flat and painful &lt;a href="http://en.wikipedia.org/wiki/Zx-81"&gt;ZX-81&lt;/a&gt; keyboard for the sake of it. I did it to see my programs turned into tangible actions on the computer. It was gratifying. And this is what I'm still looking for when writing software.&lt;/div&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;But let's go back to the main point of this discussion: TDD. With all the industry notables heavy-weighting on writing code while being driven by test, should I conclude there's something wrong with my practice? Or is the insistence on test first just a way to have developers write tests at all?&lt;/div&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;Adding features to a system, at least for the kind of systems I'm working on, mainly consist in implementing a behavior and exposing it through some sort of a public interface. Let's consider these two activities and how testing relates to them.&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Behavior&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;When I write simple utility functions, like chewing on some binary or data structure and spitting out a result, I will certainly write tests first because I will be able to express the complete intended behavior of the function with these tests.&lt;/div&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;Unfortunately, most of the functions I write are not that trivial: they interact with functions in other modules in non-obvious manners (asynchronously) and support different failure scenarios. Following a common Erlang idiom, these functions often end up replying a simple &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;ok&lt;/span&gt;: such a result is not enough to drive the development of the function (else &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;fun() -&gt; ok end&lt;/span&gt; would be the only function to write to be done). In fact, testing first this kind of functions implies expressing with mock expectations all the interactions that will happen when calling the top function. That's MDD (Mock Driven Development) and it's only a letter away from making me MAD. Sorry but writing mocks first makes me nauseous.&lt;/div&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;My approach to developing and testing complex functions is, to me, more palatable as it leads to a faster gratification: I start by creating an empty function. Then I fill it with a blueprint of the main interactions I am envisionning expressed as comments. Afterwards, I reify this blueprint by turning the few comments in the original function into a cascade of smaller functions. At this point, I fire-up the application and manually exercise the new function: this is when the fun begins as I see this new code coming to life, finding implementation bugs and fixing potential oversights. After being gratified with running code, I then proceed to unit test it thoroughly, exploring each failure scenarios with mocks and using a code coverage tool to ensure I haven't forgotten any execution branch in my tests.&lt;/div&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;This said, there is another behavior-related circumstance under which I will write tests first: when the implemented behavior is proven wrong. In that case, writing tests that make the problem visible before fixing it is the best approach to debugging as it deals with the problem of &lt;a href="http://blog.dossot.net/2008/03/bugs-of-opportunity.html" id="w4_." title="bad days and lurking regressions" style="color: rgb(85, 26, 139); "&gt;bad days and lurking regressions&lt;/a&gt;.&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Public Interface&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;Writing usable modules imply designing interfaces that are convenient to use. Discussing good API design is way beyond the point here. The point is: could writing tests first be a good guide for creating good interfaces? The immediate answer is yes, as by eating your own dog food first makes you more inclined into cooking it into the best palatable form possible (anyone who has had to eat dog food, say while enduring hazing, knows this is a parabola).&lt;/div&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;In my practice, I have found things to be a little different, again for less than trivial functions, which unfortunately compose most of a complex production system. For this class of functions, I have found that the context of a unit test is seldom enough to fairly represent the actual context where the functions will be used. And consequently, the capacity to infer a well-designed interface based on these tests first and alone is not enough. Indeed, a unit test context is not reality: look at all the mocks in it, don't they make the whole set look like a movie stage? &lt;i&gt;Do you think it's air you're breathing?&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;When creating non-trivial public functions, I've found a great help into going through a serious amount of code reading in the different places where it is envisioned these functions will be used. Reading a lot of code before writing a little of it is commonplace in our industry: while going through the reading phase, you're actually loading all sort of contextual information in your short term memory. Armed with such a mental model, it becomes possible to design new moving parts that will naturally fit in this edifice. So that I guess that practice would be RDD (reading driven development).&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;b&gt;Daring to conclude?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;I find it hard to conclude anything from the dichotomy between my practices as opposed to what TDD proponents advocate. I consider myself a well-rounded software professional producing code of reasonably good quality: unless I'm completely misguided about myself, I think the conclusion is that it's possible to write solid production code without doing it in a test-driven fashion. If you have the discipline to write tests, you can afford to not being driven by them.&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6537173628615021780?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6537173628615021780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6537173628615021780' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6537173628615021780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6537173628615021780'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/05/infected-but-not-driven.html' title='Infected but not driven'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6380371287215716161</id><published>2010-05-14T17:39:00.005-07:00</published><updated>2010-05-14T18:17:30.560-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Monitoring'/><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>Just Read: Zabbix 1.8 Network Monitoring</title><content type='html'>Since &lt;a href="http://www.zabbix.com/"&gt;Zabbix&lt;/a&gt; 1.8 came out, I have been wanting to upgrade just for the sake of getting the new and improved AJAXy front-end. Indeed, the Achilles' heel of the previous versions of this otherwise very solid and capable monitoring platform, was the poorly responsive GUI. But I kept pushing the upgrade for a later date.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When the good folks at &lt;a href="http://www.packtpub.com/"&gt;Packt Publishing&lt;/a&gt; offered me to take a peek at &lt;a href="http://www.packtpub.com/zabbix-1-8-network-monitoring/book?utm_source=blog.dossot.net&amp;amp;utm_medium=bookrev&amp;amp;utm_content=blog&amp;amp;utm_campaign=mdb_003029"&gt;their brand new Zabbix book&lt;/a&gt;, my procrastination was over. Equipped with such a complete and up-to-date reference material, I had no reason for not taking the plunge and upgrade.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.packtpub.com/zabbix-1-8-network-monitoring/book?utm_source=blog.dossot.net&amp;amp;utm_medium=bookrev&amp;amp;utm_content=blog&amp;amp;utm_campaign=mdb_003029"&gt;&lt;img src="https://www.packtpub.com/sites/default/files/imagecache/productview/bookimages/7689_MockupCover_Raw.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 125px; height: 152px;" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;This 400+ pages book is not only welcome as a supporting resource when upgrading, it is also a consummate reference guide that was much needed by all Zabbix users. I've found the book to be easy to read, as it is loaded with screenshots, but also one step beyond than a pure user guide. Indeed, the author covers general subjects about application monitoring: for example, the section on SNMP is actually a very good introduction to this protocol, with tons of hands-on example to guide you through the learning path.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On the down side of things, as it is often the case with technical books, I have found the index to be wanting (it's a little short and sometimes deceiving). This is not a big deal though because, in order to make the most of this comprehensive book, it's a good idea to get the eBook version and use full text search to reach the information needed.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Whether you're using Zabbix and want to deepen your skills or want to learn about monitoring in practice, this book will get you covered. And if you don't want to take my word on this, download &lt;a href="https://www.packtpub.com/sites/default/files/7689_Zabbix_SampleChapter.pdf"&gt;this free chapter&lt;/a&gt; and see for yourself!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6380371287215716161?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6380371287215716161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6380371287215716161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6380371287215716161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6380371287215716161'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/05/just-read-zabbix-18-network-monitoring.html' title='Just Read: Zabbix 1.8 Network Monitoring'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8609420088551329952</id><published>2010-04-30T18:39:00.004-07:00</published><updated>2010-08-27T08:35:50.552-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><title type='text'>Grafting Mule Endpoints</title><content type='html'>&lt;blockquote&gt;Note: The following code samples are applicable to Mule 2.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://www.mulesoft.com/mule-esb-open-source-esb"&gt;Mule ESB&lt;/a&gt;, outbound dispatching to a destination whose address is known at runtime only is a pretty trivial endeavor. A less frequent practice consists in programmatically defining inbound service endpoints.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I recently had to do such thing for a little side project I'm running where Mule is used as a frontal bus and load throttler in front of a &lt;a href="http://www.r-project.org/"&gt;R&lt;/a&gt; nodes exposed over RMI. The goal was to have a non-fixed number of file inbound endpoints defined in a simple properties file and declare them on a particular service during the initialization sequence of Mule.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As an integration framework, &lt;a href="http://www.mulesoft.com/mule-esb-open-source-esb"&gt;Mule ESB&lt;/a&gt; exposes all its moving parts and lets you configure them easily with its Spring-powered XML DSL: that's all we need to achieve the above goal.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let's first look at the resulting service configuration:&lt;/div&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/385957.js?file=gistfile1.xml"&gt;&lt;/script&gt;&lt;br /&gt;&lt;div&gt;As you can see the inbound router doesn't have any endpoint configured on it. This is where we will programmatically graft the file endpoints configured in an external properties file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Before digging into the code used for this grafting operation, let's look at how the grafter itself is configured:&lt;/div&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/385956.js?file=gistfile1.xml"&gt;&lt;/script&gt;&lt;br /&gt;&lt;div&gt;Unsurprisingly, we use a Spring configured POJO to perform the endpoints generation. Notice how the service and the file connector are referenced: instead of using names I'm directly referencing Mule configuration elements. Because Spring is used consistently being the scene, this kind of cross referencing is possible and the key to many advanced tricks!&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now take a deep breath and take a look at the code in charge of grafting the endpoints to the target service:&lt;/div&gt;&lt;br /&gt;&lt;script src="http://gist.github.com/385954.js?file=gistfile1.java"&gt;&lt;/script&gt;&lt;br /&gt;&lt;div&gt;The important things to pay attention to are the following:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The class implements &lt;a href="http://www.mulesoft.org/docs/site/2.2.1/apidocs/org/mule/api/context/MuleContextAware.html"&gt;MuleContextAware&lt;/a&gt; in order to receive an instance of the &lt;a href="http://www.mulesoft.org/docs/site/2.2.1/apidocs/org/mule/api/MuleContext.html"&gt;MuleContext&lt;/a&gt;, which is the key to the gate of Mule's innermosts. Some might consider fetching this class from the connector object that gets injected in this class too: I personally find this less desirable for design reasons that I'll let &lt;a href="http://en.wikipedia.org/wiki/Law_of_Demeter"&gt;Demeter&lt;/a&gt; explain.&lt;/li&gt;&lt;li&gt;The endpoint is bound to the desired connector by passing its name in the URI used to create it. This allows picking up the right connector, which is compulsory for any Mule configuration with more than one instance of a particular connector (&lt;a href="http://www.mulesoft.org/display/MULE2USER/File+Transport"&gt;file&lt;/a&gt; connectors in this case).&lt;/li&gt;&lt;li&gt;Endpoint specific configuration parameters, like &lt;span class="Apple-style-span"  style="font-family:'courier new';"&gt;moveToDirectory&lt;/span&gt;, are configured as extra URI parameters. You can also add other parameters, as key/value pairs: they will be automatically added to the message properties dispatched from this endpoint.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;And &lt;i&gt;voila&lt;/i&gt;, though you may never have to do this kind of things in your &lt;a href="http://www.mulesoft.com/mule-esb-open-source-esb"&gt;Mule ESB&lt;/a&gt; projects, you've gained some deeper experience into what a reasonably skilled gardener can do with this powerful platform.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8609420088551329952?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8609420088551329952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8609420088551329952' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8609420088551329952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8609420088551329952'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/04/grafting-mule-endpoints.html' title='Grafting Mule Endpoints'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3316789395174785316</id><published>2010-04-28T09:14:00.002-07:00</published><updated>2010-04-28T09:26:03.620-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>Just Read: 97 Things Every Programmer Should Know</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.shelfari.com/books/12981752/97-Things-Every-Programmer-Should-Know-Collective-Wisdom-from-th"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 154px; height: 231px;" src="http://ecx.images-amazon.com/images/I/51uSFVY7zjL._SL231.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;As a collection of 2 pages essays on good software practices, the book offers a pretty heterogeneous reading experience. Despite that, the book is an pleasant and quick read, which covers all aspects of software development, from coding to testing and from technical to human-related concerns.&lt;/div&gt;&lt;br /&gt;If you're familiar with the practices that the Agile, XP or Software Craftsmanship movements are putting forward, you'll find that you already knew and agreed with most of the book. In that case, the real value of this book will come from the few essays you'll find questioning or disagreeing with, as you will have to self-introspect and decide if your disagreement is founded or based on prejudices.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In conclusion, I think this book will often be found in the "must read" list of books that teams provide to their junior programmers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3316789395174785316?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3316789395174785316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3316789395174785316' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3316789395174785316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3316789395174785316'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/04/just-read-97-things-every-programmer.html' title='Just Read: 97 Things Every Programmer Should Know'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2506168637621824105</id><published>2010-04-20T22:22:00.002-07:00</published><updated>2010-04-20T22:26:18.045-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Slides'/><category scheme='http://www.blogger.com/atom/ns#' term='Monitoring'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>Looking under the covers: Using SNMP to peek inside Erlang (Slides)</title><content type='html'>&lt;center&gt;&lt;div style="width:425px" id="__ss_3798533"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;/strong&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=lookingunderthecoverserlangsnmp-100421001123-phpapp01&amp;stripped_title=looking-under-thecoverserlangsnmp" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=lookingunderthecoverserlangsnmp-100421001123-phpapp01&amp;stripped_title=looking-under-thecoverserlangsnmp" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2506168637621824105?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.slideshare.net/ddossot/looking-under-thecoverserlangsnmp' title='Looking under the covers: Using SNMP to peek inside Erlang (Slides)'/><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2506168637621824105/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2506168637621824105' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2506168637621824105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2506168637621824105'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/04/looking-under-covers-using-snmp-to-peek.html' title='Looking under the covers: Using SNMP to peek inside Erlang (Slides)'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-1078343074414663333</id><published>2010-04-14T09:09:00.002-07:00</published><updated>2010-04-14T09:14:16.886-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>Just Read: Coders at Work</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.shelfari.com/books/12442969/Coders-at-Work"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 154px; height: 223px;" src="http://ecx.images-amazon.com/images/I/51DEnAtKzBL._SL223.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;As an interview-based book, &lt;b&gt;Coders at Work&lt;/b&gt; does a pretty good job at exploring the minds, memories and practices of an impressive bunch of software old timers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To me, the main downside of this book is that it is, with a few exceptions, mainly focused on a pretty homogeneous group of people, i.e. US-based coders who started on PDP-*.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The book could have used a little more diversity because it's main value lies in the analysis that us, the readers, will do while reading about the lives of these arch-coders. More diversity would have made the commonality between top coders more salient, while in the book, commonalities feel they occur simply because most of these people worked at the same period of time on the same type of machines.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Besides that, it's definitely worth the read.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-1078343074414663333?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/1078343074414663333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=1078343074414663333' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1078343074414663333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1078343074414663333'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/04/just-read-coders-at-work.html' title='Just Read: Coders at Work'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3913573776345994795</id><published>2010-02-25T21:18:00.003-08:00</published><updated>2010-02-25T21:40:56.444-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Platform'/><title type='text'>The Holy Grail Of Persistence?</title><content type='html'>&lt;div&gt;One of the very first CTO-grade decision I had to take in the making of &lt;a href="http://snoget.com/"&gt;Snoget&lt;/a&gt; was to pick what would become our main transactional persistence engine. Since we're using Erlang exclusively for our production servers, the solution seemed easy: use &lt;a href="http://en.wikipedia.org/wiki/Mnesia"&gt;Mnesia&lt;/a&gt;. But I settled for PostgreSQL.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At this point, anyone who's been dealing with O/R mapping (like &lt;a href="http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx"&gt;Ted Neward&lt;/a&gt; who said: "&lt;i&gt;Object/relational mapping is the Vietnam of Computer Science&lt;/i&gt;"), should cry fool: Mnesia would offer me persistence without any impedence mismatch with the application runtime environment and I preferred a SQL database to it? Actually, to someone who has used an O/R mapper before and who switched to Erlang, discovering Mnesia for the first time is a sheer heavenly moment similar to that:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_wgiUOehXWyI/S4dbTxkVXvI/AAAAAAAAAgs/36RmxnTRAvc/s1600-h/mnesia_hg.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_wgiUOehXWyI/S4dbTxkVXvI/AAAAAAAAAgs/36RmxnTRAvc/s320/mnesia_hg.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5442419069981908722" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-size: small;"&gt;&lt;b&gt;The Holy Grail Of Persistence&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Though Mnesia is very clearly not presented as a replacement for general purpose RDBMSes, one can not avoid to seriously consider using it, just because there is such a low cost into moving data from and to an Erlang application.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As a developer, I already had my share of joys and pains from working with non-standard persistence engines (like &lt;a href="http://www.softwareag.com/Corporate/products/wm/tamino/default.asp"&gt;Tamino&lt;/a&gt; and &lt;a href="http://www.xml.com/pub/p/465"&gt;X-Hive&lt;/a&gt;). I also learned from others who did the same, in much greater scale than me, and &lt;a href="http://blog.carlschmidt.ca/2009/07/startup-cto-mistakes-i-rather-not.html"&gt;who shared their experience about it&lt;/a&gt;. So it is with great circumspection that I approached the decision of using a niche database engine instead of a mainstream one.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That being said, here are the four key decision points that made me favor PostgreSQL:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Schema Migration&lt;/b&gt; - &lt;i&gt;For a startup, it's critical to be able to evolve a database schema with the less friction possible as features are often in a state of flux.&lt;br /&gt;&lt;span class="Apple-style-span" style="font-style: normal; "&gt;&lt;br /&gt;Using a standard DB like PostgreSQL allowed us to leverage &lt;a href="http://api.rubyonrails.org/classes/ActiveRecord/Migration.html"&gt;Ruby's ActiveRecord Migration&lt;/a&gt;, which is not only handy for migrating forward (as you do in production) but also backwards (as you sometimes have to do in development). Though &lt;a href="http://erlanganswers.com/web/mcedemo/mnesia/SchemaMaintenance.html#advancedschemamigrations"&gt;Mnesia record evolution is possible&lt;/a&gt;, the fact that data migration concerns permeate into the application code is very unpleasant. Going &lt;a href="http://erlanganswers.com/web/mcedemo/mnesia/SchemaFree.html"&gt;schema free&lt;/a&gt; was a tempting option but would not have come close to the flexibility ActiveRecord and PostgreSQL gave us.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Supporting Resources&lt;/b&gt; - &lt;i&gt;Being able to solve problems quickly is essential for a startup: for everything that is not your core business, you usually rely a lot on the information available out there.&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;PostgreSQL has an extensive body of knowledge available online and in print. When things go haywire or in case of doubt, you're pretty much guaranteed that a Google search will bring you at least a couple of pages where people asked the exact same question and got answers for them. With Mnesia, the amount of available information is way reduced, simply because it's still very much a niche database.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Standard Connectivity&lt;/b&gt; - &lt;i&gt;When you're focused on building something new, the last thing you want is wasting time in re-inventing the wheel: interoperable building blocks are key.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Using an standard database like PostgreSQL gave us immediate access to tools like Pentaho's Data Integration, which we use to massage data. Though we could have built an army of supporting tools to perform the same on Mnesia, it's always better to use something that's already there. I has also allowed us to fully leverage Ruby On Rails to build an awesome back office in no time. Though there are some Ruby-Erlang bridges out there, none gives you all the RAD features you get when plugging Rails to a standard database.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Operational Simplicity&lt;/b&gt; - &lt;i&gt;In a startup, there's no DBA to nurse your database engine: you have to deal with it so it better be simple to operate.&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;Installing, upgrading, backing-up, restoring PostgreSQL databases are all well defined operations, supported by a wealth of tools. The security model is straightforward too. And there are plenty of options for monitoring what's happening under the hood and analyze and tune performances. I have no doubt all this is possible with Mnesia, but in a less familiar and straightforward manner.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Of course, there is a downside in using PostgreSQL with Erlang, and a pretty big one: there is no official driver for it so you're fully subject to the talent of the developer whose driver you'll be using. For us, it quickly turned out that the driver we started with was the Achilles' Heel of our application and we had to switch to &lt;a href="http://glozer.net/code.html#epgsql"&gt;another implementation&lt;/a&gt;, which turned out to be very solid. The switch was painful because there is no such thing as &lt;i&gt;edbc&lt;/i&gt;, i.e. a standard for database connectors in Erlang. If you switch driver, you get a new API!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At this point, some pundits must be fuming and asking why SQL? What about NoSQL? Partially for the same reasons quoted above. But more importantly, we're not locked with PostgreSQL: we mainly rely on this database engine for its transactional capacities, not for its relational ones. If the need arise, the way our application is architectured would allow us to swap-in another persistence engine, provided it's transactional, one functional domain at a time and this without too much pain.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finally, if you wonder if I picked up PostgreSQL because I was familiar with this database, the answer is that I never used it before. But nothing looks like a RDBMS than another RDBMS. Granted they don't shine like the Holy Grail, but still they'll happily power your software house.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3913573776345994795?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3913573776345994795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3913573776345994795' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3913573776345994795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3913573776345994795'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/02/holy-grail-of-persistence.html' title='The Holy Grail Of Persistence?'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_wgiUOehXWyI/S4dbTxkVXvI/AAAAAAAAAgs/36RmxnTRAvc/s72-c/mnesia_hg.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2665213581596644550</id><published>2010-01-06T09:04:00.008-08:00</published><updated>2010-03-04T09:28:10.290-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><title type='text'>Monitoring RabbitMQ with Zabbix</title><content type='html'>If you use &lt;a href="http://www.rabbitmq.com/"&gt;RabbitMQ&lt;/a&gt; as your message oriented middleware and &lt;a href="http://www.zabbix.com/"&gt;Zabbix&lt;/a&gt; as your monitoring and graphing tool, you're probably wondering how to monitor the former with the latter.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here is the Zabbix Agent configuration I use to keep track of the number of messages pending delivery and the total number of queues (this second parameter may not make sense for you if you don't create a lot of dynamic queues):&lt;/div&gt;&lt;br /&gt;&lt;textarea name="code" class="Python"&gt;UserParameter=rabbitmq.local.queues.count[*],sudo rabbitmqctl -q list_queues -p $1 | wc -l&lt;br /&gt;UserParameter=rabbitmq.local.messages_ready.count[*],sudo rabbitmqctl -q list_queues -p $1 messages_ready | awk '{S = S + $ 0}END{print S}'&lt;/textarea&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As you can see, these user parameters are parameterized: they take a single parameter being the virtual host path that you want to monitor. Note also that the zabbix group must be added to the non-password sudoers for rabbitmqctl.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With these parameters in place, you'll be able to build graphs and set alarms for your favorite RabbitMQ virtual hosts!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;UPDATE 10-FEB-2010: &lt;a href="http://www.cohesiveft.com/alexisrichardson/"&gt;Alexis Richardson&lt;/a&gt; has been kind enough to point towards an SNMP plug-in for RabbitMQ that has been very recently &lt;a href="http://github.com/epicadvertising/rabbitmq_snmp_plugin"&gt;released on GitHub&lt;/a&gt;. I have added a few features to it, so be sure to check &lt;a href="http://github.com/ddossot/rabbitmq_snmp_plugin"&gt;my fork&lt;/a&gt; too.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;UPDATE 04-MAR-2010: I'm now using the SNMP plug-in for RabbitMQ in production instead of the above solution, which is way more efficient. The use case for the above would then be only when SNMP is not an option for you.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2665213581596644550?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2665213581596644550/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2665213581596644550' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2665213581596644550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2665213581596644550'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2010/01/monitoring-rabbitmq-with-zabbix.html' title='Monitoring RabbitMQ with Zabbix'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-5598468275848323632</id><published>2009-12-16T23:16:00.003-08:00</published><updated>2009-12-16T23:25:56.853-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><title type='text'>Is Test Overlap A Necessary Evil?</title><content type='html'>&lt;span class="Apple-style-span"   style="  ;font-family:Verdana;font-size:13px;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;In a recent blog post titled "&lt;/span&gt;&lt;/span&gt;&lt;a id="yt5y" href="http://binstock.blogspot.com/2009/11/limitations-of-tdd.html" title="The Limitations of TDD" style="color: rgb(85, 26, 139); "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;The Limitations of TDD&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;", &lt;/span&gt;&lt;/span&gt;&lt;a id="b.o1" href="http://joltawards.com/" title="Jolt"&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;Jolt Awards&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; colleague Andrew Binstock shared some reservations &lt;/span&gt;&lt;/span&gt;&lt;a id="bm72" href="http://beust.com/" title="Cédric Beust" style="color: rgb(85, 26, 139); "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;Cédric Beust&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; has about TDD. When a person of extensive experience like Cédric speaks about testing, you pay attention. And I did.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;Among the very interesting quotes from Cédric that Andrew has reproduced, the following really struck me:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote class="webkit-indent-blockquote"  style="padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; border-width: initial; border- color:initial;"&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;Another important point is that unit tests are a convenience for *you*, the developer, while functional tests are important for your *users*. When I have limited time, I always give priority to writing functional tests. Your duty is to your users, not to your test coverage tools.&lt;br /&gt;&lt;br /&gt;You also bring up another interesting point: overtesting can lead to paralysis. I can imagine reaching a point where you don't want to modify your code because you will have too many tests to update (especially in dynamically typed languages, where you can't use tools that will automate this refactoring for you). The lesson here is to do your best so that your tests don't overlap.&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/blockquote&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;Trust me, as a test-infected developer, I would love to stay in a state of self-delusion and pretend that test-induced paralysis doesn't exist. But that would be a lie: the reality is grimmer than the wonderland of testing I would wish to live in. The reality is that &lt;/span&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;tests both encourage and resist change&lt;/span&gt;&lt;/b&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;On the one hand, tests encourage and support refactoring: when the behavior of the application should not change but the code needs to be re-organized, tests are a blessing. They give you the courage to dare changing code because of the immediate feedback they give when you've been refactoring a little too aggressively. And this is priceless.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;On the other hand, tests resist behavioral changes. Because tests have captured all the nitty-gritty of your application, when comes the time to change its behavior, you will need to invest time to adapt your tests accordingly, and this whether you rework the tests first or not. As Cédric pointed out, in a dynamically typed language, this is immensely painful as development tools are almost useless in assisting you with the required changes. Similarly, if you use mock objects, you are good for going down a deeper &lt;/span&gt;&lt;/span&gt;&lt;a id="qi45" href="http://en.wikipedia.org/wiki/Inferno_(Dante)" title="circle of hell" style="color: rgb(85, 26, 139); "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;Circle of Hell&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;, where more painful and frustrating manual fixes await you.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;So, is there any hope out of this love / hate relationship? Knowing that "&lt;/span&gt;&lt;/span&gt;&lt;i&gt;&lt;a id="i01v" href="http://programmer.97things.oreilly.com/wiki/index.php/Speed_Kills" title="the only way to go fast is to go well" style="color: rgb(85, 26, 139); "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;the only way to go fast is to go well&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/i&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;" dumping tests altogether is certainly not an option. Could the solution lies in Cédric's very last words: "&lt;/span&gt;&lt;/span&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;do your best so that your tests don't overlap&lt;/span&gt;&lt;/span&gt;&lt;span style="font-style: normal; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;"?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;At this point, I don't know yet but I've decided that, as a starting point, I should start to estimate the amount of overlap I'm dealing with in the &lt;/span&gt;&lt;/span&gt;&lt;a id="mf9v" href="http://snoget.com/" title="Erlang game server" style="color: rgb(85, 26, 139); "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;Erlang game server&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt; I'm working on. Interestingly, what I've found could pretty much apply to the vast majority of Java projects I've been previously working on. Maybe it applies to your projects too?&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;The first thing I've looked at is the testing overlap that exists between two layers of our application:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_wgiUOehXWyI/Synb_2WLlhI/AAAAAAAAAfc/0HC2KmrdLb8/s1600-h/LayersMockOverlap.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 264px; height: 111px;" src="http://2.bp.blogspot.com/_wgiUOehXWyI/Synb_2WLlhI/AAAAAAAAAfc/0HC2KmrdLb8/s320/LayersMockOverlap.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5416101916856522258" /&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: arial; "&gt;As you can see, the overlap exists because tests of the upper layer rely on mocks to simulate all the happy paths and most of the unhappy paths of the underlying layer. The overlap is not total because a layer tend to reduce the granularity of the unhappy paths it faces internally in order to expose the upper layer to a limited amount of bad situations to deal with. Hence the limited amount of mocked features in the overlap area.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;When applied to a typical vertical slice of our system, it looks like this:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_wgiUOehXWyI/SyncALfv6PI/AAAAAAAAAfk/BljODDs0HM0/s1600-h/AllLayers.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 304px; height: 127px;" src="http://3.bp.blogspot.com/_wgiUOehXWyI/SyncALfv6PI/AAAAAAAAAfk/BljODDs0HM0/s320/AllLayers.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5416101922533796082" /&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span" style="font-family: arial; "&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;span class="Apple-style-span" style="font-family: arial; "&gt;This is not too bad. Until the wind of feature change comes blowing on this mock-based card-house of tests, life is peachy.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;Until now, the tests I have been looking at were only unit and database ones. If I add our functional tests on top of the overlap diagram, here is what I get:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_wgiUOehXWyI/SyncAsF5ImI/AAAAAAAAAfs/Uz5c96jS5kw/s1600-h/FullTestsOverlap.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 287px; height: 149px;" src="http://3.bp.blogspot.com/_wgiUOehXWyI/SyncAsF5ImI/AAAAAAAAAfs/Uz5c96jS5kw/s320/FullTestsOverlap.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5416101931283718754" /&gt;&lt;/a&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: arial; "&gt;Now the application container is also tested, plus we get an insane amount of overlap.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;But the amount of overlap is not what I want to discuss first: it's the test coverage profile that I want to look at first. Notice how the functional tests explore less unhappy paths as they exercise deeper application layers. This can be explained simply: some unhappy paths are very hard to reproduce via the reduced set of functionalities exposed at the top level, oftentimes because they require a very specific and complex state to be established beforehand or conditions that could only be met in case of low level failures (loss of networking, for example).&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;It's obviously out of the question to consider dropping functional tests in order to reduce the testing overlap. As Cédric said, they are the only tests that have a true value for the end user of the system. My experience confirms that you can reach a nearly flawless first-time client integration if your functional tests have a coverage profile that is similar to the one in the last figure above.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;The only problem lies in the quality of feedback you get from functional testing: because it's impossible to make the gory details of the errors encountered when exploring unhappy paths surface at the uppermost level, your system must have a solid logging strategy that allows you to precisely track issues, should you decide to code using functional tests as your only safety net.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;So are the unit tests overlapped by the functional tests the ones that must go? Cédric again gives the answer: if time is short, it's better to focus on the functional tests. Of course, if you have a battery of unit tests in place, keep them.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;But, maybe, just maybe, as you move to your next project, consider writing functional tests firsts? That way you would have built first the tests that truly matter and, if time permits, write unit tests as you implement the features expected by the functional tests.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-top: 0px; margin-bottom: 0px; "&gt;&lt;span class="Apple-style-span"  style="font-family:arial;"&gt;&lt;span class="Apple-style-span" style="font-size: medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-5598468275848323632?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/5598468275848323632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=5598468275848323632' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5598468275848323632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5598468275848323632'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/12/is-test-overlap-necessary-evil.html' title='Is Test Overlap A Necessary Evil?'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_wgiUOehXWyI/Synb_2WLlhI/AAAAAAAAAfc/0HC2KmrdLb8/s72-c/LayersMockOverlap.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-5699951042183400988</id><published>2009-11-15T11:56:00.003-08:00</published><updated>2009-11-15T12:10:58.146-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><title type='text'>Zulu Zabbix</title><content type='html'>&lt;span style="font-style: italic;"&gt;I am posting this mainly for the sake of reference and, maybe, helping others with the same problem.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If, like us, you're running the &lt;a href="http://www.zabbix.com/"&gt;Zabbix&lt;/a&gt; monitoring platform in &lt;a href="http://en.wikipedia.org/wiki/Coordinated_Universal_Time"&gt;Zulu time&lt;/a&gt; (aka UTC), you should have noticed a time glitch when displaying historical graphs.&lt;br /&gt;&lt;br /&gt;The cause of this problem is simple: the fancy controls in the browser-based user interface are rendered using JavaScript, hence based on the time of the machine used to browse the graphs.&lt;br /&gt;&lt;br /&gt;Though we are strict in running all our servers in Zulu time, we haven't crossed the chasm and decided to run all our workstations and the rest of our life in UTC. So here is the simple fix you can apply to &lt;span style="font-weight: bold;"&gt;js/sbinit.js&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;textarea name="code" class="javascript"&gt;sbinit.js&lt;br /&gt;&lt;br /&gt;function datetoarray(unixtime){&lt;br /&gt;&lt;br /&gt;        var date = new Date();&lt;br /&gt;        date.setTime(unixtime*1000 + date.getTimezoneOffset() * 60000);&lt;br /&gt;&lt;br /&gt;...&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;The idea is to simply add the local browser time offset to the Unix time. With this fix in place, you will enjoy good looking graphs and correct navigation in them.&lt;br /&gt;&lt;br /&gt;Time is really the stumbling block of software engineering...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-5699951042183400988?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/5699951042183400988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=5699951042183400988' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5699951042183400988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5699951042183400988'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/11/zulu-zabbix.html' title='Zulu Zabbix'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6039800931844670022</id><published>2009-11-11T11:51:00.001-08:00</published><updated>2009-11-11T11:52:16.065-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hardware'/><title type='text'>Meeedia Playeeer</title><content type='html'>I've been caressing the idea to buy a Wi-Fi enabled media player in order to tap into the gigabytes of (legal) music that sits in my NAS. I've considered investing into a &lt;a href="http://www.logitechsqueezebox.com/"&gt;Logitech Squeezebox&lt;/a&gt;, or a similar product, but I wasn't sure such a device would be able to play directly from an NFS share, without any music server running somewhere.&lt;br /&gt;&lt;br /&gt;Just when I started to consider building a player out of a &lt;a href="http://www.marvell.com/products/embedded_processors/developer/kirkwood/sheevaplug.jsp"&gt;SheevaPlug&lt;/a&gt;, I remembered of the ultimate source of cheap hardware, ready to be repurposed: eBay. $125 and a few days later I had a like-new black &lt;a href="http://en.wikipedia.org/wiki/ASUS_Eee_PC"&gt;Asus &lt;span class="il"&gt;Eee&lt;/span&gt; &lt;span class="il"&gt;PC&lt;/span&gt; 2G Surf&lt;/a&gt; waiting to be turned into a music player.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://ecx.images-amazon.com/images/I/41KtCeuJNSL.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 300px; height: 300px;" src="http://ecx.images-amazon.com/images/I/41KtCeuJNSL.jpg" alt="" border="0" /&gt;&lt;/a&gt;The unit came with Ubuntu Eee Hardy Heron on it and only 50MB of free space left on its 2GB solid state drive. After a merciless review of all the installed applications, I ended up with 200 MB of free space, ready to host a music player.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_sNJ6915d4oc/SE5xAdcQ86I/AAAAAAAADAw/7PlnqVBZgiU/s200/ubuntu+eee.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 135px; height: 135px;" src="http://bp1.blogger.com/_sNJ6915d4oc/SE5xAdcQ86I/AAAAAAAADAw/7PlnqVBZgiU/s200/ubuntu+eee.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Finding the right music player was no small feat.&lt;br /&gt;&lt;br /&gt;I really enjoy &lt;a href="http://audacious-media-player.org/"&gt;Audacious&lt;/a&gt; on my work laptop because it's plain simple and is able to play music directly from an NFS mount without any glitch. But it lacks an integrated library manager, which is a must for any software powering a machine dedicated to playing music.&lt;br /&gt;&lt;br /&gt;So I went on trying all the players with integrated music library manager I could find in the Heron standard software repository  (I won't quote names because most of these applications have now better versions available). All of them were suffering from multiple woes rooted in their bad handling of network fluctuations. The most common issue was a too short not-configurable music buffer, leading to broken music replay. The worst issue was with a library manager that was not only taking ages to scan my 16+GB of music but also, on the first network glitch, would start to delete songs, one by one, from the partial library it had created (&lt;span style="font-style: italic;"&gt;talk about defensive programming gone bad&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;So I ended up installing &lt;a href="http://amarok.kde.org/"&gt;Amarok&lt;/a&gt;. The reason why I didn't immediately install it, knowing it has been my favorite player for all the time I was on Kubuntu (until the KDE 4 debacle), is its sheer size. It's a 120 MB install and on an almost full drive it didn't feel like a good idea to try it first.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://digitizor.com/wp-content/uploads/2009/09/amarok-logo.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 132px; height: 132px;" src="http://digitizor.com/wp-content/uploads/2009/09/amarok-logo.jpg" alt="" border="0" /&gt;&lt;/a&gt;This turned out to be the perfect match! Not only Amarok plays music from my NFS mount without a glitch, but its music library is totally unaffected by disturbance in the Wi-Fi signal.&lt;br /&gt;&lt;br /&gt;All in all, my Eee Music Player is doing great. It only takes a few seconds to be resurrected after being suspended and music starts playing soon after.&lt;br /&gt;&lt;br /&gt;Do you think repurposing full fledged computers into single application hosts is a crazy idea? Is it something you've considered or done already?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6039800931844670022?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6039800931844670022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6039800931844670022' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6039800931844670022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6039800931844670022'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/11/meeedia-playeeer.html' title='Meeedia Playeeer'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_sNJ6915d4oc/SE5xAdcQ86I/AAAAAAAADAw/7PlnqVBZgiU/s72-c/ubuntu+eee.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3253412839385315537</id><published>2009-10-31T12:11:00.003-07:00</published><updated>2009-10-31T17:25:43.378-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Software Manifestos: A Matter Of Trust?</title><content type='html'>As software manifestos have started to proliferate these past months, I have started to wonder what could be the root cause for their creation. Why would thought leaders gather, assert a small set of values and shrink-wrap them as a manifesto, calling for others to sign it? My feeling is that these manifestos are the expression of a pushback on a particular aspect of software development that went insane.&lt;br /&gt;&lt;br /&gt;Here is a little game: match the manifestos with the software insanities they push back on:&lt;br /&gt;&lt;br /&gt;&lt;table style="text-align: left; margin-left: auto; margin-right: auto;" class="" id="mg6z" width="60%" border="1" bordercolor="#000000" cellpadding="3" cellspacing="0"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;" width="33.333333333333336%"&gt;Big methodology and design up-front&lt;/td&gt;&lt;td style="text-align: center;" bgcolor="#cccccc"&gt;&lt;br /&gt;&lt;/td&gt;&lt;td style="text-align: center;" width="33.333333333333336%"&gt;&lt;a href="http://manifesto.softwarecraftsmanship.org/main"&gt;Software craftsmanship manifesto&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="text-align: center;" width="33.333333333333336%"&gt;Army of flying monkeys testing&lt;br /&gt;&lt;/td&gt;&lt;td style="text-align: center;" bgcolor="#cccccc"&gt;&lt;br /&gt;&lt;/td&gt;&lt;td style="text-align: center;" width="33.333333333333336%"&gt;&lt;a href="http://agilemanifesto.org/"&gt;Agile manifesto&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="text-align: center;" width="33.333333333333336%"&gt;Snake-oil vendors and ivory tower architecture&lt;/td&gt;&lt;td style="text-align: center;" bgcolor="#cccccc"&gt;&lt;br /&gt;&lt;/td&gt;&lt;td style="text-align: center;" width="33.333333333333336%"&gt;&lt;a title="QA manifesto" href="http://www.gilb.com/Real+QA+Manifesto" id="l7nf"&gt;QA manifesto&lt;/a&gt;&lt;br /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="text-align: center;" width="33.333333333333336%"&gt;Reckless programmers and incompetent coders&lt;/td&gt;&lt;td style="text-align: center;" bgcolor="#cccccc"&gt;&lt;br /&gt;&lt;/td&gt;&lt;td style="text-align: center;" width="33.333333333333336%"&gt;&lt;a href="http://soa-manifesto.org/"&gt;SOA manifesto&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-size:85%;"&gt;(One manifesto I see missing here is the "recruiter manifesto", which should push back on inane keyword-driven head hunting schemes solely able to put the wrong people at the wrong spots)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;If we dig deeper, we become tempted to ask why is our industry suffering from such insanities? What does make software different? Could it be because of complexity?&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;/i&gt;&lt;blockquote&gt;&lt;i&gt;Complexity. Software entities are more complex for their size than perhaps any other human construct because no two parts are alike (at least above the statement level). If they are, we make the two similar parts into a subroutine--open or closed. In this respect, software systems differ profoundly from computers, buildings, or automobiles, where repeated elements abound.&lt;br /&gt;&lt;/i&gt;&lt;div style="text-align: right;"&gt;Frederick P. Brooks, Jr., &lt;a title="No Silver Bullet" href="http://www.virtualschool.edu/mon/SoftwareEngineering/BrooksNoSilverBullet.html" id="rbcx"&gt;No Silver Bullet&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;  &lt;/blockquote&gt;&lt;br /&gt;The natural reaction to complexity is to try to escape it at all cost, even if it means wilfully practising self-deception. Hence silver bullets, hence snake oil vendors, hence all these methodologies, governance committees and ivory towers that are there to nurse the insecurity of higher levels of management by giving them the impression software creation is under control and, finally, &lt;i&gt;out of the hands of programmers&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Of course, it doesn't work that way: years and millions of dollars later, reality comes knocking at the door, manifestos are getting written and everyone is sent back to the same fundamental question they've been trying so hard to avoid: &lt;i&gt;how to build trust in software developers&lt;/i&gt;?&lt;br /&gt;&lt;br /&gt;And that's of course a question for us, software developers. How can we build such a trust in us when so many forces are pushing towards the opposite?&lt;br /&gt;&lt;br /&gt;Granted that software development is unpredictably complex and that this complexity reveals itself when the devil shows up (those pesky &lt;i&gt;details&lt;/i&gt;), it is clear that &lt;i&gt;the overall battle of trust is fought during each decision, when tackling each detail and writing each line of code&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;I think we could learn a few lessons from the world of aviation, where trust in pilots has been built progressively and methodically. When you fly an airplane, you have plenty of decisions to make and losing any of these battles can end up very badly for everyone. So why are pilots trusted? Aren't they fully superseded by ATC anyway? Answer is no: even if ATC has authority, the PIC (Pilot In Command) has the last word because he is the one out there dealing with the ultimate reality of flight. Despite its authority, ATC doesn't micro manage the pilot: the pilot is &lt;i&gt;in-command&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;To have the privilege to be a PIC, you have to remain current and regularly prove that you can be trusted for your judgement based on your skills, experience and training.&lt;br /&gt;&lt;br /&gt;If the acronyms didn't sound so bad, I would dare suggesting programmers should become DICs, ie &lt;i&gt;Developers In Command&lt;/i&gt;. Though working under different forms of authority, DICs would be fully trusted for taking the final decisions in the daily battle of writing code. In this world, it wouldn't be an heresy to say that developers could build large and complex software systems from the ground up, without the need for snake oil, committees or big design.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;When trust will be manifested, we won't need manifestos anymore.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3253412839385315537?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3253412839385315537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3253412839385315537' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3253412839385315537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3253412839385315537'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/10/software-manifestos-matter-of-trust.html' title='Software Manifestos: A Matter Of Trust?'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-182733854342492955</id><published>2009-09-07T18:42:00.007-07:00</published><updated>2009-09-23T16:23:00.112-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='Erlang'/><title type='text'>Looking for my seams</title><content type='html'>Like any test infected programmer switching to a new development platform, I have spent my first days working with Erlang looking for my seams. Here, I am talking about seams as defined by Michael Feathers in &lt;a title="Working Effectively with Legacy Code" href="http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052" id="hpv_"&gt;Working Effectively with Legacy Code&lt;/a&gt;: "A seam is a place where you can alter behavior in your program without editing in that place." As such, seams are key enablers for unit testing as they allow you to redirect calls leading out of your &lt;a title="SUT" href="http://en.wikipedia.org/wiki/System_Under_Test" id="cfbv"&gt;SUT&lt;/a&gt; to mocks or stubs or any kind of test double you tend to favor.&lt;br /&gt;&lt;br /&gt;In object oriented programming, this is a given thanks to polymorphism and dependency injection. But in Erlang, where SUTs are MUTs (modules under test) and the common idiom for invoking a method is &lt;i style="font-family: courier new;"&gt;module:function(parameters)&lt;/i&gt;, things are a little less obvious. Indeed, hard-wired function calls from one module to another don't leave much room for any kind of substitution. Without the capacity to fully test my modules in independence, I quickly started to feel uneasy. After a few days, it felt like free-falling without a parachute.&lt;br /&gt;&lt;br /&gt;Then I started to seriously investigate my options...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Macros&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Macros allow you to define blocks of instructions that the pre-compiler will substitute for you at the different places you refer them. When used in conjunction with flow control statements, macros can be used to switch one code fragment with another one by passing a parameter to the compiler. This seems to fit the bill as you can use conditional macros to alter behavior without editing the places where the macro is used.&lt;br /&gt;&lt;br /&gt;This said, I have quickly ruled out the use of macros as a valid seam. Imagine having to do this for all the function calls leading out of the MUT:&lt;br /&gt;&lt;textarea name="code" class="ruby"&gt;&lt;br /&gt;-ifdef(unittest).&lt;br /&gt;-define(CALL_FOO(X), foo_test:function(X)).&lt;br /&gt;-else.&lt;br /&gt;-define(CALL_FOO(X), foo:function(X)).&lt;br /&gt;-endif.&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;Moreover, if a mistake exists in the non-unit test wiring part of the conditional macro, I would have had to wait for integration tests or actual deployment to get feedback on the issue.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Funs&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Though the common idiom is to early bind the module and function you want to call, Erlang is fully capable of late binding and dynamic invocation, as this very crude example illustrate:&lt;br /&gt;&lt;textarea name="code" class="ruby"&gt;&lt;br /&gt;1&gt; Square = fun(X) -&gt; X * X end.&lt;br /&gt;#Fun&lt;erl_eval.6.13229925&gt;&lt;br /&gt;2&gt; Square(3).      &lt;br /&gt;9&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;This opens interesting possibilities for MUTs that expose &lt;a title="higher order functions" href="http://en.wikipedia.org/wiki/Higher-order_function" id="bf77"&gt;higher order functions&lt;/a&gt;. If the function that must be tested accepts one or several functions, passing a mock implementation is just a matter of providing an anonymous function of the same &lt;a title="arity" href="http://en.wikipedia.org/wiki/Arity" id="tqcq"&gt;arity&lt;/a&gt;. This mock would perform nothing besides storing the received parameters in a shared storage, like the &lt;a title="process dictionary" href="http://erlang.org/course/advanced.html#dict" id="b211"&gt;process dictionary&lt;/a&gt;, for later inspection.&lt;br /&gt;&lt;br /&gt;Unfortunately, not all functions receive their dependencies as parameters but instead perform direct calls to other functions in other modules. It could be a plausible and drastic design decision to forbid all direct inter-module calls in favor of passing dependencies as anonymous functions via additional arguments. Some have suggested to use a &lt;a title="record" href="http://20bits.com/articles/erlang-an-introduction-to-records/" id="ywsl"&gt;record&lt;/a&gt; to pass around all your application dependencies as a single extra argument added to all functions.&lt;br /&gt;&lt;br /&gt;Interesting but the idea of polluting all functions with additional arguments is less than palatable. In fact, it would great if these extra arguments could be defined module-wise and implicitly added to each of its functions... Rejoice! Parameterized modules have been introduced to perform exactly this delicious syntactic sugar trick!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Parameterized modules&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I have discovered &lt;a title="Parameterized module" href="http://www.erlang.se/workshop/2003/paper/p29-carlsson.pdf" id="g4gd"&gt;parameterized modules&lt;/a&gt; while writing controllers for &lt;a title="Mochiweb" href="http://code.google.com/p/mochiweb/" id="lgop"&gt;Mochiweb&lt;/a&gt;. In this pretty cool HTTP server, the request reference that your processing function receives points to a parameterized module, allowing this kind of neat syntax:&lt;br /&gt;&lt;textarea name="code" class="ruby"&gt;&lt;br /&gt;Method = Request.get(method).&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;Though this may feel object oriented, don't get fooled: behind the scene, there is no instance of anything. The &lt;i&gt;Request&lt;/i&gt; reference contains all the hidden parameters that the &lt;i&gt;get&lt;/i&gt; function needs besides the atom specifying what you want to get. Behind the scene, what really happens is more likely something like that:&lt;br /&gt;&lt;textarea name="code" class="ruby"&gt;&lt;br /&gt;Method = Request.get(method, Socket, Method, RawPath, Version, Headers).&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;But because the &lt;a title="Mochiweb Request" href="http://code.google.com/p/mochiweb/source/browse/trunk/src/mochiweb_request.erl" id="s9o9"&gt;Mochiweb Request&lt;/a&gt; is a parameterized module, all the extra parameters have been specified once, packed in the reference and stay hidden there for your utmost convenience!&lt;br /&gt;&lt;br /&gt;From there, it's easy to see how to write stubs for parameterized modules: just write another parameterized module that export functions with the same signature as the ones you use in the real module. Here is a very incomplete but fully working request stub for Mochiweb:&lt;br /&gt;&lt;textarea name="code" class="ruby"&gt;&lt;br /&gt;-module(mochiweb_request_stub, [Method, Path, Headers, Parameters]).&lt;br /&gt;&lt;br /&gt;-export([get/1, parse_post/0, respond/1, not_found/0]).&lt;br /&gt;&lt;br /&gt;-define(SAVE_RESPONSE, mochiweb_request_stub_response).&lt;br /&gt;&lt;br /&gt;get(method) -&gt; Method;&lt;br /&gt;get(path) -&gt; Path;&lt;br /&gt;get(headers) -&gt; Headers;&lt;br /&gt;get(response) -&gt; erlang:get(?SAVE_RESPONSE);&lt;br /&gt;get(path_tokens) -&gt; string:tokens(Path, "/").&lt;br /&gt;&lt;br /&gt;parse_post() -&gt; Parameters.&lt;br /&gt;&lt;br /&gt;respond(Response) -&gt; put(?SAVE_RESPONSE, Response).&lt;br /&gt;&lt;br /&gt;not_found() -&gt; put(?SAVE_RESPONSE, not_found).&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;Note how I use the process dictionary to store values that I will later retrieve for asserting everything went as expected. By using parameterized modules, I have been able to reach near 100% code coverage. Does this mean parameterized modules are the best thing since sliced bread?&lt;br /&gt;&lt;br /&gt;Well, so much for the free lunch as there are some drawbacks to consider:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Experimental&lt;/b&gt; - Parameterized modules are still officially considered as an experimental feature of Erlang, hence subject to change. Unlike the Java world where everything is kept for ever just in case, Erlang doesn't patronize developers, so if this feature is one day bound to oblivion, it will be tossed out. And quickly.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Unchecked&lt;/b&gt; - Unlike with a direct module's function reference, compile-time checking is not available, leading to possible bad surprises at runtime. If the parameterized module reference your code uses does not expose the expected function, you're in for a nasty error. In fact, you can totally pass a reference to a Foo module while your function expects a totally unrelated Bar module. As a tentative mitigation, I have added a verification function in my modules so they ensure at start-up time they are correctly wired. This feels like framework-envy,so I'm not fully satisfied with this approach.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;&lt;b&gt;Confusing&lt;/b&gt; - Because the actual module is not directly referred to, reading such code becomes more complicated. You have to infer from the context (or some coding conventions, or even comments) what is the module that will actually be wired-in at runtime. Decreasing understandability is definitively not a good thing.&lt;br /&gt; &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Besides these downsides, I still believe that the complete MUT isolation and behavior swapping facilities offered by parameterized modules make them a very interesting tool for the test-minded Erlang developer.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Closing notes&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;MUTs have other kinds of dependencies that you will want to substitute at unit testing time. To name a few:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Process dependencies&lt;/b&gt; - A MUT can contain functions that directly depend on other processes via their PIDs (process IDs). An interesting seam here is the &lt;a title="local registry of processes" href="http://erlang.org/doc/man/erlang.html#register-2" id="fa:t"&gt;local registry of processes&lt;/a&gt; (and ports) that you can use to set-up test processes and register them under the same name as the ones used at runtime.&lt;br /&gt; &lt;/li&gt;&lt;li&gt;&lt;b&gt;Mnesia&lt;/b&gt; - Stubbing out calls from the controllers to the DAO is a good strategy but what about the DAO itself? Instead of stubbing out each Mnesia call, I have opted for running it in-memory at unit test time (à la &lt;a title="hsqlddb" href="http://hsqldb.org/" id="pr4h"&gt;hsqlddb&lt;/a&gt;) and activating file persistence only at runtime. This is extremely fast so very well suited for the task.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Finally, if you wonder what unit testing framework I am using, I have opted for &lt;a title="etap" href="http://github.com/ngerakines/etap/tree/master" id="r20o"&gt;etap&lt;/a&gt;, which I find very simple and powerful enough for my needs. If you want something more structured and feature-rich, &lt;a title="EUnit" href="http://svn.process-one.net/contribs/trunk/eunit/doc/index.html" id="gb.s"&gt;EUnit&lt;/a&gt; is the answer.&lt;br /&gt;&lt;br /&gt;Free fall is over: I have found my seams and landed seamlessly. Please share your own test infected adventures in Erlang.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;UPDATE 23-SEP-2009&lt;/b&gt;: Hot code swapping is also a very powerful seam, that has been smartly leveraged to create &lt;a href="http://sheyll.blogspot.com/2009/02/erlang-mock-erlymock.html"&gt;ErlyMock&lt;/a&gt;, a quite capable mock framework for Erlang.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-182733854342492955?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/182733854342492955/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=182733854342492955' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/182733854342492955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/182733854342492955'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/09/looking-for-my-seams.html' title='Looking for my seams'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-5472016980139020519</id><published>2009-08-15T14:58:00.004-07:00</published><updated>2009-08-15T15:02:27.729-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Why Software Craftsmanship?</title><content type='html'>If you wonder why is the &lt;a href="http://en.wikipedia.org/wiki/Software_Craftsmanship"&gt;Software Craftsmanship&lt;/a&gt; movement valuable, Calvin and Hobbes have the answer for you:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_wgiUOehXWyI/Socv2G3kjaI/AAAAAAAAAVw/mYN1I9W4E9w/s1600-h/why_craftsmanship.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 326px; height: 400px;" src="http://2.bp.blogspot.com/_wgiUOehXWyI/Socv2G3kjaI/AAAAAAAAAVw/mYN1I9W4E9w/s400/why_craftsmanship.jpg" alt="" id="BLOGGER_PHOTO_ID_5370313687265742242" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;© 1996 Bill Watterson&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-5472016980139020519?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/5472016980139020519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=5472016980139020519' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5472016980139020519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5472016980139020519'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/08/why-software-craftsmanship.html' title='Why Software Craftsmanship?'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_wgiUOehXWyI/Socv2G3kjaI/AAAAAAAAAVw/mYN1I9W4E9w/s72-c/why_craftsmanship.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8448365047152562485</id><published>2009-08-12T11:49:00.000-07:00</published><updated>2009-08-12T11:51:43.700-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><category scheme='http://www.blogger.com/atom/ns#' term='Pragmatic ESB'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Zombie ESBs and the Integration Craftsman</title><content type='html'>&lt;p&gt;During the past months, ToughtWorkers have been regularly pounding on ESBs in a manner that &lt;a href="http://martinfowler.com/bliki/RequestStreamMap.html"&gt;&lt;span style="color:#0000ff;"&gt;&lt;u&gt;Martin Fowler&lt;/u&gt;&lt;/span&gt;&lt;/a&gt; has neatly summarized like this:&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;"Hang around my colleagues at ThoughtWorks and you soon get the impression that the only good Enterprise Service Bus (ESB) is a dead ESB. Jim Webber refers to them as Egregious Spaghetti Boxes. So it's not uncommon to hear tales of attempts to get them out of systems that don't need them."&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt; &lt;p&gt; &lt;/p&gt; &lt;p align="left"&gt;The reasons for such a reaction to ESBs are multiple and, more often than not, very valid. I think they stem from two main issues: the proprietary nature of such platforms (see Ford's "&lt;a href="http://memeagora.blogspot.com/2009/01/standards-based-vs-standardized-soa.html"&gt;&lt;span style="color:#0000ff;"&gt;&lt;u&gt;Standards Based versus Standardized&lt;/u&gt;&lt;/span&gt;&lt;/a&gt;") and the architectural quagmire an excess of "enthusiasm" towards them can entail (see Dörnenburg's "&lt;a title="Making ESB pain visible" href="http://erik.doernenburg.com/2009/07/making-esb-pain-visible/" id="ey-v"&gt;Making ESB pain visible&lt;/a&gt;" and Webber's "&lt;a title="Guerilla SOA" href="http://www.infoq.com/presentations/webber-guerilla-soa" id="s:8g"&gt;Guerilla SOA&lt;/a&gt;").&lt;/p&gt;  &lt;p align="left"&gt;The only problem I have with thought leaders pounding on ESBs is the negative aura it can create around developers involved in integration projects.&lt;/p&gt;  &lt;p align="left"&gt;What? Why do I dare talking about integration while the subject is about ESBs? Well, both subjects have become intertwined because many so-called ESBs out there are simply re-purposed integration platforms. And by re-purposed I really mean &lt;i&gt;deployed as an ESB topology&lt;/i&gt; because ESB is first and foremost a topology and not a product (as Ross Mason pointed out in "&lt;a href="http://blog.mulesource.org/2009/07/to-esb-or-not-to-esb"&gt;To ESB or not to ESB&lt;/a&gt;").&lt;/p&gt;  &lt;p align="left"&gt;So can developers working on integration projects be real craftsmen? &lt;b&gt;I think they can and I think they should&lt;/b&gt;.&lt;br /&gt;&lt;/p&gt;  &lt;p align="left"&gt;This may sound a little naive but it's not. Consider the following:&lt;/p&gt;  &lt;ul&gt;&lt;li&gt;&lt;b&gt;Integration has patterns&lt;/b&gt;. Thanks the work of Gregor Hohpe and Bobby Woolf, developers have access to a vendor-independent semantics under the form of the &lt;a title="Enterprise Integration Patterns" href="http://www.eaipatterns.com/eaipatterns.html" id="ckz4"&gt;Enterprise Integration Patterns&lt;/a&gt;. Being able to model and discuss integration without referring to a particular implementation is invaluable for craftsmen.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Integration has testing&lt;/b&gt;. It is oftentimes a challenge to test complex integration project and developers could be tempted to skip it altogether. Once again thanks to Gregor Hohpe, but with Wendy Istvanick this time, testing at all level of an integration project &lt;a title="has been proven possible and documented" href="http://bit.ly/tdeai" id="g3-7"&gt;has been proven possible and documented&lt;/a&gt;.&lt;br /&gt;  &lt;/li&gt;&lt;li&gt;&lt;b&gt;Integration does not preclude SDLC practices&lt;/b&gt;: one point we tried to make in &lt;a title="Mule in Action" href="http://muleinaction.com/" id="hue-"&gt;Mule in Action&lt;/a&gt;, is that even if your project consists in configuring an integration tool, you should not cease to be a craftsman and you should exercise good judgment and abide by your professional standards. You want to shoot for no less than reproducible builds and deployments in your integration projects.&lt;br /&gt;  &lt;/li&gt;&lt;/ul&gt;  &lt;p align="left"&gt;So, whether ESBs are better dead or undead, &lt;b&gt;developers dealing with integration projects should strive to be software craftsmen above anything else&lt;/b&gt;.&lt;br /&gt;&lt;/p&gt;  &lt;p align="left"&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;PS. Isn't it ironic that Gregor is an ex-Thoughtworker?&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8448365047152562485?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8448365047152562485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8448365047152562485' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8448365047152562485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8448365047152562485'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/08/zombie-esbs-and-integration-craftsman.html' title='Zombie ESBs and the Integration Craftsman'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2732905219926635343</id><published>2009-07-18T11:47:00.002-07:00</published><updated>2009-07-18T11:52:47.492-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Writings'/><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><title type='text'>Mule in Action: Now Treeware!</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_wgiUOehXWyI/SmIZOfQxBII/AAAAAAAAATI/4LIebkj3o0U/s1600-h/P1010799.JPG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_wgiUOehXWyI/SmIZOfQxBII/AAAAAAAAATI/4LIebkj3o0U/s320/P1010799.JPG" alt="" id="BLOGGER_PHOTO_ID_5359874243224994946" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;I feel a little like George McFly, now...&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;Trees had to die to get us there by here we are: &lt;a href="http://muleinaction.com"&gt;Mule in Action&lt;/a&gt; is now treeware. And in case you missed it, the making of was &lt;a href="http://ddossot.blogspot.com/2008/12/mule-in-action-making-of.html"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Enjoy the reading!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2732905219926635343?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2732905219926635343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2732905219926635343' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2732905219926635343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2732905219926635343'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/07/mule-in-action-now-treeware.html' title='Mule in Action: Now Treeware!'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_wgiUOehXWyI/SmIZOfQxBII/AAAAAAAAATI/4LIebkj3o0U/s72-c/P1010799.JPG' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2980557050761416214</id><published>2009-07-07T12:09:00.003-07:00</published><updated>2009-07-07T12:47:14.288-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Legacy Code Sonar Signature</title><content type='html'>In "&lt;a href="http://www.amazon.ca/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052"&gt;Working Effectively with Legacy Code&lt;/a&gt;", &lt;a href="http://www.objectmentor.com/omTeam/feathers_m.html"&gt;Michael Feathers&lt;/a&gt; gives this definition:&lt;br /&gt;&lt;i&gt;&lt;/i&gt;&lt;blockquote&gt;To me, &lt;i&gt;legacy code&lt;/i&gt; is simply code without tests.&lt;/blockquote&gt;He also adds:&lt;br /&gt;&lt;blockquote&gt;I've gotten some grief for this definition.&lt;/blockquote&gt;Indeed, defining legacy code is hard.&lt;br /&gt;&lt;br /&gt;After purging one of our project from code that we consider legacy (deprecated, EJB2...), we noticed this interesting trend in our &lt;a href="http://sonar.codehaus.org/"&gt;Sonar&lt;/a&gt; dashboard:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_wgiUOehXWyI/SlOiUvq8Y6I/AAAAAAAAATA/AdRiDzcqxVQ/s1600-h/sonar.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 220px;" src="http://4.bp.blogspot.com/_wgiUOehXWyI/SlOiUvq8Y6I/AAAAAAAAATA/AdRiDzcqxVQ/s400/sonar.png" alt="" id="BLOGGER_PHOTO_ID_5355802859151319970" border="0" /&gt;&lt;/a&gt;Notice how &lt;span style="font-style: italic;"&gt;code coverage&lt;/span&gt; is way less affected than &lt;span style="font-style: italic;"&gt;complexity&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;rules compliance&lt;/span&gt;. Our legacy code had test coverage, not the greatest ever, but it had some.&lt;br /&gt;&lt;br /&gt;Therefore, I am wondering if we could  then postulate that legacy code is &lt;span style="font-style: italic; font-weight: bold;"&gt;code that has fallen short of software development standards&lt;/span&gt;?&lt;br /&gt;&lt;br /&gt;This is actually what is expressed by the above graph: ditching legacy code drastically improved compliance to standards expressed as acceptable complexity and compliance to coding rules. These standards evolve over time: as legacy code is left abandoned, it slowly drifts away and gets less and less compliant by just standing still.&lt;br /&gt;&lt;br /&gt;Have you noticed similar trends?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2980557050761416214?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2980557050761416214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2980557050761416214' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2980557050761416214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2980557050761416214'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/07/legacy-code-sonar-signature.html' title='Legacy Code Sonar Signature'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_wgiUOehXWyI/SlOiUvq8Y6I/AAAAAAAAATA/AdRiDzcqxVQ/s72-c/sonar.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-133263096349453525</id><published>2009-06-29T22:08:00.003-07:00</published><updated>2009-06-29T22:38:01.715-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Demeter's Wrath and Angry Monkeys</title><content type='html'>Transgressing the &lt;a href="http://encyclopedia.tfd.com/Law+of+Demeter"&gt;Law of Demeter&lt;/a&gt; can not only attract the grain goddess' wrath on you but can also turn classes into &lt;a href="http://rtpscrolls.blogspot.com/2006/11/angry-monkeys-and-cargo-cults.html"&gt;angry monkeys&lt;/a&gt;. Let's see how.&lt;br /&gt;&lt;br /&gt;Consider this freshly created method and notice how it asks for more than it needs, setting the stage for the upcoming drama that involves a fuming Demeter in her heavenly spa:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;&lt;br /&gt;int computeSchniblitz(User user) {&lt;br /&gt;  return schniblitzator.process(user.getCountryCode());&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;This method needs a country code to perform its unspeakable computation but asks for a User object. Why would anyone do that? Well, if User objects are common goods around the class that holds this method, it may look like a natural thing to do.&lt;br /&gt;&lt;br /&gt;Inevitably, methods in other classes will have the need for a schniblitz to be computed for them. They will use the above method and will, therefore, need to provide a User object for them. And they may well be cool with that.&lt;br /&gt;&lt;br /&gt;Now enter the angry monkeys. From dependency to dependency, the fact that a User object is needed to compute a schniblitz will get propagated. After a while, once the client call will be far enough from the original method, in another module or project, handled by a different team in another site, no-one will have the slightest clue why a User object is needed. But a barrage of classes will angrily ask for it.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://yuml.me/diagram/scruffy;dir=td/class/%5BDemeter%27s%20Violator%7Bbg:orange%7D%5D%3C-%5BAngry%20Macaque%7Bbg:red%7D%5D,%20%5BDemeter%27s%20Violator%5D%3C-%5BAngry%20Baboon%7Bbg:red%7D%5D,%20%5BDemeter%27s%20Violator%5D%3C-%5BAngry%20Gorilla%7Bbg:red%7D%5D,%20%5BAngry%20Baboon%5D%3C-%5BInnocent%20Victim%5D."&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 509px; height: 456px;" src="http://yuml.me/diagram/scruffy;dir=td/class/%5BDemeter%27s%20Violator%7Bbg:orange%7D%5D%3C-%5BAngry%20Macaque%7Bbg:red%7D%5D,%20%5BDemeter%27s%20Violator%5D%3C-%5BAngry%20Baboon%7Bbg:red%7D%5D,%20%5BDemeter%27s%20Violator%5D%3C-%5BAngry%20Gorilla%7Bbg:red%7D%5D,%20%5BAngry%20Baboon%5D%3C-%5BInnocent%20Victim%5D." alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;So when an innocent victim comes around, it will be badly beaten if it doesn't present a valid User object in exchange for a nicely computed schniblitz.&lt;br /&gt;&lt;br /&gt;But, for this victim, this may well be a big deal. Perhaps, it does not have a full User object handy, so it will need several database calls to completely build it so it can pass it and get its schniblitz. Or perhaps, it deals with NewUser objects, which are the next great things on its side of the world, forcing it to create complex and error-prone object converters in order to turn a NewUser into a User and... get the darn schniblitz!&lt;br /&gt;&lt;br /&gt;The kicker is that the innocent victim had a contextually-valid country code. So should the original method had reduced its needs and simply had asked for what it needed, the angry monkeys would have had no "Thou Shalt Provide A User" mantra to sing and life would have been beautiful.&lt;br /&gt;&lt;br /&gt;If you find that this whole story sounds too made-up to be true, take a closer look at your code. I bet that, if your code base has a few gray hairs and a bunch of modules, you're more than likely to have a few angry monkeys here and there.&lt;br /&gt;&lt;br /&gt;Eek. Eek.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-133263096349453525?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/133263096349453525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=133263096349453525' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/133263096349453525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/133263096349453525'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/06/demeters-wrath-and-angry-classes.html' title='Demeter&apos;s Wrath and Angry Monkeys'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3820543389998293581</id><published>2009-06-09T12:07:00.004-07:00</published><updated>2009-08-25T21:14:54.806-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><category scheme='http://www.blogger.com/atom/ns#' term='REST'/><title type='text'>Mule + Groovy = REST</title><content type='html'>Groovy's MarkupBuilder makes outputting REST microformats a bliss.&lt;br /&gt;&lt;br /&gt;Read more about this in my guest blog entry "&lt;a href="http://blog.mulesource.org/2009/06/having-some-rest-with-mules-power-tools/"&gt;Having Some REST with Mule’s Power Tools&lt;/a&gt;" that MuleSource has just published on "&lt;a href="http://blog.mulesource.org/"&gt;From the Mule’s mouth&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;UPDATE AUG-2009: InfoQ has just &lt;a href="http://www.infoq.com/articles/restful-services-mule"&gt;published a longer version of this blog entry&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3820543389998293581?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3820543389998293581/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3820543389998293581' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3820543389998293581'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3820543389998293581'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/06/mule-groovy-rest.html' title='Mule + Groovy = REST'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-9055956093415346934</id><published>2009-05-25T22:07:00.003-07:00</published><updated>2009-05-25T22:30:23.342-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Strict Unit Tests for Public Data Contracts</title><content type='html'>Suppose we have the following code:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;public class Thinger {&lt;br /&gt;  private static final RESULT = "Joy";&lt;br /&gt;&lt;br /&gt;  public String doThing() {&lt;br /&gt;    return RESULT;&lt;br /&gt;  }&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;When testing such a code, it is tempting to modify the visibility of &lt;span style="font-family: courier new;"&gt;RESULT&lt;/span&gt; to &lt;span style="font-style: italic;"&gt;package protected&lt;/span&gt; in order to write tests that share the constant value:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;&lt;br /&gt;@Test&lt;br /&gt;public void doThingWorks() {&lt;br /&gt;  assertEquals(Thinger.RESULT, thinger.doThing());&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;After all, reuse is good, right?&lt;br /&gt;&lt;br /&gt;Well, in this case, I think that reusing this constant is not a good idea if your API is a public one (or if this code gets exposed as a service, which is practically the same thing).&lt;br /&gt;&lt;br /&gt;In fact, I advocate to write the test like this:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;&lt;br /&gt;@Test&lt;br /&gt;public void doThingWorks() {&lt;br /&gt;  assertEquals("Joy", thinger.doThing());&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;But why the duplication?&lt;br /&gt;&lt;br /&gt;The catch with public APIs is that they create long lasting expectations in an uncontrolled number of users and systems. Consequently, stability should be their essential characteristic. Through interfaces, it is easy to provide an illusion of stability: as long as the API is backwards-compatible binary-wise (or operation-wise for services), it can change at will and life is peachy.&lt;br /&gt;&lt;br /&gt;So what is so risky with the static field above?&lt;br /&gt;&lt;br /&gt;Well, the fact of the matter is that the value returned by the &lt;span style="font-family:courier new;"&gt;doThing()&lt;/span&gt; method is also part of the contract. Indeed, beyond the object-oriented concept of interface, data is also part of the overall contract with a particular class (or service). So data should exhibit the same stability as the interface itself.&lt;br /&gt;&lt;br /&gt;When sharing a constant in the unit test, it is possible to modify the data contract without noticing. Suppose I change the value of &lt;span style="font-family:courier new;"&gt;RESULT&lt;/span&gt; from &lt;span style="font-family:courier new;"&gt;"Joy"&lt;/span&gt; to &lt;span style="font-family:courier new;"&gt;"Happy"&lt;/span&gt;. The first test will give me a green light, while the second will be red. And it is the latter that I am looking for: &lt;span style="font-weight: bold;"&gt;I want my unit tests to tell me that I have broken the data contract of my class&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Not its users...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-9055956093415346934?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/9055956093415346934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=9055956093415346934' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/9055956093415346934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/9055956093415346934'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/05/strict-unit-tests-for-public-data.html' title='Strict Unit Tests for Public Data Contracts'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2038209176918156577</id><published>2009-05-11T21:48:00.006-07:00</published><updated>2009-05-11T22:18:37.131-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>Mule and the Home Service Bus</title><content type='html'>While following the discussions on &lt;a href="http://www.oasis-open.org/resources/white-papers/blue/"&gt;Oasis Blue&lt;/a&gt;'s &lt;a href="http://lists.oasis-open.org/archives/smartgrid-interest/200903/msg00001.html"&gt;SmartGrid Interest List&lt;/a&gt;, I noticed that smart device makers quickly reacted to the draft charter for the proposed OASIS Energy Market Information Exchange (eMIX) Technical Committee by stating that their capacity to implement full-fledged SOAP clients was limited. Looking at the bare-metal specifications of protocols like Zigbee, it is easy to understand that SOAP would be another board game.&lt;br /&gt;&lt;br /&gt;Of course, when I heard about this need for protocol adaptation, my favorite quadruped quickly came to mind (I know, when you have a hammer...). So I came up speculating about this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_wgiUOehXWyI/SgkBh4YOPmI/AAAAAAAAASY/sEKmf3hX2qQ/s1600-h/mule-sheeva-plug.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 218px; height: 320px;" src="http://1.bp.blogspot.com/_wgiUOehXWyI/SgkBh4YOPmI/AAAAAAAAASY/sEKmf3hX2qQ/s320/mule-sheeva-plug.png" alt="" id="BLOGGER_PHOTO_ID_5334796915178356322" border="0" /&gt;&lt;/a&gt;Yes, that is &lt;a href="http://mulesource.org"&gt;Mule ESB&lt;/a&gt; running on a &lt;a href="http://www.marvell.com/products/embedded_processors/developer/kirkwood/sheevaplug.jsp"&gt;Sheeva Plug&lt;/a&gt;. In fact, I should say &lt;span style="font-weight: bold;"&gt;Mule HSB&lt;/span&gt;, as in this case the platform would serve as a Home Service Bus.&lt;br /&gt;&lt;br /&gt;What could be the role of such an HSB?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Protocol adaptation&lt;/span&gt; comes first to mind&lt;span style="font-weight: bold;"&gt;.&lt;/span&gt; Allowing all your home devices to interact together internally but also with the outside world with "higher order protocols", like SOAP or anything more RESTful. What would happen if your smart meter starts talking with your dryer?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Orchestration&lt;/span&gt; would be another benefit. Here I am not thinking in term of the classic and already solved home automation problem. Imagine orchestrating your home devices in order to satisfy some predefined power consumption patterns. What would happen if a BPEL engine was running your house?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Home rules application&lt;/span&gt; would be the ultimate benefit. By plugging a rules engine to Mule, one could define advanced scenarios when a house would automatically negotiate energy purchases and sales based on inference rules and facts (like: do you have an plug-in hybrid sleeping in your garage). What would happen if your house was smart enough to make money while you sleep?&lt;br /&gt;&lt;br /&gt;I agree, this is a lot of speculation. But I reckon that &lt;span style="font-weight: bold;"&gt;a capable Home Service Bus will one day become a must in our habitations&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;PS. Google just told me that &lt;/span&gt;&lt;a style="font-style: italic;" href="http://willy.boerland.com/myblog/drupal_as_a_home_service_bus_beyond_home_automation"&gt;Bert Boerland coined the Home Service Bus term&lt;/a&gt;&lt;span style="font-style: italic;"&gt;. We must be up to something ;-)&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2038209176918156577?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2038209176918156577/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2038209176918156577' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2038209176918156577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2038209176918156577'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/05/mule-and-home-service-bus.html' title='Mule and the Home Service Bus'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_wgiUOehXWyI/SgkBh4YOPmI/AAAAAAAAASY/sEKmf3hX2qQ/s72-c/mule-sheeva-plug.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6714958754707411331</id><published>2009-05-10T07:43:00.003-07:00</published><updated>2009-05-10T08:19:28.461-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Organic Distributed Systems</title><content type='html'>Migrating monolithic systems to distributed ones is probably one of the most exhilarating tasks in software development.&lt;br /&gt;&lt;br /&gt;Monolithic systems, even if they engage in interconnected relationships,  remain pretty much like silos (I like compare a network of monolithic systems to silos connected by monkey bridges). Reflecting on the work I have been doing in this domain for the past years, I came to realize how much an IT landscape of distributed systems ends up resembling a living organism.&lt;br /&gt;&lt;br /&gt;Indeed, some proprieties of the organic world emerge in a system that evolves towards distribution.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Distributed systems are more resilient.&lt;/span&gt; Local issues in living organisms tend to remain local instead of endangering the whole system. This is achieved via redundancy, heterogeneity and a limited coupling between each part of an organism. Interestingly, the same applies to distributed software systems: if properly decoupled (interface-wise and time-wise), a particular system can be in pain without taking down the whole operation.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Distributed systems are harder to diagnose.&lt;/span&gt; Rare or complex diseases are uneasy to diagnose and often require many analysis to be performed. Distributed systems present the same challenge, complicating forensics tasks when something went haywire. Using tracing mechanisms, like correlation IDs, can simplify such diagnostics, the same way DNA-tracing can help figuring out the spread of a particular gene (or virus!).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Distributed systems can self-heal.&lt;/span&gt; Living organisms embark all sorts of self-healing mechanisms, from localized ones (cicatrization) to global ones (fever). Because each member of a distributed system focus on specific tasks and has reduced coupling to the rest, it has more freedom to perform recovery operations in isolation without needing the involvement of any other member. This said, it will still need an escalation mechanism in case the issue can not be treated locally.&lt;br /&gt;&lt;br /&gt;There are surely other qualities distributed systems exhibit that make them look like living things. Do you think of any?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6714958754707411331?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6714958754707411331/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6714958754707411331' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6714958754707411331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6714958754707411331'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/05/organic-distributed-systems.html' title='Organic Distributed Systems'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2497975256060205229</id><published>2009-04-09T16:27:00.005-07:00</published><updated>2009-04-29T08:48:51.414-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Pragmatic ESB'/><title type='text'>Jitter Mule Functional Tests With Jitr</title><content type='html'>&lt;a href="http://www.mulesource.org/display/MULE2USER/Embedding+Mule+in+a+Java+Application+or+Webapp"&gt;Embedding Mule in a web application&lt;/a&gt; allows you to tap the Servlet layer of your favorite web container, which is a good thing as you are supposedly very familiar with its behavior and tuning.&lt;br /&gt;&lt;br /&gt;When it comes to writing functional tests for such an application, my strategy was to replace the &lt;a href="http://www.mulesource.org/display/MULE2USER/Servlet+Transport"&gt;Servlet endpoints&lt;/a&gt; with &lt;a href="http://www.mulesource.org/display/MULE2USER/HTTP+Transport"&gt;stock HTTP ones&lt;/a&gt;, a substitution that is trivial to perform thanks to the modularity of Mule configuration files: I simply loaded a slightly different set of files at functional test time than the actual file configured in my &lt;span style="font-family:courier new;"&gt;web.xml&lt;/span&gt; file. Since I was writing the tests as subclasses of &lt;span style="font-family:courier new;"&gt;org.mule.tck.FunctionalTestCase&lt;/span&gt;, all the goodness of Mule was readily available as protected methods or members.&lt;br /&gt;&lt;br /&gt;Still, I was not very satisfied with this approach because of the discrepancy between what my functional tests were exercising (the stock HTTP transport) and what I was actually using (the Servlet transport). This discrepancy bit me badly in the past weeks with a problem only showing up with the Servlet transport.&lt;br /&gt;&lt;br /&gt;Then came &lt;a style="font-weight: bold;" href="http://jitr.org/"&gt;Jitr&lt;/a&gt;, the latest creation of international software samurai Josh Devins:&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;Jitr (pronounced "jitter") is a JUnit Integration Test Runner. It allows your web application integration tests to easily run against a lightweight web container in the same JVM as your tests.&lt;/blockquote&gt;It happens &lt;span style="font-weight: bold;"&gt;Jitr&lt;/span&gt; is extremely well fitted for functionally testing a Mule instance embedded in a web application. Here is the structure of such a &lt;span style="font-weight: bold;"&gt;Jitr&lt;/span&gt; powered test:&lt;br /&gt;&lt;br /&gt;&lt;textarea name="code" class="java"&gt;&lt;br /&gt;@RunWith(Jitr.class)&lt;br /&gt;public class ServicesFunctionalTest {&lt;br /&gt;    @BaseUri&lt;br /&gt;    private String baseUri;&lt;br /&gt;&lt;br /&gt;    private HttpClient httpClient;&lt;br /&gt;&lt;br /&gt;    private MuleContext muleContext;&lt;br /&gt;&lt;br /&gt;    @Before&lt;br /&gt;    public void initializeTest() throws MuleException {&lt;br /&gt;        httpClient = new HttpClient();&lt;br /&gt;        muleContext = MuleServer.getMuleContext();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test&lt;br /&gt;    public void pingService() throws Exception {&lt;br /&gt;        final HttpMethod method = new GetMethod(baseUri + "ping");&lt;br /&gt;        httpClient.executeMethod(method);&lt;br /&gt;        assertEquals("PING: OK", method.getResponseBodyAsString());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;}&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;Thanks to the access to the &lt;span style="font-family:courier new;"&gt;MuleContext&lt;/span&gt;, all the internals of the loaded Mule instance are available, which means that I am free to use my &lt;a href="http://ddossot.blogspot.com/2009/02/integration-testing-asynchronous.html"&gt;asynchronous testing strategies&lt;/a&gt;. It's party time. really!&lt;br /&gt;&lt;br /&gt;Note that &lt;span style="font-weight: bold;"&gt;Jitr&lt;/span&gt; tests are pure JUnit 4 tests, without any sub-classing needed.&lt;br /&gt;&lt;br /&gt;Because I am still loading a slightly different configuration at test time, as I am replacing file endpoints with VM ones for easier testing, I have to load a different &lt;span style="font-family:courier new;"&gt;web.xml&lt;/span&gt; file. Nothing to worry, as &lt;span style="font-weight: bold;"&gt;Jitr&lt;/span&gt; offers the possibility to load this file from an alternate location by means of configuration only. So here is the actual beginning of my test class:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;&lt;br /&gt;@RunWith(Jitr.class)&lt;br /&gt;@JitrConfiguration(warPath = "src/it/resources/webapp-it")&lt;br /&gt;public class ServicesFunctionalTest {&lt;br/&gt;...&lt;/textarea&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Jitr&lt;/span&gt; is a capable new tool that will complement the tool box of any developer having to run functional tests on web services.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2497975256060205229?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2497975256060205229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2497975256060205229' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2497975256060205229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2497975256060205229'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/04/jitter-mule-functional-tests-with-jitr.html' title='Jitter Mule Functional Tests With Jitr'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3144039277312841102</id><published>2009-03-20T22:30:00.005-07:00</published><updated>2009-03-22T14:11:57.860-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Application Pwnership</title><content type='html'>Who owns this application? What can possibly be complicated about such a simple and innocent question?&lt;br /&gt;&lt;br /&gt;Unfortunately, the answer to such a question is not that easy. Or at least, we have created software organizations that make it hard to answer.&lt;br /&gt;&lt;br /&gt;Though it makes sense to have a division of labor between different teams qualified on certain aspects of software applications, the main problem resides in the partial system views that such a division creates.&lt;br /&gt;&lt;br /&gt;Out of developers' hands, an application is oftentimes perceived by QA, DBAs or Operation teams as a giant black box:&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_wgiUOehXWyI/ScSCYIssEbI/AAAAAAAAAQI/1CfRf39ABNw/s1600-h/pwned.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 329px; height: 309px;" src="http://3.bp.blogspot.com/_wgiUOehXWyI/ScSCYIssEbI/AAAAAAAAAQI/1CfRf39ABNw/s400/pwned.png" alt="" id="BLOGGER_PHOTO_ID_5315516811367420338" border="0" /&gt;&lt;/a&gt;&lt;span style="font-style: italic;font-size:85%;" &gt;&lt;span style="color: rgb(102, 102, 102);"&gt;(yes, it is a canonical black monolith of 1-4-9 proportions)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;In fact, this giant black box has a few keyholes on it and, through these keyholes, they can barely peer into it. Consequently, the black box effect leads to QA teams seeing applications as sets of buttons to push, DBAs seeing them as data and table spaces and Operation teams dealing only with cryptic log files and alarms of all sorts.&lt;br /&gt;&lt;br /&gt;No-one knows what is inside this darn black box. And when somethings goes haywire, only the Magician of Oz is deemed able to do something:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_wgiUOehXWyI/ScSG23xrCVI/AAAAAAAAAQY/GVR-pgip_mQ/s1600-h/magic.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 185px; height: 192px;" src="http://1.bp.blogspot.com/_wgiUOehXWyI/ScSG23xrCVI/AAAAAAAAAQY/GVR-pgip_mQ/s400/magic.png" alt="" id="BLOGGER_PHOTO_ID_5315521737447377234" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Now that everybody is &lt;span style="font-style: italic;"&gt;so&lt;/span&gt; agile, this kind of concern may sound irrelevant. After all, developers are now generalizing specialists, so the barrier between them and other teams is now significantly lowered. Or is it?&lt;br /&gt;&lt;br /&gt;The reality remains for the most part a difficult hand-off of applications between teams. I have seen different tentatives to improve things (including detailed operational manuals), but at the end of the day most of these attempts amounted to shallow knowledge transfers.&lt;br /&gt;&lt;br /&gt;Ownership needs more.&lt;br /&gt;&lt;br /&gt;Do you have any success story where applications have been successfully pwned by different teams?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3144039277312841102?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3144039277312841102/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3144039277312841102' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3144039277312841102'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3144039277312841102'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/03/application-pwnership.html' title='Application Pwnership'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_wgiUOehXWyI/ScSCYIssEbI/AAAAAAAAAQI/1CfRf39ABNw/s72-c/pwned.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6052026997133879358</id><published>2009-03-11T18:01:00.008-07:00</published><updated>2009-03-11T23:30:29.183-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Multi-threading'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Hot reload and the SRP</title><content type='html'>Not so long ago, I have been tasked with the development of an in-memory IP address geolocation library. Yep, that was pretty cool and challenging at the same time (well, the challenge made it cool, right?).&lt;br /&gt;&lt;br /&gt;In this short post, I want to share how the design of one component, the data driver, has evolved over time and how the &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;Single Responsibility Principle (SRP)&lt;/a&gt; inspired this refactoring. The data driver was the poor guy charged of loading millions of geolocation data entry with the smallest possible memory footprint on a JVM (it did his job quite well, as the sizes of the zipped raw data and its in-memory form were of the same magnitude).&lt;br /&gt;&lt;br /&gt;Like in any projects, everything started nice and simple. I have removed many moving parts and simplified the design to focus only on the discussion point, but what you see hereafter is pretty similar to where I started:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_wgiUOehXWyI/SbhfnenALTI/AAAAAAAAAOY/MS5nDLJKuBg/s1600-h/s-ref-1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 122px; height: 190px;" src="http://4.bp.blogspot.com/_wgiUOehXWyI/SbhfnenALTI/AAAAAAAAAOY/MS5nDLJKuBg/s400/s-ref-1.png" alt="" id="BLOGGER_PHOTO_ID_5312100892319690034" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Quickly enough though, the rosy picture turned to a slightly less appealing color (kinda sorta brownish).&lt;br /&gt;&lt;br /&gt;Loading all this data in memory takes time (around 15 seconds). It quickly became unacceptable to further slow down the usual crippled bootstrap of a JEE application server by holding the initialization thread longer than necessary. Consequently, the data driver had to delegate its actual initialization to another thread in order to free the main thread so it could perform its lengthy EJB bootstrapping business.&lt;br /&gt;&lt;br /&gt;On top of that, because IP address blocks get re-assigned regularly, a geolocation database must be refreshed frequently, else you end-up with clients that appear to be in Antarctica instead of Kansas (that would be tough on the penguins). So the data driver had to be capable of hot reloading its data at any point of time while still being responsive (i.e. by keeping to use the old data until the new ones were fully loaded).&lt;br /&gt;&lt;br /&gt;So here I went adding all these features and I ended up with that:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_wgiUOehXWyI/SbhfnW1pAQI/AAAAAAAAAOg/T_AJKAt5zg4/s1600-h/s-ref-2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 230px; height: 242px;" src="http://1.bp.blogspot.com/_wgiUOehXWyI/SbhfnW1pAQI/AAAAAAAAAOg/T_AJKAt5zg4/s400/s-ref-2.png" alt="" id="BLOGGER_PHOTO_ID_5312100890233602306" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;In complete violation of the SRP, my original jolly little driver had become the Mother Of All Drivers, capable of doing everything and even more.&lt;br /&gt;&lt;br /&gt;At this point, my virtual &lt;a href="http://butunclebob.com/ArticleS.UncleBob.GreenWristBand"&gt;green wristband&lt;/a&gt; started to burn my wrist pretty badly. I was hearing Uncle Bob's voice threatening me of disasters of cosmic proportions if I would not live up to my professional standards and refactor the code right away.&lt;br /&gt;&lt;br /&gt;So I came up with this refactoring:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_wgiUOehXWyI/SbinxMRj0cI/AAAAAAAAAPI/28a2sYRdo9U/s1600-h/s-ref-3.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 202px;" src="http://2.bp.blogspot.com/_wgiUOehXWyI/SbinxMRj0cI/AAAAAAAAAPI/28a2sYRdo9U/s400/s-ref-3.png" alt="" id="BLOGGER_PHOTO_ID_5312180224033804738" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I gave the ReloadingDriver the single responsibility of hot reloading. It delegated the data access operation to the actual driver, to which it kept a private reference. Instead of dealing with state with flags, I refactored it according to the &lt;a href="http://en.wikipedia.org/wiki/State_pattern"&gt;state pattern&lt;/a&gt; and used a &lt;a href="http://en.wikipedia.org/wiki/Null_object"&gt;null object&lt;/a&gt; to represent the "not ready" state.&lt;br /&gt;&lt;br /&gt;To give you a better idea of how the state of the ReloadingDriver evolves, I have added a vertical time-line to the following diagram:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_wgiUOehXWyI/Sbii_I9juMI/AAAAAAAAAPA/HB5uvmYSXQY/s1600-h/s-ref-4.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 286px;" src="http://2.bp.blogspot.com/_wgiUOehXWyI/Sbii_I9juMI/AAAAAAAAAPA/HB5uvmYSXQY/s400/s-ref-4.png" alt="" id="BLOGGER_PHOTO_ID_5312174966104635586" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Interestingly, the mechanism that performs the regular reload is the same the performs the initial load that transitions from "not ready" to "Version1".&lt;br /&gt;&lt;br /&gt;As a closing note, nothing of this would have been possible without my best friends: the &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/concurrent/Executor.html"&gt;Executor&lt;/a&gt; and the &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicReference.html"&gt;AtomicReference&lt;/a&gt;. I want to thank them here for their constant support in my concurrency software development endeavors.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6052026997133879358?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6052026997133879358/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6052026997133879358' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6052026997133879358'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6052026997133879358'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/03/hot-reload-and-srp.html' title='Hot reload and the SRP'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_wgiUOehXWyI/SbhfnenALTI/AAAAAAAAAOY/MS5nDLJKuBg/s72-c/s-ref-1.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8621851255771049356</id><published>2009-03-10T12:54:00.001-07:00</published><updated>2009-03-10T12:56:13.689-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SOA'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>SOA's Eulogy is Liberating</title><content type='html'>One of the thoughts I gathered from last night's panel on the possible death of SOA, pertains to the natural consequence of the push back on the WS-DeathStar and the spike of interest in the REST architecture.&lt;br /&gt;&lt;br /&gt;So what is the consequence of dropping the dream of web-level distributed transactions and beyond-the-firewall data consistency?&lt;br /&gt;&lt;br /&gt;Except for Juval Löwy (who I guess was playing devil's advocate with a mischievous wit), the panelists were unanimous on the need to create systems that handle failures gracefully, can self-heal and achieve eventual consistency.&lt;br /&gt;&lt;br /&gt;David Platt said it very clearly: we need to design systems so they handle failures gracefully at each level of their architecture. Michele Leroux Bustamante added that this obviously does not remove the need for reliable storage (or messaging) at some point, but never beyond the firewall.&lt;br /&gt;&lt;br /&gt;They presented these concepts with a baffling unabashed attitude, which I immensely appreciated. &lt;span style="font-weight: bold;"&gt;There is nothing more liberating than thought leaders debunking FUD.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8621851255771049356?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8621851255771049356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8621851255771049356' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8621851255771049356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8621851255771049356'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/03/soas-eulogy-is-liberating.html' title='SOA&apos;s Eulogy is Liberating'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-4622436377091504115</id><published>2009-02-27T18:00:00.005-08:00</published><updated>2009-02-28T11:19:56.042-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Multi-threading'/><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Conversation with a Web Thread</title><content type='html'>&lt;span style="color: rgb(0, 0, 102);"&gt;DD: Hi Mr. Web Thread and thanks for joining us.&lt;/span&gt;&lt;br /&gt;WT: My pleasure. Do you mind if I stay in the pool?&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: Hmm? Sure, why not. So, can you please tell us how is your life nowadays?&lt;/span&gt;&lt;br /&gt;WT: Life has been pretty good. I have become very popular recently and came to perform some massive gigs in highly trafficked web sites. I really like this pool.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: Mmhh, okay. How do you think developers treat you, nowadays?&lt;/span&gt;&lt;br /&gt;WT: Well, I am glad you ask. I think things have improved a lot, thanks to the emergence of concepts like continuations and AJAX. Still, I sometimes get badly beaten by some reckless coders. This pool is awesome.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: So, if you were to give a piece of advice to these programmers, what would it be?&lt;/span&gt;&lt;br /&gt;WT: I think that these developers only need to understand what is the ultimate goal of my life.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: Which is?&lt;/span&gt;&lt;br /&gt;WT: Coming back to that pool!&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: Pardon me?&lt;/span&gt;&lt;br /&gt;WT: You see, I get pulled of this pool very often and sometimes I am forced out of it for too long. In that case, I am like a fish out of water. And when I suffer like that, the whole application suffers.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: So what you are saying is that developers should thrive to let you return to the pool as quick as possible?&lt;/span&gt;&lt;br /&gt;WT: Absolutely.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: Whatever the cost may be?&lt;/span&gt;&lt;br /&gt;WT: Well, it depends of course, but if they can afford letting me return with slightly stale data, that is the thing to do.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: Where would they get such a stale data from?&lt;/span&gt;&lt;br /&gt;WT: Oh, I realize I never introduced you to Mrs. Web Thread, née Cache. She usually takes care of this.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: But ladies, sorry, caches are complex. They require eviction strategies, invalidation messages broadcasts, etc.&lt;/span&gt;&lt;br /&gt;WT: Or not. You can use a simple time-evicted opportunistic cache, provided it matches your business needs.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: Ah, I see, something like a 5 minutes cache.&lt;/span&gt;&lt;br /&gt;WT: Or 5 seconds.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: You got to be kidding me, what's a 5 seconds cache worth?&lt;/span&gt;&lt;br /&gt;WT: Do you have any idea of all the things I can do in 5 seconds? Do you realize that it is an agonizing eternity for me?&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: Well, uh, I guess not. Let us lighten up the debate a little. Now that you are a rock star, thanks to your success in multi-million users web sites, do you get to sign a lot of autographs? Do people recognize you a lot?&lt;/span&gt;&lt;br /&gt;WT: Sure, I can hardly go anywhere without being spotted. But, believe it or not, it still happens that I get mixed up with my cousins.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: Oh, you have cousins?&lt;/span&gt;&lt;br /&gt;WT: Yes, Worker Thread and Background Thread. Sometimes, I get confused with one of them and receive way too much work to do or work that simply does not concern me at all.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: What do you do in that case?&lt;/span&gt;&lt;br /&gt;WT: As I said before: I become grumpy and the whole web tier suffers with me too. I kind of like to share my pain!&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 102);"&gt;DD: OK, Mr. Web Thread, I think it is time we wrap up now. Thanks a lot for your time and sharing your experience with us.&lt;/span&gt;&lt;br /&gt;WT: You are welcome. Now back to the pool.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Splash!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-4622436377091504115?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/4622436377091504115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=4622436377091504115' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4622436377091504115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4622436377091504115'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/02/conversation-with-web-thread.html' title='Conversation with a Web Thread'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-4764966458710765059</id><published>2009-02-27T17:32:00.002-08:00</published><updated>2009-02-27T17:57:45.477-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>Just Read: Statistics Hacks</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.shelfari.com/books/78434"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://ecx.images-amazon.com/images/I/511BfHtF-XL._SL240_.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;More than twenty years after my last statistics class, this book really tasted like a rejuvenating read. It is well structured, with an opening focused on theory followed by numerous applications in all sorts of domains (yes, including poker, though my preferred subject was the &lt;a href="http://en.wikipedia.org/wiki/Drake_equation"&gt;Drake Equation&lt;/a&gt;). As such, the book will stand as a quick reference guide to which the reader will return every now and then.&lt;br /&gt;&lt;br /&gt;Recommended for aging minds in need of a refresher (like mine) or curious minds wanting to learn more about statistics and how relevant they are to their every day's life.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;As a side note, this is the first e-book I bought: I got it under EPUB format, which renders almost flawlessly on my Sony PSR-700 (texts, figures, schemas are good, very large tables are cut though). Kudos to O'Reilly who do a truly great job with their &lt;/span&gt;&lt;a style="font-style: italic;" href="http://oreilly.com/ebooks/"&gt;e-books&lt;/a&gt;&lt;span style="font-style: italic;"&gt;, providing them in three formats&lt;/span&gt; &lt;span style="font-style: italic;"&gt;and not limiting you in the number of times you download them (so I don't even bother backing-up my purchases).&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-4764966458710765059?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/4764966458710765059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=4764966458710765059' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4764966458710765059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4764966458710765059'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/02/just-read-statistics-hacks.html' title='Just Read: Statistics Hacks'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-5931638583418341028</id><published>2009-02-25T18:12:00.003-08:00</published><updated>2009-02-26T20:25:12.879-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><category scheme='http://www.blogger.com/atom/ns#' term='Platform'/><title type='text'>Standards vs. Upgrade pains</title><content type='html'>In &lt;a href="http://memeagora.blogspot.com/2009/01/standards-based-vs-standardized-soa.html"&gt;Standards Based vs. Standardized&lt;/a&gt; Neal Ford develops a very interesting rhetoric that is mainly focused on what he sees being "&lt;span style="font-style: italic;"&gt;wrong with SOA (Service Oriented Architecture) in the way that it's being sold by vendors&lt;/span&gt;", but really touches a vast subject that has many thought provoking ramifications.&lt;br /&gt;&lt;br /&gt;While considering the application upgrades I am involved in or that occur around me, it is clear that applications deployed on standardized platforms have easier upgrade paths. Or have they?&lt;br /&gt;&lt;br /&gt;Let me consider the whole spectrum of applications I am involved with and discuss the related upgrade pains, how standards play a role there and if they are worth the effort. I won't discuss the necessity of upgrading application platforms: I reckon everybody feels the same itch when they see an application running on a platform that is many releases behind its current revision.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Non-standardized&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Neal mentions ESBs as canonical non-standardized platforms, so I will start with them and consider my experience with following Mule versions. Many aspects of Mule are standards-based, from its protocol stacks to the zillions of libraries it is built upon (which I consider as being industry standards). Even its configuration mechanism piggybacks on Spring's schema driven configuration. What is not standardized are Mule's API and configuration syntax. Therefore they tend to evolve quickly, and sometimes drastically, as Mule expands and refines its feature base. Consequently, following Mule versions is not a small feat: it requires a pretty advanced knowledge of the platform to be performed right (and the assistance of extensive unit and integration tests, but everyone has this already, right?). Why would anyone willingly accept to jump through such hoops? Because it is worth it: being exposed to Mule's non-standard aspects is rewarded by a full access to its complete feature set and its full power.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Standardized&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At the other end of the spectrum lies web applications that fully pack their dependencies and can be deployed on pretty much any container that understands their standardized configuration. A typical example is a Spring/Hibernate application deployed on JEE web container, like Tomcat or Jetty. It is to be noted that, even if this kind of applications can have very complex needs, their reliance on the JEE standard is actually quite small: a few entries in web.xml that hook some basic application entry points to the container and that is pretty much it. The rest is not standardized but fully resides in the realm of what the application controls (Spring and Hibernate configurations for example). Hence migrating between different versions or even different implementations of the JEE container is usually a no-brainer.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Somewhat standardized&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Finally, in the middle of the spectrum, we find the applications deployed on platforms where standards fall short of allowing them to easily follow releases. Consider a full fledged JEE application, say deployed on JBoss. In this case, two forces act against the standard. The first one is the limitation in scope of this standard: anything that has been left to the interpretation of the implementor will likely differ enough between major releases to cause troubles. The second force is the fact that the standard itself is a &lt;a href="http://se.ethz.ch/%7Emeyer/publications/OTHERS/scott_meyers/keyhole.pdf"&gt;keyhole&lt;/a&gt; applied against the full range of features of the platform itself: these features are there, accessible, often compelling, and it requires a lot of willpower to refuse to use them directly (by shielding them behind a custom facade) or not at all (by using extra dependencies to get these needed features). These two forces combined usually lead to full-range JEE applications that do not evolve gracefully when their underlying standardized platform is upgraded.&lt;br /&gt;&lt;br /&gt;So, there is a clear trade off between having full access to a platform and being isolated from the disruptive aspects of its evolution over time. It is also true that standards with more teeth are probably needed (OSGi is an interesting one in this matter).&lt;br /&gt;&lt;br /&gt;But everybody knew this already.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-5931638583418341028?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/5931638583418341028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=5931638583418341028' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5931638583418341028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5931638583418341028'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/02/standards-vs-upgrade-pains.html' title='Standards vs. Upgrade pains'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-519639821600944521</id><published>2009-02-22T21:51:00.006-08:00</published><updated>2009-02-22T22:24:49.161-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Off-topic'/><category scheme='http://www.blogger.com/atom/ns#' term='World'/><title type='text'>Two minutes on Ping.fm</title><content type='html'>Always interested in sharing the futility of my own existence, I thought that I could use &lt;a href="http://ping.fm/"&gt;Ping.fm&lt;/a&gt; to broadcast my boredom level (i.e. LinkedIn status) on different channels.&lt;br /&gt;&lt;br /&gt;All went fine until I hit the page for connecting my Ping.fm account to my LinkedIn one. See for yourself:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_wgiUOehXWyI/SaI-HVO6wzI/AAAAAAAAAMw/8oKAT2pmMHQ/s1600-h/pfm-li.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 179px;" src="http://4.bp.blogspot.com/_wgiUOehXWyI/SaI-HVO6wzI/AAAAAAAAAMw/8oKAT2pmMHQ/s400/pfm-li.png" alt="" id="BLOGGER_PHOTO_ID_5305871606675587890" border="0" /&gt;&lt;/a&gt;Seriously, guys, you want the password of my LinkedIn account? Is this really the best we can do for integrating social networks? Are we waiting until the &lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;Wrath of OWASP&lt;/span&gt; falls on us to fix this?&lt;br /&gt;&lt;br /&gt;Then I closed my Ping.fm account.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-519639821600944521?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/519639821600944521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=519639821600944521' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/519639821600944521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/519639821600944521'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/02/two-minutes-on-pingfm.html' title='Two minutes on Ping.fm'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_wgiUOehXWyI/SaI-HVO6wzI/AAAAAAAAAMw/8oKAT2pmMHQ/s72-c/pfm-li.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-1194547393932704779</id><published>2009-02-19T15:32:00.009-08:00</published><updated>2009-04-29T08:48:40.264-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><category scheme='http://www.blogger.com/atom/ns#' term='Multi-threading'/><category scheme='http://www.blogger.com/atom/ns#' term='Pragmatic ESB'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Integration Testing Asynchronous Services</title><content type='html'>Whether you use &lt;a href="http://mulesource.org"&gt;Mule&lt;/a&gt; or &lt;a href="http://www.springsource.org/spring-integration"&gt;another integration framework&lt;/a&gt;, writing integration tests for asynchronous services can be a little tricky, as you may start running assertions in your main test thread while messages are still being processed.&lt;br /&gt;&lt;br /&gt;Suppose you want to ensure that your content based router sends messages to the expected target services. Your integration test suite will consist in sending valid and invalid messages to the input channel in front of this router and check they end-up in the expected destination services.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;But how to be sure that the delivery has happened and it is safe to start asserting values?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The naive solution to this problem consists in:&lt;br /&gt;&lt;pre name="code" class="java"&gt;Thread.sleep(1000);&lt;/pre&gt;&lt;br /&gt;It is naive because it arbitrarily slows down your test suite without giving any guarantee that the message will be delivered. It may work on your machine but the same suite running on a busy integration server will behave very differently: one second may not be enough a wait if the threads handling the message delivery behind the scene are slower than usual.&lt;br /&gt;&lt;br /&gt;A problematic fix to this broken solution consists in:&lt;br /&gt;&lt;pre name="code" class="java"&gt;while (messageNotReceived) Thread.sleep(1000);&lt;/pre&gt;&lt;br /&gt;This is problematic because if, for any reason, the message does not hit the expected service, this loop will hang the test suite for ever. Of course, you can add a counter to limit the loop and reduce the sleep time to be more reactive, but this amounts to re-inventing the wheel when higher level concurrency primitives are ready-made for that.&lt;br /&gt;&lt;br /&gt;Indeed, we can use a countdown latch to hold the main test thread until the message hits the expected service. Here is the code I use for my Mule integration testing:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;&lt;br /&gt;private MuleMessage getMessageReceivedByService(final Runnable testAction,&lt;br /&gt;        final String expectedServiceName) throws Exception {&lt;br /&gt;&lt;br /&gt;    final AtomicReference&lt;MuleEventContext&gt; muleEventContextReference =&lt;br /&gt;            new AtomicReference&lt;MuleEventContext&gt;();&lt;br /&gt;&lt;br /&gt;    final CountDownLatch latch = new CountDownLatch(1);&lt;br /&gt;&lt;br /&gt;    muleContext.registerListener(new FunctionalTestNotificationListener() {&lt;br /&gt;        @Override&lt;br /&gt;        public void onNotification(final ServerNotification notification) {&lt;br /&gt;            if (expectedServiceName.equals(notification.getResourceIdentifier())) {&lt;br /&gt;                final FunctionalTestNotification functionalTestNotification = (FunctionalTestNotification) notification;&lt;br /&gt;                muleEventContextReference.set(functionalTestNotification.getEventContext());&lt;br /&gt;                latch.countDown();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    testAction.run();&lt;br /&gt;&lt;br /&gt;    assertTrue("Message did not reach service on time", latch.await(15,&lt;br /&gt;            TimeUnit.SECONDS));&lt;br /&gt;&lt;br /&gt;    return muleEventContextReference.get().getMessage();&lt;br /&gt;}&lt;br /&gt;&lt;/textarea&gt;&lt;br /&gt;I leverage the notification mechanism of Mule and the capacity its functional test component has to broadcast such an event when it is hit by a message. Though a Mule specific implementation, the design principle I discuss here is applicable to other situations.&lt;br /&gt;&lt;br /&gt;Notice how I pass the triggering action of the test (like sending a message with the MuleClient) as a Runnable to this method. This allows me to prepare a latch and register a listener before calling this Runnable and, then, to wait on the latch until it is lowered. When the execution comes back to the caller method, it can safely assess properties on the received message.&lt;br /&gt;&lt;br /&gt;Obviously, the test is designed so its normal execution leads to a message always hitting the right service. Hence, in practice, the wait on the latch is very short, way under the safeguard timeout of 15 seconds.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;But what if we want to test that no message will hit a particular service?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is when things get tricky with asynchronous testing, because there is not systematic approach to testing the absence of an event when it can occur unpredictably in the future.&lt;br /&gt;&lt;br /&gt;One strategy I use is to turn the problem around and change the negative assertion into a positive one. For example, by always ensuring a message will go somewhere, even if it is a service that sends messages to oblivion. By doing so, instead of testing that a bad message never hits a good service, I test that a bad message hits the oblivion service.&lt;br /&gt;&lt;br /&gt;Do you have other advices to share about asynchronous testing?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-1194547393932704779?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/1194547393932704779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=1194547393932704779' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1194547393932704779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1194547393932704779'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/02/integration-testing-asynchronous.html' title='Integration Testing Asynchronous Services'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-300817373125528429</id><published>2009-01-23T11:45:00.003-08:00</published><updated>2009-01-23T12:12:41.954-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>The Sin of Generalization</title><content type='html'>The more I progress in my journey as a software engineer, the more I realize how our profession suffers from the Sin of Generalization. The good news is that this sin can be fought with a rope and a mast. Let me explain.&lt;br /&gt;&lt;br /&gt;This almost deadly sin manifests itself in two ways:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A tool or a methodology that has been sucessful in one context gets generalized and becomes applied to other contexts, where it ill fits.&lt;/li&gt;&lt;li&gt;A generic platform or framework is created to solve all sorts of needs, while ad hoc solutions would have been more straight to the point.&lt;/li&gt;&lt;/ul&gt;This may sound funny from me, as I am the lead of &lt;a href="http://nxbre.org/"&gt;NxBRE&lt;/a&gt;, a .NET generalized rule engine! The reality is that NxBRE, like all rules engines and al generalized tools, has a sweet spot where its usage makes sense. Outside of this sweet spot, using a generalized tool is in fact counterproductive, because the indiosyncracies it is bringing (limitations, bugs, specific configuration...) outweight its benefits.&lt;br /&gt;&lt;br /&gt;Of course, there is value in re-use and generic tools. The point of the matter is that it is always worth considering the relevance of a generic tool or methodology everytime you intend to use it. This sounds like an obvious statement but experience shows that generalized solutions are as attractive and noxious as &lt;a href="http://simple.wikipedia.org/wiki/Siren"&gt;sirens&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Hence the rope and the mast.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-300817373125528429?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/300817373125528429/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=300817373125528429' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/300817373125528429'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/300817373125528429'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2009/01/sin-of-generalization.html' title='The Sin of Generalization'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8405703307047995718</id><published>2009-01-18T15:19:00.000-08:00</published><updated>2009-01-18T15:20:04.549-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Writings'/><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><title type='text'>Mule in Action, the Making of</title><content type='html'>Now that dust has started to settle, I have some time to reflect on writing &lt;a href="http://muleinaction.com/"&gt;Mule in Action&lt;/a&gt; and share my experience with this process.&lt;br /&gt;&lt;br /&gt;I will spare you the "&lt;span style="font-style: italic;"&gt;it's a long and exhausting process that is a true trial for one's will&lt;/span&gt;", because you already know that such an endeavor requires a personal investment that is beyond whatever time-consuming hobby you could have (that is basically about sacrificing all evenings and Saturdays on the altar of authorship for a solid 6 months).&lt;br /&gt;&lt;br /&gt;A technical book like &lt;a href="http://muleinaction.com/"&gt;Mule in Action&lt;/a&gt; gets its relevance from the richness and correctness of the examples it contains. Inspired by Brian Goetz's experience about writing &lt;a href="http://www.briangoetz.com/blog/?p=51"&gt;Java Concurrency in Practice&lt;/a&gt;, &lt;a href="http://johndemic.blogspot.com/"&gt;John&lt;/a&gt; and I have decided to treat our examples like a full fledged project. For this we have created a &lt;a href="http://code.google.com/p/muleinaction/"&gt;Google code project&lt;/a&gt; and built all the samples with Maven. These examples are sometimes started by a command line script, but the true value resides in the unit and integration tests that cover them.&lt;br /&gt;&lt;br /&gt;These tests are a life saver because the community edition of Mule 2, especially in its early days, was a moving target, with non-backward compatible API changes and deep behavioral alteration occurring between releases. Any time a new version of Mule is released, we upgrade to it and run a full build of the book examples. Anything that breaks signals a potential change in the book itself. But how do we know if the book needs to be changed and where?&lt;br /&gt;&lt;br /&gt;We did not use a code extraction/insertion script, like Brian did, but we decided to enable a complete traceability by tagging our code fragments and keeping this tag along them in a hidden field in the body of the book. This way, whenever we modify the source code, we know if and where the book is affected.&lt;br /&gt;&lt;br /&gt;This leads us to the format of the book itself. We opted for &lt;a href="http://www.docbook.org/"&gt;DocBook&lt;/a&gt;, which is "just" XML backed by a schema. What does this gives us? First, the possibility to &lt;span style="font-family:courier new;"&gt;grep&lt;/span&gt; for a specific code tag or sentence and replace using simple commands. Second, the possibility to &lt;span style="font-family:courier new;"&gt;diff&lt;/span&gt; two versions of the text (because, of course, we store all the chapters and related images in Subversion): this is extremely convenient in a multi-author environment like ours. And, finally, the possibility to use a simple but strict writing environment. Indeed, you do not need a word processor for writing a book: it is just a useless collection of bells and whistles. Any editor with schema validation and a basic spell checker is all you need.&lt;br /&gt;&lt;br /&gt;That is for the tooling but what about the practice itself? I have quickly realized that, like a movie, a book is produced in an out-of-order manner. Trying to write a whole chapter in the reading order is futile and could lead to a very frustrating writer's block. Once I started to accept this idea, writing became way easier, with chapters appearing in the order inspiration was leading me to and backing code samples where being created. Even for a purely technical book, inspiration matters: it is a pretty stubborn animal that goes only the way it wants (am I talking about &lt;a href="http://www.mulesource.org/"&gt;Mule&lt;/a&gt;?) and must not be forced otherwise.&lt;br /&gt;&lt;br /&gt;Finally, I have found that music was an extremely powerful productivity booster. Maintaining a high productivity is essential for such a technical book, which is condemned to premature obsolescence if it is not written within a short period of time. Listening to lyric-less music was for me a way to boostrap my writing sessions, while oftentimes I would have preferred to call the day over and get some rest!&lt;br /&gt;&lt;br /&gt;We struggled hard to stay away from writing a user guide, which is &lt;a href="http://mulesource.org/display/MULE2USER/Home"&gt;available on-line&lt;/a&gt; anyway, and opted to focus on practical examples touching most of the common and advanced usage of this ESB. Hopefully, the book will prove good enough for our readers to get both a deep and wide coverage of Mule.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8405703307047995718?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8405703307047995718/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8405703307047995718' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8405703307047995718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8405703307047995718'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/12/mule-in-action-making-of.html' title='Mule in Action, the Making of'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-297679708081253561</id><published>2008-12-31T17:35:00.001-08:00</published><updated>2008-12-31T17:36:58.025-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Beware Phony Model Objects!</title><content type='html'>While I am refactoring huge amounts of code out of EJB2 (and trying not to break too much things), I have noticed a bad design pattern that is so noxious I thought I should blog about it.&lt;br /&gt;&lt;br /&gt;I call this the &lt;span style="font-weight: bold;"&gt;Phony Model Objects&lt;/span&gt; (PMO) antipattern.&lt;br /&gt;&lt;br /&gt;It basically amounts to sharing as first class model objects entities that should never be publicly exposed. These bad citizens may look inocuous at first glance. In fact, they oftentimes carry a deep functional dependency on the technical framework they depend from or are subject to change at a different pace than actual domain objects would do it.&lt;br /&gt;&lt;br /&gt;Interestingly I have found that all these PMOs are generated: whether they are EJB2 artifacts (home interfaces, entity beans, value objects, primary keys...) or web service client stubs. This re-enforces the idea that they are by-products and should be treated as such.&lt;br /&gt;&lt;br /&gt;So, if you return or accept this kind of PMOs in public methods, do not wait and immediately refactor your code to share only proper domain model objects and keep the phony ones hidden behind the surface of your API.&lt;br /&gt;&lt;br /&gt;This will eventually save you a lot of pain and efforts when the technical framework to which your PMOs happen to be coupled to will disappear and you will have to move away from them. Trust me on that one!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-297679708081253561?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/297679708081253561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=297679708081253561' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/297679708081253561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/297679708081253561'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/12/beware-phony-model-objects.html' title='Beware Phony Model Objects!'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6833676805854165942</id><published>2008-12-23T12:11:00.002-08:00</published><updated>2008-12-23T12:14:54.590-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><category scheme='http://www.blogger.com/atom/ns#' term='My OSS'/><title type='text'>MuleCast: A Conversation with the creator of the JCR Transport</title><content type='html'>Ross Mason has interviewed me (again) about the &lt;a href="http://www.mulesource.org/display/JCR/Home"&gt;JCR transport for Mule&lt;/a&gt;. I also had a chance to give a few words about the brand new &lt;a href="http://www.mulesource.org/display/COMMONRETRYPOLICIES"&gt;Common Retry Policies module&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://blog.mulesource.org/2008/12/mulecast-a-conversation-with-the-creator-of-the-jcr-transport/"&gt;Enjoy&lt;/a&gt;!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6833676805854165942?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6833676805854165942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6833676805854165942' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6833676805854165942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6833676805854165942'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/12/mulecast-conversation-with-creator-of.html' title='MuleCast: A Conversation with the creator of the JCR Transport'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-651880454957756942</id><published>2008-12-20T11:52:00.002-08:00</published><updated>2008-12-21T09:04:42.574-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>A month of e-reading</title><content type='html'>After months of procrastination, I have decided to give a try to e-ink and go paperless as much as I can. I have been using a &lt;a href="http://www.sonystyle.ca/commerce/servlet/ProductDetailDisplay?storeId=10001&amp;amp;catalogId=10001&amp;amp;langId=-1&amp;amp;productId=1005736"&gt;Sony PRS-700&lt;/a&gt; for a month now and I must say I am really happy with it.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://i63.photobucket.com/albums/h122/ddossot/misc/Mia-Ereader.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 301px; height: 384px;" src="http://i63.photobucket.com/albums/h122/ddossot/misc/Mia-Ereader.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-style: italic;"&gt;This picture does not render the actual contrast and precision of the e-ink surface.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;I opted for the Sony reader because of its openness: you plug it in an USB port and voila! You are free to drag and drop files into the reader.&lt;br /&gt;&lt;br /&gt;I used it in all sorts of lighting and places: in the dim light and shaky environment of public transportation to the comfort of a sun lit office. So far I successfully used it for:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Paperless meetings: instead of printing meetings' material, I now upload them to my reader.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Long blog entries: I simply can not read long articles on a computer screen so I use the reader for long blog posts.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Reference guides: the search feature of the reader is convenient to find passages of reference guides or technical books (like &lt;a href="http://muleinaction.com/"&gt;Mule in Action&lt;/a&gt;).&lt;/li&gt;&lt;li&gt;Book reviews: instead of printing the books I am reviewing, I now upload them to the reader. The annotation feature is a little too slow to take long notes on pages but fast enough to attach a few words that are reminders for building the final review.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Full fledged e-book of course! So far, I have only read a few technical e-books from InfoQ. Hundreds of pages later, I can tell it is really a great reading experience. I sometimes have to zoom on a schema, but most of the time using the landscape orientation guarantees a seamless reading.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Despite wishing a bigger screen for a smaller price (it's Christmas time after all), my only concrete suggestion to Sony would be the addition of a smart zoom mode that would automatically trim all the useless white margins that oftentimes waste PDFs' page estate.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-651880454957756942?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/651880454957756942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=651880454957756942' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/651880454957756942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/651880454957756942'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/12/month-of-e-reading.html' title='A month of e-reading'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://i63.photobucket.com/albums/h122/ddossot/misc/th_Mia-Ereader.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-4088444047658421184</id><published>2008-12-15T21:01:00.002-08:00</published><updated>2008-12-15T21:18:01.424-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>How To Guarantee That Your Software Will Suck</title><content type='html'>You may have recently read two eponymic &lt;a href="http://blog.objectmentor.com/articles/2008/12/08/how-to-guarantee-that-your-software-will-suck"&gt;blog&lt;/a&gt; &lt;a href="http://www.codethinked.com/post/2008/12/07/How-To-Guarantee-That-Your-Software-Will-Suck.aspx"&gt;posts&lt;/a&gt; about this crucial subject, so I won't give you ten more ways to suck at programming but just one.&lt;br /&gt;&lt;br /&gt;Here it is:&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;"&gt;Don't critique your code.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;If you never ever have a critique view of your code, you are on your way to write software that sucks.&lt;br /&gt;&lt;br /&gt;People who pair program may chuckle: they already have a continuous critique process that helps producing high quality code. People who practice code reviews may chuckle too: they already have a process (and, often, tools) for ensuring code is properly discussed.&lt;br /&gt;&lt;br /&gt;So what is left for those who do not pair program or practice code review? The same applies: whenever you come back to your own code, critique it. Oftentimes, while adding a new feature, you will realize that a particular design is convoluted, a class is ill named or a method is hard to read.&lt;br /&gt;&lt;br /&gt;Do not fall into complacency with your own code: love it, hate it, critique it, refactor it!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-4088444047658421184?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/4088444047658421184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=4088444047658421184' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4088444047658421184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4088444047658421184'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/12/how-to-guarantee-that-your-software.html' title='How To Guarantee That Your Software Will Suck'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8692869871574393101</id><published>2008-12-13T15:23:00.006-08:00</published><updated>2008-12-13T15:37:28.307-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Software That Kills</title><content type='html'>In the latest installment of his monthly &lt;a href="http://www.computer.org/portal/site/software/"&gt;IEEE Software&lt;/a&gt; column, Philippe Kruchten asks about the relevance of &lt;a href="http://www.computer.org/portal/cms_docs_software/software/homepage/2008/s6car.pdf"&gt;licensing software engineers&lt;/a&gt;. In this article, he states:&lt;br /&gt;&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;The only purpose of licensing software engineers is to protect the public.&lt;/blockquote&gt;&lt;br /&gt;He then details the reasons why it makes sense to license people who write or certify “software-that-kills”.&lt;br /&gt;&lt;br /&gt;Even if I am not licensed (and may never be), I fully agree with his positions. In fact, I feel compelled to ask why limiting licensing only to software that kills people. &lt;span style="font-weight: bold;"&gt;What about software that kills businesses?&lt;/span&gt; &lt;span style="font-weight: bold;"&gt;What about software that kills privacy?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Except when human lives are in jeopardy, software developers are basically free to do whatever they want when they build an application. Businesses and end users are left to goodwill and luck when it comes to receiving from software developers the professional standards they can legitimately expect from them.&lt;br /&gt;&lt;br /&gt;Should licensed software engineers be engaged to at least review the design and architecture of software that can kill businesses or privacy? Would it be enough to restore trust in a profession from which the common wisdom is to expect so few?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8692869871574393101?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8692869871574393101/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8692869871574393101' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8692869871574393101'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8692869871574393101'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/12/software-that-kills.html' title='Software That Kills'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-4793844081385255627</id><published>2008-12-13T13:13:00.001-08:00</published><updated>2008-12-13T13:16:52.784-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><title type='text'>A new module for Mule!</title><content type='html'>I am happy to announce the very first release of the Common Retry Policies module for Mule 2.&lt;br /&gt;&lt;br /&gt;The goal of this project is to encourage the Mule community to nurture a set of production grade retry policies. At this point, the available policies have been tested only with a limited set of transports (JCR with JBossMQ and ActiveMQ).&lt;br /&gt;&lt;br /&gt;I expect the feedback of the community under several forms:&lt;br /&gt;&lt;p&gt; &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Configuration samples that worked for you,&lt;/li&gt;&lt;li&gt;Bug reports, fixes and improvement patches,&lt;/li&gt;&lt;li&gt;Features requests.&lt;/li&gt;&lt;/ul&gt; Visit  &lt;a class="jive-link-external" href="http://www.mulesource.org/display/COMMONRETRYPOLICIES/Home"&gt;the project page&lt;/a&gt;  for configuration samples, links to the downloadable artifacts (Maven, standalone distribution) and to JIRA.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-4793844081385255627?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/4793844081385255627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=4793844081385255627' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4793844081385255627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4793844081385255627'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/12/new-module-for-mule.html' title='A new module for Mule!'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8712241782168252668</id><published>2008-12-04T10:42:00.004-08:00</published><updated>2008-12-04T10:47:22.317-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='World'/><title type='text'>Hope in hardship?</title><content type='html'>&lt;blockquote&gt;&lt;span style="font-style: italic;"&gt;Hard times provide opportunity for change. Can't afford for a project to fail? Applying agile development principles can help. Doing projects with fewer people? Applying agile development principles can help. Limited resources throw options in sharp relief where a surfeit of resources makes putting off change easier.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;Kent Beck, &lt;a href="http://www.linkedin.com/newsArticle?viewDiscussion=&amp;amp;articleID=19153559&amp;amp;gid=1010877&amp;amp;goback=.hom.ana_1010877_1228415448004_1"&gt;posted in Agile Interest Group Luxembourg&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span style="font-style: italic;"&gt;Right now every organisation is assessing all their costs (most companies have cut between 10-30% of their workforce). In this process, CIO and Managers are being asked to do more with less, to keep the engine running with half the budget. This means they have to look to open source.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;Ross Mason, &lt;a href="http://rossmason.blogspot.com/2008/12/open-source-upturn-in-economic-downturn.html"&gt;from his blog&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;These sound like there is a future for agile minded open source addicted developers out there. Time will tell...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8712241782168252668?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8712241782168252668/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8712241782168252668' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8712241782168252668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8712241782168252668'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/12/hope-in-hardship.html' title='Hope in hardship?'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-7671253266885068296</id><published>2008-11-26T14:08:00.002-08:00</published><updated>2008-11-26T14:29:45.765-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Conferences'/><title type='text'>Last Night Eclipse Demo Camp</title><content type='html'>I attended my first &lt;a href="http://wiki.eclipse.org/Eclipse_DemoCamps_November_2008/Vancouver"&gt;Eclipse Demo Camp last night in Vancouver&lt;/a&gt; and it was really a great event! Of course, the profusion of food and beer offered by the Eclipse Foundation at the end of the evening surely helped building such a great impression...&lt;br /&gt;&lt;br /&gt;The whole evening was driven by the &lt;a href="http://tasktop.com/"&gt;Tasktop&lt;/a&gt; guys, which gave us a chance to get a feel of the interesting ecosystem that is growing around Mylyn. I would like to turn the spotlight on two projects which are worth discovering on your own:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://programmerproductivity.info/tripoli/index.php"&gt;Tripoli&lt;/a&gt;, an EclEmma-powered code coverage diff tool that allows you to pinpoint issues in an efficient manner.&lt;/li&gt;&lt;li&gt;&lt;a href="http://pleiad.dcc.uchile.cl/tod/"&gt;TOD&lt;/a&gt;, a so-called omniscient debugger that allows you to do back-in-time debugging without a DeLorean (which made me think a lot about what &lt;a href="http://www.replaysolutions.com/"&gt;ReplaySolutions&lt;/a&gt; is building).&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;These two projects are brilliant illustrations that academia can produce concrete results in software engineering. That is surely encouraging for practitioners!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;As a closing note, if you happen to be in Luxembourg tomorrow evening be sure to hit the &lt;/span&gt;&lt;a style="font-style: italic;" href="http://wiki.eclipse.org/Eclipse_DemoCamps_November_2008/Luxembourg"&gt;Eclipse Demo Camp&lt;/a&gt;&lt;span style="font-style: italic;"&gt; over there. You will have a chance to see &lt;/span&gt;&lt;a style="font-style: italic;" href="http://zepag.blogspot.com/"&gt;Pierre-Antoine&lt;/a&gt;&lt;span style="font-style: italic;"&gt; and &lt;/span&gt;&lt;a style="font-style: italic;" href="http://fdewasmes.free.fr"&gt;Fabrice&lt;/a&gt;&lt;span style="font-style: italic;"&gt; live, which is really worth the trip!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-7671253266885068296?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/7671253266885068296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=7671253266885068296' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7671253266885068296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7671253266885068296'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/11/last-night-eclipse-demo-camp.html' title='Last Night Eclipse Demo Camp'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-1948624113740010044</id><published>2008-11-24T12:32:00.003-08:00</published><updated>2008-11-26T21:48:51.816-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Writings'/><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><title type='text'>Mulecast: “Mule in Action” book interview</title><content type='html'>Ross Mason has interviewed John D'Emic and I about &lt;a href="http://muleinaction.com/"&gt;Mule in Action&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you &lt;a href="http://blog.mulesource.org/2008/11/mulecast-mule-in-action-book-interview/"&gt;listen to the podcast&lt;/a&gt;, you will get a 27% discount voucher as a compensation for ear damages caused by my broken English.&lt;br /&gt;&lt;br /&gt;Isn't life a bliss?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-1948624113740010044?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/1948624113740010044/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=1948624113740010044' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1948624113740010044'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1948624113740010044'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/11/mulecast-mule-in-action-book-interview.html' title='Mulecast: “Mule in Action” book interview'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6786509608056703586</id><published>2008-11-17T13:01:00.002-08:00</published><updated>2008-11-17T13:32:32.693-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Seven Years To Rot</title><content type='html'>So here we are, seven years after the &lt;a href="http://agilemanifesto.org/"&gt;Manifesto&lt;/a&gt;, and the webersphere is pontificating about the decline of &lt;a href="http://www.infoq.com/news/2008/11/decline-of-agile"&gt;agile&lt;/a&gt;, to the point that &lt;a href="http://blog.objectmentor.com/articles/2008/11/16/dirty-rotten-scrumdrels"&gt;Uncle Bob has hard time containing his anger&lt;/a&gt; in front of such a display of nonsense and dishonesty.&lt;br /&gt;&lt;br /&gt;What is going on with agile? After seven years of existence (&lt;span style="font-style: italic;"&gt;I know, the techniques and approaches agile promotes predate the Manifesto&lt;/span&gt;), has it started to rot?&lt;br /&gt;&lt;br /&gt;Some suggest that agile is following the &lt;a href="http://en.wikipedia.org/wiki/Hype_cycle"&gt;Gartner hype-cycle&lt;/a&gt; and has now past its "peak of inflated expectations":&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/en/thumb/9/94/Gartner_Hype_Cycle.svg/400px-Gartner_Hype_Cycle.svg.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 260px;" src="http://upload.wikimedia.org/wikipedia/en/thumb/9/94/Gartner_Hype_Cycle.svg/400px-Gartner_Hype_Cycle.svg.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Of course, there is hype around agile and the diatribe of some of its fanatics can be a little over the top. But I think that the current "decline" in agile is not due to some disillusionment.&lt;br /&gt;&lt;br /&gt;I think this so-called "decline" comes from the numerous software sweat shops and less-than average programmers who started to pretend they do "agile" without changing anything in their craftsmanship. &lt;span style="font-weight: bold;"&gt;Instead of a disillusionment, agile suffers from dilution.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Hopefully, people will be able to &lt;span class="illustration"&gt;sort the wheat from the chaff and debunk these agile fraudsters.&lt;/span&gt; When this will happen, agile will start climbing its "slope of enlightenment".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6786509608056703586?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6786509608056703586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6786509608056703586' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6786509608056703586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6786509608056703586'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/11/seven-years-to-rot.html' title='Seven Years To Rot'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-106501582094314544</id><published>2008-11-13T19:54:00.004-08:00</published><updated>2008-11-13T20:42:39.198-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>The Path of Least Resistance</title><content type='html'>While fighting with monsters of legacy code, I have kept thinking of all the possible reasons why developers would end up building such a man-made hell. My capacity to analyze the situation and figure out possible causes is limited to the knowledge of the external forces that these developers where exposed to. For what was happening inside of them, I am limited to build analogies after looking at my own battles and shortcomings.&lt;br /&gt;&lt;br /&gt;I have been trying to distill a unique question. Here it is: &lt;span style="font-weight: bold;"&gt;why would a developer choose to the walk the path of least resistance?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Though skill, experience and professional standards are factors at play, I do not think they can explain the whole picture. Deadline pressure certainly encourage to cut corners and follow the easiest and dirtiest path. But the crux of the problem is not there. It is in the &lt;span style="font-weight: bold;"&gt;resistance&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;What is this resistance anyway? It is multiform and hard to characterize. Any developer surely has felt at least once the slight despair it entails: you want to progress and get blocked by a wall of resistance that is not insurmountable but would incur a great cost in term of work disturbance.&lt;br /&gt;&lt;br /&gt;Here are a few example of the outcome produced by such a resistance:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Teams entrenched behind layers of management feel encouraged not to wait for &lt;span style="font-style: italic;"&gt;the others &lt;/span&gt;to do something that they need and end-up building sub-optimal solutions with what they have now.&lt;/li&gt;&lt;li&gt;High cost of database changes can drive developers to extremes like the reuse of existing fields, the use of inadequate field types or the storage of serialized objects in BLOBs when a few extra columns would have done the trick.&lt;/li&gt;&lt;li&gt;Long feedback loops between a code change and the result of testing orient developers towards implementing new features with minimal changes to existing code, which ends up with code duplication, spaghetti plates and design-less applications.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt; Facing resistance, it is very hard for a developer to postpone the completion of his work because, when he is building something, he is driven by the goal to reach and tend to disregard warning signs. This is the same challenge that airplane pilots face when their guts tell them to stay on the ground or to turn back but their focus on reaching the planned destination make them fly into trouble. The only difference is that, oftentimes, these pilots will not survive their decision to ignore warnings, while in software we can move on to a new job and pretend nothing happened.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Taking intelligent decisions while being goal driven is hard. Everybody knows that the path of least resistance is rarely the best one. Alas, we walk it and, I suspect, not by laziness but by renouncement.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-106501582094314544?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/106501582094314544/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=106501582094314544' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/106501582094314544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/106501582094314544'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/11/path-of-least-resistance.html' title='The Path of Least Resistance'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-17465786305325614</id><published>2008-11-11T18:53:00.001-08:00</published><updated>2008-11-11T19:30:20.679-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>Just Read: Facts and Fallacies of Software Engineering</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.shelfari.com/books/122116"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://ecx.images-amazon.com/images/I/41FQDEB4DNL._SL240_.jpg" alt="" border="0" /&gt;&lt;/a&gt;Sometimes, when I read a book, I look at the publication date and wonder out loud: "what on earth was I doing this year to miss this one?". This is exactly what happened while reading this book from by Robert L. Glass. What on earth was I doing in 2002 to have missed such an excellent book?&lt;br /&gt;&lt;br /&gt;Known as the &lt;span style="font-weight: bold;"&gt;F-Book&lt;/span&gt;, after its original title proposition ("&lt;i&gt;Fifty-Five Frequently Forgotten Fundamental Facts (and a Few Fallacies) about Software Engineering&lt;/i&gt;", which thankfully was not kept by the editor), this dense book is truly the sum of all truths and untruths about software engineering.&lt;br /&gt;&lt;br /&gt;This book is really invaluable as an aid for debunking hype of all sorts and performing &lt;a href="http://ddossot.blogspot.com/2008/11/reality-check-levels.html"&gt;reality checks&lt;/a&gt; on tools and methods that oftentimes are dumped on software engineers with the promise of a brighter future (that never materializes).&lt;br /&gt;&lt;br /&gt;With half a century in the field, Robert has seen it all and heard it all already. If you think your problems or questions are new or unique, then read this book and keep it, because you will have to come back to it and quote it whenever you will need to challenge a snake-oil vendors or an ivory tower methodologists (pretty much like you do with the &lt;a href="http://c2.com/cgi/wiki?AntiPatternsCatalog"&gt;anti-patterns catalog&lt;/a&gt; for development mispractices).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-17465786305325614?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/17465786305325614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=17465786305325614' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/17465786305325614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/17465786305325614'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/11/just-read-facts-and-fallacies-of.html' title='Just Read: Facts and Fallacies of Software Engineering'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2510856543246200589</id><published>2008-11-10T19:55:00.001-08:00</published><updated>2008-11-11T19:04:11.366-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Platform'/><category scheme='http://www.blogger.com/atom/ns#' term='MS'/><title type='text'>Silver Still Very Light</title><content type='html'>I have just switched to the latest version of &lt;a href="http://www.mono-project.com/Moonlight"&gt;Moonlight&lt;/a&gt;, the port of Microsoft Silverlight on Linux, and the least I can say is that things have significantly progressed &lt;a href="http://ddossot.blogspot.com/2008/08/silverfight.html"&gt;since the last time I tried&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So far, I have found only one site of use whose Silverlight application runs fine on Linux: the &lt;a href="http://www.ryanair.com/site/EN/dests.php"&gt;Ryanair destination map&lt;/a&gt;. Though the plug-in reports a rendering speed of close to 100 FPS, the zooming and panning is still way behind what pure JavaScript or Flash applications provide. But it is very impressive already.&lt;br /&gt;&lt;br /&gt;The only problem seems to reside in the Silverlight detection algorithm used by most of the sites. Most of them give me the Redmond finger:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_wgiUOehXWyI/SRjGTPl0ZuI/AAAAAAAAAKc/-9zZV-XcGbo/s1600-h/silverschnitzed.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 221px; height: 65px;" src="http://3.bp.blogspot.com/_wgiUOehXWyI/SRjGTPl0ZuI/AAAAAAAAAKc/-9zZV-XcGbo/s320/silverschnitzed.png" alt="" id="BLOGGER_PHOTO_ID_5267177798114764514" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;... while Moonlight is there and ready to chew XAML and render it! Too bad, I would like to see more of these sites and keep track on how this runner up technology will compete with the ones already in place.&lt;br /&gt;&lt;br /&gt;At the end of the day, I have no doubt Silverlight/Moonlight can become a credible alternative to the current RIA browser-side technologies. &lt;span style="font-weight: bold;"&gt;My main concern is that sloppy developers may create Silverlight-powered sites that will only work with a limited set of platforms (browsers, OSes), which would be a regression from the current state of the web nation.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2510856543246200589?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2510856543246200589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2510856543246200589' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2510856543246200589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2510856543246200589'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/11/silver-still-very-light.html' title='Silver Still Very Light'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_wgiUOehXWyI/SRjGTPl0ZuI/AAAAAAAAAKc/-9zZV-XcGbo/s72-c/silverschnitzed.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-1948727923918215549</id><published>2008-11-08T09:47:00.003-08:00</published><updated>2008-11-11T19:04:04.553-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Off-topic'/><title type='text'>Where the hell is... Alineo?</title><content type='html'>After &lt;a href="http://www.wherethehellismatt.com/"&gt;Matt and his little dance&lt;/a&gt;, my brother in law, of &lt;a href="http://voilasvn.com/"&gt;VoilaSVN&lt;/a&gt; fame, has decided to go freelining worldwide.&lt;br /&gt;&lt;br /&gt;Two episodes so far: the classic grand Canyon and the way more exotic Luxembourg.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://vimeo.com/2185384"&gt;Enjoy&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-1948727923918215549?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/1948727923918215549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=1948727923918215549' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1948727923918215549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1948727923918215549'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/11/where-hell-is-alineo.html' title='Where the hell is... Alineo?'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-7732484203154418844</id><published>2008-11-07T13:25:00.004-08:00</published><updated>2008-11-11T19:03:57.067-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>Reality Check Levels</title><content type='html'>I am in a "question everything" phase. Maybe it is a side-effect of reading the excellent &lt;a href="http://www.amazon.com/Facts-Fallacies-Software-Engineering-Development/dp/0321117425"&gt;F-book&lt;/a&gt; (review coming soon) or the outcome of learning about the software &lt;a href="http://ddossot.blogspot.com/2008/10/in-latest-edition-of-excellent-ieee.html"&gt;half-life hypothesis&lt;/a&gt;? All in all, I am more and more dubious about what I read and hear about in the field of software. I have grown tired of half-baked ideas (including mine) that present possibilities as realities and niche solutions as widely applicable ones.&lt;br /&gt;&lt;br /&gt;It seems this is natural: smart people have started to &lt;a href="http://jim.webber.name/2008/10/05/fdfe86e2-3679-4540-b006-b9f10c02b3f8.aspx"&gt;change their views on important subjects&lt;/a&gt;. Since I am not that smart, I would like reviewers of articles and publications to add something like the color-coded terrorist threat level to indicate the reality-check level of what I am reading.&lt;br /&gt;&lt;br /&gt;That could be something like:&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-weight: bold; color: rgb(255, 0, 0);"&gt;RC0&lt;/span&gt;: This is highly hypothetical material. Mainly works in the vendor's environment, on the open source committer's laptop or in the researcher's lab.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(255, 153, 0);"&gt;RC1&lt;/span&gt;: This plays well in the F100 or governmental field. Complex committee-driven years-long BDUF-minded expensive concepts can be applied here. But nowhere else.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(0, 153, 0);"&gt;RC3&lt;/span&gt;: This is the field of pragmatists. The ideas, methodologies or products are based on simple, well-established and proven concepts.&lt;/blockquote&gt;&lt;br /&gt;Like the threat level, this scale is coarse and over simplistic. Would you like it anyway? Would you had more levels?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-7732484203154418844?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/7732484203154418844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=7732484203154418844' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7732484203154418844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7732484203154418844'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/11/reality-check-levels.html' title='Reality Check Levels'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-1815927192477188199</id><published>2008-11-06T19:41:00.003-08:00</published><updated>2008-11-11T19:03:52.225-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Legacy Tests</title><content type='html'>In &lt;a href="http://www.amazon.com/Working-Effectively-Legacy-Robert-Martin/dp/0131177052"&gt;Working Effectively with Legacy Code&lt;/a&gt;, Michael Feathers states that, for him, "&lt;i&gt;legacy code&lt;/i&gt; is simply code without tests". As he says it himself, he has "gotten some grief for this definition". I can understand why.&lt;br /&gt;&lt;br /&gt;I have come to deal with some legacy code monsters recently and came to realize that this code had tests written for it. So could it be that this code was not legacy after all?&lt;br /&gt;&lt;br /&gt;After a closer inspection, the truth finally came out:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;the test coverage is very low (less than 30%),&lt;/li&gt;&lt;li&gt;the tests explore counter-intuitive paths (for example, just the unhappy ones),&lt;/li&gt;&lt;li&gt;the tests themselves are monstrous (created in what looks like a copy/paste spree),&lt;/li&gt;&lt;li&gt;they overuse mocks in a lax manner (many are not verified at tear down),&lt;/li&gt;&lt;li&gt;they do not verify the complete state after execution (no validation of indirect outputs like request and session attributes),&lt;/li&gt;&lt;li&gt;and, corollary of the legacy framework the code targets (EJB 2), full correctness can only be proven when deployed in an application container.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;I immediately thought of chapter 9 of Uncle Bob's &lt;a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882"&gt;Clean Code&lt;/a&gt;, where he advocates that unit tests should be written with the same care than for actual code. The tearful hours I spend refactoring these tests so I can then refactor the code they are supposed to exercise, are a good testimony to this imperious necessity. &lt;span style="font-weight: bold;"&gt;Keep tests clean!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Else you will end up with nearly worthless legacy tests.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-1815927192477188199?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/1815927192477188199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=1815927192477188199' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1815927192477188199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1815927192477188199'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/11/legacy-tests.html' title='Legacy Tests'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-625575081490209225</id><published>2008-11-04T12:42:00.003-08:00</published><updated>2008-11-26T21:48:51.818-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Writings'/><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><title type='text'>Two third of a Mule in Action</title><content type='html'>I am happy to report that two third of &lt;a href="http://www.manning.com/affiliate/idevaffiliate.php?id=1054_135"&gt;Mule in Action&lt;/a&gt; is now available from Manning's Early Access Program.&lt;br /&gt;&lt;br /&gt;If you were deferring buying the book, now is a great time to part from a few bucks and get it! Indeed, you will find in these 280 pages a lot of practical knowledge about &lt;a href="http://mulesource.org/"&gt;Mule&lt;/a&gt; that John and I have put together for your utmost enjoyment!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.manning.com/affiliate/idevaffiliate.php?id=1054_135"&gt;&lt;br /&gt;&lt;/a&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://www.manning.com/affiliate/idevaffiliate.php?id=1054_135"&gt;&lt;img src="http://lh5.ggpht.com/_wgiUOehXWyI/SRCyzQ4HG0I/AAAAAAAAAJ8/-1jDkSjFehY/MuleInAction.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;And just to thank you for spending your time reading this blog, I will share a little secret with you. If you use the &lt;span style="font-weight: bold;"&gt;aupromo25&lt;/span&gt; promo code when &lt;a href="http://www.manning.com/affiliate/idevaffiliate.php?id=1054_135"&gt;buying the book&lt;/a&gt;, you will get 25% off the price. But please, don't repeat it.&lt;br /&gt;&lt;br /&gt;Finally, just so you don't think it is all about money, you can always &lt;a href="http://code.google.com/p/muleinaction/"&gt;get the source code for the book&lt;/a&gt; for free. That is zero Dollar, which is also zilch Euro and no much more of any other currency you happen to have in your pocket.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-625575081490209225?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/625575081490209225/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=625575081490209225' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/625575081490209225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/625575081490209225'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/11/two-third-of-mule-in-action.html' title='Two third of a Mule in Action'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_wgiUOehXWyI/SRCyzQ4HG0I/AAAAAAAAAJ8/-1jDkSjFehY/s72-c/MuleInAction.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6643970911810862211</id><published>2008-11-01T17:34:00.002-07:00</published><updated>2008-11-01T17:37:35.880-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='My OSS'/><title type='text'>JBound 1.1 is out</title><content type='html'>I have just released &lt;a href="http://www.assembla.com/spaces/jbound/documents/dff-scQhur3AwJab7jnrAJ/download/jbound-1.1.jar"&gt;version 1.1 of JBound&lt;/a&gt;, my simple utility that performs boundary checks on domain model objects.&lt;br /&gt;&lt;br /&gt;This new release features native support for more JDK data types and the possibility to register custom data types.&lt;br /&gt;&lt;br /&gt;Consult the daunting &lt;a href="http://jbound.org"&gt;one page user guide&lt;/a&gt; for more information.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6643970911810862211?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6643970911810862211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6643970911810862211' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6643970911810862211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6643970911810862211'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/11/jbound-11-is-out.html' title='JBound 1.1 is out'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6487895312217562036</id><published>2008-10-24T17:16:00.002-07:00</published><updated>2008-10-24T17:18:53.401-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>SpringSource's Elitism</title><content type='html'>SpringSource community is elitist and despises juniors. Here is the captcha I just go on their &lt;a href="http://forum.springframework.org"&gt;forums&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_wgiUOehXWyI/SQJluAzfm3I/AAAAAAAAAIk/juKamWSIYa4/s1600-h/useless-junior.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 152px;" src="http://4.bp.blogspot.com/_wgiUOehXWyI/SQJluAzfm3I/AAAAAAAAAIk/juKamWSIYa4/s320/useless-junior.png" alt="" id="BLOGGER_PHOTO_ID_5260879155886529394" border="0" /&gt;&lt;/a&gt;Why so much hatred? Seriously guys?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6487895312217562036?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6487895312217562036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6487895312217562036' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6487895312217562036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6487895312217562036'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/10/springsources-elitism.html' title='SpringSource&apos;s Elitism'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_wgiUOehXWyI/SQJluAzfm3I/AAAAAAAAAIk/juKamWSIYa4/s72-c/useless-junior.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2928357395594575002</id><published>2008-10-24T14:52:00.003-07:00</published><updated>2008-10-24T15:17:59.865-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Half Life And No Regrets</title><content type='html'>In the latest edition of the excellent &lt;a href="http://www.computer.org/portal/site/software/"&gt;IEEE Software&lt;/a&gt; magazine, the non less excellent &lt;a href="http://www.kruchten.org"&gt;Philippe Kruchten&lt;/a&gt; has conjectured about the existence of a &lt;a href="http://www.computer.org/portal/cms_docs_software/software/homepage/2008/s5car.pdf"&gt;five years half-life for software engineering ideas&lt;/a&gt;. That would mean that 50% of our current fads would be gone within five years.&lt;br /&gt;&lt;br /&gt;Though not (yet) backed by any hard numbers, his experience (as mine and yours) suggest that this is most probably true.&lt;br /&gt;&lt;br /&gt;All in all, the sheer idea of such an half-life decay pattern helps letting obsolete knowledge go without regret. It is fine to forget everything about EJBs and code with POJOs. JavaBeans are evil: you can come back to pure OO development. You can bury your loved-hated-O/R-mapper skillset in favor of writing efficient SQL.  It is OK to drop the WS-Death* for REST (&lt;span style="font-style: italic;"&gt;this one is purposefully provocative, if a WS-nazi reads this blog I am dead&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;Unlearning things that were so incredibly painful to learn may feel like a waste but it is not. This half-life decay is in fact great news because it translates into less knowledge overload and more focus on what matters... or, unfortunately, the adoption of new short-lived fads! And the latter is the scariest part. &lt;span style="font-weight: bold;"&gt;How much about what we are currently learning will survive more than five years?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Nothing platform or even language specific, I would say. But sound software engineering practices will remain: building elevated personal and professional standards, treasuring clean code, challenging our love for hype with the need for pragmatism...&lt;br /&gt;&lt;br /&gt;This is where our today's investment must be: in the things that last.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2928357395594575002?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2928357395594575002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2928357395594575002' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2928357395594575002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2928357395594575002'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/10/in-latest-edition-of-excellent-ieee.html' title='Half Life And No Regrets'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2824114550454127644</id><published>2008-10-24T13:37:00.003-07:00</published><updated>2010-06-30T16:45:09.574-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>Just Read: The Productive Programmer</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.shelfari.com/books/4121984/The-Productive-Programmer-%28Theory-in-Practice-%28O-Reilly%29%29"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://ecx.images-amazon.com/images/I/61dx4Iu-fyL._BO2,204,203,35,-76_AA300_SH20_OU01_.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;In this concise book, Neal Ford shares his hard gained real world experience with software development. Because he is consulting for the &lt;a href="http://thoughtworks.com"&gt;best&lt;/a&gt;, his experience is diverse and rich, hence definitively worth reading.&lt;br /&gt;&lt;br /&gt;This book feels a lot like "&lt;a href="http://www.shelfari.com/books/20843/The-Pragmatic-Programmer-From-Journeyman-to-Master"&gt;The Pragmatic Programmer&lt;/a&gt; Reloaded": same concepts with updated samples and situations. It is a perfect read for any junior developer, as the book will instill the right mindset. It is also a recommended book for any developer who struggles with his own practice (all of us, right?) and want to engage the next gear.&lt;br /&gt;&lt;br /&gt;Personally, having attended some of Neal's conference speeches and being somewhat an old dog in the field of software, I kind of knew where he would take me in this book hence I did not have any big surprise nor made any huge discovery while reading it. This said, three chapters are truly outstanding and can talk to experienced geeks: "Ancient Philosophers", "Question Authority" and "Polyglot Programming".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2824114550454127644?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2824114550454127644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2824114550454127644' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2824114550454127644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2824114550454127644'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/10/just-read-productive-programmer.html' title='Just Read: The Productive Programmer'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-1298601830913848067</id><published>2008-10-18T12:52:00.021-07:00</published><updated>2009-05-10T08:30:46.525-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Scala'/><title type='text'>Two-Minutes Scala Rules Engine</title><content type='html'>Scala is really &lt;a href="http://blog.objectmentor.com/articles/tag/scala"&gt;seductive&lt;/a&gt;. To drive my learning of this &lt;a href="http://www.scala-lang.org/"&gt;JVM programming language&lt;/a&gt;, I thought I should go beyond the obvious experiments and try to tackle a subject &lt;a href="http://nxbre.org/"&gt;dear to my heart&lt;/a&gt;: building a general purpose rules engine.&lt;br /&gt;&lt;br /&gt;Of course, the implementation I am going to talk about here is naive and inefficient but the rules engine is just a pretext here: this is about Scala and how it shines. And it is also a subset of what Scala is good at: I mainly scratch the surface by focusing on pattern matching and collections handling.&lt;br /&gt;&lt;br /&gt;The fact representation I use is the same than the one used by &lt;a href="http://ruleml.org/"&gt;RuleML&lt;/a&gt;: a fact is a named relationship between predicates. For example, in "blue is the color of the sky", &lt;span style="font-style: italic;"&gt;color&lt;/span&gt; is the relationship between &lt;span style="font-style: italic;"&gt;blue&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;sky&lt;/span&gt;. The rules engine matches these facts on predefined patterns and infers new facts out of these matches.&lt;br /&gt;&lt;br /&gt;In Scala, I naturally opted for using a &lt;a href="http://www.scala-lang.org/node/107"&gt;case class&lt;/a&gt; to define a fact, as the pattern matching feature it offers is all what is needed to build inference rules:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;case class Fact(rel: String, predicates: Any*) {&lt;br /&gt;override def toString: String = rel + "{" + predicates.mkString(",") + "}"&lt;br /&gt;&lt;br /&gt;override def hashCode : Int = {&lt;br /&gt; var h = 31 + rel.hashCode&lt;br /&gt; predicates.foreach(predicate =&amp;gt; h = 31 * h + predicate.hashCode)&lt;br /&gt; return h&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/textarea&gt;Normally you do not need to implement your own hashcode functions, as Scala's default ones are very smart about your objects' internals, but there is a &lt;a href="http://lampsvn.epfl.ch/trac/scala/ticket/1332"&gt;known issue&lt;/a&gt; with case classes that forced me to do so.&lt;br /&gt;&lt;br /&gt;For rules, I opted to have them created as objects constrained by a particular &lt;a href="http://www.scala-lang.org/node/126"&gt;trait&lt;/a&gt;:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;trait Rule {&lt;br /&gt;def arity(): Int&lt;br /&gt;def run(facts: List[Fact]): Option[Fact]&lt;br /&gt;}&lt;br /&gt;&lt;/textarea&gt;The method of note in this trait is &lt;span style="font-style: italic;"&gt;run&lt;/span&gt; which accepts a list of &lt;span style="font-style: italic;"&gt;n&lt;/span&gt; facts and returns zero (None) or one (Some)   new fact ; with n equals to the value of the &lt;span style="font-style: italic;"&gt;arity&lt;/span&gt; function.&lt;br /&gt;&lt;br /&gt;So how is the list of facts fed to the rule &lt;span style="font-style: italic;"&gt;run&lt;/span&gt; method created? This is where the naive and inefficient part comes into play: each rule tells the engine the number of facts it needs to receive as arguments when called. The engine then feeds the rule with all the unique combinations of facts that match its arity.&lt;br /&gt;&lt;br /&gt;This is an inefficient but working design. The really amazing part here is how Scala shines again by providing all what is required to build these combinations in a concise manner. This is achieved thanks to the &lt;a href="http://www.scala-lang.org/node/111"&gt;for-comprehension&lt;/a&gt; mechanism as shown here:&lt;br /&gt;&lt;textarea name="code" class="java"&gt; def combine[E](source : List[E], arity : Int) : List[List[E]] =&lt;br /&gt;arity match {&lt;br /&gt; case 0 =&amp;gt; List(List())&lt;br /&gt;&lt;br /&gt; case _ =&amp;gt;&lt;br /&gt; for {&lt;br /&gt;   a &amp;lt;- combine(source.tail ::: List(source.head), arity-1)&lt;br /&gt;   b &amp;lt;- source&lt;br /&gt;   if (!a.contains(b))&lt;br /&gt; } yield a ::: List(b)&lt;br /&gt;}&lt;br /&gt;&lt;/textarea&gt;Notice how this code is generic and knows nothing about the objects it combines. With this combination function in place, the engine itself is a mere three functions:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;def processUntilDone(factBase : Set[Fact], ruleBase : List[Rule]) : Set[Fact] =&lt;br /&gt;// call process until the fact base stabilizes&lt;br /&gt;processRules(factBase, ruleBase) match {&lt;br /&gt;case processedFactBase if (processedFactBase == factBase)&lt;br /&gt;  =&amp;gt; factBase&lt;br /&gt;&lt;br /&gt;case processedFactBase&lt;br /&gt;  =&amp;gt; processUntilDone(processedFactBase, ruleBase)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def processRules(factBase : Set[Fact], ruleBase : List[Rule]) : Set[Fact] =&lt;br /&gt;ruleBase match {&lt;br /&gt;case rule :: tail&lt;br /&gt;  =&amp;gt; processOneRule(factBase, rule) ++ processRules(factBase, tail)&lt;br /&gt;&lt;br /&gt;case Nil&lt;br /&gt;  =&amp;gt; factBase&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def processOneRule(factBase : Set[Fact], rule : Rule) =&lt;br /&gt;Set() ++ combine(factBase.toList, rule.arity).flatMap(facts =&amp;gt; rule.run(facts))&lt;br /&gt;&lt;br /&gt;&lt;/textarea&gt;With this in place, let us look at the facts and rules I created to solve the &lt;a href="http://www.ruleml.org/papers/tutorial-ruleml-20050513.html"&gt;classic RuleML discount problem&lt;/a&gt; (I added an extra customer). Here is the initial facts definition:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;val factBase = Set[Fact](&lt;br /&gt;     Fact("Luxury", "Porsche"),&lt;br /&gt;     Fact("Regular", "Honda"),&lt;br /&gt;     Fact("Spending", "Peter Miller", 2007, 5500),&lt;br /&gt;     Fact("Spending", "John Doe", 2007, 4500))&lt;br /&gt;&lt;/textarea&gt;And here are the two rules:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;object premiumCustomerRule extends Rule {&lt;br /&gt;def arity() = 1&lt;br /&gt;&lt;br /&gt;def run(facts: List[Fact]): Option[Fact] =&lt;br /&gt;facts match {&lt;br /&gt; case List(Fact("Spending", customer: String, year: Int, amount: Int)) if (amount &amp;gt;= 5000)&lt;br /&gt;   =&amp;gt; Some(Fact("Premium", customer))&lt;br /&gt;&lt;br /&gt; case _&lt;br /&gt;   =&amp;gt; None&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;object luxuryDiscountRule extends Rule {&lt;br /&gt;def arity() = 2&lt;br /&gt;&lt;br /&gt;def run(facts: List[Fact]): Option[Fact] =&lt;br /&gt;facts match {&lt;br /&gt; case List(Fact("Premium", customer: String), Fact("Luxury", item: String))&lt;br /&gt;   =&amp;gt; Some(Fact("Discount", customer, item, "7.5%"))&lt;br /&gt;&lt;br /&gt; case _&lt;br /&gt;   =&amp;gt; None&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;val ruleBase = premiumCustomerRule :: luxuryDiscountRule :: Nil&lt;br /&gt;&lt;/textarea&gt;With this in place, calling:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;processUntilDone(factBase, ruleBase).foreach(fact =&amp;gt; println(fact))&lt;br /&gt;&lt;/textarea&gt;produces this new fact base with the correct discount granted to good old Peter Miller but not to the infamously cheap John Doe:&lt;br /&gt;&lt;textarea name="code" class="java"&gt;Spending{Peter Miller,2007,5500}&lt;br /&gt;Spending{John Doe,2007,4500}&lt;br /&gt;Regular{Honda}&lt;br /&gt;Luxury{Porsche}&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Premium{Peter Miller}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Discount{Peter Miller,Porsche,7.5%}&lt;/span&gt;&lt;br /&gt;&lt;/textarea&gt;This is truly a two minutes rules engine: don't ship it to production! Thanks to the standard pattern matching and collection handling functions in Scala, this was truly a bliss to develop. On top of that, Scala's advanced type inference mechanism and very smart and explicit compiler take strong typing to another dimension, one that could seduce ducks addicts.&lt;br /&gt;&lt;br /&gt;So why does Scala matter? I believe the JVM is still the best execution platform available as of today. It is stable, fast, optimized, cross-platform and manageable. An alternative byte-code compiled language like Scala opens the door to new approaches in software development on the JVM.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Closing note: an interesting next step will consist in parallelizing the engine by using &lt;/span&gt;&lt;a style="font-style: italic;" href="http://www.scala-lang.org/node/242"&gt;Scala actors&lt;/a&gt;&lt;span style="font-style: italic;"&gt;. But this is another story...&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-1298601830913848067?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/1298601830913848067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=1298601830913848067' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1298601830913848067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1298601830913848067'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/10/two-minutes-scala-rules-engine.html' title='Two-Minutes Scala Rules Engine'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8522040288024405766</id><published>2008-10-08T20:49:00.003-07:00</published><updated>2008-10-08T21:16:29.435-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Database Cargo Cult</title><content type='html'>Today, I have attended an epic product walk-through. When the demonstrator came to explore the database of the application and opened the stored procedures directory, the audience was aghast at the shocking display of hundreds of these entities. I have been told it is the canonical way of developing applications in the Microsoft world. It is well possible, as it creates a favorable vendor coupling, but, to me, it is more a matter of &lt;span style="font-weight: bold;"&gt;database cargo cult&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The fallacy of the database as an application tier is only equated by the folly of using it as an integration platform. Both approaches create a paramount technical debt that takes many years to pay, if it is ever paid. Why? Because both approaches lack the abstraction layer that you need to create loosely coupled systems. Why again? Because both approaches preclude any sound testing strategy.&lt;br /&gt;&lt;br /&gt;I have &lt;a href="http://tinyurl.com/storedprocs"&gt;already talked about&lt;/a&gt; what I think are valid use cases for stored procedures. You do not need to believe me. Check what my colleague &lt;a href="http://timmeighen.blogspot.com/2008/07/stored-procedures-vs-orm-cutting.html"&gt;Tim has to say about it&lt;/a&gt;. And you do not need to believe him either, but at least read what &lt;a href="http://memeagora.blogspot.com/2008/09/soa-sidekick-oriented-architecture.html"&gt;Neal Ford says about it&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you are still not convinced, then I have for you the perfect shape for your diagrams:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_wgiUOehXWyI/SO2E7eNecCI/AAAAAAAAAHo/lSJP_RT6lys/s1600-h/1bdb.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_wgiUOehXWyI/SO2E7eNecCI/AAAAAAAAAHo/lSJP_RT6lys/s320/1bdb.png" alt="" id="BLOGGER_PHOTO_ID_5255002497467969570" border="0" /&gt;&lt;/a&gt;&lt;span style="font-weight: bold;"&gt;1BDB&lt;/span&gt; stands for &lt;span style="font-style: italic;"&gt;one big database&lt;/span&gt;. And if you are in a database cargo cult, you already know why it is in flame.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8522040288024405766?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8522040288024405766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8522040288024405766' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8522040288024405766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8522040288024405766'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/10/database-cargo-cult.html' title='Database Cargo Cult'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_wgiUOehXWyI/SO2E7eNecCI/AAAAAAAAAHo/lSJP_RT6lys/s72-c/1bdb.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-4194733272018315173</id><published>2008-10-02T10:27:00.002-07:00</published><updated>2008-10-02T10:35:06.964-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DDJ'/><title type='text'>Jolting 2008</title><content type='html'>The doors are now open for the 2008 &lt;a href="http://www.joltawards.com/"&gt;Jolt Product Excellence Awards&lt;/a&gt; nominations.&lt;br /&gt;&lt;br /&gt;If you have a great book or a cool product that has been published or had a significant version release   in 2008, then do not wait any longer and &lt;a href="https://www.joltnominations.com/"&gt;enter the competition&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;Oh, did I mention that early birds and open-source non-profit organizations get a discount?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-4194733272018315173?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/4194733272018315173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=4194733272018315173' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4194733272018315173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4194733272018315173'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/10/jolting-2008.html' title='Jolting 2008'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-7417573371971871088</id><published>2008-10-01T13:42:00.003-07:00</published><updated>2008-10-01T14:20:32.746-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>Just Read: Working effectively with legacy code</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.shelfari.com/books/500794/Working-Effectively-with-Legacy-Code-%28Robert-C-Martin-Series%29"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://ecx.images-amazon.com/images/I/51RCXGPXQ8L._SL500_AA240_.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;This book from Michael C. Feathers came at a perfect moment in my software developer's life, as I started to read it right before I came to work on a legacy monstrosity.&lt;br /&gt;&lt;br /&gt;The book is well organized, easy to ready and full of practical guidelines and best practices for taming the legacy codebases that are lurking out there.&lt;br /&gt;&lt;br /&gt;I really appreciated Michael's definition of legacy code: for him "it is simply code without tests". And, indeed, untested code is both the cause and the characteristic of legacy code.&lt;br /&gt;&lt;br /&gt;Near the end of the book, Michael has written a short chapter titled "We feel overwhelmed" that I have found encouraging and inspiring. Yes, working with legacy code can actually be fun if you look at it on the right side. My experience in this domain is that increasing test coverage is elating, deleting dead code and inane comments is bliss and seeing design emerge where only chaos existed is ecstatic.&lt;br /&gt;&lt;br /&gt;Conclusion: read this book if you are dealing with today's legacy code or if you do not want to &lt;a href="http://powdermonkey.blogs.com/powdermonkey/BuildingLegacy.png"&gt;build tomorrow's&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-7417573371971871088?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/7417573371971871088/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=7417573371971871088' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7417573371971871088'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7417573371971871088'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/10/just-read-working-effectively-with.html' title='Just Read: Working effectively with legacy code'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-841431389891010292</id><published>2008-10-01T12:03:00.003-07:00</published><updated>2008-10-02T11:09:45.843-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>Meme(me)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_wgiUOehXWyI/SOPJej2rmvI/AAAAAAAAAHc/qVGflflr4F0/s1600-h/DSC00116.JPG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_wgiUOehXWyI/SOPJej2rmvI/AAAAAAAAAHc/qVGflflr4F0/s320/DSC00116.JPG" alt="" id="BLOGGER_PHOTO_ID_5252263117301979890" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;From &lt;a href="http://sacha.labourey.com/2008/10/01/mememe/trackback/"&gt;Sacha&lt;/a&gt;:&lt;br /&gt;1. Take a picture of yourself right now.&lt;br /&gt;2. Don’t change your clothes,  don’t fix your hair…just take a picture.&lt;br /&gt;3. Post that picture with NO  editing.&lt;br /&gt;4. Post these instructions with your picture.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-841431389891010292?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/841431389891010292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=841431389891010292' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/841431389891010292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/841431389891010292'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/10/mememe.html' title='Meme(me)'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_wgiUOehXWyI/SOPJej2rmvI/AAAAAAAAAHc/qVGflflr4F0/s72-c/DSC00116.JPG' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-4728000792713949957</id><published>2008-09-30T14:15:00.002-07:00</published><updated>2008-11-26T21:48:51.819-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Mule'/><category scheme='http://www.blogger.com/atom/ns#' term='Platform'/><title type='text'>Can Mule Spring further?</title><content type='html'>Just wondering.&lt;br /&gt;&lt;br /&gt;Mule 2 is already very Spring-oriented, or at least very Spring-friendly. Will Mule's distribution, which is currently a nice set of Maven-build artifacts, evolve to a set of OSGI bundles &lt;span style="font-style: italic;"&gt;a la&lt;/span&gt; Spring for version 3?&lt;br /&gt;&lt;br /&gt;If MuleSource follows that path and distributes Spring Dynamic Modules, that would allow people to run on the SpringSource dm Server, if they want it, and benefit from sweetnesses like hot service replacement.&lt;br /&gt;&lt;br /&gt;I doubt that Mule could use SpringSource dm Server as a default platform unless they clear up what I think could be licensing incompatbilities. But end users could make that choice and put the two Sources, Mule and Spring, together.&lt;br /&gt;&lt;br /&gt;Just wondering.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-4728000792713949957?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/4728000792713949957/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=4728000792713949957' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4728000792713949957'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4728000792713949957'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/09/can-mule-spring-further.html' title='Can Mule Spring further?'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8097749799354267751</id><published>2008-09-24T20:14:00.004-07:00</published><updated>2008-09-24T21:17:57.042-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>The Build Manifesto</title><content type='html'>My ex-colleague &lt;a href="http://www.linkedin.com/in/ojacobson"&gt;Owen&lt;/a&gt; has just introduced &lt;a href="http://codex.grimoire.ca/2008/09/24/nobody-cares-about-your-build/trackback/"&gt;the Build Manifesto&lt;/a&gt;. I invite you to read it and share your thoughts with him.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://codex.grimoire.ca/2008/09/24/nobody-cares-about-your-build/trackback/"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px" src="http://codex.grimoire.ca/wp-content/uploads/2008/09/buildifesto-pyramid.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8097749799354267751?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8097749799354267751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8097749799354267751' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8097749799354267751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8097749799354267751'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/09/build-manifesto.html' title='The Build Manifesto'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6205381436676151285</id><published>2008-09-23T12:35:00.000-07:00</published><updated>2008-09-23T12:40:18.185-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Platform'/><title type='text'>Soon Serving Spring</title><content type='html'>I finally had a chance to step beyond trivialities with the &lt;a href="http://www.springsource.com/products/suite/dmserver"&gt;SpringSource dm Server&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;To make things clear, &lt;span style="font-weight: bold;"&gt;this server is all about giving life to Spring Dynamic Modules &lt;/span&gt;(DM). Spring DM is not new but putting this technology in action was awkward: you had to deal with an embedded OSGI container and figure a lot of things out. The SpringSource dm Server provides an integrated no-nonsense environment where dynamic modules live a happy and fruitful life.&lt;br /&gt;&lt;br /&gt;The benefits of dynamic modules are well known, and mostly derived from the OSGI architecture. The goodness Spring adds on OSGI is the clean model for service declaration and referencing. This is priceless as &lt;span style="font-weight: bold;"&gt;it enables a true highly cohesive and loosely coupled application architecture within a single JVM&lt;/span&gt;. If you come from a world of EJBs and troubled class loaders, this is the holy grail.&lt;br /&gt;&lt;br /&gt;To exercise this sweet platform beyond the obvious, I have built the prototype of a JMS-driven application. The architecture was pretty simple: a bundle using Message Driven POJOs to consume a Sun OpenMQ destination, which then informs clients of new messages through a collection of listener service references. The idea was to allow the deployment of new clients or the hot replacement of a particular client at runtime. Verdict? It just works. The SpringSource dm Server goes to great length to isolate you from bundles going up and down (depending on the cardinality of your references to OSGI services, you may still get a "service non available" exception).&lt;br /&gt;&lt;br /&gt;What I really enjoyed was the possibility to use bundles of &lt;span style="font-weight: bold;"&gt;Spring wired beans as first class citizen applications&lt;/span&gt;. Gone is the need for wrapping Spring in a web application to get a proper life cycle... POJOs rule!&lt;br /&gt;&lt;br /&gt;Version RC2 of the server still has some rough edges (for example, the deployment order in the pickup directory is fuzzy and the logging messages are badly truncated and ill formatted) but they are minor compared to the amount of work done on the platform itself.&lt;br /&gt;&lt;br /&gt;For me, the main challenge remains in making this server truly production-grade. Here are some points that I think need improvement:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Consoles all the way down&lt;/span&gt;: You have to juggle between the Web Admin Console, the Equinox OSGI console and JConsole to perform different bundle management operations. The SpringSource dm Server needs a single console to rule them all.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;The configuration management is unclear&lt;/span&gt;: I ended up using an extra module, the Pax ConfigManager, to load external properties file in the OSGI Configuration Admin service. The SpringSource dm Server needs a default tool for this before going to production.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;A proper service Shell script is missing&lt;/span&gt;: you just get a start and a stop script, which is not enough for production. A unique script with the classic start/restart/stop/status commands would be way better. If the matter of licensing was not such a hot subject in SpringSource currently, I would suggest them to use Tanuki's Wrapper as their boot script.&lt;/li&gt;&lt;/ul&gt;It is obvious that SpringSource will take this server to the next level and make it production ready pretty soon. It might already be done while I write this.&lt;br /&gt;&lt;br /&gt;I you are a latecomer like me and have not started to seriously investigate this technology, now is the time.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6205381436676151285?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6205381436676151285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6205381436676151285' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6205381436676151285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6205381436676151285'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/09/soon-serving-spring.html' title='Soon Serving Spring'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-5515667905246840861</id><published>2008-09-21T16:56:00.003-07:00</published><updated>2008-09-21T17:30:24.519-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Final painted all over it</title><content type='html'>In my previous post, I mentioned that I let Eclipse add &lt;span style="font-style: italic;"&gt;final&lt;/span&gt; statements everywhere in my code. I initially was reluctant to this idea.&lt;br /&gt;&lt;br /&gt;Then I came to work on a piece of code which was heavily dealing with string processing. The temptation to re-use a variable and assign a different string to it several times, as the processing was happening, was really high. Using the &lt;span style="font-style: italic;"&gt;final&lt;/span&gt; keyword forced me to declare a new variable each time. The great benefit was that I had to create new variable name each time, thus making the code clearer in its intention.&lt;br /&gt;&lt;br /&gt;Hence, using only final variables makes the code stricter and cleaner. Moreover it is a safety net for the days when I am sloppy: final variables give me the big no-no if I feel inclined to repurpose one of them!&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://www.amazon.co.uk/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882"&gt;Clean Code&lt;/a&gt; Uncle Bob advocates against such a systematic use of the &lt;span style="font-style: italic;"&gt;final&lt;/span&gt; keyword for the reason it creates too much visual clutter. I agree with him though you quickly tend to visually ignore these keywords. Scala has solved the cluttering issue elegantly thanks to specific declaration keywords instead of a modifier (&lt;span style="font-style: italic;"&gt;val&lt;/span&gt; for values and &lt;span style="font-style: italic;"&gt;var&lt;/span&gt; for variable).&lt;br /&gt;&lt;br /&gt;Did I just say Scala?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-5515667905246840861?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/5515667905246840861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=5515667905246840861' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5515667905246840861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5515667905246840861'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/09/final-painted-all-over-it.html' title='Final painted all over it'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-5890435689327414271</id><published>2008-09-20T12:32:00.003-07:00</published><updated>2008-09-20T12:51:44.923-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Microtechniques: a little more conversation?</title><content type='html'>Interestingly, just when I was about to write about the pleasure of not typing many things while coding in Eclipse, &lt;a href="http://www.jbrains.info/permalink/209"&gt;J. B. Rainsberger just posted about the potential importance of typing fast&lt;/a&gt;. I guess this is the nature of the webernet: everything and its opposite at the same time, and leave it to the readers to sort things out!&lt;br /&gt;&lt;br /&gt;I was reflecting about my coding habits with Eclipse after a thread in the Java forums, where a poster was complaining about the continuous compilation feature, prompted some internal debates (my, myself and I often disagree). Interestingly, this feature has been &lt;a href="http://renaud.waldura.com/doc/java/eclipse-ten-reasons.shtml"&gt;touted by others as a key one&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I personally like the continuous feedback. The rare time I write C# code in SharpDevelop, it takes me a while to remember that I have to tell the IDE to look at my code. First, I do not like to have to tell my friend the computer to do things.  Second, I want the continuous feedback. I do not mind if the compiler is temporarily confused because my syntax is momentarily broken. I want the early warning that this feature gives me.&lt;br /&gt;&lt;br /&gt;In fact, continuous compilation creates a neat state of flow, where you actually engage into a conversation with the IDE. And this is where my stance about not typing comes into play. I do not type class names, but merely each capital letter of its name and let the code assistance propose me something that fits. I do not write variable declarations: I either assign it automatically or extract it from existing code. I less and less write method declarations but extract them. I allow Eclipse to add keywords (like final) and attributes (like @Override) everywhere it thinks necessary. I leave it up to the code formatter to clean up my mess and make it stick with the coding conventions in place.&lt;br /&gt;&lt;br /&gt;All these automatic features do not dumb me down. They establish a rich conversation between my slow and fuzzy brain and the fast and strict development environment. The compiler tells me: "ok, this is what I understand" and the IDE tells me: "alright, here is what I propose". And then I correct course or keep going.&lt;br /&gt;&lt;br /&gt;So maybe we need a little less typing and  a little more conversation?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-5890435689327414271?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/5890435689327414271/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=5890435689327414271' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5890435689327414271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/5890435689327414271'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/09/microtechniques-little-more.html' title='Microtechniques: a little more conversation?'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-1830498408240972332</id><published>2008-09-16T17:24:00.003-07:00</published><updated>2008-10-01T14:05:39.804-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>Just Read: Clean Code</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.shelfari.com/books/4017020/Clean-Code-A-Handbook-of-Agile-Software-Craftsmanship"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://ecx.images-amazon.com/images/I/419EFaGEGvL._SL240_.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I have been expecting this new book from Uncle Bob for quite a while so, as soon as I have got my copy, I rushed through it!&lt;br /&gt;&lt;br /&gt;If you have no idea about who is this guy named Robert C. Martin and mainly expect people to "sent you teh codez", then you have to read this book. This will not transmogrify you into a craftsman but, at least, you will get a fair measure of the journey you still have to go through and be pointed in the right direction.&lt;br /&gt;&lt;br /&gt;If you are familiar with Uncle Bob's writings and attend his conference talks, there will be no new concepts for you in this book. It will still be an insightful reading because of the extensive code samples and the refactoring sessions where you can actually follow the train of thoughts, and the actions they entail, as if you were in the master's head. It's like being John Malkovitch, but a little geekier.&lt;br /&gt;&lt;br /&gt;The book itself is somewhat structurally challenged and lacks a little consistency, from a reader standpoint.&lt;br /&gt;&lt;br /&gt;But who cares? As long as you can read this kind of stuff:&lt;br /&gt;&lt;blockquote&gt;Clean code is not written by following a set of rules. You don't become a software craftsman by learning a list of heuristics. Professionalism and craftsmanship come from values that drive disciplines.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;span style="font-style: italic;"&gt;Robert C. Martin, Clean Code&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;/blockquote&gt;... is the form so important?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-1830498408240972332?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/1830498408240972332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=1830498408240972332' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1830498408240972332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1830498408240972332'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/09/just-read-clean-code.html' title='Just Read: Clean Code'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-1705636904739656703</id><published>2008-09-11T11:01:00.009-07:00</published><updated>2008-09-23T19:37:21.967-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Science'/><category scheme='http://www.blogger.com/atom/ns#' term='Off-topic'/><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>Colliding Cow Bells</title><content type='html'>&lt;p&gt;I found that the original &lt;a href="http://www.youtube.com/watch?v=j50ZssEojtM"&gt;Large Hadron Collider Rap&lt;/a&gt; was lacking cowbells. Here is the reviewed version that is now fully compliant with Christopher Walken and Blue Oyster Cult's standards:&lt;/p&gt;&lt;br /&gt;&lt;embed type="application/x-shockwave-flash" flashvars="cowbellID=C65Xyu&amp;amp;cowbellTitle=CERN - Large Hadron Rap" pluginspage="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" quality="high" bgcolor="#ffffff" src="http://www.morecowbell.dj/swf/player.swf" width="400" height="170"&gt;&lt;/embed&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-1705636904739656703?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/1705636904739656703/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=1705636904739656703' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1705636904739656703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1705636904739656703'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/09/colliding-cow-bells.html' title='Colliding Cow Bells'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6196126455912841254</id><published>2008-09-05T17:36:00.005-07:00</published><updated>2008-09-05T17:43:12.358-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Code Onion</title><content type='html'>The code of an application is like an onion, which is why it may make you cry sometimes. It looks like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_wgiUOehXWyI/SMHQodQoPrI/AAAAAAAAAFc/Phl1wBGna5c/s1600-h/onion.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_wgiUOehXWyI/SMHQodQoPrI/AAAAAAAAAFc/Phl1wBGna5c/s320/onion.png" alt="" id="BLOGGER_PHOTO_ID_5242700834703687346" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The core&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;This is the code domain where unit test coverage is the highest, hence refactoring is free. This code is as clean as it can be. This is the comfortable place where everybody wants to work in. Thanks to high test coverage, the feedback loop is short and fast so morale and courage are high when it comes to touch anything in this area.&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;The borders&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;This is where most of the compromises happen. Dictated by the use of frameworks or application containers, code becomes invaded with inane accessors, class names end up hard-coded in configuration files, out-of-code indirections (like JNDI based look-ups) weaken the edifice. Unit and integration tests help building reasonable confidence but some refactoring can induce issues that can only be detected when deploying in a target container. This slow and long feedback loop reduces the opportunities to make things better in this area.&lt;/ul&gt;&lt;span style="font-weight: bold;"&gt;The wilderness&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;This is the outside world, where the rift between the world of code and the harsh reality of life resides. Databases inhabit this place and provide great services but they mismatch with objects. The network is there too, always happy to teach your application pesky lessons about latency, droped packets or broken pipes. Worst of all, users (yes, Tron, they exist) have invaded this area: from there they will constantly find creative ways to abuse your innocent code.&lt;/ul&gt;Tensions exist at the touch surfaces between these three layers, resulting in incongruous invasions of concerns and perversions of one layer into another. Ideally these layers would not exist: we would not need frameworks to bridge the world of pure code with the real world. In the meantime this dream comes true, we will have to keep dealing with the code onion and, every now and then, shed a tear on less than ideal code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6196126455912841254?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6196126455912841254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6196126455912841254' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6196126455912841254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6196126455912841254'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/09/code-onion.html' title='Code Onion'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_wgiUOehXWyI/SMHQodQoPrI/AAAAAAAAAFc/Phl1wBGna5c/s72-c/onion.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6427691075911527711</id><published>2008-09-05T10:55:00.003-07:00</published><updated>2008-09-05T22:57:12.314-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Writings'/><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><title type='text'>ESB Testing Strategies with Mule</title><content type='html'>SOA World Magazine has just put online my latest article, "&lt;a href="http://soa.sys-con.com/node/665712"&gt;&lt;span class="storytitle"&gt;ESB Testing Strategies with Mule&lt;/span&gt;&lt;/a&gt;", which they have published in their August issue.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6427691075911527711?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://soa.sys-con.com/node/665712' title='ESB Testing Strategies with Mule'/><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6427691075911527711/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6427691075911527711' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6427691075911527711'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6427691075911527711'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/09/esb-testing-strategies-with-mule.html' title='ESB Testing Strategies with Mule'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-3294201532257793080</id><published>2008-09-02T19:14:00.003-07:00</published><updated>2008-09-02T21:55:26.744-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Writings'/><title type='text'>That's silver, Jerry!</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_wgiUOehXWyI/SL3zQiMCYGI/AAAAAAAAAFU/Vg6jhh02PAc/s1600-h/mia-silver.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_wgiUOehXWyI/SL3zQiMCYGI/AAAAAAAAAFU/Vg6jhh02PAc/s320/mia-silver.png" alt="" id="BLOGGER_PHOTO_ID_5241613006709874786" border="0" /&gt;&lt;/a&gt;That's silver... for &lt;a href="http://muleinaction.com/"&gt;Mule In Action&lt;/a&gt; in the current &lt;a href="http://manning.com/"&gt;Manning&lt;/a&gt; early access best seller roaster. And the book is only getting better thanks to our great reviewers!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-3294201532257793080?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.youtube.com/watch?v=j0qm0KUPeD8' title='That&apos;s silver, Jerry!'/><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/3294201532257793080/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=3294201532257793080' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3294201532257793080'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/3294201532257793080'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/09/thats-silver-jerry.html' title='That&apos;s silver, Jerry!'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_wgiUOehXWyI/SL3zQiMCYGI/AAAAAAAAAFU/Vg6jhh02PAc/s72-c/mia-silver.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-2468984996923016746</id><published>2008-09-01T09:35:00.003-07:00</published><updated>2008-09-01T09:41:27.756-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>Reading Calendar Irony</title><content type='html'>My six readers (according to Google Reader), will certainly appreciate the irony of my reading calendar.&lt;br /&gt;&lt;br /&gt;Here are the two books I am currently reading:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_wgiUOehXWyI/SLwacBTd80I/AAAAAAAAAE0/yoxhiSrzHVs/s1600-h/opposite-readings.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_wgiUOehXWyI/SLwacBTd80I/AAAAAAAAAE0/yoxhiSrzHVs/s320/opposite-readings.png" alt="" id="BLOGGER_PHOTO_ID_5241093135041164098" border="0" /&gt;&lt;/a&gt;Isn't this coincidence really fun?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-2468984996923016746?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/2468984996923016746/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=2468984996923016746' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2468984996923016746'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/2468984996923016746'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/09/reading-calendar-irony.html' title='Reading Calendar Irony'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_wgiUOehXWyI/SLwacBTd80I/AAAAAAAAAE0/yoxhiSrzHVs/s72-c/opposite-readings.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-678755196967658620</id><published>2008-08-29T17:58:00.003-07:00</published><updated>2008-08-29T18:41:50.946-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='My OSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Commit Risk Analysis</title><content type='html'>I like to compare the stability of a legacy application as a saddle point:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/commons/4/40/Saddle_point.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px;" src="http://upload.wikimedia.org/wikipedia/commons/4/40/Saddle_point.png" alt="" border="0" /&gt;&lt;/a&gt;QA provides some lateral stability that prevents the legacy application (this little funny red dot) to fall sideways. But, still, a little push on the wrong side and down the hole the application will fall.&lt;br /&gt;&lt;br /&gt;What the legacy code typically misses is unit tests. With unit tests, the saddle disappear and the code stability ends up in a pretty stable parabola:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_wgiUOehXWyI/SLiiJ_NVzjI/AAAAAAAAAEs/9ZNyF5WeZQk/s1600-h/hyperbola.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_wgiUOehXWyI/SLiiJ_NVzjI/AAAAAAAAAEs/9ZNyF5WeZQk/s320/hyperbola.gif" alt="" id="BLOGGER_PHOTO_ID_5240116458915483186" border="0" /&gt;&lt;/a&gt;In an ideal world, there will be no legacy code. In a little less ideal world, there will be legacy code but every time a developer would touch any class, he would first write unit tests to fully cover the code he is about to modify.&lt;br /&gt;&lt;br /&gt;Unfortunately, in our world, code is written by human beings. Human beings turned the original code into legacy code and human beings will maintain and evolve this legacy code. Hence there will be modifications on non unit tested code that will end up checked in. Inevitably, the little red ball will drift on the wrong side of the saddle.&lt;br /&gt;&lt;br /&gt;I came to wonder what could be a way to estimate the risk that has been introduced by changes in a code base. Basically, the risk would be inversely proportional to the test coverage of the modified class.&lt;br /&gt;&lt;br /&gt;I came with a very basic tool, &lt;a href="http://www.assembla.com/wiki/show/corian"&gt;Corian&lt;/a&gt; (Commit Risk Analyzer), that simply fetches the Cobertura coverage percentage for classes that were modified in Subversion for a particular number of days in the past.&lt;br /&gt;&lt;br /&gt;Do you know of any method or tool for estimating the risk that a series of revisions could have introduced in a code base?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-678755196967658620?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/678755196967658620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=678755196967658620' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/678755196967658620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/678755196967658620'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/08/commit-risk-analysis.html' title='Commit Risk Analysis'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_wgiUOehXWyI/SLiiJ_NVzjI/AAAAAAAAAEs/9ZNyF5WeZQk/s72-c/hyperbola.gif' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-4385948530317178250</id><published>2008-08-27T20:09:00.003-07:00</published><updated>2008-08-27T20:43:16.897-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Bauhaus &amp; Software Development</title><content type='html'>It took me a while to realize this but I finally noticed the deep similitudes between software development and the &lt;a href="http://en.wikipedia.org/wiki/Bauhaus"&gt;Bauhaus&lt;/a&gt; school of design. My CS teacher and mentor, who was knowledgeable about almost everything, had a particular penchant for the Bauhaus: it only took me 16 years to grok why...&lt;br /&gt;&lt;br /&gt;Quoting Wikipedia, "&lt;span style="font-weight: bold;"&gt;one of the main objectives of the Bauhaus was to unify art, craft, and technology&lt;/span&gt;". Is not this unification realized in software development? In fact, should not this unification be the basis of successful, satisfying and fulfilling endeavors in this field?&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;span style="font-weight: bold;"&gt;Technology&lt;/span&gt; - This is the easiest one. Software development is obviously about technology, as the concrete manifestation of scientific and engineering progresses. The smaller the transistors, the denser the processors, the more powerful the computers, the happiest the software developers!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Craft&lt;/span&gt; - Uncle Bob speaks about it better than &lt;a href="http://ddossot.ovh.org/datastore/MystiqueOfSoftwareCraftsmanship.pdf"&gt;I&lt;/a&gt; could ever dream of. He has just proposed &lt;a href="http://blog.objectmentor.com/articles/2008/08/14/quintessence-the-fifth-element-for-the-agile-manifesto"&gt;a fifth element for the Agile Manifesto&lt;/a&gt;:&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;&lt;div style="text-align: center;"&gt;Craftsmanship over Execution   &lt;/div&gt;&lt;p&gt;   &lt;/p&gt;&lt;p&gt;Most software development teams &lt;em&gt;execute&lt;/em&gt;, but they don’t take &lt;em&gt;care&lt;/em&gt;.  We value execution, but we value craftsmanship more.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Art&lt;/span&gt; - The connection between software development and art is often controversial. Here, I will let Kent Beck convince you, with an excerpt of &lt;a href="http://ddossot.blogspot.com/2008/08/just-read-implementation-patterns.html"&gt;Implementation Patterns&lt;/a&gt;:&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;Aesthetics engage more of your brain than strictly linear logical thought. Once you have cultivated your sense of the aesthetics of code, the aesthetic impressions you receive of your code is valuable feedback about the quality of the code.&lt;/blockquote&gt;&lt;br /&gt;&lt;/div&gt;&lt;/ul&gt;A superficial look at Bauhaus buildings or paintings may give an impression of coldness and impersonality. But if you look again while keeping in mind the objective to unify art, craft and technology in an harmonious design, you will see things differently.&lt;br /&gt;&lt;br /&gt;Try with this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Bauhaus-Dessau_Wohnheim_Balkone.jpg/566px-Bauhaus-Dessau_Wohnheim_Balkone.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px;" src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Bauhaus-Dessau_Wohnheim_Balkone.jpg/566px-Bauhaus-Dessau_Wohnheim_Balkone.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Or that:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/en/3/39/Kandinsky_white.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px;" src="http://upload.wikimedia.org/wikipedia/en/3/39/Kandinsky_white.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;And now with that:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/en/9/90/State_Design_Pattern_UML_Class_Diagram.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px;" src="http://upload.wikimedia.org/wikipedia/en/9/90/State_Design_Pattern_UML_Class_Diagram.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-4385948530317178250?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/4385948530317178250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=4385948530317178250' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4385948530317178250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4385948530317178250'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/08/bauhaus-software-development.html' title='Bauhaus &amp; Software Development'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8754152639707030317</id><published>2008-08-26T14:09:00.002-07:00</published><updated>2008-08-26T14:34:31.829-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>Just Read: Managing Humans</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.shelfari.com/books/3514071/Managing-Humans-Biting-and-Humorous-Tales-of-a-Software-Engineer"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://ecx.images-amazon.com/images/I/51EsVJJbHkL._SL160_.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Michael Lopps' capacity to deconstruct and analyze every aspects of both software engineering management and nerd internal mechanics is simply outstanding.&lt;br /&gt;&lt;br /&gt;This book is not only insightful and amusing, but is a looking glass where all the intricacies of humans' management get revealed.&lt;br /&gt;&lt;br /&gt;A. Must. Read.&lt;span class="q"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8754152639707030317?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8754152639707030317/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8754152639707030317' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8754152639707030317'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8754152639707030317'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/08/just-read-managing-humans.html' title='Just Read: Managing Humans'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-1633678847465035701</id><published>2008-08-26T00:39:00.004-07:00</published><updated>2008-09-02T19:18:43.562-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Writings'/><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><title type='text'>Blog Inaction</title><content type='html'>Larry O'Brien &lt;a href="http://www.knowing.net/PermaLink,guid,e6f0f12c-0404-40ef-9eb5-eaefc0ed163e.aspx"&gt;said it&lt;/a&gt; better that I could ever formulate it, so here you go:&lt;br /&gt;&lt;blockquote&gt;I've been busier than some metaphorical thing in some metaphorical place where things are really busy.  &lt;/blockquote&gt;&lt;br /&gt;And here is what kept me and is still keeping me busy those days:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://muleinaction.com/"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://muleinaction.googlecode.com/files/MuleInAction.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-1633678847465035701?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/1633678847465035701/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=1633678847465035701' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1633678847465035701'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/1633678847465035701'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/08/blog-inaction.html' title='Blog Inaction'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-7621701995763806025</id><published>2008-08-18T12:46:00.004-07:00</published><updated>2008-08-18T13:06:49.689-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Platform'/><category scheme='http://www.blogger.com/atom/ns#' term='MS'/><title type='text'>Silverfight</title><content type='html'>The Register is running what seems to be &lt;a href="http://www.theregister.co.uk/2008/08/18/silverlight_pros_and_cons/"&gt;a balanced review&lt;/a&gt; of (the yet to come) &lt;a href="http://silverlight.net/"&gt;Microsoft &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Silverlight&lt;/span&gt;&lt;/a&gt; (2.0).&lt;br /&gt;&lt;br /&gt;It seems balanced because you have ten pros and ten cons, which might suggest that adopting &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Silverlight&lt;/span&gt; is merely a matter of taste (XAML is attractive) or politics (like for the &lt;a href="http://www.nbcolympics.com/"&gt;NBC Olympics&lt;/a&gt;). But I think that, if you &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;ponderate&lt;/span&gt; the different pros and cons, you might end-up with a balance that leans on a particular side (I let you guess which one).&lt;br /&gt;&lt;br /&gt;The availability of designers' tools that runs on the Macintosh platform will certainly be critical if Microsoft wants to entice them out of the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;Macromedia&lt;/span&gt; world.&lt;br /&gt;&lt;br /&gt;Similarly, the heroic efforts deployed in &lt;a href="http://www.mono-project.com/Moonlight"&gt;Moonlight&lt;/a&gt; to make &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;Silverlight&lt;/span&gt; cross platform will be key to the overall success of this, otherwise proprietary, platform.&lt;br /&gt;&lt;br /&gt;As of today, here is how a &lt;a href="http://www.itwriting.com/primetest"&gt;simple example&lt;/a&gt; comparing &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;Silverlight&lt;/span&gt; and Flash runs on my machine:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_wgiUOehXWyI/SKnUrNlUh3I/AAAAAAAAAEI/1X_TZaKLGRo/s1600-h/silverfight.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_wgiUOehXWyI/SKnUrNlUh3I/AAAAAAAAAEI/1X_TZaKLGRo/s400/silverfight.png" alt="" id="BLOGGER_PHOTO_ID_5235949880640571250" border="0" /&gt;&lt;/a&gt;Yep, this is a big empty white box with statistics about how fast &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;Silverlight&lt;/span&gt; renders it in the status bar. If Microsoft is serious about dethroning Flash, which I am not entirely convinced of, they will have to go past this kind of... emptiness.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-7621701995763806025?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/7621701995763806025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=7621701995763806025' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7621701995763806025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7621701995763806025'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/08/silverfight.html' title='Silverfight'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_wgiUOehXWyI/SKnUrNlUh3I/AAAAAAAAAEI/1X_TZaKLGRo/s72-c/silverfight.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-4619562635904468607</id><published>2008-08-13T21:59:00.004-07:00</published><updated>2008-08-26T13:26:29.164-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Readings'/><title type='text'>Just Read: Implementation patterns</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.shelfari.com/books/514775/Implementation-Patterns-%28The-Addison-Wesley-Signature-Series%29"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://ecx.images-amazon.com/images/I/51JHn-6oNwL._SL160_AA115_.jpg" alt="" border="0" /&gt;&lt;/a&gt;If you are an aficionado of formal pattern books, you might be disappointed by the latest book from Kent Beck. This book is more about a mentor sharing his experience than a succession of diagrams, code samples and rules for applying or not a particular pattern.&lt;br /&gt;&lt;br /&gt;In this book, Kent clearly took the decision to engage the reader in a direct manner: there is no fluff, just the nitty-gritty. Just years of experience and experiments summarized in less than 150 pages. I leave to your imagination to figure out how dense the book is. It is sometimes so rich that I came to wish that a little bit of code or a neat hand-drawn schema could be added here and there, just to make a particular pattern more edible for a slow brain like mine.&lt;br /&gt;&lt;br /&gt;There is an intense tension in this book: I have been fulminating after reading some takes from Kent where he states counter intuitive approaches as far as defensive coding is concerned. And then I reached the last part ("Evolving Frameworks") and it striked me: so far in book, Kent was not coding for public APIs. And it striked me again: Kent is a master, he adapts his way of coding to the context.&lt;br /&gt;&lt;br /&gt;Let Kent Keck talk to you: buy this short book and listen to what he wants to share with you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-4619562635904468607?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/4619562635904468607/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=4619562635904468607' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4619562635904468607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4619562635904468607'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/08/just-read-implementation-patterns.html' title='Just Read: Implementation patterns'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-6760174774679233493</id><published>2008-08-11T10:08:00.003-07:00</published><updated>2008-08-11T10:19:54.413-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><title type='text'>GMail Auto-resizing Rules!</title><content type='html'>Just a quick "thank you" to GMail's team for the new auto-resizing feature that makes the edit box use efficiently the available screen real estate.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;This is good.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-6760174774679233493?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/6760174774679233493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=6760174774679233493' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6760174774679233493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/6760174774679233493'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/08/gmail-auto-resizing-rules.html' title='GMail Auto-resizing Rules!'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-8673026910624837925</id><published>2008-08-06T22:12:00.002-07:00</published><updated>2008-08-06T22:32:47.069-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>Cuil Geared To Hidden Success</title><content type='html'>It took me a while to realize this but &lt;a href="http://cuil.com/"&gt;Cuil&lt;/a&gt;, the new flashy search engine that &lt;a href="http://www.theregister.co.uk/2008/08/01/cuil_apology/"&gt;randomly displays porn&lt;/a&gt; and has a name that looks like the French word for an &lt;a href="http://www.wordreference.com/fren/couilles"&gt;unspeakable part of the male anatomy&lt;/a&gt;, bears in its name the inevitable fate of a &lt;span style="font-style: italic;"&gt;hidden success&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Let me explain. To succeed on the webernets, you need two Os in your domain name. Amazon made the risky choice of a M-separated-double-A and they surprinsingly do well, so far. But anyway, if we narrow down the field to search engines only, it is pretty obvious that the double-O is &lt;span style="font-style: italic;"&gt;de rigueur&lt;/span&gt; for success.&lt;br /&gt;&lt;br /&gt;So what on Earth did happen to the guys at Cuil? Well, you see, the trick is in the pronunciation. It is pronounced "cool". Here you go! The double-O, that was &lt;span style="font-style: italic;"&gt;hidden&lt;/span&gt; in the domain name, becomes visible when you say it.&lt;br /&gt;&lt;br /&gt;Consequently, a hidden double-O can only lead to a hidden success. Which is not a failure by the way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-8673026910624837925?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/8673026910624837925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=8673026910624837925' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8673026910624837925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/8673026910624837925'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/08/cuil-geared-to-hidden-success.html' title='Cuil Geared To Hidden Success'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-9066671547213103486</id><published>2008-07-29T12:29:00.002-07:00</published><updated>2008-07-29T12:57:16.940-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='My OSS'/><category scheme='http://www.blogger.com/atom/ns#' term='MS'/><title type='text'>Tainted Heroes?</title><content type='html'>I am perplexed by the recent &lt;a href="http://www.microsoft.com/opensource/heroes"&gt;Microsoft's {Open Source} Heroes campaign&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Believe me, I am working very hard to fight any bias against the stuff that comes from Redmond (just by respect to the great people they have and the cool stuff they are cooking in their labs). But for this campaign I can not help but smelling something fishy. Maybe because I am (lightly) &lt;a href="http://nxbre.org"&gt;active in the .NET open source community&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Anyway, for this campaign, Microsoft was granting a Hack Pack containing a trial copy of Windows Server 2008 and Visual Studio 2008 to open source developers all around the world. How is that going to help the .NET open source community? I do not have the faintest idea. But I can easily see how it can benefit Microsoft, especially when the trial period is over and the hero needs to buy a license.&lt;br /&gt;&lt;br /&gt;I do believe &lt;a href="http://www.infoq.com/news/2008/07/Castle-Hammett-Microsoft"&gt;there are real open source minded people at Microsoft&lt;/a&gt;. I also believe they are not allowed to come anywhere near the marketing department. They probably wear a special dress and have "&lt;a href="http://www.google.ca/search?hl=en&amp;amp;q=%22to+ring+bells+to+warn+people+of+their+presence%22"&gt;to ring bells to warn people of their presence&lt;/a&gt;" too.&lt;br /&gt;&lt;br /&gt;My open source experience in .NET land, compared to the one I have in the Java-lala-land, suggests that the last thing Microsoft developers need is yet another tool-lock-in scheme. I find .NET developers deeply engrossed with their IDE, sorry, with &lt;span style="font-style: italic;"&gt;the IDE&lt;/span&gt;, to the extent that any project that is not formatted and designed for Visual Studio is a real challenge.&lt;br /&gt;&lt;br /&gt;A few years ago, I made the choice to use &lt;a href="http://sharpdevelop.net/OpenSource/SD/"&gt;SharpDevelop&lt;/a&gt; for developing &lt;a href="http://nxbre.org"&gt;NxBRE&lt;/a&gt;. The first versions of this IDE were pretty rough but I was immediately convinced by the fact a version of SharpDevelop was not tied to a particular version of .NET. This establishes the necessary distinction between the CLR and the SDK on one hand, and the development environment on the other hand.&lt;br /&gt;&lt;br /&gt;So what about our heroes? Open source developers do not need time-trialed (or not) vendor specific tooling. They need 36 hours days and 2 extra arms, something for which Microsoft can not do anything. They also need &lt;span style="font-weight: bold;"&gt;a community of like-minded developers&lt;/span&gt;, something Microsoft should stop smothering and start fostering.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-9066671547213103486?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/9066671547213103486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=9066671547213103486' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/9066671547213103486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/9066671547213103486'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/07/tainted-heroes.html' title='Tainted Heroes?'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-4163796397627560527</id><published>2008-07-27T14:57:00.004-07:00</published><updated>2008-07-27T15:05:46.400-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Craftsmanship'/><title type='text'>Ouch of the day</title><content type='html'>&lt;blockquote&gt;This book is built on a rather fragile premise: that good code matters. I have seen too much ugly code make too much money to believe that quality of code is either necessary or sufficient for commercial success or widespread use. However, I still believe that quality of code matters even if it doesn't provide control over the future. Businesses that are able to develop and release with confidence, shift direction in response to opportunities and competition, and maintain positive morale through challenges and setbacks will tend to be more successful than businesses with shoddy, buggy code.&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;div style="text-align: right;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Kent_Beck"&gt;Kent Beck&lt;/a&gt;, preface of &lt;a href="http://www.amazon.com/Implementation-Patterns-Addison-Wesley-Signature-Kent/dp/0321413091"&gt;Implementation Patterns&lt;/a&gt;.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-4163796397627560527?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/4163796397627560527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=4163796397627560527' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4163796397627560527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/4163796397627560527'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/07/ouch-of-day.html' title='Ouch of the day'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13243193.post-7597598089100009634</id><published>2008-07-24T13:07:00.003-07:00</published><updated>2008-07-24T13:17:30.717-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Fun'/><title type='text'>GR8 JRB MOO!</title><content type='html'>As this screen shot shows it, Mercury does not care if I have a 24" monitor. &lt;span style="font-style: italic;"&gt;It is going to be 200 pixels and not one more, sir! Get over it, sir!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_wgiUOehXWyI/SIjhKc9C9wI/AAAAAAAAABc/h4CVww81E5g/s1600-h/Screenshot-Mercury+SiteScope+-+Mozilla+Firefox.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_wgiUOehXWyI/SIjhKc9C9wI/AAAAAAAAABc/h4CVww81E5g/s400/Screenshot-Mercury+SiteScope+-+Mozilla+Firefox.png" alt="" id="BLOGGER_PHOTO_ID_5226674937250641666" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Has anybody tested this page? In the same vein: has anybody tested Outlook Web Access 2007? It behaves like a web mail from the early 2000s.&lt;br /&gt;&lt;br /&gt;Why do expensive enterprise tools feel they must be sub-standard in their GUIs? Why is that that as soon as a product is deemed &lt;span style="font-style: italic;"&gt;enterprise&lt;/span&gt; &lt;span style="font-style: italic;"&gt;grade&lt;/span&gt;, the game changes and it suddenly is all about paying six figure license fees for something an open source project would feel embarrassed with.&lt;br /&gt;&lt;br /&gt;Will vendors react or do they just try to milk the cow until it decides to kick them away? Or does the cow care at all? Maybe the cow likes arid and painful tools so they feel &lt;span style="font-style: italic;"&gt;enterprisey&lt;/span&gt;?&lt;br /&gt;&lt;br /&gt;Moo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/13243193-7597598089100009634?l=blog.dossot.net' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.dossot.net/feeds/7597598089100009634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=13243193&amp;postID=7597598089100009634' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7597598089100009634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13243193/posts/default/7597598089100009634'/><link rel='alternate' type='text/html' href='http://blog.dossot.net/2008/07/gr8-jrb-moo.html' title='GR8 JRB MOO!'/><author><name>David Dossot</name><uri>http://www.blogger.com/profile/13987512594987806769</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://4.bp.blogspot.com/_wgiUOehXWyI/SNMVc_IHoII/AAAAAAAAAGA/0Z7-478Vet4/s1600-R/c48948f53594545aa48de2146389f48a.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_wgiUOehXWyI/SIjhKc9C9wI/AAAAAAAAABc/h4CVww81E5g/s72-c/Screenshot-Mercury+SiteScope+-+Mozilla+Firefox.png' height='72' width='72'/><thr:total>2</thr:total></entry></feed>
