<?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'><id>tag:blogger.com,1999:blog-6675534776398892468</id><updated>2010-03-12T14:59:23.683+01:00</updated><title type='text'>sharp bites</title><subtitle type='html'>Standing on the shoulders of giants</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default?start-index=26&amp;max-results=25'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>54</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-8970130574201855675</id><published>2010-02-27T17:01:00.000+01:00</published><updated>2010-02-27T17:01:02.033+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><title type='text'>Bash completion for symfony</title><content type='html'>&lt;a href="http://www.tatai.es/"&gt;Fran&lt;/a&gt;&amp;nbsp;(a.k.a. tatai), one of my teammates at Biko, was kind enough to make us a nice (and unreadable) script to get &lt;a href="http://github.com/biko2/symfony_complete"&gt;symfony bash completion&lt;/a&gt;. Get it while it's hot!&lt;br /&gt;&lt;br /&gt;You can read more about the script on &lt;a href="http://www.tatai.es/2010/02/26/bash-completion-for-symfony/"&gt;tatai's blog&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Kudos @tatai for your work!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-8970130574201855675?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/8970130574201855675/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=8970130574201855675' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/8970130574201855675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/8970130574201855675'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2010/02/bash-completion-for-symfony.html' title='Bash completion for symfony'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-2750932543022742863</id><published>2009-11-08T02:23:00.000+01:00</published><updated>2009-11-08T02:23:25.626+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='analogic life'/><category scheme='http://www.blogger.com/atom/ns#' term='work'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Sometimes You Have To Take A Step Back Before You Can Move Forward</title><content type='html'>Or how I am moving to a PHP team to free myself from WebForms.&lt;br /&gt;&lt;br /&gt;So expect to find some stuff (probably including some rants) here about PHP from now on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-2750932543022742863?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/2750932543022742863/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=2750932543022742863' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2750932543022742863'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2750932543022742863'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/11/sometimes-you-have-to-take-step-back.html' title='Sometimes You Have To Take A Step Back Before You Can Move Forward'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-2630109774270324437</id><published>2009-10-19T21:14:00.001+02:00</published><updated>2009-10-19T21:14:46.263+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='altnerddinner'/><category scheme='http://www.blogger.com/atom/ns#' term='dependency injection'/><category scheme='http://www.blogger.com/atom/ns#' term='nhibernate'/><title type='text'>AltNerDinner: Part 4. Introducing NHibernate. Because POCO is enough</title><content type='html'>&lt;p&gt;It's time already to introduce a proper persistence solution. NHibernate can be a little intimidating at first for a new-comer, but I undoubtedly think it's the way to go. And it's not really more difficult than the other contenders anymore. Its two major drawbacks (hand writing all that XMhelL mapping and not strongly typed queries) are solved (or in serious process of it) by Fluent NHibernate and NHibernate.Linq.&lt;/p&gt;  &lt;p&gt;Other than that, the only difficulty relies in learning a few concepts inherent to OR/Ms. Most notably the &lt;a href="http://martinfowler.com/eaaCatalog/unitOfWork.html"&gt;Unit of Work&lt;/a&gt; pattern and &lt;a href="http://martinfowler.com/eaaCatalog/lazyLoad.html"&gt;Lazy Loading&lt;/a&gt;, and all the stuff around them (namely repositories, query objects, persistence ignorance, POCOs, DTOs, entities/value objects and equality, inheritance mapping, dynamic proxies, caching, anemic domains, active record, transactions, concurrency, session lifetime, unit testing, select n+1 problems and other pitfalls to avoid,&amp;#160; ...). [NOTE: If you need more info on this topics I'd recommend you to visit the &lt;a href="http://nhforge.org/"&gt;official nhibernate site&lt;/a&gt;.]&lt;/p&gt;  &lt;p&gt;Sounds scary? It might seem using an OR/M brings in more problems that the ones it solves, but I don't think it is the case, except for maybe the most trivial apps (like AltNerdDinner, hehe, I know). Even if you are writing a relatively simple app, you can still greatly benefit from using NHibernate (or Active Record on top of it). If your app has inherent complexity, well, of course you'll have to do your homework and learn a few concepts, but that's not your OR/M's fault. Using a hand-rolled DAL won't make your problems go away (quite the opposite, I'd dare to say).&lt;/p&gt;  &lt;p&gt;As I said, most (if not all) of this problems exist in all OR/M, it's just that some of them somehow try to hide this complexity in one or another way. The problem is, this is a can of worms that can lead to very bad practices and slap on your face at any moment. And this is were I think this is were NHibernate excels at, its flexibility. It gets out of your way.&lt;/p&gt;  &lt;h4&gt;Ok, enough talking! Show me the code!&lt;/h4&gt;  &lt;p&gt;To use NHibernate and NH.Linq we need to add a reference in our project to the following dll's: NHibernate, NHibernate.Linq, FluentNHibernate (if we hadn't already) and lastly NHibernate.ByteCode.Castle if we want to use Castle's dynamic proxy as our proxy generator of choice.&lt;/p&gt;  &lt;p&gt;Here is the code for my DinnerRepository implementation using NHibernate:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NhDinnerRepository &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;IDinnerRepository&lt;br /&gt;&lt;/span&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;private readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ISession &lt;/span&gt;_session;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;NhDinnerRepository(&lt;span style="color: #2b91af"&gt;ISession &lt;/span&gt;session)&lt;br /&gt;    {&lt;br /&gt;        _session = session;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;private &lt;/span&gt;&lt;span style="color: #2b91af"&gt;INHibernateQueryable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Dinner&lt;/span&gt;&amp;gt; GetDbContext()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;_session.Linq&amp;lt;&lt;span style="color: #2b91af"&gt;Dinner&lt;/span&gt;&amp;gt;();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Dinner&lt;/span&gt;&amp;gt; FindAllDinners()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;GetDbContext().AsQueryable();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Dinner&lt;/span&gt;&amp;gt; FindByLocation(&lt;span style="color: blue"&gt;float &lt;/span&gt;latitude, &lt;span style="color: blue"&gt;float &lt;/span&gt;longitude)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;GetDbContext().Where(d =&amp;gt; d.Distance(latitude, longitude) &amp;lt; 100).AsQueryable();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IQueryable&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Dinner&lt;/span&gt;&amp;gt; FindUpcomingDinners()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return from &lt;/span&gt;dinner &lt;span style="color: blue"&gt;in &lt;/span&gt;GetDbContext()&lt;br /&gt;               &lt;span style="color: blue"&gt;where &lt;/span&gt;dinner.EventDate &amp;gt; &lt;span style="color: #2b91af"&gt;DateTime&lt;/span&gt;.Now&lt;br /&gt;               &lt;span style="color: blue"&gt;orderby &lt;/span&gt;dinner.EventDate&lt;br /&gt;               &lt;span style="color: blue"&gt;select &lt;/span&gt;dinner;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Dinner &lt;/span&gt;GetDinner(&lt;span style="color: blue"&gt;int &lt;/span&gt;id)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;GetDbContext().SingleOrDefault(d =&amp;gt; d.DinnerID == id);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public void &lt;/span&gt;Save(&lt;span style="color: #2b91af"&gt;Dinner &lt;/span&gt;dinner)&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;if &lt;/span&gt;(!dinner.IsValid)&lt;br /&gt;        {&lt;br /&gt;            &lt;span style="color: blue"&gt;throw new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ApplicationException&lt;/span&gt;(&lt;span style="color: #a31515"&gt;&amp;quot;Rule violations&amp;quot;&lt;/span&gt;);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        _session.SaveOrUpdate(dinner);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public void &lt;/span&gt;Delete(&lt;span style="color: #2b91af"&gt;Dinner &lt;/span&gt;dinner)&lt;br /&gt;    {&lt;br /&gt;        _session.Delete(dinner);&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;As you see, I am returning IQueryable&amp;lt;Dinner&amp;gt; instead of traditional .NET collections. Some people think &lt;a href="http://mikehadlow.blogspot.com/2009/01/should-my-repository-expose-iqueryable.html"&gt;IQueryable is the best thing since slice bread&lt;/a&gt;, others are &lt;a href="http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx"&gt;ditching repositories entirely&lt;/a&gt;, some prefer &lt;a href="http://www.udidahan.com/2007/03/28/query-objects-vs-methods-on-a-repository/"&gt;using query objects&lt;/a&gt;, others advocate for &lt;a href="http://codebetter.com/blogs/gregyoung/archive/2009/01/16/ddd-the-generic-repository.aspx"&gt;explicit repositories&lt;/a&gt;, some use &lt;a href="http://serialseb.blogspot.com/2009/08/nhibernate-repository-that-oren-wont.html"&gt;generic ones&lt;/a&gt; and I just don't know yet, but decided to go at least with repositories because I want to take &lt;a href="http://www.udidahan.com/2008/02/15/from-crud-to-domain-driven-fluency/"&gt;control of how entities are persisted&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;To instantiate my NHibernate repository, I need to supply it with an ISession. I &lt;a href="http://ayende.com/Blog/archive/2008/07/24/How-to-review-NHibernate-application.aspx"&gt;don't create the ISession inside the repository&lt;/a&gt;, since this is considered a bad practice. Instead, I create a new Session per request. To do that, I expected I would have some infrastructure in place in MvcContrib, but that was not the case. &lt;a href="http://jeffreypalermo.com"&gt;Jeffrey Palermo&lt;/a&gt; posted a &lt;a href="http://jeffreypalermo.com/blog/use-this-nhibernate-wrapper-to-keep-your-repository-classes-simple/"&gt;NHibernate wrapper to manage ISession&lt;/a&gt;, but I thought that class had too many responsibilities, so I separated it in the following.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;SessionFactoryBuilder&lt;br /&gt;&lt;/span&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;private static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ISessionFactory &lt;/span&gt;_sessionFactory;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;private readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IPersistenceConfigurer &lt;/span&gt;_dbConfiguration;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;SessionFactoryBuilder(&lt;span style="color: #2b91af"&gt;IPersistenceConfigurer &lt;/span&gt;dbConfiguration)&lt;br /&gt;    {&lt;br /&gt;        _dbConfiguration = dbConfiguration;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ISessionFactory &lt;/span&gt;Build()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;if &lt;/span&gt;(_sessionFactory == &lt;span style="color: blue"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            _sessionFactory  = GetDbConfiguration().BuildSessionFactory();   &lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;_sessionFactory;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Configuration &lt;/span&gt;GetDbConfiguration()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Fluently&lt;/span&gt;.Configure()&lt;br /&gt;                .Mappings(m =&amp;gt; m.FluentMappings.AddFromAssemblyOf&amp;lt;&lt;span style="color: #2b91af"&gt;Dinner&lt;/span&gt;&amp;gt;())&lt;br /&gt;                .Database(_dbConfiguration)                    &lt;br /&gt;                .BuildConfiguration();&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This builds the session factory and also returns the configuration (useful to create the schema). It needs an IPersistenceConfigurer, which I supply from the constructor, in order to be able to switch between different configurations (i.e. MSSQL and SQLite), as shown below:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MsSqlPersistenceConfigurerFactory &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;IPersistenceConfigurerFactory&lt;br /&gt;&lt;/span&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;private string &lt;/span&gt;_connectionString;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;MsSqlPersistenceConfigurerFactory(&lt;span style="color: blue"&gt;string &lt;/span&gt;connectionString)&lt;br /&gt;    {&lt;br /&gt;        _connectionString = connectionString;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IPersistenceConfigurer &lt;/span&gt;GetPersistenceConfigurer()&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;return &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MsSqlConfiguration&lt;/span&gt;.MsSql2005&lt;br /&gt;                .ConnectionString(c =&amp;gt; c.Is(_connectionString))&lt;br /&gt;                .ShowSql()&lt;br /&gt;                .FormatSql()&lt;br /&gt;                .ProxyFactoryFactory&amp;lt;&lt;span style="color: #2b91af"&gt;ProxyFactoryFactory&lt;/span&gt;&amp;gt;();&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Life of a Session&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;We need to create the aforementioned ISession somehow. In Web applications, it's generally a good practice to create a new Session on every request. For that, Ayende recently &lt;a href="http://ayende.com/Blog/archive/2009/08/05/do-you-need-a-framework.aspx"&gt;suggested&lt;/a&gt; to just stick it in the global.asax, but I prefer to put it in a separate&amp;#160; IHttpModule.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NhSessionPerRequestModule &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;IHttpModule&lt;br /&gt;&lt;/span&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;private readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ISessionFactory &lt;/span&gt;_sessionFactory;&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;NhSessionPerRequestModule(&lt;span style="color: #2b91af"&gt;ISessionFactory &lt;/span&gt;sessionFactory)&lt;br /&gt;    {&lt;br /&gt;        _sessionFactory = sessionFactory;&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color: blue"&gt;public void &lt;/span&gt;Init(&lt;span style="color: #2b91af"&gt;HttpApplication &lt;/span&gt;application)&lt;br /&gt;    {&lt;br /&gt;        application.BeginRequest += &lt;span style="color: blue"&gt;delegate&lt;br /&gt;                                    &lt;/span&gt;{&lt;br /&gt;                                        CurrentSession = _sessionFactory.OpenSession();&lt;br /&gt;                                    };&lt;br /&gt;&lt;br /&gt;        application.EndRequest += &lt;span style="color: blue"&gt;delegate&lt;br /&gt;                                  &lt;/span&gt;{&lt;br /&gt;                                      &lt;span style="color: blue"&gt;if &lt;/span&gt;(CurrentSession != &lt;span style="color: blue"&gt;null&lt;/span&gt;)&lt;br /&gt;                                      {&lt;br /&gt;                                          CurrentSession.Dispose();&lt;br /&gt;                                      }&lt;br /&gt;                                  };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ISession &lt;/span&gt;CurrentSession&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="color: blue"&gt;get &lt;/span&gt;{ &lt;span style="color: blue"&gt;return &lt;/span&gt;(&lt;span style="color: #2b91af"&gt;ISession&lt;/span&gt;)&lt;span style="color: #2b91af"&gt;HttpContext&lt;/span&gt;.Current.Items[&lt;span style="color: #a31515"&gt;&amp;quot;current.session&amp;quot;&lt;/span&gt;]; }&lt;br /&gt;        &lt;span style="color: blue"&gt;private set &lt;/span&gt;{ &lt;span style="color: #2b91af"&gt;HttpContext&lt;/span&gt;.Current.Items[&lt;span style="color: #a31515"&gt;&amp;quot;current.session&amp;quot;&lt;/span&gt;] = &lt;span style="color: blue"&gt;value&lt;/span&gt;; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span style="color: blue"&gt;public void &lt;/span&gt;Dispose()&lt;br /&gt;    {        &lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In my Global.asax, I configure it as follows:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;private static readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ISessionFactory &lt;/span&gt;SessionFactory = CreateSessionFactory();&lt;br /&gt;&lt;span style="color: blue"&gt;private static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;IWindsorContainer &lt;/span&gt;_container;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue"&gt;private static &lt;/span&gt;&lt;span style="color: #2b91af"&gt;ISessionFactory &lt;/span&gt;CreateSessionFactory()&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;string &lt;/span&gt;connString = &lt;span style="color: #2b91af"&gt;ConfigurationManager&lt;/span&gt;.ConnectionStrings[&lt;span style="color: #a31515"&gt;&amp;quot;AltNerdDinner&amp;quot;&lt;/span&gt;].ConnectionString;&lt;br /&gt;    &lt;span style="color: blue"&gt;return new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;SessionFactoryBuilder&lt;/span&gt;(&lt;br /&gt;            &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;MsSqlPersistenceConfigurerFactory&lt;/span&gt;(connString)&lt;br /&gt;                    .GetPersistenceConfigurer())&lt;br /&gt;            .Build();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue"&gt;private readonly &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NhSessionLifetimeModule &lt;/span&gt;_nhSessionLifetimeModule =&lt;br /&gt;        &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;NhSessionLifetimeModule&lt;/span&gt;(SessionFactory);&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue"&gt;public override void &lt;/span&gt;Init()&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;base&lt;/span&gt;.Init();&lt;br /&gt;    _nhSessionLifetimeModule.Init(&lt;span style="color: blue"&gt;this&lt;/span&gt;);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Lastly, this is my current configuration of the container in order to register the components:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;private void &lt;/span&gt;RegisterComponents()&lt;br /&gt; {&lt;br /&gt;     _container = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;WindsorContainer&lt;/span&gt;();&lt;br /&gt;     _container.AddFacility&amp;lt;&lt;span style="color: #2b91af"&gt;FactorySupportFacility&lt;/span&gt;&amp;gt;();&lt;br /&gt;&lt;br /&gt;     &lt;span style="color: #2b91af"&gt;ControllerBuilder&lt;/span&gt;.Current.SetControllerFactory(&lt;br /&gt;         &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;WindsorControllerFactory&lt;/span&gt;(_container));&lt;br /&gt;&lt;br /&gt;     _container.Register(&lt;br /&gt;             &lt;span style="color: #2b91af"&gt;Component&lt;/span&gt;.For&amp;lt;&lt;span style="color: #2b91af"&gt;ISession&lt;/span&gt;&amp;gt;()&lt;br /&gt;                     .UsingFactoryMethod(() =&amp;gt; &lt;span style="color: #2b91af"&gt;NhSessionLifetimeModule&lt;/span&gt;.CurrentSession)&lt;br /&gt;                     .LifeStyle.Transient);&lt;br /&gt;  &lt;br /&gt;     _container.Register(&lt;br /&gt;             &lt;span style="color: #2b91af"&gt;Component&lt;/span&gt;.For&amp;lt;&lt;span style="color: #2b91af"&gt;IDinnerRepository&lt;/span&gt;&amp;gt;()&lt;br /&gt;                     .ImplementedBy&amp;lt;&lt;span style="color: #2b91af"&gt;NhDinnerRepository&lt;/span&gt;&amp;gt;().LifeStyle.Transient);&lt;br /&gt;&lt;br /&gt;     _container.RegisterControllers(&lt;span style="color: #2b91af"&gt;Assembly&lt;/span&gt;.GetExecutingAssembly());&lt;br /&gt; }&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-2630109774270324437?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/2630109774270324437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=2630109774270324437' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2630109774270324437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2630109774270324437'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/10/altnerdinner-part-4-introducing.html' title='AltNerDinner: Part 4. Introducing NHibernate. Because POCO is enough'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-5361056737775209402</id><published>2009-10-16T17:34:00.001+02:00</published><updated>2009-10-16T17:34:44.460+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bits'/><category scheme='http://www.blogger.com/atom/ns#' term='wtf'/><category scheme='http://www.blogger.com/atom/ns#' term='convention over configuration'/><title type='text'>Java and (the lack of) CoC</title><content type='html'>&lt;blockquote&gt;   &lt;p&gt;&amp;quot;Java is a DSL to transform big Xml documents into long exception stack traces.&amp;quot;&lt;/p&gt;   &lt;cite&gt;-- Scott Bellware&lt;/cite&gt;&lt;/blockquote&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-5361056737775209402?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/5361056737775209402/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=5361056737775209402' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/5361056737775209402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/5361056737775209402'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/10/java-and-lack-of-coc.html' title='Java and (the lack of) CoC'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-3235742071083678195</id><published>2009-10-14T23:02:00.001+02:00</published><updated>2009-10-14T23:19:48.589+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='altnerddinner'/><category scheme='http://www.blogger.com/atom/ns#' term='nhibernate'/><title type='text'>AltNerdDinner: Part 3. Introducing Fluent NHibernate. Mapping, the easy way</title><content type='html'>&lt;p&gt;&lt;em&gt;This is part 3 of the &lt;a href="http://sharpbites.blogspot.com/2009/08/introducing-altnerddinner.html"&gt;AltNerdDinner&lt;/a&gt; Series.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;One of the things I always disliked the most when exploring NHibernate was the need of declaring all the mappings in XMhelL. And don't know about you, but that's not something I want to be spending my time creating, modifying, hand-refactoring or debugging tedious tons of this crap.&lt;/p&gt;  &lt;p&gt;Fast forward to 2008 and say hello to &lt;a href="http://fluentnhibernate.org/"&gt;Fluent NHibernate&lt;/a&gt;. (And don't forget to thank &lt;a href="http://codebetter.com/blogs/jeremy.miller/"&gt;Jeremy Miller&lt;/a&gt;, &lt;a href="http://blog.jagregory.com/"&gt;James Gregory&lt;/a&gt; &lt;a href="http://code.google.com/p/fluent-nhibernate/people/list"&gt;&lt;em&gt;et al&lt;/em&gt;&lt;/a&gt;!). It is basically a way to programmatically declare the mappings, allowing you to go from this:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #a31515"&gt;xml &lt;/span&gt;&lt;span style="color: red"&gt;version&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;1.0&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;encoding&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;utf-8&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;?&amp;gt;  &lt;br /&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;hibernate-mapping &lt;/span&gt;&lt;span style="color: red"&gt;xmlns&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;urn:nhibernate-mapping-2.2&lt;/span&gt;&amp;quot;  &lt;br /&gt;  &lt;span style="color: red"&gt;namespace&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;QuickStart&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;assembly&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;QuickStart&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;  &lt;br /&gt; &lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;class &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Cat&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;table&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Cat&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;  &lt;br /&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;id &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Id&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;  &lt;br /&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;generator &lt;/span&gt;&lt;span style="color: red"&gt;class&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;identity&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;  &lt;br /&gt;    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;id&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;  &lt;br /&gt; &lt;br /&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;property &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Name&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;  &lt;br /&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;column &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Name&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;length&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;16&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;not-null&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;true&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;  &lt;br /&gt;    &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;property&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;  &lt;br /&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;property &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Sex&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;  &lt;br /&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;many-to-one &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Mate&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;  &lt;br /&gt;    &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;bag &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Kittens&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;  &lt;br /&gt;      &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;key &lt;/span&gt;&lt;span style="color: red"&gt;column&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;mother_id&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;  &lt;br /&gt;        &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;one-to-many &lt;/span&gt;&lt;span style="color: red"&gt;class&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;Cat&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;  &lt;br /&gt;      &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;bag&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;  &lt;br /&gt;  &amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;class&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;  &lt;br /&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;hibernate-mapping&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;To this:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;CatMap &lt;/span&gt;: ClassMap&amp;lt;Cat&amp;gt;&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;CatMap()&lt;br /&gt;    {&lt;br /&gt;        Id(x =&amp;gt; x.Id);&lt;br /&gt;        Map(x =&amp;gt; x.Name)&lt;br /&gt;          .Length(16)&lt;br /&gt;          .Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.Sex);&lt;br /&gt;        References(x =&amp;gt; x.Mate);&lt;br /&gt;        HasMany(x =&amp;gt; x.Kittens);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;What it gives you, you may ask? Compile-time checks and refactoring support, for a start.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;But wait, there is more!&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Fluent NHibernate is built with &lt;a href="http://en.wikipedia.org/wiki/Convention_over_Configuration"&gt;Convention over Configuration&lt;/a&gt; in mind. So, if you adhere to it, you can greatly reduce the amount of mapping needed, by virtue of &lt;a href="http://wiki.fluentnhibernate.org/Auto_mapping"&gt;auto mapping&lt;/a&gt;. And you can combine that with explicit ClassMap mappings, like the one above, they are not mutually exclusive.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Mapping your domain can be as simple as:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;AutoMap.AssemblyOf&amp;lt;Product&amp;gt;();&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;And if you call within the next 5 minutes we throw in Conventions for free!&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&amp;quot;Ok, that might be great for a greenfield project, but I am working in a big brown piece of ... code&amp;quot;, I hear you saying. So you may not have the choice to call your Id's &amp;quot;Id&amp;quot; or name your tables exactly after your classes. &lt;a href="http://wiki.fluentnhibernate.org/Conventions"&gt;Conventions&lt;/a&gt; can greatly help here, allowing you to define your own conventions. That is, if your database naming follows any convention at all, and wasn't defined by a bunch of monkeys typing at random.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;For further info, check the &lt;a href="http://fluentnhibernate.org/"&gt;site&lt;/a&gt;, &lt;a href="http://wiki.fluentnhibernate.org/"&gt;wiki&lt;/a&gt; and &lt;a href="http://groups.google.com/group/fluent-nhibernate"&gt;mailing list&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;AltNerdDinner's mappings&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Here are the mapping files for AltNerdDinner.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DinnerMap &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;ClassMap&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Dinner&lt;/span&gt;&amp;gt;&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;DinnerMap()&lt;br /&gt;    {&lt;br /&gt;        Id(x =&amp;gt; x.DinnerID);&lt;br /&gt;        Map(x =&amp;gt; x.Address).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.ContactPhone).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.Country).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.Description).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.EventDate).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.HostedBy).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.Latitude).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.Longitude).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.Title).Not.Nullable();&lt;br /&gt;        HasMany(x =&amp;gt; x.RSVPs).Cascade.AllDeleteOrphan();&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;RSVPMap &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;ClassMap&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;RSVP&lt;/span&gt;&amp;gt;&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;RSVPMap()&lt;br /&gt;    {&lt;br /&gt;        Id(x =&amp;gt; x.RsvpId);&lt;br /&gt;        Map(x =&amp;gt; x.AttendeeName).Not.Nullable();&lt;br /&gt;        References(r =&amp;gt; r.Dinner).&lt;strong&gt;Nullable()&lt;/strong&gt;;            &lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;One gotcha that had me fiddling around for a while was that Nullable part on the Dinner reference in RSVPMap. If you don't set it to nullable, you'll get an exception when trying to persist the entities. And even if you set it to nullable, you'll find out, NHibernate executes two queries to insert the RSVP.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; INSERT INTO&amp;#160; [RSVP] (AttendeeName, Dinner_id) VALUES (@p0, @p1); &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; select SCOPE_IDENTITY(); &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @p0 = 'alberto', &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; @p1 = 9 &lt;br /&gt;&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; UPDATE [RSVP] SET Dinner_id = @p0 WHERE RsvpId = @p1; @p0 = 9, @p1 = 21&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;You can find &lt;a href="http://nhforge.org/doc/nh/en/index.html#example-parentchild-bidir"&gt;more info&lt;/a&gt; about this behavior in the &lt;a href="http://nhforge.org/"&gt;official nhibernate site&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So, what I have done instead is to set the RSVP as the managing part of the relationship, changing it back to not nullable and using Inverse() on the Dinner's mapping side.&lt;/p&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;It is not possible to make the &amp;quot;many part&amp;quot; responsible for this. What this means is that we have to persist our entities calling:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;Dinner &lt;/span&gt;dinner = _dinnerRepository.GetDinner(id);&lt;br /&gt;&lt;span style="color: blue"&gt;var &lt;/span&gt;rsvp = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;RSVP&lt;/span&gt;{ AttendeeName = username };&lt;br /&gt;rsvp.Dinner = dinner;&lt;br /&gt;dinner.Rsvps.Add(rsvp);&lt;br /&gt;_dinnerRepository.Save(dinner);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;That's not very ideal, so I have included an AddRsvp() method in Dinner to handle that. Now I have:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: #2b91af"&gt;Dinner &lt;/span&gt;dinner = _dinnerRepository.GetDinner(id);&lt;br /&gt;dinner.AddRsvp(&lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;RSVP&lt;/span&gt;{ AttendeeName = User.Identity.Name });&lt;br /&gt;_dinnerRepository.Save(dinner);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Much cleaner! In order to avoid confusion when adding an RSVO, I have changed the type of the collection to an IEnumerable&amp;lt;RSVP&amp;gt;, so that the collection cannot be modified directly, but only by means of Dinner (which is a good practice if you want to follow DDD, anyway). Because of that, I had to modified the DinnerMap to use a backing field for it. In the future I might revisit this relationship to include the User in the domain again and change it to a less CRUD-y style. You can read more on &lt;a href="http://www.udidahan.com/2008/02/15/from-crud-to-domain-driven-fluency/"&gt;Domain-Driven fluency&lt;/a&gt; from &lt;a href="http://www.udidahan.com/2008/02/15/from-crud-to-domain-driven-fluency/"&gt;Udi Dahan&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Anyway, here is the final mapping I have come up with:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;RSVPMap &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;ClassMap&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;RSVP&lt;/span&gt;&amp;gt;&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;RSVPMap()&lt;br /&gt;    {&lt;br /&gt;        Id(x =&amp;gt; x.RsvpId);&lt;br /&gt;        Map(x =&amp;gt; x.AttendeeName).Not.Nullable();&lt;br /&gt;        References(r =&amp;gt; r.Dinner).Not.Nullable();            &lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;DinnerMap &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;ClassMap&lt;/span&gt;&amp;lt;&lt;span style="color: #2b91af"&gt;Dinner&lt;/span&gt;&amp;gt;&lt;br /&gt;{&lt;br /&gt;    &lt;span style="color: blue"&gt;public &lt;/span&gt;DinnerMap()&lt;br /&gt;    {&lt;br /&gt;        Id(x =&amp;gt; x.DinnerID);&lt;br /&gt;        Map(x =&amp;gt; x.Address).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.ContactPhone).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.Country).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.Description).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.EventDate).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.HostedBy).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.Latitude).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.Longitude).Not.Nullable();&lt;br /&gt;        Map(x =&amp;gt; x.Title).Not.Nullable();&lt;br /&gt;        HasMany(x =&amp;gt; x.Rsvps).Access.CamelCaseField(&lt;span style="color: #2b91af"&gt;Prefix&lt;/span&gt;.Underscore)&lt;br /&gt;            .Inverse().Cascade.AllDeleteOrphan();&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-3235742071083678195?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/3235742071083678195/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=3235742071083678195' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/3235742071083678195'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/3235742071083678195'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/10/altnerddinner-part-3-introducing-fluent.html' title='AltNerdDinner: Part 3. Introducing Fluent NHibernate. Mapping, the easy way'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-6720675466522579576</id><published>2009-10-06T21:02:00.001+02:00</published><updated>2009-10-06T21:02:25.642+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='altnerddinner'/><category scheme='http://www.blogger.com/atom/ns#' term='dependency injection'/><category scheme='http://www.blogger.com/atom/ns#' term='good practices'/><title type='text'>AltNerdDinner: Part 2. Rich Man's Dependency Injection</title><content type='html'>&lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;This is part 2 of the &lt;a href="http://sharpbites.blogspot.com/2009/08/introducing-altnerddinner.html"&gt;AltNerdDinner&lt;/a&gt; Series.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;The classes in &lt;a href="http://nerddinner.codeplex.com/"&gt;NerdDinner&lt;/a&gt; use &lt;a href="http://martinfowler.com/articles/injection.html"&gt;dependency injection&lt;/a&gt; (&lt;a href="http://martinfowler.com/articles/injection.html#ConstructorInjectionWithPicocontainer"&gt;constructor injection&lt;/a&gt;, to be more precise), which is a form of &lt;a href="http://martinfowler.com/bliki/InversionOfControl.html"&gt;Inversion of Control&lt;/a&gt; that allows you to break the dependencies between classes, minimizing coupling (i.e. a Good Thing &amp;#8482;). Instead having classes with direct dependencies&amp;#160; on other classes, and instantiating them directly, classes are dependent on interfaces, and the concrete implementation is injected via the constructor, in this case, or via a setter in the case of &lt;a href="http://martinfowler.com/articles/injection.html#SetterInjectionWithSpring"&gt;setter injection&lt;/a&gt;. Constructor injection is preferred for required dependencies, as it makes dependencies more explicit, and setter injection is usually reserved for optional dependencies.&lt;/p&gt;  &lt;p&gt;Using this technique, the responsibility of providing the dependencies is delegated to the calling object (hence the term Inversion of Control).&lt;/p&gt;  &lt;h4&gt;Poor Man's Dependency Injection&lt;/h4&gt;  &lt;p&gt;The problem with the NerdDinner codebase is that, besides the constructor that accepts the required dependencies, they added a default constructor that news up those dependencies. Here is an example:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;public &lt;/span&gt;DinnersController() : &lt;span style="color: blue"&gt;this&lt;/span&gt;(&lt;span style="color: blue"&gt;new &lt;/span&gt;DinnerRepository())&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: blue"&gt;public &lt;/span&gt;DinnersController(&lt;span style="color: #2b91af"&gt;IDinnerRepository &lt;/span&gt;repository) {&lt;br /&gt;    dinnerRepository = repository;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This may look like a good compromise. You get the decoupling needed to run your tests (by means of the constructor accepting parameters) and you are also able to instantiate you classes calling the default constructor, without the added complexity of an IoC container. However this technique is considered an &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/07/03/how-not-to-do-dependency-injection-in-nerddinner.aspx"&gt;anti-pattern&lt;/a&gt; (although &lt;a href="http://devlicio.us/blogs/tim_barcz/archive/2009/07/12/why-there-s-nothing-wrong-with-dependency-injection-in-nerddinner.aspx"&gt;not everybody agrees&lt;/a&gt;) &lt;a href="http://www.lostechies.com/blogs/chad_myers/archive/2009/07/14/the-usual-result-of-poor-man-s-dependency-injection.aspx"&gt;leading to many headaches&lt;/a&gt;. By adding this constructor we're almost at square one again. Our classes are still coupled, and if we need to add new dependencies, we'll have to go hunting around to fix all the constructor calls.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;If I were a rich man&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;So now you are convinced to use an IoC container, you can have a look this &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/09/12/some-ioc-container-guidelines.aspx"&gt;container guidelines&lt;/a&gt; by &lt;a href="http://www.lostechies.com/blogs/jimmy_bogard/default.aspx"&gt;Jimmy Bogard&lt;/a&gt;. He may not consider his recommendations as best practices, but I do (and so should you, IMHO). I picked &lt;a href="http://www.castleproject.org/container/gettingstarted/index.html"&gt;Castle Windsor&lt;/a&gt; as my framework of choice. As usual, &lt;a href="http://structuremap.sourceforge.net/"&gt;there&lt;/a&gt; &lt;a href="http://code.google.com/p/autofac/"&gt;are&lt;/a&gt; &lt;a href="http://ninject.org/"&gt;plenty&lt;/a&gt;&amp;#160;&lt;a href="http://www.spring.net/"&gt;of&lt;/a&gt; &lt;a href="http://www.codeplex.com/unity"&gt;alternatives&lt;/a&gt;. Even though the API is not the cleanest of all the frameworks, I favored Windsor because it is very mature, is widely adopted, it also supports .NET 2.0, and has good integration with NHibernate. It also is the container used in &lt;a href="http://code.google.com/p/sharp-architecture/"&gt;S#arp Architecture&lt;/a&gt;, which is something I will probably end up using. Otherwise, my choice would be &lt;a href="http://structuremap.sourceforge.net/"&gt;StructureMap&lt;/a&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;In order to use Windsor, you have to reference on your project &lt;em&gt;Castle.Core&lt;/em&gt;, &lt;em&gt;Castle.MicroKernel&lt;/em&gt; and &lt;em&gt;Castle.Windsor&lt;/em&gt;. To ease the configuration of the container, I also downloaded &lt;a href="http://www.codeplex.com/MVCContrib"&gt;MvcContrib&lt;/a&gt; (which I was planning to use anyway) and added a reference to &lt;em&gt;MvcContrib.Castle&lt;/em&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;This is the code needed to register the controllers and the Repository.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;private void &lt;/span&gt;RegisterComponents()&lt;br /&gt;{&lt;br /&gt;    _container = &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;WindsorContainer&lt;/span&gt;();&lt;br /&gt;    &lt;span style="color: #2b91af"&gt;ControllerBuilder&lt;/span&gt;.Current.SetControllerFactory(&lt;br /&gt;        &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;WindsorControllerFactory&lt;/span&gt;(_container));&lt;br /&gt;    _container.RegisterControllers(&lt;span style="color: #2b91af"&gt;Assembly&lt;/span&gt;.GetExecutingAssembly());&lt;br /&gt;    _container.Register(&lt;br /&gt;            &lt;span style="color: #2b91af"&gt;Component&lt;/span&gt;.For&amp;lt;&lt;span style="color: #2b91af"&gt;IDinnerRepository&lt;/span&gt;&amp;gt;()&lt;br /&gt;            .ImplementedBy&amp;lt;&lt;span style="color: #2b91af"&gt;InMemoryDinnerRepository&lt;/span&gt;&amp;gt;());&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;To allow the creation of the controllers by the MVC framework, you need to supply a ControllerFactory that can instantiate them, as they now take dependencies on their constructors. MvcContrib provides one for Windsor, as well as the method RegisterControllers to, guess what, registering all the controllers in a specified assembly. I also registered my DinnerRepository, so that Windsor can resolve the references to it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-6720675466522579576?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/6720675466522579576/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=6720675466522579576' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/6720675466522579576'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/6720675466522579576'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/10/altnerddinner-part-2-rich-man.html' title='AltNerdDinner: Part 2. Rich Man&amp;#39;s Dependency Injection'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-463388537583013388</id><published>2009-10-03T18:56:00.001+02:00</published><updated>2009-10-03T18:56:16.244+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='altnerddinner'/><title type='text'>AltNerdDinner: Part 1. Removing unwanted dependencies</title><content type='html'>&lt;p&gt;The first thing I have done is to set up the project on &lt;a href="http://github.com/"&gt;github&lt;/a&gt;, so if you want to have a look at the code, check the &lt;a href="http://github.com/alberto/altnerddinner"&gt;AltNerdDinner repository&lt;/a&gt;. Then I set up the project following the guidelines of my series &lt;a href="http://sharpbites.blogspot.com/2009/09/road-to-continuous-integration.html"&gt;Continuous Integration series&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Now we are set, there is some stuff I don't want in AltNerdDinner, so I am mercilessly going to get rid of it.&lt;/p&gt;  &lt;h4&gt;Bye, MSTest&lt;/h4&gt;  &lt;p&gt;MSTest gives nothing useful beyond integration in VS (for which I prefer ReSharper's Test Runner or TDD.NET). I won't say it sucks, but &lt;a href="http://haacked.com/archive/2007/09/04/should-microsoft-really-bundle-open-source-software.aspx"&gt;Phil Haack did&lt;/a&gt;. It's just there to satisfy MS-Only shops. It's slow, and it evolves slowly too. It lags behind &lt;a href="http://www.nunit.org/index.php"&gt;the&lt;/a&gt;&amp;#160;&lt;a href="http://www.gallio.org/"&gt;alternative&lt;/a&gt; &lt;a href="http://www.codeplex.com/xunit"&gt;frameworks&lt;/a&gt;. Oh, and it requires VS to be installed on your build server (crazy!), and... &lt;/p&gt;  &lt;p&gt;So I replaced it with good ol'&amp;#160; &lt;a href="http://www.nunit.org/index.php"&gt;NUnit&lt;/a&gt;. It basically involves replacing:&lt;/p&gt;  &lt;p&gt;using Microsoft.VisualStudio.TestTools.UnitTesting; by using NUnit.Framework;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;[TestClass] and [TestMethod] by [TestFixture],&amp;#160; and [Test]&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;and a bunch of calls to Assert.IsInstanceOfType(object, type); by Assert.IsInstanceOf(type, object); (pay attention to the signature change!).&lt;/p&gt;  &lt;h4&gt;We don't need no membership provider&lt;/h4&gt;  &lt;p&gt;Right now I don't want to deal with membership provider. I think it's bloated and I don't want to have to mess with the authentication right now, so I am going to replace it with a FakeMembershipService for the moment and leave the decision of whether revisiting it or completely replacing it (probably the latter) for a later time.&lt;/p&gt;  &lt;h4&gt;LINQ to SQL is dead, long live NHibernate&lt;/h4&gt;  &lt;p&gt;L2S is probably a decent option for this kind of simple app, and it's very easy to quickly duct-tape a simple app. It has some goodies, like the visual designer and of course Linq. But it's not the best option if your app gets bigger and you need some more advanced ORM features, like different mapping capabilities or different databases support. It's not a bad tool, but it has &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2008/07/01/architecting-linq-to-sql-part-10.aspx"&gt;some limitations&lt;/a&gt; that need to be addressed and, unfortunately, the fact that &lt;a href="http://www.infoq.com/news/2008/11/DLINQ-Future"&gt;L2S is being killed&lt;/a&gt; means you are better not investing hard into it.&lt;/p&gt;  &lt;p&gt;So I am planning to replace it with NHibernate, a mature and tested product&amp;#160; that fits my needs. But just not yet. Right now, I will simply remove the L2S stuff and work with POCOs and an InMemoryRepository implementation (which is basically the FakeDinnerRepository present in the Tests project).&lt;/p&gt;  &lt;h5&gt;The model&lt;/h5&gt;  &lt;p&gt;As we can see on the picture of the original model, the domain is quite simple.&lt;a href="http://lh3.ggpht.com/_kQ7iivKjVno/SseCJ_ZEG0I/AAAAAAAAAMQ/ehF8shEf9Dg/s1600-h/image11.png"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" src="http://lh3.ggpht.com/_kQ7iivKjVno/SseCKvw9G1I/AAAAAAAAAMU/ft6vs8PlB_0/image_thumb9.png?imgmax=800" width="488" height="259" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I have simply created POCO classes replacing the L2S generated ones.&lt;/p&gt;  &lt;p&gt;After all the changes, we run all the tests and...&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_kQ7iivKjVno/SseCLKN9WMI/AAAAAAAAAMY/KpeLlk_F18c/s1600-h/testsgreen2.jpg"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="tests-green" src="http://lh5.ggpht.com/_kQ7iivKjVno/SseCL4M-ONI/AAAAAAAAAMc/Nr3Jv3PFVPc/testsgreen_thumb.jpg?imgmax=800" width="184" height="34" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;We're done!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-463388537583013388?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/463388537583013388/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=463388537583013388' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/463388537583013388'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/463388537583013388'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/10/altnerddinner-part-1-removing-unwanted.html' title='AltNerdDinner: Part 1. Removing unwanted dependencies'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-3255220909010797137</id><published>2009-09-28T21:03:00.003+02:00</published><updated>2009-09-28T21:15:15.914+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='project automation'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>The road to Continuous Integration. Part 3: Script it, build it, test it, break it, fix it. Commit it.</title><content type='html'>Ideally, any new developer in your team should be able to build your project with a single command or double-click. To accomplish that, we are going to use a build script.  &lt;br /&gt;You can also &lt;a href="http://nant.sourceforge.net/"&gt;pick&lt;/a&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/0k6kkbsd.aspx"&gt;your&lt;/a&gt; &lt;a href="http://rake.rubyforge.org/"&gt;poison&lt;/a&gt; here, too. I am going to stick with nant for the moment, because it's the most mature and broadly used, and the one I know better, despite of the &lt;i&gt;XMHell&lt;/i&gt; that is the angle-bracket orgy it imposes. &lt;a href="http://codebetter.com/blogs/david_laribee/archive/2008/08/25/omg-rake.aspx"&gt;Rake seems nice&lt;/a&gt;, and has less noise than the others, but I don't like the fact that I have to install ruby and rake separately. As I said, I like all of my dependencies being included in source control, so that my projects are self-contained (there are some efforts to get &lt;a href="http://www.stephenbalkum.com/archive/2009/06/09/when-all-you-need-is-a-rake.aspx"&gt;ruby and rake as a single executable&lt;/a&gt;, though). If you are hesitating between msbuild and nant, you can check out a &lt;a href="http://sharpbites.blogspot.com/2008/09/nant-vs-msbuild.html"&gt;comparison between nant and msbuild&lt;/a&gt; I did a while ago.  &lt;br /&gt;&lt;a href="http://lh5.ggpht.com/_kQ7iivKjVno/SsEIh_i4iCI/AAAAAAAAAME/oexhq-gr7N4/s1600-h/projectstructure10.jpg"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="project-structure" align="left" src="http://lh6.ggpht.com/_kQ7iivKjVno/SsEIiowefII/AAAAAAAAAMI/TuxGRy-ffPI/projectstructure_thumb8.jpg?imgmax=800" width="155" height="244" /&gt;&lt;/a&gt;  &lt;br /&gt;As you can see on the picture, I have added two build scripts to the root of &lt;a href="http://github.com/alberto/altnerddinner"&gt;AltNerdDinner&lt;/a&gt;. &lt;i&gt;&lt;a href="http://github.com/alberto/altnerddinner/blob/master/common-targets.build"&gt;common-targets.build&lt;/a&gt;&lt;/i&gt; has, you know, common nant targets. It's a script I reuse between projects and it has all the tasks I usually execute (compile, recompile, publish or package the project, run the tests, analyze the code or binaries, etc). &lt;i&gt;&lt;a href="http://github.com/alberto/altnerddinner/blob/master/AltNerdDinner.build"&gt;AltNerdDinner.build&lt;/a&gt;&lt;/i&gt; is the specific script for this project. By virtue of &lt;a href="http://en.wikipedia.org/wiki/Convention_over_configuration"&gt;Convention over Configuration&lt;/a&gt; on the project structure and directory and file names, we can remove a lot of unnecessary noise. By adhering to conventions, we just have to set up a couple of properties and simply delegate on common-targets.build for most (if not all) of the tasks, just defining the dependencies between tasks and passing parameters to configure the task where needed.  &lt;br /&gt;  &lt;br /&gt;You can see below how simple it gets, with only 16 lines of code:  &lt;br /&gt;  &lt;br /&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&lt;/span&gt;&lt;span style="color: blue"&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;&amp;lt;?&lt;/span&gt;&lt;span style="color: #a31515"&gt;xml &lt;/span&gt;&lt;span style="color: red"&gt;version&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;1.0&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;?&amp;gt;&lt;br /&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;project &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;AltNerdDinner&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;default&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;compile&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;property &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;dir.root&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;value&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;${path::get-full-path('.')}&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;include &lt;/span&gt;&lt;span style="color: red"&gt;buildfile&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;${dir.root}/common-targets.build&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;property &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;file.solution&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;value&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;${dir.root}/NerdDinner.sln&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;property &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;file.project&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;value&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;${dir.root}/src/NerdDinner/NerdDinner.csproj&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;property &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;assembly.tests&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;value&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;NerdDinner.Tests.dll&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;target &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;compile&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;depends&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;common.clean, common.init, common.compile&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;target &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;test&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;depends&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;compile, common.test&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;target &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;publish&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;depends&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;test, common.publish&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;target &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;zip&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;depends&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;publish, common.zip&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;target &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;analyze&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;depends&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;publish, common.stylecop, common.ndepend&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;target &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;build&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;depends&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;publish, analyze&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;  &amp;lt;&lt;/span&gt;&lt;span style="color: #a31515"&gt;target &lt;/span&gt;&lt;span style="color: red"&gt;name&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;build-full&lt;/span&gt;&amp;quot; &lt;span style="color: red"&gt;depends&lt;/span&gt;&lt;span style="color: blue"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color: blue"&gt;publish, analyze, zip&lt;/span&gt;&amp;quot; &lt;span style="color: blue"&gt;/&amp;gt;&lt;br /&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #a31515"&gt;project&lt;/span&gt;&lt;span style="color: blue"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;There is also a &lt;a href="http://github.com/alberto/altnerddinner/blob/master/go.bat"&gt;go.bat&lt;/a&gt; script, which just calls nant, passing AltNerdDinner.build as the build file. As a side note, notice that my solution file is in the root of the project instead of in src. I like to keep it there so that I can easily refer to the root of the project from it (useful if you want to dome some pre/post build stuff on Visual Studio or for other tools than reference your solution).&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-3255220909010797137?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/3255220909010797137/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=3255220909010797137' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/3255220909010797137'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/3255220909010797137'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/09/road-to-continuous-integration-part-3.html' title='The road to Continuous Integration. Part 3: Script it, build it, test it, break it, fix it. Commit it.'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-7426619163897805663</id><published>2009-09-15T11:33:00.002+02:00</published><updated>2009-09-15T11:34:59.466+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wtf'/><title type='text'>What do you see on the picture?</title><content type='html'>&lt;div class="separator" style="clear: both; float: left; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_kQ7iivKjVno/Sq9dG5dZPCI/AAAAAAAAAL8/Z4vqxop7-cY/s1600-h/monofinger.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_kQ7iivKjVno/Sq9dG5dZPCI/AAAAAAAAAL8/Z4vqxop7-cY/s320/monofinger.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;a href="http://monotouch.net/"&gt;Monotouch&lt;/a&gt; 1.0 was released today. I was quite shocked when I saw the logo. Look at it for a second. What do you see there?&lt;br /&gt;It might be my perturbated mind, but I was quite shocked when I felt it was "showing me the finger". It actually took me a minute (I said I was shocked) to realize it was not &lt;i&gt;that &lt;/i&gt;finger. Still, maybe that logo deserves a revamp. Just making clear the first finger is a thumb will suffice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-7426619163897805663?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/7426619163897805663/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=7426619163897805663' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/7426619163897805663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/7426619163897805663'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/09/what-do-you-see-on-picture.html' title='What do you see on the picture?'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_kQ7iivKjVno/Sq9dG5dZPCI/AAAAAAAAAL8/Z4vqxop7-cY/s72-c/monofinger.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-6331902920249328748</id><published>2009-09-13T20:11:00.001+02:00</published><updated>2009-09-13T20:11:17.785+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='project automation'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>The road to Continuous Integration. Part 2: Shake your tree</title><content type='html'>&lt;p&gt;As I stated in the &lt;a href="http://sharpbites.blogspot.com/2009/09/road-to-continuous-integration-part-1.html"&gt;first part&lt;/a&gt; of this &lt;a href="http://sharpbites.blogspot.com/2009/09/road-to-continuous-integration.html"&gt;Continuous Integration series&lt;/a&gt;, one of the aims of storing your stuff under source control is being able to build your project from a fresh checkout, without needing to manually install or configure anything.&lt;/p&gt;  &lt;p&gt;To accomplish this, it is always useful to use a standardized tree structure. You can have a look at some of the popular open source projects you use and love to get ideas on how to organize things. Now that your have &lt;a href="http://sharpbites.blogspot.com/2009/09/road-to-continuous-integration-part-1.html"&gt;everything under source control&lt;/a&gt; (don't you?), we can start moving a few things around.&lt;/p&gt;  &lt;p&gt;&lt;img align="right" src="http://4.bp.blogspot.com/_kQ7iivKjVno/SpghIOjZSzI/AAAAAAAAALc/SkfsSCTd74E/s400/project-structure.jpg" /&gt; On the picture you can see a very typical structure for a project.&lt;/p&gt;  &lt;p&gt;The &lt;strong&gt;src&lt;/strong&gt; folder contains the different projects in their respective folders.     &lt;br /&gt;The &lt;strong&gt;lib&lt;/strong&gt; folder will contain any third-party library needed to run our project. This is, any dependency that has to be deployed with our project (e.g. NHibernate, Windsor, etc).     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;The &lt;strong&gt;tools&lt;/strong&gt; folders will contain any tools needed to build our project. It will contain tools like nant, nunit or fxcop, which we will use but won't distribute with our application.     &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;The &lt;strong&gt;build&lt;/strong&gt; folder will hold the artifacts of the build.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;Again, the purpose of putting all these libraries and frameworks under source control is to make EVERITHING needed to build and run your project available. Any new developer getting into your team should then be able to checkout your code and build it successfully, without needing to download and/or install anything from the Internet or hunt down any other dependencies your project builds upon. &lt;/p&gt;  &lt;p&gt;If you need further info, I would recommend you to watch &lt;a href="http://www.dimecasts.net/Casts/CastDetails/16"&gt;this screencast&lt;/a&gt; by &lt;a href="http://codebetter.com/blogs/kyle.baley/"&gt;Kyle &amp;quot;Dissociative identity disorder&amp;quot; Baley&lt;/a&gt;.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-6331902920249328748?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/6331902920249328748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=6331902920249328748' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/6331902920249328748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/6331902920249328748'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/09/road-to-continuous-integration-part-2.html' title='The road to Continuous Integration. Part 2: Shake your tree'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_kQ7iivKjVno/SpghIOjZSzI/AAAAAAAAALc/SkfsSCTd74E/s72-c/project-structure.jpg' height='72' width='72'/><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-8714907535387450764</id><published>2009-09-11T22:44:00.001+02:00</published><updated>2009-09-11T22:44:39.386+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quality'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='software development'/><category scheme='http://www.blogger.com/atom/ns#' term='project automation'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>The road to Continuous Integration. Part 1: Get your source under control!</title><content type='html'>&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_kQ7iivKjVno/Sqq2s0-EiHI/AAAAAAAAAL0/DFQJE0sWIhc/s1600-h/timemachine6.jpg"&gt;&lt;img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="time-machine" align="right" src="http://lh3.ggpht.com/_kQ7iivKjVno/Sqq2tpkGKTI/AAAAAAAAAL4/g1pf0RP_k7Q/timemachine_thumb6.jpg?imgmax=800" width="115" height="115" /&gt;&lt;/a&gt; If you are not already doing so, put your stuff under source control. Right now. It doesn't matter how small your project is or whether you are working alone. If it's worth your time, it's worth putting it under source control. &lt;/p&gt;  &lt;h4&gt;What is Source Control?&lt;/h4&gt;  &lt;p&gt;Source control, often referred to as VCS (Version Control System) or SCM (Source Code Management) is the management of changes in files. It's a time machine that lets you see how your project looked like at any given point in time.&lt;/p&gt;  &lt;p&gt;For a more detailed introduction, see &lt;a href="http://www.ericsink.com/scm/source_control.html"&gt;Eric Sink's Source Control HOWTO&lt;/a&gt; or the &lt;a href="http://svnbook.red-bean.com/nightly/en/index.html"&gt;SVN book&lt;/a&gt;.&lt;/p&gt;  &lt;h4&gt;Why you should use a SCM tool&lt;/h4&gt;  &lt;p&gt;It gives you an infinite undo-button. No matter how much you have screwed up, you can always go back to a stable point.&lt;/p&gt;  &lt;p&gt;You can share code with other people.&lt;/p&gt;  &lt;p&gt;You can keep track of your changes over time. This allows you to know who changed what, when and (luckily, if you use meaningful comments) why.&lt;/p&gt;  &lt;p&gt;You can maintain multiple code bases of your software. Even if you only have one active version at a time, it's useful to start new development independently.&lt;/p&gt;  &lt;h4&gt;What should you store?&lt;/h4&gt;  &lt;p&gt;Everything you need to build your product. That includes your sources, of course, but also any libraries your projects depends on (avoid referencing GAC'ed or installed libraries), any tools you use and any scripts that you need as part of the process. Nothing should be dependent of your machine installation.&lt;/p&gt;  &lt;p&gt;The goal is to be able to get into a clean machine, get a copy of the codebase from your source repository, build it (automatically) and voil&amp;#224;, you are done and ready to start working!&lt;/p&gt;  &lt;h4&gt;WHICH SCM ARE YOU?&lt;/h4&gt;  &lt;p&gt;&lt;a href="http://subversion.tigris.org/"&gt;There&lt;/a&gt; &lt;a href="http://www.git-scm.org/"&gt;are&lt;/a&gt; &lt;a href="http://www.selenic.com/mercurial/"&gt;many&lt;/a&gt; &lt;a href="http://bazaar-vcs.org/"&gt;alternatives&lt;/a&gt;, just pick one, (oh well, &lt;a href="http://www.codinghorror.com/blog/archives/000660.html"&gt;not THAT one&lt;/a&gt;). If you don't want to set up and maintain a server, you can use &lt;a href="http://code.google.com/"&gt;one&lt;/a&gt; &lt;a href="http://sourceforge.net"&gt;of&lt;/a&gt; &lt;a href="http://www.assembla.com"&gt;the&lt;/a&gt; &lt;a href="http://github.com/"&gt;many&lt;/a&gt; &lt;a href="http://bitbucket.org/"&gt;online&lt;/a&gt; &lt;a href="http://www.launchpad.net"&gt;services&lt;/a&gt; &lt;a href="http://www.codeplex.com"&gt;available&lt;/a&gt; (some of them are just for open source projects, and some have free and paid plans). Which one is best will depend on your specific needs:&lt;/p&gt;  &lt;h5&gt;If you...&lt;/h5&gt;  &lt;ul&gt;   &lt;li&gt;want an easy to install, easy to start tool -&amp;gt; svn &lt;/li&gt;    &lt;li&gt;want a powerful tool, at the expense of a bit steeper learning curve -&amp;gt; git, mercurial, bazaar &lt;/li&gt;    &lt;li&gt;need to use a mature GUI/integration with Visual Studio -&amp;gt; svn, tfs &lt;/li&gt;    &lt;li&gt;need good branching and merging support -&amp;gt; git, mercurial, bazaar &lt;/li&gt;    &lt;li&gt;need an all-in-one tool (source control, bug tracking system, continuous integration) completely integrated, even if the individual tools are not-so-great for the -&amp;gt; tfs &lt;/li&gt;    &lt;li&gt;are a Microsoft-only shop -&amp;gt; tfs &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;For the clients there are also a myriad of tools available for all platforms. You have command-line interfaces, standalone GUI tools (&lt;a href="http://tortoisesvn.net/"&gt;tortoisesvn&lt;/a&gt;, &lt;a href="http://bitbucket.org/tortoisehg/stable/wiki/Home"&gt;tortoisehg&lt;/a&gt;, &lt;a href="http://code.google.com/p/tortoisegit/"&gt;tortoisegit&lt;/a&gt;) and IDE integrated (&lt;a href="http://www.visualsvn.com/"&gt;VisualSVN&lt;/a&gt;, &lt;a href="http://ankhsvn.open.collab.net/"&gt;AnhkSVN&lt;/a&gt;, &lt;a href="http://code.google.com/p/gitextensions/"&gt;Git Extensions&lt;/a&gt;).&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-8714907535387450764?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/8714907535387450764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=8714907535387450764' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/8714907535387450764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/8714907535387450764'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/09/road-to-continuous-integration-part-1.html' title='The road to Continuous Integration. Part 1: Get your source under control!'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-2007036761059099750</id><published>2009-09-08T20:38:00.002+02:00</published><updated>2009-09-08T21:05:10.382+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='work'/><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='recruiting'/><title type='text'>Agile enterprise culture</title><content type='html'>&lt;div style="width:425px;text-align:left" id="__ss_1798664"&gt;&lt;a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/reed2001/culture-1798664" title="Culture"&gt;Culture&lt;/a&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=culture9-090801103430-phpapp02&amp;rel=0&amp;stripped_title=culture-1798664" /&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=culture9-090801103430-phpapp02&amp;rel=0&amp;stripped_title=culture-1798664" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"&gt;View more &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/reed2001"&gt;Reed Hastings&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;Some highlights:&lt;br /&gt;&lt;blockquote&gt;"The real company values, as opposed to the nice-sounding values, are shown by who gets rewarded, promoted or let-go"&lt;/blockquote&gt;&lt;blockquote&gt;"The Keeper Test: 'Which of my people, if they told me they were leaving in two months for a similar job at a peer company, would I fight hard to keep?'"&lt;/blockquote&gt;&lt;blockquote&gt;"You should periodically ask your manager: 'If I told you I were leaving, how hard would you work to change my mind?'"&lt;/blockquote&gt;&lt;blockquote&gt;"In procedural work, the best are 2x better than the average."&lt;/blockquote&gt;&lt;blockquote&gt;"In creative work, the best are 10x better than the average, so huge premium on creating effective teams of the best"&lt;/blockquote&gt;&lt;blockquote&gt;"Vacation policy and Tracking: there is no policy or tracking"&lt;/blockquote&gt;&lt;blockquote&gt;"One outstanding employee gets more done and costs less than two adequate employees"&lt;/blockquote&gt;&lt;blockquote&gt;"It is a good idea, not a traitorous idea, to understand what other firms would pay you, by interviewing and talking to peers at other companies"&lt;/blockquote&gt;&lt;blockquote&gt;Three Tests for Top of Market for a Person:&lt;br /&gt;1. What could person get elsewhere?&lt;br /&gt;2. What would we pay for replacement?&lt;br /&gt;3. What would we pay to keep person?&lt;br /&gt;&lt;/blockquote&gt;&lt;blockquote&gt;"We should celebrate someone leaving for a bigger job that we didn't have available to offer them"&lt;/blockquote&gt;&lt;blockquote&gt;"If manager would promote employee to keep them [...], manager should promote him now, and not wait"&lt;/blockquote&gt;&lt;blockquote&gt;"Mediocre colleagues and unchallenging work is what kills progress of a person's skills"&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-2007036761059099750?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/2007036761059099750/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=2007036761059099750' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2007036761059099750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2007036761059099750'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/09/agile-enterprise-culture.html' title='Agile enterprise culture'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-7228160131340565306</id><published>2009-09-01T19:54:00.002+02:00</published><updated>2009-10-03T17:58:31.563+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software development'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>The road to continuous integration</title><content type='html'>&lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" border="0" alt="road" align="right" src="http://lh6.ggpht.com/_kQ7iivKjVno/Ssd0pucIX_I/AAAAAAAAAMM/KxJlsxekJj8/carretera%5B1%5D.jpg?imgmax=800" width="244" height="177" /&gt; After my introductory post in the &lt;a href="http://sharpbites.blogspot.com/2009/08/introducing-altnerddinner.html"&gt;AltNerdDinner&lt;/a&gt; series, I thought it would be a good idea to roll out an independent series of posts about the things I have learnt in the past two years on setting up a code base for continuous integration. Nothing really new under the sun, but it might help a few people to get started.    &lt;br /&gt;I will update this post with links backs to each element of the series.    &lt;br /&gt;&lt;a href="http://sharpbites.blogspot.com/2009/09/road-to-continuous-integration-part-1.html"&gt;Part 1: Get your source under control&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sharpbites.blogspot.com/2009/09/road-to-continuous-integration-part-2.html"&gt;Part 2: Shake your tree&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sharpbites.blogspot.com/2009/09/road-to-continuous-integration-part-3.html"&gt;Part 3: Script it, build it, test it, break it, fix it. Commit it&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-7228160131340565306?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/7228160131340565306/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=7228160131340565306' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/7228160131340565306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/7228160131340565306'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/09/road-to-continuous-integration.html' title='The road to continuous integration'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-143013625843200762</id><published>2009-08-27T19:49:00.004+02:00</published><updated>2009-10-19T21:19:37.785+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='altnerddinner'/><title type='text'>Introducing AltNerdDinner</title><content type='html'>&lt;p&gt;This is the first in a series of posts in my quest to get my hands dirty with ASP.NET MVC framework, MVCContrib, Spark, NHibernate, FluentNhibernate, Linq2NHibernate, Windsor and a whatnot. For that, I have decided to take &lt;a href="http://nerddinner.codeplex.com/"&gt;NerdDinner&lt;/a&gt; for a spin (not extremely original, I know), replacing what I think could be better and extending from there. If you are interested, you can have a look at the &lt;a href="http://github.com/alberto/altnerddinner"&gt;AltNerdDinner repository&lt;/a&gt; on github.&lt;/p&gt;  &lt;p&gt;Here is a list of the posts published so far:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sharpbites.blogspot.com/2009/10/altnerddinner-part-1-removing-unwanted.html"&gt;Part 1: Removing unwanted dependencies&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sharpbites.blogspot.com/2009/10/altnerddinner-part-2-rich-man.html"&gt;Part 2: Rich Man's Dependency Injection&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sharpbites.blogspot.com/2009/10/altnerddinner-part-3-introducing-fluent.html"&gt;Part 3: Introducing Fluent NHibernate. Mapping, the easy way&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://sharpbites.blogspot.com/2009/10/altnerdinner-part-4-introducing.html"&gt;Part 4: Introducing NHibernate. Because POCO is enough&lt;/a&gt;&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-143013625843200762?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/143013625843200762/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=143013625843200762' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/143013625843200762'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/143013625843200762'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/08/introducing-altnerddinner.html' title='Introducing AltNerdDinner'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-5849871751148410741</id><published>2009-08-26T20:38:00.003+02:00</published><updated>2009-08-27T19:49:02.678+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='tdd'/><title type='text'>TDD Masterclass</title><content type='html'>&lt;p&gt;Roy Osherove is giving an hands-on TDD Masterclass in the UK, September 21-25. Roy is author of "The Art of Unit Testing" (&lt;a href="http://www.artofunittesting.com/"&gt;http://www.artofunittesting.com/&lt;/a&gt;), a leading tdd &amp;amp; unit testing book; he maintains a blog at &lt;a href="http://iserializable.com"&gt;http://iserializable.com&lt;/a&gt; (which amoung other things has critiqued tests written by Microsoft for &lt;a href="http://asp.net"&gt;asp.net&lt;/a&gt; MVC - check out the testreviews category) and has recently been on the Scott Hanselman podcast (&lt;a href="http://bit.ly/psgYO"&gt;http://bit.ly/psgYO&lt;/a&gt;) where he educated Scott on best practices in Unit Testing techniques. For a further insight into Roy's style, be sure to also check out Roy's talk at the recent Norwegian Developer's Conference (&lt;a href="http://bit.ly/NuJVa"&gt;http://bit.ly/NuJVa&lt;/a&gt;).  &lt;/p&gt;  &lt;p&gt;Full Details here: &lt;a href="http://bbits.co.uk/tddmasterclass"&gt;http://bbits.co.uk/tddmasterclass&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;bbits are holding a raffle for a free ticket for the event. To be eligible to win the ticket (worth £2395!) you MUST paste this text, including all links, into your blog and email &lt;a href="mailto:Ian@bbits.co.uk"&gt;Ian@bbits.co.uk&lt;/a&gt; with the url to the blog entry.  The draw will be made on September 1st and the winner informed by email and on &lt;a href="http://bbits.co.uk/blog"&gt;bbits.co.uk/blog&lt;/a&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-5849871751148410741?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/5849871751148410741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=5849871751148410741' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/5849871751148410741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/5849871751148410741'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/08/tdd-masterclass.html' title='TDD Masterclass'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-9130050944998521521</id><published>2009-08-15T20:04:00.004+02:00</published><updated>2009-08-15T20:10:54.643+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quality'/><category scheme='http://www.blogger.com/atom/ns#' term='bits'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='software development'/><category scheme='http://www.blogger.com/atom/ns#' term='work'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><category scheme='http://www.blogger.com/atom/ns#' term='recruiting'/><title type='text'>It's the people, stupid!</title><content type='html'>&lt;blockquote&gt;You need people who are passionate about what they do. People who care about their craft — and actually think of it as a craft. People who take pride in their work, regardless of the monetary reward involved. People who sweat the details even if 95% of folks don't know the difference. People who want to build something great and won't settle for less. [...]Anyhow, when you find those people, hold onto them. In the end, the folks on your team will make or break your project — and your company.&lt;br /&gt;&lt;cite&gt;-- &lt;a href="http://gettingreal.37signals.com/"&gt;Getting Real&lt;/a&gt;, &lt;a href="http://www.37signals.com/"&gt;37signals&lt;/a&gt;&lt;/cite&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-9130050944998521521?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/9130050944998521521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=9130050944998521521' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/9130050944998521521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/9130050944998521521'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/08/its-people-stupid.html' title='It&apos;s the people, stupid!'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-2326612763605213066</id><published>2009-05-08T21:08:00.000+02:00</published><updated>2009-05-08T21:11:38.711+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quality'/><category scheme='http://www.blogger.com/atom/ns#' term='bits'/><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><title type='text'>Excellence</title><content type='html'>&lt;blockquote&gt;We are what we repeatedly do. Excellence, then, is not an act, but a habit.&lt;br /&gt;&lt;cite&gt;-- Aristotle&lt;/cite&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-2326612763605213066?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/2326612763605213066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=2326612763605213066' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2326612763605213066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2326612763605213066'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/05/excellence.html' title='Excellence'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-3545936206328924571</id><published>2009-05-01T20:51:00.006+02:00</published><updated>2009-05-01T21:07:17.593+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bits'/><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><title type='text'>The role of the Scrum Sensei</title><content type='html'>&lt;blockquote&gt;When you need me, but do not want me, then I will stay.&lt;br /&gt;When you want me, but do not need me, then I have to go.&lt;br /&gt;&lt;br /&gt;&lt;cite&gt;-- Nanny McPhee, &lt;a href="http://blog.jayway.com/2008/12/17/scrum-shock-therapy-part-2/"&gt;via&lt;/a&gt; &lt;a href="http://blog.jayway.com/author/bjorngranvik/"&gt;Björn Granvik&lt;/a&gt;&lt;/cite&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-3545936206328924571?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/3545936206328924571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=3545936206328924571' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/3545936206328924571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/3545936206328924571'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/05/role-of-scrum-sensei.html' title='The role of the Scrum Sensei'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-5049695300289449332</id><published>2009-04-27T23:50:00.004+02:00</published><updated>2009-04-27T23:57:21.771+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='c#'/><title type='text'>On value types vs reference types and premature optimization</title><content type='html'>Eric Lippert, wrote a great post about value types vs reference types, and how, many times, the discussion is shifted to the-heap-and-the-stack, when it should really be about the differences when those types are passed (by value) as parameters.&lt;br /&gt;&lt;br /&gt;He nails it when he says:&lt;br /&gt;&lt;blockquote&gt;Making the nano-optimization of making a type that really should be a ref type into a value type for a few nanoseconds of perf gain is probably not worth it. I would only be making that choice if profiling data showed that there was a large, real-world-customer-impacting performance problem directly mitigated by using value types. Absent such data, I’d always make the choice of value type vs reference type based on whether the type is semantically representing a value or semantically a reference to something.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-5049695300289449332?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/5049695300289449332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=5049695300289449332' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/5049695300289449332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/5049695300289449332'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/04/on-value-types-vs-reference-types-and.html' title='On value types vs reference types and premature optimization'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-4196294956640410616</id><published>2009-03-14T21:18:00.002+01:00</published><updated>2009-03-14T21:21:24.913+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bits'/><category scheme='http://www.blogger.com/atom/ns#' term='project management'/><title type='text'>To plan or not to plan</title><content type='html'>&lt;blockquote&gt;In preparing for battle I have always found that plans are useless, but planning is indispensable.&lt;/blockquote&gt;&lt;cite&gt;-- Dwight D. Eisenhower&lt;/cite&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-4196294956640410616?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/4196294956640410616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=4196294956640410616' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/4196294956640410616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/4196294956640410616'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/03/to-plan-or-not-to-plan.html' title='To plan or not to plan'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-1385828474376140835</id><published>2009-03-12T17:20:00.001+01:00</published><updated>2009-03-12T17:23:25.050+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quality'/><category scheme='http://www.blogger.com/atom/ns#' term='bits'/><title type='text'>The price of change</title><content type='html'>&lt;blockquote&gt;Change is expensive, no question about it. However, consider the alternative—stagnation.&lt;/blockquote&gt;&lt;cite&gt;-- Jim Highsmith&lt;/cite&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-1385828474376140835?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/1385828474376140835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=1385828474376140835' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/1385828474376140835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/1385828474376140835'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/03/price-of-change.html' title='The price of change'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-2111807431828420986</id><published>2009-03-10T13:20:00.003+01:00</published><updated>2009-03-10T13:29:32.308+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='nant'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='tips'/><category scheme='http://www.blogger.com/atom/ns#' term='msbuild'/><category scheme='http://www.blogger.com/atom/ns#' term='continuous integration'/><title type='text'>Targetting .NET 2.0 with Nant and Visual Studio 2008</title><content type='html'>If you try to migrate a solution to VS2008 and you are using nant, you'll probably find a few problems. This is one of them I am documenting for you.&lt;br /&gt;I wanted to use VS2008 and nant, but still want target the .net 2.0 framework. I read somewhere I needed to install the .net 2.0 sdk, but I was still having issues, where msbuild was complaining it didn't recognize the format of the solution file.&lt;br /&gt;It turns out you need to change nant.settings.currentframework to "net-3.5", so that it is the version of msbuild that comes with msbuild who compiles the solution (so I am not sure anymore you need the .net 2.0 sdk). It will still target the .net 2.0 framework for your projects if you set that that way in VS, as msbuild uses that info for the target.&lt;br /&gt;&lt;br /&gt;Hope it helps someone out there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-2111807431828420986?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/2111807431828420986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=2111807431828420986' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2111807431828420986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2111807431828420986'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/03/targetting-net-20-with-nant-and-visual.html' title='Targetting .NET 2.0 with Nant and Visual Studio 2008'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-2647250444581656545</id><published>2009-02-22T19:12:00.004+01:00</published><updated>2009-02-22T20:39:19.793+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quality'/><category scheme='http://www.blogger.com/atom/ns#' term='deadline driven development'/><category scheme='http://www.blogger.com/atom/ns#' term='software development'/><title type='text'>Programming for the Mob sharks? No, thanks.</title><content type='html'>&lt;a href="http://c2.com/"&gt;Ward Cunniham&lt;/a&gt;, of &lt;a href="http://c2.com/cgi/wiki"&gt;Ward's Wiki&lt;/a&gt; fame, was the coiner of the term "technical debt". He made an interesting clarification in the following video:&lt;br /&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/pqeJFYwnkjE&amp;hl=es&amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/pqeJFYwnkjE&amp;hl=es&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;According to his intention, the term is usually misused to reflect (and even encourage) the writing of sloppy code with the excuse that it will be refactored later. His original vision was more aligned with the XP style of simple design.&lt;br /&gt;&lt;br /&gt;Doing bad code with the excuse of refactoring somewhere in the future is not technical debt we are going to pay, but rather asking money from loan mob sharks at an astronomic interest rate and the expenses of losing a few body parts in the way.&lt;br /&gt;&lt;br /&gt;PS: It is funny how the metaphor was coined as an analogy that his boss could understand, but it has grown to be used and abused by everybody in the industry. Maybe that's also related to the debt culture that has drawn our uneducated society into the current situation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-2647250444581656545?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/2647250444581656545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=2647250444581656545' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2647250444581656545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2647250444581656545'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2009/02/programming-for-mob-sharks-no-thanks.html' title='Programming for the Mob sharks? No, thanks.'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-4526547592830608239</id><published>2008-12-04T23:56:00.004+01:00</published><updated>2009-01-17T17:12:31.128+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='quality'/><category scheme='http://www.blogger.com/atom/ns#' term='bits'/><category scheme='http://www.blogger.com/atom/ns#' term='deadline driven development'/><category scheme='http://www.blogger.com/atom/ns#' term='software development'/><title type='text'>Quality</title><content type='html'>&lt;blockquote&gt;Quality means doing it right when no one is looking.&lt;/blockquote&gt;&lt;cite&gt;-- Henry Ford&lt;/cite&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-4526547592830608239?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/4526547592830608239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=4526547592830608239' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/4526547592830608239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/4526547592830608239'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2008/12/quality.html' title='Quality'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6675534776398892468.post-2455655948596927098</id><published>2008-12-04T21:49:00.002+01:00</published><updated>2008-12-04T21:52:39.349+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bits'/><category scheme='http://www.blogger.com/atom/ns#' term='software development'/><category scheme='http://www.blogger.com/atom/ns#' term='work'/><category scheme='http://www.blogger.com/atom/ns#' term='philosophy'/><title type='text'>Assumptions</title><content type='html'>&lt;blockquote&gt;Assumption is the mother of all screw-ups.&lt;/blockquote&gt;&lt;cite&gt;-- Wethern's Law of Suspended Judgment&lt;/cite&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6675534776398892468-2455655948596927098?l=sharpbites.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://sharpbites.blogspot.com/feeds/2455655948596927098/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6675534776398892468&amp;postID=2455655948596927098' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2455655948596927098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6675534776398892468/posts/default/2455655948596927098'/><link rel='alternate' type='text/html' href='http://sharpbites.blogspot.com/2008/12/assumptions.html' title='Assumptions'/><author><name>alberto</name><uri>http://www.blogger.com/profile/03053589431434029905</uri><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='15643250039248637654'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>