<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://codebetter.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Ian Cooper</title><link>http://codebetter.com/blogs/ian_cooper/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>MVC or WebForms: It's more about client side vs server side</title><link>http://codebetter.com/blogs/ian_cooper/archive/2010/01/27/mvc-or-webforms.aspx</link><pubDate>Wed, 27 Jan 2010 03:34:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:605604</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>17</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=605604</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2010/01/27/mvc-or-webforms.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://weblogs.asp.net/scottgu/archive/2010/01/24/about-technical-debates-both-in-general-and-regarding-asp-net-web-forms-and-asp-net-mvc-in-particular.aspx"&gt;Scott Guthrie has posted&lt;/a&gt; on the &lt;a href="http://www.google.co.uk/search?q=webforms+vs+mvc&amp;amp;ie=utf-8&amp;amp;oe=utf-8&amp;amp;aq=t&amp;amp;rls=org.mozilla:en-GB:official&amp;amp;client=firefox-a"&gt;growing debate&lt;/a&gt; over &lt;a href="http://codebetter.com/blogs/karlseguin/archive/2010/01/22/the-webforms-rant.aspx"&gt;Webforms vs. MVC&lt;/a&gt;, a debate that seems to be raging everywhere (although there is &lt;a href="http://trac.caffeine-it.com/openrasta"&gt;more that one&lt;/a&gt; &lt;a href="http://www.castleproject.org/monorail/index.html"&gt;MVC framework &lt;/a&gt;&lt;a href="http://fubumvc.com/"&gt;out there&lt;/a&gt; too). I agree with Scott&amp;#39;s point about the nature of technical debates, and the acceptance that there are different schools of thought. However, that does not always imply that all schools are equally good solutions to a given problem. &lt;/p&gt;
&lt;p&gt;The issue has been though I think not solely about the MVC pattern, it is also about the shift from providing rich client behavior server-side or client-side. In this area the renewed interest in &lt;a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29"&gt;AJAX&lt;/a&gt; and the emergence of Javascript libraries like &lt;a href="http://www.prototypejs.org/"&gt;Prototype&lt;/a&gt;, &lt;a href="http://script.aculo.us/"&gt;script.aculo.us&lt;/a&gt; and &lt;a href="http://jquery.com/"&gt;JQuery &lt;/a&gt;have been game changers. And for me those RIA paradigms dovetail better with MVC apps than with Webforms applications. At the same time the growth of &lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;REST &lt;/a&gt;has meant many have re-engaged with the HTTP protocol and its resource oriented model, have turned attention away from&lt;a href="http://msdn.microsoft.com/en-us/library/ms998548.aspx"&gt; page based approaches&lt;/a&gt; to web development toward resource oriented ones. There is a correspondence here, because as the use of client side scripting grows so does the perspective of the server as a resource provider used by the client.&lt;/p&gt;
&lt;p&gt;It is in many ways this shift of paradigm that MVC supports better and why using MVP approaches with WebForms is not a &amp;#39;seperate but equal&amp;#39; answer to modern web development. Its not simply about better conformance to&lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt; Single Responsibility Principle.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;What our frameworks do for us&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Our average web framework has some pretty basic requirements - handle requests for resources from the server by returning an appropriate response. In our case this is HTML. The simple nature of this model underlies the success of the web.&lt;br /&gt;&lt;br /&gt;To support this model our framework needs to route to an appropriate handler in our code that can read the request. Now we could just interrogate that request to pull out post data or query strings, but writing a lot of that code would get old fast, so it helps if our framework can map between form, params and query string values and part of our object model. That way we can manipulate the variables of the request more easily. Now we have to take an appropriate action in response to the request. Generally this is where most of our code plugs in. We get some data and compose a response, in HTML to return in the response. Now just using Response.Write() to output our HTML becomes hard to maintain, so most of us expect our framework to give us&amp;nbsp; some sort of template so that we can separate the static and dynamic portions of our response.&lt;br /&gt;&lt;br /&gt;The MVC pattern enters the fray here when frameworks separate the responsibilities of template to provide view, model to provide response to action, and co-ordination between the two for a request. Criticism of Webforms as lacking effective separation cf concerns is because the aspx file is both responsible for rendering the HTML used as a response and providing the controller for the request. It thus has two reasons to change, because the template changes or because the co-ordination of handling a request changes. These may be orthogonal concerns and make maintenance harder. Some patterns such as MVP try to alleviate this by enforcing separation of these two responsibilities within the framework. this criticism is valid but not complete issue; the significance of &amp;#39;MVC&amp;#39; frameworks is not solely their better separation of concerns.&lt;br /&gt;&lt;br /&gt;Now for sure the devil is in the details, but that&amp;#39;s pretty much it.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Bare Bones&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;#39;MVC&amp;#39; frameworks such as &lt;a href="http://www.asp.net/%28S%28d35rmemuuono1wvm1gsp2n45%29%29/mvc/"&gt;ASP.NET MVC&lt;/a&gt; or &lt;a href="http://www.castleproject.org/monorail/index.html"&gt;Monorail &lt;/a&gt;ttend to have a bare bones approach to meeting these requirements. The framework takes requests and calls an action to service them, mapping request to action parameters. We then carry out the appropriate task and render html through a view engine. MVC frameworks add little on top of this paradigm. The big win here is that this makes them simple to learn and easy to use, because the surface area of the API is small. The surface area for ASP.NET MVC is smaller than that for Webforms and is easier for new developers to learn. It also works in harmony with http and thus expectations. The principle of least surprise is important to APIs because it makes them easier to discover. Understand the problem and you are likely led in search of the solution.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Rich Internet Applications&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Now ASP.NET MVC etc. allow you to return an HTML response, but HTML has its limitations in that it is static. You need to post a request to the server each time you want some new action to occur. In some cases this &amp;#39;complete form and submit&amp;#39; model works, but we have become used, from smart clients, to a more dynamic model that provides feedback as we make selections. We expect choosing from one dropdown such as country to restrict choices such as US State vs. UK county or Post Code vs. Zip Code.&lt;br /&gt;&lt;br /&gt;Out-of-the-box support in web browsers for dynamic behaviour came in the form of Javascript and manipulation of the &lt;a href="http://en.wikipedia.org/wiki/Document_Object_Model"&gt;DOM&lt;/a&gt;. The browser is the smart client in this approach. The issue here is that Javascript development was a challenge for many developers and consequently many development shops. Why? Because folks found client side behaviour did not just require switching to another language, but also learning the DOM, which was also sometimes uncomfortably close to metal for developers weaned on smart client Forms frameworks like Windows Forms, VB, or PowerBuilder. In addition the browser wars meant that the model for programming against the DOM was not the same from browser to browser, further complicating the code that was needed to implement a rich client in the browser. In truth it was expensive. Finally the debugging experience was poor. We were back to tracing the state of variables in order to isolate and fix problems in the browser. For many MIS departments writing sites with a rich client, heavy on javascript, was out-of-reach in other cost or skills.&lt;br /&gt;&lt;br /&gt;To solve this problem WebForms introduces the concept of server side controls - essentially shifting the rich interaction to the server. The server side control abstracts the html control from the client side. The benefit is that it allows you a development approach familiar to forms based programmers. You set and get control properties and write handlers to react to events. But as the events are raised client-side you need effectively mirror all of the control state from the client side to the server. The problem here is that html does not share this with you on a post. You also need to record the event raised for the server side too, as a post is all you know about from http. This brings in ViewState, which captures all the state which a post is not giving you. But once it is implemented I can provide all that dynamic behaviour on the server, skipping and jumping over issues like knowledge of Javascipt and the DOM, as well as browser compatibility issues.&lt;br /&gt;&lt;br /&gt;Of course we can quickly see that with any complex enough page ViewState will grow. As it is embedded in a page it increases the page weight which can hamper performance In addition because we must do an http post to transfer the state of our application back to the server, and then display the response, events are handled by a page refresh. This has the consequence of making the system slower than one which handles the event locally, giving rise to user complaints of flicker or slow response. In addition if you try to cope by adding some AJAX callbacks from your client&amp;nbsp; the question quickly becomes &amp;#39;who owns this state&amp;#39; as you may have copies of the state both on the client and in ViewData being marshalled back and forth to the server.&lt;/p&gt;
&lt;p&gt;Webforms is also a more complex API than MVC and thus harder for developers to learn. Most of us have been at an interview where we have asked, or been asked the question - what is the Webforms lifecycle? Understanding the stages, where viewdata is available and modifiable is not an insignificant learning challenge.&lt;/p&gt;
&lt;p&gt;Given that, for some time I used to recommend building applications using WebForms server-side control model over building applications with client side behaviour. Why? Because of the cost and difficulty of building rich client behaviour in Javascript with the DOM outweighed the cost of learning Webforms.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What Changed?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;MVC trades the complexity of server side controls for a simpler programming model, supported by client side controls. The emergence of the new breed of Javascript frameworks like &lt;a href="http://www.prototypejs.org/"&gt;Prototype&lt;/a&gt;, &lt;a href="http://jquery.com/"&gt;JQuery&lt;/a&gt;, and &lt;a href="http://script.aculo.us/"&gt;script.aculo.us&lt;/a&gt;, made it far cheaper to code the client behaviour on the client. The elegance and simplicity of these frameworks, their &lt;a href="http://docs.jquery.com/Browser_Compatibility"&gt;abstraction of browser API differences&lt;/a&gt;, and their &lt;a href="http://plugins.jquery.com/"&gt;rich ecosystem&lt;/a&gt; of control &lt;a href="http://docs.jquery.com/Plugins/Authoring"&gt;providers&lt;/a&gt;, lowered the barrier to entry for client-side development providing solutions to common needs such as&amp;nbsp; &lt;a href="http://stackoverflow.com/questions/159025/jquery-grid-recommendations"&gt;grids &lt;/a&gt;. The availability of &lt;a href="http://designbeep.com/2009/11/21/free-amazing-jquery-plugins-and-tutorials-with-demos/"&gt;many free&lt;/a&gt; controls lowers the cost of common UI widgets&amp;nbsp;&lt;a href="http://stackoverflow.com/questions/159025/jquery-grid-recommendations"&gt;&lt;/a&gt;that have often been the preserve of expensive vendor solutions.&lt;/p&gt;
&lt;p&gt;In addition the debugging experience for Javascript has significantly improved from the old trace and dump model with browser plugins such as &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/1843"&gt;Firebug &lt;/a&gt;and &lt;a href="http://weblogs.asp.net/scottgu/archive/2007/07/19/vs-2008-javascript-debugging.aspx"&gt;Visual Studio&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;With a lower cost it has become commercially viable for more development shops to build rich client applications. Best of breed applications do not suffer from the postback flicker issue because they manipulate state locally on the browser and use AJAX calls to the server. With effective client side development, the user experience is akin to smart clients of yesterday, with none of the distribution problems for central IT departments. This rich experience available for the web lies at the heart of the SaaS revolution.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;The MVC model truly shines with AJAX where the target for an AJAX call is just an action on a controller. The affinity to http&amp;rsquo;s resource based model allows for easy definition of the server side support for rich clients. The advatange of MVC frameworks is the &lt;a href="http://mikehadlow.blogspot.com/2008/10/mvc-framework-and-jquery-ajax-heaven.html"&gt;ease with which they dovetail to client-code using frameworks like JQuery&lt;/a&gt;. Client-side programming is back, using modern Javascript libraries!&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;It is this, IMO, which has shifted the balance in favour of MVC. I do not think it any accident that the ASP.NET team shipped JQuery with ASP.NET MVC. I think it was essential to shipping an ASP.NET MVC application that a modern Javascript client library was included to support rich client behaviour on the browser instead of server side. &lt;br /&gt;&lt;b&gt;&lt;br /&gt;From my cold dead hands&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The attitude of many developers may be &amp;lsquo;you will pry Weforms &lt;a href="http://www.youtube.com/watch?v=O0B_UZNtEk4"&gt;from my cold dead hands&lt;/a&gt;&amp;rsquo;. The march of progress is threatening to do just that. Much of theresistance is based on prior experiences with the cost of client-side development using Javascript, without understanding that the new frameworks available have significantly lowered the barrier to entry there. In addition, Silverlight opens a second front against Webforms by offering rich client development using XAML. If Javascript does not replace Webforms, then XAML will. Server-side controls had their day. They built careers, companies, and fortunes but they are legacy applications now. Client-side controls have returned with fresh offensives that will see their end. If you are building a new web project today you should be looking at an MVC framework.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;For my part the question of Webforms vs. MVC is already an irrelevance. That is yesterday&amp;rsquo;s fight and victory has been declared despite a few units continuing to fight on. The next war is likely to be between Silverlight and Javascript for ownership of the smart client&amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=605604" width="1" height="1"&gt;</description></item><item><title>Whither Alt.Net?</title><link>http://codebetter.com/blogs/ian_cooper/archive/2010/01/19/whither-alt-net.aspx</link><pubDate>Tue, 19 Jan 2010 13:00:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:587174</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>30</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=587174</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2010/01/19/whither-alt-net.aspx#comments</comments><description>&lt;p&gt;&lt;b&gt;Rage, rage against the dying of the light&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The lack of visibility for the idea of &amp;quot;Alt.Net&amp;quot; of late has led me to ask myself the question whither &lt;a href="http://altdotnet.org/"&gt;Alt.Net&lt;/a&gt;. Or perhaps is alt.net withering? A couple of years ago the alt.net meme had real traction in blogs and events. It had become a &lt;a href="http://laribee.com/blog/2007/04/10/altnet/"&gt;cri de coeur&lt;/a&gt; for the disaffected members of the .NET community. For many who felt there was a &amp;#39;better&amp;#39; way, that solid principles and practices that alleviate the pain of some software developers ills were available if you looked up and far enough around, the knowledge that like-minded people were out there gave a sense of strength and purpose. We were not alone in the dark, others like us were out there. At the first altnetconf we ran in the UK, inspired by those in the US, what was overwhelming was the feeling of &amp;#39;community&amp;#39; between like-minded people who suddenly found others they could communicate with about the ideas that burnt so very brightly within them.&lt;/p&gt;
&lt;p&gt;At the time there were warnings and criticisms of the new community. Some reasoned it would become an &amp;#39;echo chamber&amp;#39;. Other critics suggested that it could be ignored as those involved would just burn out leaving only silence.&lt;/p&gt;
&lt;p&gt;Today as I ponder the state we are in I wonder if the critics have not triumphed in there soothsaying over the enthusiasm that once fired our souls. Blogs wane in fire and passion. We seem tired from the fight.&lt;/p&gt;
&lt;p&gt;I for one say &amp;quot;Do not go gently into that good night, rage, rage against the dying of the light&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;What is in a name?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;First I want to step aside from the question about name. David Laribee&amp;#39;s &lt;a href="http://laribee.com/blog/2007/04/10/altnet/"&gt;original manifesto&lt;/a&gt; set out the stall of ideas clearly whatever you want to call it.I think that all these remain true, but perhaps the heart of the movement for me is that &amp;quot;You&amp;rsquo;re not content with the status quo. Things can always be better
expressed, more elegant and&amp;nbsp;simple, more mutable,&amp;nbsp;higher quality, etc.&amp;quot;&lt;/p&gt;
&lt;p&gt;Call it what you will. The point is not the name, but the passion for better software development. Objecting to the tag should not blind you to agreement on the ideals. I accept people might not like some of the baggage associated with alt.net. But let&amp;#39;s move on and accept that we all agree on the need for a movement that expresses the desire to be ill-content with the status quo, to rebel against the orthodoxy, to rage against the machine.&lt;/p&gt;
&lt;p&gt;&lt;span style="font-weight:bold;"&gt;&lt;/span&gt;&amp;quot;There&amp;#39;s a time
when the operation of the machine becomes so odious, makes you so sick
at heart, that you can&amp;#39;t take part, you can&amp;#39;t even passively take part,
and you&amp;#39;ve got to put your bodies on the gears and upon the wheels,
upon the levers, upon all the apparatus, and you&amp;#39;ve got to make it
stop! And you&amp;#39;ve got to indicate to the people who run it, to the
people who own it, that unless you&amp;#39;re free, the machine will be
prevented from working at all!&amp;quot; - Mario Savio&lt;b&gt;&lt;span style="font-weight:bold;"&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Is the movement needed any more, and should we just declare victory and bring the troops home?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Scott Bellware recently bemoaned on Twitter that .NET developers doing
web development should be using MVC and not webforms. He pointed out
that attempts to pander to some developers by suggesting that WebForms
and ASP.Net MVC were separate but equal were disingenuous &amp;quot;As more good
web devs move to MVC, the WebForms camp looks ever more like
paint-by-numbers web development. The shifting demographics of web
development in .Net should be a clarion call for everyone to go back
into learning mode. The paint-by-numbers crowd is feeling the heat of
all the learning that Microsoft told them they didn&amp;#39;t have to pay
attention to. The amazing thing: rather that pour on the learning,
ungodly efforts are being spent on perpetuating uninformed
justifications. Dumb. No. Squarely. Definitively. ASP MVC and WebForms
are not equals. Here, I&amp;#39;ll say it: better web developers use MVC. The
ultimate destructive force in .Net development: Microsoft convincing
developers not to worry about deepening their skills&amp;quot;.&lt;/p&gt;
&lt;p&gt;This is not academic. I regularly meet people through London .NET user group that tell me this or that senior developer has blocked use of ASP.NET MVC at this or that company because it would require learning something new. People are still struggling with this issue at development shops all around us. The &amp;#39;senior&amp;#39; developer invested in maintaing his position through better knowledge of a framework or tool over transferrable skills like patterns &amp;amp; practices shuts down introduction of new technologies by junior developers out of fear that it might level the playing field and bring their authority into question. I hear from junior developers that entrenched senior developers unwilling to learn try to kill attempts to adopt TDD/BDD because they
do not understand and worry it will undermine their authority. Further
hint, your authority has already been undermined with those junior
developers who have long ago worked out that your fear and ignorance is
keeping you from implementing. They already understand that it is not genuine judgment that it is not
needed in a given circumstance or you have adopted and alternative like
Design By Contract.&lt;/p&gt;
&lt;p&gt;I still hear people suggest that TDD is too expensive, and yet complain that developers are not producing quality code and they have too much re-work. Hint the cost of re-work is greater than the cost of doing TDD to prevent re-work (or the cost of manual testing to prevent defects exceeds the cost of TDD by a large margin). I still hear people object to story tests but complain about developers building software that does not match customer expectation. HInt, the cost of adopting a BDD approach to building the right thing is less than the cost of re-work from incorrectly fulfilled requirements.&lt;/p&gt;
&lt;p&gt;People talk about having adopted agile at an organization but are often practicing &lt;a href="http://www.exotribe.com/node/16"&gt;cargo-cult agile&lt;/a&gt;, &lt;a href="http://www.agileprogrammer.com/dotnetguy/archive/2006/07/08/16855.aspx"&gt;scrumerfall&lt;/a&gt; or &lt;a href="http://blogs.msdn.com/nickmalik/archive/2007/06/04/waterscrum-vs-scrummerfall.aspx"&gt;waterscrum&lt;/a&gt; or worse &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2009/09/11/agile-is-never-no-process.aspx"&gt;agile as no-process at all&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We have by no means won this struggle. It is still being played out every day, despite the fact that the solutions may seem obvious to us.In some ways we have only reached the point of witnessing the creation of evasions, half-truths,and lies as to why such practices are inappropriate to an organization or covering up incorrect adoption.&lt;/p&gt;
&lt;p&gt;Alt.Net was always about challenging these &amp;#39;comfortable lies&amp;#39;. As a community we cannot become content to live with
the &amp;#39;comfortable lies&amp;#39;.&lt;/p&gt;
&lt;p&gt;Sometimes effecting change can seem like a war. There are a lot of
people who have established comfortable positions for themselves as
prophets of a technology and do not want that comfortable home
disrupted. Unfortunately we cannot accept the lure of that comfortable
position without our skills eroding and failing to keep pace with the
wider industry. This necessitates conflict between the prohets of the
new and the saints of the old: &amp;quot;The &lt;i&gt;tree of liberty must from time to time&lt;/i&gt; be &lt;i&gt;refreshed&lt;/i&gt; with the blood of &lt;i&gt;patriots&lt;/i&gt; and &lt;i&gt;tyrants&lt;/i&gt;. It is its natural manure.&amp;quot; If you have not engaged with ASP.NET MVC you need to be, &lt;i&gt;now&lt;/i&gt;. If you have you need to be exploring the new alternatives to understand their implicit criticism.&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t think we can declare victory in any sense. We may be tired of
the casualties, but walking away from the fight right now just lets the
other side know that they can outwait us. Someone told me a story recently of an IT department that went agile and became extremely productive. But when the thought leadership behind the change,&amp;nbsp; the nay-sayers moved in to crush the agile practices and return to their old safe comfortable world. There is a group that reckons it can outlast the adherents of change and return to mediocrity when those agents tire or move on. You just can&amp;#39;t quit the fight if you don&amp;#39;t want that to happen.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Did the movement simply become the new orthodoxy&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;One criticism raised against alt.net is that it would simply become
the new orthodoxy. It could be suggested that the decline inalt.net activity is because people have simply become comfortable with a new set of orthodoxies: Scrum, TDD, NHibernate etc, that they will not challenge.&lt;/p&gt;
&lt;p&gt;However, nothing stands still. The orthodoxies of Agile development Scrum, XP, and Crystal amongst others, are being challenged. &lt;a href="http://www.limitedwipsociety.org/"&gt;Kanban &lt;/a&gt;grows rapidly as an alternative to agile storyboards sometimes &lt;a href="http://www.agilemanagement.net/Articles/Weblog/WIPLimitsareforAdultstoo.html"&gt;provoking debate&lt;/a&gt;. The notion that we ahve adopted Scrum or XP and can rest on our laurels is to fall into the trap.&lt;/p&gt;
&lt;p&gt;Many find
limitations with
ASP.NET MVC&amp;#39;s implementation, which has led to projects like &lt;a href="http://fubumvc.com/"&gt;FubuMVC&lt;/a&gt; and &lt;a href="http://trac.caffeine-it.com/openrasta"&gt;OpenRasta&lt;/a&gt; let alone &lt;a href="http://www.castleproject.org/monorail/"&gt;MonoRail&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Source control seems to be leaving behind the centralized model of CVS and SVN for the distributed model from &lt;a href="http://jeffreypalermo.com/blog/subversion-seems-to-be-losing-favor-among-version-control-users/"&gt;GiT&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Many of the people involved in championing these alternatives, championed thier predecessors. So I don&amp;#39;t think the movement is doomed to become the new orthodoxy provided it continues to embrace investigating and adopting these alternatives as they emerge. The goal is to do the best we can, and what is &amp;#39;best&amp;#39; will keep changing. Sure alt.net might pause for a period, absorbing one revolution before seeing its shortcomings and starting another, but I don&amp;#39;t believe the community incapable of moving forward, mired in some new orthodoxy.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Did we scratch the itch of &amp;#39;people like us&amp;#39; and just move on to Twitter?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;There is a danger that the biggest need we had was to feel less alone, and once we found people who thought like us moved into an echo chamber where we could moan about everyone else. In some ways Twitter is the ultimate example of this echo chamber. We can follow like minded people and hold conversations with them, ignoring everyone else.&lt;/p&gt;
&lt;p&gt;I like Twitter, please don&amp;#39;t get me wrong. It has enabled the kind of informal social activity for altnetuk and the London .NET user group that I found difficult to support through mailing lists. But a lot of the discussion around practices, tools, ideas seems to have moved there. Twitter has become a great radar for seeing what folks think is important and interesting out there that merits further research. However, I think there is a danger for the community here for two reasons.&lt;/p&gt;
&lt;p&gt; First Twitter is a passable medium for conversation, but not a good vehicle for a comprehensive discussion of ideas. The length of tweets is too limiting, the ability to construct argument too limited. I am as bad as anyone for having spread a reply or opinion across a half-dozen tweets. But we should recognize that Twitter is ineffective at explaining complex ideas. It&amp;#39;s great that snapshot comments have somewhere to go and don&amp;#39;t crowd the blogosphere, but we need to continue to blog or write articles about the ideas for clarity.&lt;/p&gt;
&lt;p&gt;Second Twitter relies much more on you knowing about the person with the key ideas and following them. Blogs are easier to find by searching, or by following links. They have far more discoverability. The rise of blogs represented a phenomenal democratization of software development knowledge. Previously such knowledge had often been hoarded by cliques as an exploitable resource through books, training, or consultancy. Blogs shared knowledge in a way that meant best practice ideas were widely available. The danger is a drift back to cliques as bloggers, tired of criticism, return to narrow cliques to disseminate knowledge and practice. Ultimately this becomes self-defeating and prevents wider acceptance of standards and practices.&lt;/p&gt;
&lt;p&gt;The danger of Twitter becoming an echo chamber is far greater than the danger of blogs becoming such. So I believe alt.net needs to continue to blog to reach out beyond the echo chamber. But more than this, alt.net represents confort and support to other people making the journey. All those developers looking for someone to say &amp;#39;I believe in being the best developer that I can&amp;#39; too&amp;#39;. That moral support can mean a lot to people struggling with obstinate colleagues and managers. It can mean a lot to point to a group and say &amp;quot;but I&amp;#39;m not the only one that thinks this way&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Was struggle replaced with co-operation&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We might be hopeful and consider that it is possible we moved from opposition and rebellion to cooperation and inclusion. Did we achieve its goals and simply become incorporated in the mainstream. Is the rise of ASP.NET MVC, MSTest, POCO options for EF just a sign that the movement has been incorporated in the mainstream? Whilst I think engagement is positive, after all it is the only way to succeed and driving change, I don&amp;#39;t think that engagment means there is no need fo alt.net any more, because I think the movement was about more than just a few &amp;quot;poster-child&amp;quot; issues. I also don&amp;#39;t think it is about rebellion against co-operation with MS or anyone else. I think it is about driving forward the quality of our own practice.&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Software Craftsmanship&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Many of the ideals of Alt.NET seem to be shared with the Software Craftsmanship movement. In some ways &lt;a href="http://manifesto.softwarecraftsmanship.org/main"&gt;Software Craftsmanship&lt;/a&gt; seems to be the generic form of the alt.net movement. For me key texts in Software Craftsmanship are those like T&lt;a href="http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X"&gt;he Pragmatic
Programmer&lt;/a&gt;, &lt;a href="http://www.amazon.com/Software-Craftsmanship-Imperative-Pete-McBreen/dp/0201733862"&gt;Software Craftsmanship the New Imperative&lt;/a&gt;, &lt;a href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1263923187&amp;amp;sr=1-1"&gt;Clean Code&lt;/a&gt;, &lt;a href="http://www.amazon.com/Agile-Principles-Patterns-Practices-C/dp/0131857258/ref=pd_sim_b_3"&gt;Agile Principles, Patterns and Practices in C#&lt;/a&gt;, &lt;a href="http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530/ref=ntt_at_ep_dpi_3"&gt;Test Driven Development By Example&lt;/a&gt; to name just a few. Indeed the XP
movement could be seen as a call to craftsmanship.&amp;nbsp; &lt;/p&gt;
&lt;p&gt; I talked about the asset of looking back to craftsmanship for models when talking about &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2008/01/02/architects-back-to-the-future.aspx"&gt;master builders instead of architects &lt;/a&gt;back at the beginning of 2008. One quote from Goldthwaite is worth repeating&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&amp;quot;a mason could operate as an architect only if he became head of a
works staff. ...he had to prove himself also as an administrator and
supervisor who could be responsible for procuring materials and
equipment, hiring and supervising workers, and, in general, directing
all the technical operations of the construction enterprise&amp;quot;.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;This idea that a journeyman becomes a master by understanding the
whole enterprise is particularly appealing as an ideal. You cannot just
focus on code, you need to understand the whole enterprise of
construction.&lt;/p&gt;
&lt;p&gt;I think that the manifesto is something that many who consider themselves alt.net would agree with. It is also an indication that the passion to improve on a community&amp;#39;s existing practices does not reflect unique problems in the .NET community but is parter of a wider agenda in the software development community to improve the standards of our industry.&lt;/p&gt;
&lt;p&gt; I&amp;#39;m not proposing dropping the alt.net moniker in favor or Software Craftsmanship. The Software Craftsmanship movement has specific goals and practices which align with alt.net, but it is not alt.net. What I am suggesting is that the alt.net movement intersect with broader movements like software crafstmanship. I think that engagement with broad movements like Software Craftsmanship would help many of us to broaden our horizons to the initiatives within the wider software community to improvement. Attending dojos or katas for different languages would help us all. I don&amp;#39;t think alt.net engagement needs to be replaced by Software Craftsmanship engagment, I think membership of both communities should not be orthogonal or exclusive in our minds at all.&lt;/p&gt;
&lt;p&gt;Wither ALt.NET?&lt;/p&gt;
&lt;p&gt;So I don&amp;#39;t think Alt.Net needs wither or be replaced by something else. I think its spirit ou&amp;rsquo;re not content with the status quo. Things can always be better
expressed, more elegant and&amp;nbsp;simple, more mutable,&amp;nbsp;higher quality, etc.&amp;quot; remains alive. I think the value in a community that supports those who practice that within the .NET community remains, even if needs to re-invent its passions on a regular basis.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=587174" width="1" height="1"&gt;</description></item><item><title>Where is the next Access?</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/11/19/where-is-the-next-access.aspx</link><pubDate>Thu, 19 Nov 2009 17:26:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:386951</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=386951</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/11/19/where-is-the-next-access.aspx#comments</comments><description>&lt;p&gt;Ted Neward recently &lt;a href="http://blogs.tedneward.com/2009/10/12/quotAgile+Is+Treating+The+Symptoms+Not+The+Diseasequot.aspx"&gt;posted a response&lt;/a&gt; to a talk by Biily Hollis, and asked &amp;quot;Where is this decade&amp;#39;s Access&amp;quot;. I think it is a great question, if only because I asked &lt;a href="http://weblogs.asp.net/Scottgu/"&gt;Scott Guthrie&lt;/a&gt; practically the same thing the other week.&lt;/p&gt;
&lt;p&gt;Like many of the people Ted refers to, I started my professional career in &lt;a href="http://en.wikipedia.org/wiki/FoxPro_2"&gt;FoxPro &lt;/a&gt;(I always find it amusing that productivity aspects of that tool, such as manipulating data as part of your 3GL, has only made it into the mainstream with LINQ To SQL, many years later). FoxPro had a &lt;a href="http://www.foxprohistory.org/articles_17.htm"&gt;passionate following&lt;/a&gt;, indeed I have heard it suggested that much of what we consider developer community today, was started by the FoxPro user base. For a whole class of scenarios, particularly a small workgroup of about a dozen users, FoxPro made it very quick to rapidly code and deploy applications. Even Visual Basic and Access, those other poster children of the &amp;#39;long tail&amp;#39; (as Ted puts it) developer market, did not have the capabilities that came with FoxPro for many years. FoxPro was ideal for applications that were essentially CRUD based. FoxPro was one of the &lt;a href="http://en.wikipedia.org/wiki/Xbase"&gt;XBase &lt;/a&gt;family of programming languages, a basic derived dynamic language but with a heavy slant to data retrieval and manipulation. When I used it, there was no RDMS attached, but the flat file DBF data format.&amp;nbsp; In many cases that was ideal our customers could not support the RDBMS solutions available at the time, and utlizing a file server was the easiest way to a networked database. Fox was an ideal tool for the time, when PC applications targetted less than a dozen users working on a LAN.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;I have to agree with Ted&amp;#39;s assertion that today, professional development tools, targetted at RAD application of solutions for small businesses do not seem to engender the same passion and commitment that FoxPro once did. Nor do they seem to offer the same productivity. And that may be a gap, because there is probably  still a market for applications that target a dozen people in a workgroup. &lt;/p&gt;
&lt;p&gt;Now before anyone worries I&amp;#39;m not about to have some damscence conversion to point-and-click development. When I used it FoxPro was certainly not a point-and click too anyway. But there is still a place for a toolset that makes it easy to knock up CRUD based sites. In a previous post I talked about DDD&amp;#39;s idea of strategic design, dividing up into generic domain, supporting sub-domain, and core domain. RAD tools are often ideal in the &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2009/09/28/beating-the-duct-programmer-with-generic-domains-subdomains-and-core-domains.aspx"&gt;supporting sub-domain development&lt;/a&gt; (by duct tape programmers).&lt;/p&gt;
&lt;p&gt;A lot of the Ruby enthusiasts I meet seem to love &lt;a href="http://en.wikipedia.org/wiki/Ruby_on_Rails"&gt;Rails &lt;/a&gt;for exactly the same reason I loved FoxPro. The ability to knock out usable applications quickly and with little fuss, yet still produce something professional. Rails works &amp;#39;out-of-the-box&amp;#39; to deliver CMS like systems to a wide range of customers. No one is suggesting the Rails crowd is dumbed-down, but their tools do embrace simplicity. &lt;a href="http://www.wired.com/techbiz/media/magazine/16-03/mf_signals?currentPage=1"&gt;37 Signals embraced the principle of keep it stupid, simple&lt;/a&gt;, for Rails to enable folks to build just this kind of applicaiton easily with configuration and &lt;a href="http://gettingreal.37signals.com/"&gt;outright reject attempts to add complexity&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So when Ted talks about simplicity he is chanelling the spirit of the Rails crew with their focus on keeping it stupid and simple. &lt;/p&gt;
&lt;p&gt;The closest thing we have today would seem to be ASP.NET MVC with jQuery and LINQ-To-SQL. That MVC should that level of simplicity may be no suprise because both it and Monorail take influence from Rails. Both pick up on the cleaner abstraction of MVC over the page controller approach that WebForms uses with its byzantine server side control model. I would agree with Jeffrey Palermo that the triumph of MVC is of &lt;a href="http://jeffreypalermo.com/blog/asp-net-mvc-wins-with-simplicity-not-features/"&gt;simplicity over features&lt;/a&gt;. Still MVC lacks some of the convention-over-configuration that gives Rails its edge. LINQ-To-SQL wins by a simple ORM. In this field its shortcomings when compared to NHibernate are its strengths, it is simpler and therefore more approachable to a mass audience. Finally jQuery makes JavaScript programming approachable, without the kind of effort that made dynamic behaviour on web sites so expensive in the past.&lt;/p&gt;
&lt;p&gt;The question is whether there is the commitment to take this combination forward or not from MS.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=386951" width="1" height="1"&gt;</description></item><item><title>The catalogue metaphor and command-query seperation architectures</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/10/08/the-catalogue-metaphor-and-command-query-seperation-architectures.aspx</link><pubDate>Thu, 08 Oct 2009 07:47:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:358683</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=358683</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/10/08/the-catalogue-metaphor-and-command-query-seperation-architectures.aspx#comments</comments><description>&lt;p&gt;Command-Query separation is being popularized today with architects like &lt;a href="http://codebetter.com/blogs/gregyoung/archive/2009/08/13/command-query-separation.aspx"&gt;Greg Young&lt;/a&gt;
and &lt;a href="http://www.udidahan.com/2008/08/11/command-query-separation-and-soa/"&gt;Udi Dahan&lt;/a&gt; as a way of architecting systems. It can be hard to grasp as a concept, even if we understand command-query seperation as a design pattern that influences the methods on our classes. It can be difficult to see how the principle scales to the level of architectures.&lt;/p&gt;
&lt;p&gt;Pat Helland&amp;#39;s article &lt;a href="http://msdn.microsoft.com/en-us/library/ms954587.aspx"&gt;Data on the Outside vs. Data on the Inside&lt;/a&gt; remains key for me in trying to understand this model. Pat distinguishes between operators and operands. Operators are commands, things we can do like order a meal, or order a book. Operands are the data that we use for that command. So order a Thai Green Curry, or orderDan Bropwn&amp;#39;s The Lost Symbol. This implies that we have to publish those operands so that people can discover them to use in the command. A way to think of this list of operands is as catalogue data.&lt;/p&gt;
&lt;p&gt;I find that the XP idea of an architectural metaphor helps me to
understand the seperation between operator and operand when architecting a solution.&lt;/p&gt;
&lt;p&gt;If I want to order a take-away from the Thai restaurant I need a menu that tells me what they deliver and how much it costs. The menu is not the food itself, it&amp;rsquo;s just an number, a name, and a price I can use to order the food with. Catalogue data has some interesting characteristics such as often being cacheable because it changes infrequently, or being versioned if we can deal with different varieties of it. But the key to this discussion is to appreciate that in order to carry out the task of ordering a takeway I need first to have a menu that lets us communicate about what I can order. In patterns terms I need to query for the food menu, and then issue the command to order the food.&lt;/p&gt;
&lt;p&gt;Now in software we have the same  need to present a user with catalogue data so that they can carry out a task. We have to tell them what operators are valid for our operands. This is where the query side of command-query comes in when thinking about command-query architectures. The query builds the catalogue - it grabs the list of acceptable operands for our operators.&lt;/p&gt;
&lt;p&gt;This is often easy to comprehend in the context of MVC architecures. When I get a request for a page that allows you to perform a task, I want to populate it with my operands. For example, if I want to enable the task of ordering food I need to
give you a menu. I do not want to load my food or customer entities for
this, because all I need is the name for you to display in&amp;nbsp; a pick list
(and possibly an id). When you perform the task, ordering the food, then I may need to
load the customer or food entities from their repository, create an order entity etc.&lt;/p&gt;
&lt;p&gt;Now the nature of the operands creates some interesting opportunities architecturally. At the simplest leve, instead of using repositories we might just use queries. I think this is some of the answer in the &lt;a href="http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx"&gt;repositories vs. queries debate&lt;/a&gt; - it also explains why FindAll on a Repository is often seen as a smell, because we
are using to obtain a collection of catalogue data and that is not a repository concern. We might use a different strategy altogether to make these queries such as NHibernate report queries or even ADO.NET (In a previous project we created a generic DataRader for reading objects with an ID and Name, called a SmartReference that we passed a stored procedure to load our catalogue data and then loaded into picklists). The objects you deal with here will often be anaemic, exactly the kind you fear in your domain model. But that is fine here, you are not creating domain objects but the operands for the operations you will perform on the domain. Some will indeed be catalogue data for items within your domain, and you load the full object in response to the command.&lt;/p&gt;
&lt;p&gt;We might even query against a different relational store to obtain our catalogue data. This may simply be to reduce load, but it might also be because our catalogue data might be published to this store from another application. In that case the catalogue data might well not be consistent with the current state of the publisher, if there is a delay, so our catalogue data might even be versioned.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;The important point is to realize that an application may have a healthy mix between domain data and catalogue data, and should handle each appropriately.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=358683" width="1" height="1"&gt;</description></item><item><title>Beating the duct programmer with generic domains, subdomains, and core domains</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/09/28/beating-the-duct-programmer-with-generic-domains-subdomains-and-core-domains.aspx</link><pubDate>Mon, 28 Sep 2009 03:27:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:367199</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>31</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=367199</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/09/28/beating-the-duct-programmer-with-generic-domains-subdomains-and-core-domains.aspx#comments</comments><description>&lt;p&gt;There has been&amp;nbsp; a certain amount of &lt;a href="http://blog.objectmentor.com/articles/2009/09/24/the-duct-tape-programmer"&gt;noise&lt;/a&gt; and &lt;a href="http://jeffreypalermo.com/blog/debunking-the-duct-tape-programmer/"&gt;comment &lt;/a&gt;around Joel Spolsky&amp;#39;s post on the &lt;a href="http://www.joelonsoftware.com/items/2009/09/23.html"&gt;duct tape programmer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is, for me, just another manifestation of the hero coder - the guy the business love because he &amp;#39;gets things done&amp;#39;. He is the guy who is turning out the features to the customer while you are still implementing top down from your acceptance to your unit tests. While you are trying to build a domain model, focusing on the ubiquitous language, and trying to create a model expressed in software, he has hacked out some procedural code that just works. While you create your ORM mappings in Fluent NHibernate, his DataReader has grabbed everything he needs from a custom stored procedure and pumped out the web page. In the customer&amp;#39;s eyes he is responsive, he gets their needs, and you don&amp;#39;t. &lt;/p&gt;
&lt;p&gt;The trouble with the hero programmer is that the customer does not know he uses duct tape, and your explanation of why it is an issue anyway is so complicated they lose interest. The truth is they just don&amp;#39;t care about your engineering principles. And the worst of it is that he will go on to write new features, while you fix
up his last duct-tape special, because he is the guy the customers want,
the hero programmer. He is the guy they think of when they used the word agile - responsive, adaptable to new requirements.&lt;/p&gt;
&lt;p&gt;Eric Evans has a fair amount to say about engineers being beaten by the duct tape, or hero programmer, and how those of committed to strong engineering priniciples can thrive in this &lt;a href="http://bit.ly/RHaH9"&gt;presentation.&lt;/a&gt; We talked this over at our development book club, con-incidentally the day after Joels&amp;#39; post broke. &lt;/p&gt;
&lt;p&gt;The presentation draws on the &amp;#39;second-half&amp;#39; of the &lt;a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215"&gt;DDD &amp;#39;blue&amp;#39; book&lt;/a&gt;, , the Strategic Design section, a part that is tragically overlooked in favor of the patterns in the first. Tragic because some of the strongest insights of Eric&amp;#39;s work are in this second half, but everyone focuses on aggregates and repositories in the first.&lt;/p&gt;
&lt;p&gt;The key idea here is that we need to focus on dividing our solution up into three areas: generic domain, supporting subdomain, and core domain. &lt;/p&gt;
&lt;p&gt;&lt;b&gt;Generic Sub-domain&lt;/b&gt;: This part of the software can just be bought off the shelf, or found from open source, because it has become ubiquitous and is comoditized. It might be a generic application such as accounts, document generation, CRM, ERP. It might be a generic framework such ORM, RDBMS, Reporting etc. Your customers are not doing anything here that gives them competitive advantage. In some cases they make want to work in a different way to that supported by the generic software; even so, in this case there is no return on supporting their way of working, so they need to conform to the generic model. Note the inclusion of both inftrastructure frameworks and applications. You might think you can build a better ORM or BUS, but unless your customer gains competitive advantage from that, do not tackle it.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Supporting Sub-domain&lt;/b&gt;: This is not commoditized, but your customer gains very little here. There is no special sauce, no clear case on return on investment. Identifying this area can be hard, because this is often specific to your customer&amp;#39;s domain, and you can&amp;#39;t find it off the-shelf. The key is that there is little competitive advantage to this code. The code here might be non-customer facing admin utilities such as user administration, but it also might be code that faces your customers, but provides little competitive advantage for you to get right. This is an area where use an off-the-shelf model if one exists. It is the area where you might outsource your requirements. It is the area where you deploy your hero programmer, because you just need it done and you don&amp;#39;t care if it is done with duct-tape. Often when there is change here your strategy is just to throw away your existing implementation and start again. This is highly disposable code.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Core Domain&lt;/b&gt;: This is where your customer gains competitive advantage. it is where custom development has a high return on investment. This is where you deploy your best programmers to build a domain model, make sure you use disciplined engineering approaches like automated tests and CI. This is where you don&amp;#39;t deploy your duct-tape programmer, you are worried about total cost of ownership here, because you don&amp;#39;t want to throw this code away and start again. It is a strategic investment.&lt;/p&gt;
&lt;p&gt;The core domain is almost certainly not the whole solution, but perhaps more suprisingly it may not even be a whole application. If your cutomer&amp;#39;s special sauce is a better rating, shipping, or pricing algorithm then that is your core domain. The web site that collects the data which you pass to that engine may not be - it might just be a supporting sub-domain your hero/duct-tape coder hacks out for you while your engineering team focuses on the core domain.&lt;/p&gt;
&lt;p&gt;You may well need an anti-corruption layer between your core domain and generic and supporting sub-domains, to prevent their model bleeding into your domain model. That anti-corruption layers also allows you to be defensive to quality concerns.&lt;/p&gt;
&lt;p&gt;The key here is working smarter, figuring out where the team focused on a costlier but disciplined engineering approach, can get return on the investment. With this approach you get to deliver the parts that make a difference to the customer instead of expending your effort on the supporting infrastructure.&lt;/p&gt;
&lt;p&gt;We watched Eric&amp;#39;s presentation above for our Developer Book Club and the war stories agreed with Eric. This pattern seems to be ubiquitous and we need to fnd a smarter way out that simply sticking our heads in the sand and denying the problem while pursuing an &amp;#39;ivory tower architecture&amp;#39; that the customer will never remain committed too.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=367199" width="1" height="1"&gt;</description></item><item><title>Agile is never 'no process'</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/09/11/agile-is-never-no-process.aspx</link><pubDate>Fri, 11 Sep 2009 08:19:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:345489</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>12</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=345489</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/09/11/agile-is-never-no-process.aspx#comments</comments><description>&lt;p&gt;David comments that agile is about &lt;a href="http://codebetter.com/blogs/david_laribee/archive/2009/09/08/the-secret-sauce.aspx"&gt;discipline&lt;/a&gt;. I could not agree more.&lt;br /&gt;&lt;br /&gt;Having encountered organizations that failed in a previous attempt at agile, one consistent story seems to be that agile was&amp;nbsp; brought on board as a developers initiative in response to &amp;#39;lack of process&amp;#39; complaints. However, agile seems to have been chosen by those developers as an answer not to up their game, but to give them an excuse for continuig with a low discipline approach to development. It&amp;#39;s the agile as a pseudonym for &amp;quot;we don&amp;#39;t want no stinking engineering practices paradigm&amp;quot;. It is for me, a big reason why agile has a bad name with some CTOs.&lt;br /&gt;&lt;br /&gt;It is usually a shock for developers at those organizations when they encounter genuine agile, with a high-discipline approach to software engineering. That is not what they believed it to be. A lot of them balk, commenting that the high-discipline approach cannot be agile, because it seems to involve them in a lot more software engineering than they were used to. A lot of them resist BDD style approaches as taking time which they could use to deliver, at planning and retrospective sessions as getting in the way of &amp;#39;writing code&amp;#39;. For them agile means &amp;#39;everyone gets out of my face and I hack code as fast as I can&amp;#39;. There is often a corollary here with developers who have a background in waterfall projects that get handed over the fence once live. They never had to support the project once delivered, so only care about &amp;#39;time to market&amp;#39; over &amp;#39;cost of owneship&amp;#39; so cannot see the value of these practices.&lt;br /&gt;&lt;br /&gt;The problem here is usually predicated not by classical waterfall approaches but organizations with homebrewed approaches to software engineering. (By homebrewed by the way I don&amp;#39;t mean the adapt the methodology to fit the project approach of the Crystal family, I mean the voodoo like approach of a collection of rituals to software delivery whose purpose or origin is usually shrouded in time or some incident).&amp;nbsp; The term agile refers to the ability of the methodoligies to react to feedback, not their process cost by contrast to those homebrew approaches to development.&lt;br /&gt;&lt;br /&gt;The problem her eis often that the term agile (or even lean) don&amp;#39;t recognize the fact that these homebrew methodologies are usually lightwieght and that agile practices seem heavywight by comparison. Some term that implies high responsiveness to feedback might well have been better, because it is more honest at describing their benefit.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=345489" width="1" height="1"&gt;</description></item><item><title>It's turtles all the way down</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/09/11/it-s-turtles-all-the-way-down.aspx</link><pubDate>Fri, 11 Sep 2009 07:14:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:307220</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=307220</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/09/11/it-s-turtles-all-the-way-down.aspx#comments</comments><description>
 
  Normal
  0
  
  
  
  
  false
  false
  false
  
  EN-GB
  X-NONE
  X-NONE
  
   
   
   
   
   
   
   
   
   
   
   
  
  MicrosoftInternetExplorer4
  
   
   
   
   
   
   
   
   
   
   
   
  

 
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
 

&lt;p&gt;

&lt;/p&gt;


&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Classically an ORM persists an object model to a relational model. Typically
just use it to retrieve or persist the state of the objects in our model, not
provide integration through models. Though obviously there is some translation
between the models in the act of persistence, the greater distance between the
two models the greater the effort we have to expend on the persistence mapping.
&lt;/p&gt;
&lt;p&gt;This becomes an issue when we are tempted by using a shared database schema
as a mechanism for system integration. The approach is simple in concept: two
systems with differing models, communicate by virtue of the fact that they
share a relational schema. In &lt;a href="http://www.eaipatterns.com/"&gt;Hohpe&amp;#39;s Enterprise Integration Patterns&lt;/a&gt;,
&lt;a href="http://martinfowler.com/"&gt;Martin
Fowler&lt;/a&gt; calls this integration style &lt;a href="http://www.eaipatterns.com/SharedDataBaseIntegration.html"&gt;Shared
Database&lt;/a&gt;. The two systems don&amp;#39;t exchange information, they share
information.&lt;/p&gt;
&lt;p&gt;Shared Database seems an attractive way to integrate systems within your
enterprise at first. You do not have the &lt;a href="http://www.ddj.com/architect/184414966"&gt;complexity multiplier of
distributed systems&lt;/a&gt; and the skills sets required to make them work.
Corporate MI does not have to map between models to report, it just points to
an reporting store created from the shared repository (or in poor
implementations to the transactional store itself). &lt;/p&gt;
&lt;p&gt;There are a number of problems that flow out of shared database approaches. &lt;/p&gt;
&lt;p&gt;The applications have both data and behaviour. Interpreting what a field
such as premium means to source systems often requires an understanding of the behaviour
to eliminate ambiguities. Is a field called premium net or gross of tax, for
example? Looking at the source system may be required to determine the
properties of the field. The source system will also contain rules about the
validity of records, information that we often can&amp;#39;t capture with constraints.
We can try to work around this by ensuring that we document the usage along
with the schema, but documentation tends to fall behind a system which leads to
an insidious growth in inaccuracy.&amp;nbsp; If we are to create a schema that
multiple applications can use to store their data, we need to remove any&amp;nbsp;ambiguity.
If that was not hard enough, we need to have a schema that is both a superset
of all their data, and this often makes the representation complex. Those
complex representations are not just hard to comprehend, they often perform
badly.&lt;/p&gt;
&lt;p&gt;In addition the database schema now has multiple owners, so we need to
negotiate how changes to the model impact consumers. We might have an adequate
test suite to allow us to use continuous integration, but often the systems
involved in shared database include legacy applications that have no such
ability to understand the impact of changes across all consumers of the model.
That makes change very expensive and so tends to lead to software atrophy as we
are no longer able to keep our software in synchronization with business needs.&lt;/p&gt;
&lt;p&gt;These complex models prove difficult for developers and domain experts
alike. Domain experts may find that they do not represent the model of the
problem domain. In Domain Driven Design (DDD) terms we have two bounded
contexts, the model for the application and the model for the shared database.
The developers is then confronted with some unpalatable choices. Does he
conform to the model in the Shared Database, hydrating an object model that is
essentially an OO representation of the ER model? This will prevent him from
using the principle of ubiquitous language to share the same model as the
domain expert within the implementation of the software. This is not just an
academic issue, it becomes a significant overhead to translate the requirements
from the domain expert to their expression in the model, and is often lossy and
error prone. Even something as simple as responding to a live issue becomes
more complicated when the model bears little relation to the problem
experienced by the end user. &amp;quot;My broker&amp;#39;s address details are not being
refreshed correctly&amp;quot; becomes much more complicated if you do not have an
entity called broker in your system but a Party with a PartyRole of Broker.
Someone needs to understand the translation to solve the issue.&lt;/p&gt;
&lt;p&gt;So it can seem tempting to try and use our ORM tool to elide this problem,
by mapping from the ER into the OO model. After all an ORM tool allows
model-to-model mapping, so why not leverage it? So ORM tools such as Linq to
SQL are not really sophisticated enough to handle this kind of translation.
Others are though and this kind of sophistication can be tempting. Indeed, this
seems to me to be one of the supposed benefits of the EF is its ability to put
some kind of anti-corruption layer between the relational schema and the OO
model. &lt;/p&gt;
&lt;p&gt;The problem is that this leads to a growth in complexity that seems contradictory
to our supposed benefit for using shared database, low cost, in the first place.&lt;/p&gt;
&lt;p&gt;Eric Evans points out in Domain Driven Design that:&lt;/p&gt;
&lt;p&gt;&amp;quot;Technically, the relational table design does not have to reflect the
domain model. Mapping tools are sophisticated enough to bridge significant
differences. The trouble is, multiple overlapping models are just too
complicated. Many of the same arguments presented for &lt;span class="docemphsmaller"&gt;MODEL-DRIVEN DESIGN&lt;/span&gt;&amp;mdash;avoiding separate analysis and
design models&amp;mdash;apply to this mismatch. This does entail some sacrifice in the
richness of the object model, and sometimes compromises have to be made in the &lt;span class="doctexthighlight"&gt;database&lt;/span&gt; design (such as selective
denormalization), but to do otherwise is to risk losing the tight coupling of
model and implementation.&amp;quot; - Eric Evans, Domain Driven Design&lt;/p&gt;
&lt;p&gt;The danger with better tooling is that it can sometimes make approaches that
we once have found to difficult to swallow seem more digestible. However, just
because the cost to implement drops does not mean that the cost of ownership drops
along with it, in fact it often increases.&lt;/p&gt;
&lt;p&gt;Try to keep the idea that it is &amp;lsquo;turtles all the way&amp;rsquo; down and keep the
design of your relational model the same as your object model. In addition, avoid
the use of shared database as an integration strategy within the Enterprise and
prefer messaging. What you gain in implementation cost you will lose many times
over in ownership cost.&lt;/p&gt;
&lt;p&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=307220" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/Object-Orientation/default.aspx">Object-Orientation</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/ORM/default.aspx">ORM</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/DDD/default.aspx">DDD</category></item><item><title>Agile Fails Better</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/07/14/agile-fails-better.aspx</link><pubDate>Tue, 14 Jul 2009 08:57:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:249962</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=249962</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/07/14/agile-fails-better.aspx#comments</comments><description>&lt;p&gt;One overlooked aspect of agile is that it fails well. People tend to talk about this obliquely referring to the &lt;a href="http://www.ambysoft.com/essays/whyAgileWorksFeedback.html"&gt;feedback mechanism&lt;/a&gt; as being an important part of the agile process. I suspect the reason is that people do not like to talk about project failure when discussing agile; because, they want to give the idea that agile is somehow innoculated against failure. I believe that agile is instead better at reducing the damage of failure and increasing the chance of recovery from the failure. The goal in agile is to fail fast, when you can still react positively to that failure. Now I would agree that &amp;#39;agile engineering processes&amp;#39; (really just &amp;#39;good enginnering practices&amp;#39;) can help reduce the chance of failure, but &lt;a href="http://serialseb.blogspot.com/2009/02/agile-and-scrum-failure-stories.html"&gt;no project is immune to failure&lt;/a&gt; or atl least being considered &lt;a href="http://community.ca.com/blogs/theitgovernanceevangelist/archive/2009/05/04/understanding-project-failure-rates.aspx"&gt;challenged&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Consider a project that requires six man-months to deliver. Let us presume, for the purpose of argument that this is two months each of analysis, development, and testing regardless of our decision to use a waterfall or agile approach. Under a classic waterfall model we would plan this as two months of analysis, followed by equal periods of development and testing. Under a classic agile model we might plan this as twelve iterations of two weeks. Now assume that we are going to uncover an architectural problem during QA that we do not see in developer testing. Under the waterfall approach the earliest we are going to learn about this would be 4 months into the project when we begin testing. More likely we might find it 5 months in or later. Under an agile project we might find this within two weeks. This is especially true if we plan our iterations with an early release targetted as &lt;a href="http://alistair.cockburn.us/Walking+skeleton"&gt;walking skeleton&lt;/a&gt; (Lean calls this a spanning application and the Pragmatic Programmers a &lt;a href="http://www.artima.com/intv/tracer.html"&gt;tracer bullet&lt;/a&gt;). If we had opted for an initial walking skeleton release with agile iterations we could have flushed out architectural failures early.&lt;/p&gt;
&lt;p&gt;If I fail within say six weeks as opposed to within five months I dramatically increase my range of options. I could decide to abandon the project. Because my sunk costs are probably lower my capacity to walk away improves. &lt;/p&gt;
&lt;p&gt;Early failure is positive for more than just avoiding waste here. It is useful because it modifies my perception of risk. Because my risk is lower I may feel more able to make the decision to begin a project, so I may spend less on &amp;#39;due diligence&amp;#39; up front, increasing my ability to sieze market opportunities. I also have much more ability to assess what is wrong, re-plan and re-commence, because telling the customer this far in advance of any delays or increased costs gives them much more ability to react. Especially if the customer knows that I am trying to get the suprises out of the way up front.&lt;/p&gt;
&lt;p&gt;Kent Beck said in an &lt;a href="http://www.computerworld.com/s/article/9046399/Extreme_Programming_inventor_talks_about_agile_development?source=rss_news50"&gt;interview with ComputerWorld&lt;/a&gt;&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;i&gt;No. I think software projects are still going to fail because there
still [will be] the promising ideas that don&amp;#39;t work out in practice.
One thing that agile development can give you is to make sure those
projects fail faster, sooner, cheaper, so you can get on with the next
thing&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=249962" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/Agile/default.aspx">Agile</category></item><item><title>Embrace Pain</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/07/07/embrace-pain.aspx</link><pubDate>Tue, 07 Jul 2009 11:38:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:249813</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>17</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=249813</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/07/07/embrace-pain.aspx#comments</comments><description>&lt;p&gt;Agile is about surfacing pain. It&amp;#39;s not about roses, perfume, and happy candlelight dinners together. Traditional project management methodologies made it easy to sweep the pain under the carpet, lying about how you were doing up until the end of the project, when you hoped everything would just go away emerged to haunt or kill you. Traditional project management methodologies are all about denial. Why do predictive methodology plans fail so often? The release plan correctly goes out of alignment with the reality. A task overruns, a task underruns, a dependency holds up delivery. Sometimes people re-plan, but the effort mean most just ignore it, burying technical debt to stay on track, ignoring opportunities to take on more work, lying to their stakeholders about where they really are. Agile uses an adaptive approach, because that allows you to surface the truth about when and where things are failing, or where there are opportunites that could be exploited.&lt;br /&gt;&lt;br /&gt;Being agile hurts. It exposes you before your peers with all your insecurities, wounds, failures and weaknesses. But accepting those problems lets you take steps to fix them.&lt;br /&gt;&lt;br /&gt;So if you think you are an agile project and you are not constantly surfacing nasty, miserable pain, then you might not be doing it right.&lt;br /&gt;&lt;br /&gt;What are generally called agile development processes are best practices for fixing the pain that agile can surface, without creating more pain in turn. Now Scrum&amp;nbsp; gets a lot of ragging for not including engineering processes. But I think that the point here though is that heart of Agile is about the surfacing of those problems, not the fixing of them. We want to fix them, and you may want to go to your XP, Crystal or Scrum library and pull out remedies for your pain from those cupboards. You might even want to vaccinate your project from them. These engineering processes are in important part of your methodology, but they are a response to the pain that agile surfaces. You do continuous integration because you don&amp;#39;t want the pain of integrating code streams after days of effort, or taking several days to do the build.&lt;br /&gt;&lt;br /&gt;The key to agile is that you are bringing down the pain. Because then you can deal with it.&lt;br /&gt;&lt;br /&gt;I suspect that the reason a lot of Scrum implementations seem to be failing is because the attitude of those using them is to hide the pain, not to surface it. That is self-defeating, but emerges because the stakeholders of the organization become scared when they see so much pain early in a project&amp;#39;s lifecycle. They are not used to that level of honesty. So they think something must be wrong. In fact something is terribly right. However,&amp;nbsp; you have to set expectations to understand that you intend to bring down the pain so that you won&amp;#39;t be finding it all when its too late or too expensive to do anything about it.&lt;br /&gt;&lt;br /&gt;Everything always done , every sprint always 100%, no defects? These are often lies we tell ourselves to defer the day of reckoning. Maybe you&amp;#39;re getting it right, but don&amp;#39;t lie to make it look like success, because it isn&amp;#39;t.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=249813" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/XP/default.aspx">XP</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/Agile/default.aspx">Agile</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/SCRUM/default.aspx">SCRUM</category></item><item><title>Making your code easier to understand context/specification style unit tests</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/06/29/making-your-code-easier-to-understand-context-specification-style-unit-tests.aspx</link><pubDate>Mon, 29 Jun 2009 04:08:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:249314</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>13</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=249314</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/06/29/making-your-code-easier-to-understand-context-specification-style-unit-tests.aspx#comments</comments><description>&lt;p&gt;When we started our current project we did not use &lt;a href="http://stevenharman.net/blog/archive/2009/05/27/toward-a-better-use-of-context-specification.aspx"&gt;context/specification style testing&lt;/a&gt;, instead we used &lt;a href="http://xunitpatterns.com/Testcase%20Class%20per%20Class.html"&gt;testcase-per-class&lt;/a&gt; with a &lt;a href="http://xunitpatterns.com/Four%20Phase%20Test.html"&gt;four-phase test model&lt;/a&gt; (also known as &lt;a href="http://c2.com/cgi/wiki?ArrangeActAssert"&gt;arrange-act-assert&lt;/a&gt;). Although we followed &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2009/03/31/seizing-the-bdd-nettle.aspx"&gt;story-test driven development&lt;/a&gt; (STDD) we were not explicitly Behavior-Driven Development &lt;a href="http://dannorth.net/introducing-bdd"&gt;BDD &lt;/a&gt;when we set out. Over time I began to see the path between STDD and BDD we shifted toward a BDD approach.&lt;/p&gt;
&lt;p&gt;That is really background for what comes next. As part of this shift we started writing more context/specification style tests. We did not re-write our existing testcase-per-class fixtures (then and still now I would see the possibility of using multiple &lt;a href="http://xunitpatterns.com/Test%20Organization.html"&gt;test organisational patterns&lt;/a&gt; within a project; some of our tests still seem better with testcase-per-class). Recently we have had new developers join the team. One interesting, if anecdotal, observation has been that those developers find it easier to use tests as a source of documentation for what the software is doing when they are in the context/specification style. This is a useful observation, because the rest of the team is able to supply much of the context for testcase-per-class fixtures by virtue of having worked on the codebase and so do not see the lack so easily.&lt;/p&gt;
&lt;p&gt;To build a maintainable system you have to build one where the behavior can be understood. Tests offer this promise, but often we have found that tests failed us, because the tests were no easier to comprehend than the code under test. Context/specification style tests seem to be better on this account. Of course there is no silver bullet in software. You still have to put the effort into making your context/specification tests readable, but the form seems helpful toward achieving that goal.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ll try to post more on my experiences with BDD style approaches as they come out. I would also recommend that anyone interested in the topic look at the&lt;a href="http://www.pragprog.com/titles/achbd/the-rspec-book"&gt; RSpec book&lt;/a&gt; from the Pragmatic Programmers which offers a great overview of the topic.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=249314" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/TDD/default.aspx">TDD</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/xUnit/default.aspx">xUnit</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/BDD/default.aspx">BDD</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/Behavior+Specification/default.aspx">Behavior Specification</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/ATDD/default.aspx">ATDD</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/STDD/default.aspx">STDD</category></item><item><title>Should you learn frameworks or principles</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/06/11/should-you-learn-frameworks-or-principles.aspx</link><pubDate>Thu, 11 Jun 2009 02:12:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:248069</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>26</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=248069</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/06/11/should-you-learn-frameworks-or-principles.aspx#comments</comments><description>&lt;p&gt;







&lt;/p&gt;

 
  Normal
  0
  
  
  
  
  false
  false
  false
  
  EN-GB
  X-NONE
  X-NONE
  
   
   
   
   
   
   
   
   
   
   
   
  
  MicrosoftInternetExplorer4
  
   
   
   
   
   
   
   
   
   
   
   
  

 
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
 

&lt;p&gt;

&lt;/p&gt;



&lt;p&gt;There was a comment on the &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2009/04/14/on-learning-boo.aspx"&gt;On
Learning Boo&lt;/a&gt; post along the lines of : &lt;i&gt;I only focus on learning
frameworks, because they increase my marketability, learning new languages,
ideas like DSLs just takes time away from that effort&lt;/i&gt;. It is a fairly
common attitude. I have spoken to people who have told me that their focus is
on &lt;i&gt;learning the Microsoft .NET toolset&lt;/i&gt;, commenting that they feel that
is enough of a challenge and one that translates best into career
opportunities. I have seen recruiters and companies assessed with statements
like&lt;i&gt; 2 years of ASP.NET MVC&lt;/i&gt; as some means to indicate the competence of
a developer to join a team.&lt;/p&gt;
&lt;p&gt;At the same time for many developers the number of new frameworks tumbling
out of Redmond makes it seems like a struggle to keep up. Those who feel that they
must keep up, naturally feel overwhelmed. Restricting their focus to just what
comes out of Redmond seems like a good strategy to manage the problem.
Unfortunately, focusing on learning vendor frameworks is a trap. There will
always be another new framework to learn to do what you were doing yesterday.
Look at the churn in data access frameworks in the Microsoft space. Knowledge
gained is quickly outdated. You end up on a treadmill, learning one vendor
framework after another. You fall into the trap of appraising your next job
solely on the criteria of what frameworks your prospective employer is using, just
so that you can gain some experience using that new framework and keep your
C.V. up to date.&lt;/p&gt;
&lt;p&gt;Assessing developers by their knowledge of them, especially through
certifications is an equally bad trap for employers to fall into. At best it is
deceptive about what skills developers actually need. At worst it is a prison
because the investment of knowledge in a particular technology becomes a
ball-and-chain that makes individuals and corporations resistant to change.
Having hired all those skilled Webforms developers and learnt all those vendor
control kits, how could you rationally adopt ASP.NET MVC for your next project?
After all you don&amp;#39;t have any experience with it. Should you now dismiss your
entire team and hire experienced ASP.NET developers? Or if you do change, what
good did it do you to recruit people based on their understanding of the
ASP.NET page lifecycle. Would it not have been better to hire people who had
the skills to learn new frameworks?&lt;/p&gt;
&lt;p&gt;When I was younger, I used to focus on learning the latest toolkit because I
saw that as the best way to improve my marketability.&amp;nbsp; I spent ages poring
over the internals of MFC, ATL etc. I could talk about the details of the STL,
Boost, Loki with the best of them. I wanted to be an expert on those libraries.
I looked for new jobs when old ones did not offer me the opportunity to use the
latest and greatest frameworks. Did it make me better developer? Maybe, but not
in the way I expected. What I gained from poring over those frameworks
eventually was an appreciation of the common underlying patterns. I might have
learned something from understanding how the internals were implemented too,
but it was pattern recognition of ideas like iterators, factories, template
methods that gave me the most benefit. The next time I tried to learn a
library, seeing how it solved problems I understood, seeing how it use patterns
and principles I recognized, meant that I was able to being working with the
framework faster. But I did this hard way, not by recognizing patterns I was
aware of and seeing where they were implemented, but by discovering them seeing
them repeated.&lt;/p&gt;
&lt;p&gt;The reason so many of us get excited by books like Fowler&amp;#39;s &lt;a href="http://martinfowler.com/eaaCatalog/"&gt;Patterns of Enterprise
Application Architecture&lt;/a&gt;, his work on &lt;a href="http://martinfowler.com/eaaDev/uiArchs.html"&gt;GUI Architectures&lt;/a&gt; of
&lt;a href="http://www.martinfowler.com/bliki/DomainSpecificLanguage.html"&gt;DSLs&lt;/a&gt;
(and the work of others) is that they capture those patterns and principles.&amp;nbsp;
A solid knowledge of the principles relating models, views, and controllers
would enable you to learn a range of web frameworks ore quickly because you
look to see how they solve problems. &lt;/p&gt;
&lt;p&gt;Learning new skills such as how to write a DSL in Boo will give you the breadth of aproaches that enable you to deliver better architected applications. The burden of maintenance is greater than the burden of writing, so a better architected application is always a good investment for a company. Far more than squeezing some obscure feature out of your latest framework is.&lt;/p&gt;
&lt;p&gt;If anything the industry has moved on from those nuts and bots frameworks,
and the abstractions have gotten better. Less and less do you need to
understand the how and more and more the why? Knowledge of the patterns and
principles provide continuing value to you as frameworks change. It also helps
you understand how to use the frameworks, how to judge their quality against
some kind of best practice yardstick and how to manipulate them when they fall
short of best practice&lt;br /&gt;
&lt;br /&gt;
As someone who interviews people I look more for understanding of the
principles than the minutiae. The problem is that there will always be a new
&amp;#39;better&amp;#39; framework, a new popular paradigm. There is always the possibility
that a new language comes along that we want to use instead for a given
project. People who understand the principles can adapt. People who focus on
the detail are intransigent to change, because they have too much invested in
the framework that they have become an expert in.&lt;/p&gt;
&lt;p&gt;Now before someone suggests otherwise I am not implying that people do not
need to know how to use their tools to get the best out of them. Of course they
do. But you will find a more efficient path to assessing and learning new
frameworks through understanding the principles behind them than through
learning each one in isolation.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=248069" width="1" height="1"&gt;</description></item><item><title>Introduction to NHibernate, pt. 7</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/06/04/introduction-to-nhibernate-pt-7.aspx</link><pubDate>Thu, 04 Jun 2009 03:56:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:248066</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>16</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=248066</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/06/04/introduction-to-nhibernate-pt-7.aspx#comments</comments><description>&lt;p&gt;In earlier parts of this series we looked at &lt;a href="http://codebetter.com/blogs/ian_cooper/archive/2008/12/12/introduction-to-nhibernate-part-2.aspx"&gt;mapping via XML mapping files&lt;/a&gt;. I wanted to look at some alternatives to the angle bracket tax. First up is the Castle project&amp;#39;s Active Record. Next time we will look at Fluent NHibernate.&lt;/p&gt;
&lt;h2&gt;Active Record Support for Attribute Based Mapping&lt;/h2&gt;
&lt;p&gt;While mapping via an xml file allows access to the full range of options that NHibernate gives us, it can be slow, because it forces us to context switch between C# and XML. Both NHibernate and Castle have attribute mapping options. NNHibernate.Mapping.Attributes is an add-in for NHibernate contributed by Pierre Henri Kuat&amp;eacute;. Active Record is part of the Castle project, originally intended to support the Active Record pattern favored by Ruby On Rails.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;We&amp;#39;ll just discuss how to use Active Record&amp;#39;s Attribute Support here. Essentially ActiveRecord contains attributes that are the equivalent of elements from the mapping file. For example to map the Customer class we mark it up as follows.&lt;/p&gt;
&lt;h3&gt;Adding the required references&lt;br /&gt;&lt;/h3&gt;
&lt;p&gt;We need to reference a number of assemblies to get ActiveRecord support:&lt;br /&gt;Castle.ActiveRecord.dll&lt;br /&gt;Castle.Core.dll&lt;br /&gt;Castle.Components.Validator.dll&lt;br /&gt;Castle.DynamicProxy.dll&lt;br /&gt;NHibernate.dll&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;We also need to change our configuration file to configure ActiveRecord instead of NHibernate (ActiveRecord configures NHibernate from this information). We an configure either by a stand-alone xml file or through the app.config. For simplicity we configure through the app.config file here. &lt;/p&gt;
&lt;p&gt;&lt;br /&gt;We need to add a config section handler for the active record section of our configuration file:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;configSections&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;section name=&amp;quot;activerecord&amp;quot; type=&amp;quot;Castle.ActiveRecord.Framework.Config.ActiveRecordSectionHandler, Castle.ActiveRecord&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/configSections&amp;gt;&lt;br /&gt;&lt;br /&gt;The configuration mainly tells NHibernate how to access the Db. There are two key attributes of the &amp;lt;activerecord&amp;gt; element. We need to set the IsWeb attribute to true if we are an asp.net web application. We need to set the IsDebug attribute to true, if we want to see the generated mapping files (see below).&lt;/p&gt;
&lt;p&gt;Note that when working with NHibernate 2.0+ the sample code given on the Castle site for Active Record uses incorrect key values that are prefixed with NHibernate. You need to change these to omit the &amp;quot;hibernate.&amp;quot; from the name. If you forget to do this you will get messages about invalid key from log4net. This is because the hibernate.* keys are no longer in the schema.&lt;/p&gt;
&lt;p&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;utf-8&amp;quot; ?&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;configSections&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;section name=&amp;quot;activerecord&amp;quot; type=&amp;quot;Castle.ActiveRecord.Framework.Config.ActiveRecordSectionHandler, Castle.ActiveRecord&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;section name=&amp;quot;log4net&amp;quot; type=&amp;quot;log4net.Config.Log4NetConfigurationSectionHandler, log4net&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/configSections&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;lt;activerecord isWeb=&amp;quot;false&amp;quot; isDebug=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;config&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; key=&amp;quot;connection.driver_class&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; value=&amp;quot;NHibernate.Driver.SqlClientDriver&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; key=&amp;quot;dialect&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; value=&amp;quot;NHibernate.Dialect.MsSql2000Dialect&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; key=&amp;quot;connection.provider&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; value=&amp;quot;NHibernate.Connection.DriverConnectionProvider&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; key=&amp;quot;connection.connection_string&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; value=&amp;quot;Data Source=.;Initial Catalog=nhibernate;Integrated Security=SSPI&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/config&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/activerecord&amp;gt;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp; &amp;lt;log4net&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;appender name=&amp;quot;ConsoleAppender&amp;quot; type=&amp;quot;log4net.Appender.ConsoleAppender, log4net&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;layout type=&amp;quot;log4net.Layout.PatternLayout, log4net&amp;quot;&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;param name=&amp;quot;ConversionPattern&amp;quot; value=&amp;quot;%m&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/layout&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/appender&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;root&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;priority value=&amp;quot;DEBUG&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;appender-ref ref=&amp;quot;ConsoleAppender&amp;quot; /&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/root&amp;gt;&lt;br /&gt;&amp;nbsp; &amp;lt;/log4net&amp;gt;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;Using attributes to peform our mapping&lt;/h3&gt;
&lt;p&gt;We mark the entity with an [ActiveRecord] attribute to indicate that we want NHibernate to persist it. We can add the table name if it does not match the entity name [ActiveRecord(&amp;quot;MyTableName&amp;quot;)]. We can indicate that we want the entity to be loaded, by adding the Lazy attribute as in [ActiveRecord(Lazy=true)].&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;We can declare that our class inherits from ActiveRecordBase if we want Active Record pattern semantics, i.e. the entity knows how to retrieve and persist itself. We want true seperation of concerns, so we do not intend to mix CRUD mechanics with our entity. For this reason we do not derive our class from ActiveRecordBase.&lt;/p&gt;
&lt;p&gt;We mark up the identity of our entity using the [PrimaryKey] attribute. The default primary key type is native, so we do not need to mark this up, but if we have a different strategy then we have to explicitly indicate that. For example to use a GUID we would use: PrimaryKey(PrimaryKeyType.UuidHex, Params=&amp;quot;format=D,seperator=-&amp;quot;)]&lt;/p&gt;
&lt;p&gt;We can mark up a property using the [Property] attribute. In addition, we can use [Field] if we want to map a private member of the class. If we need to map to a column with a different name to the property then we can pass it as a parameter to the attribute [Property(&amp;quot;MyColumnName&amp;quot;)]. If we have a large object then we can set the column type - see the the Active Record documentation.&lt;/p&gt;
&lt;p&gt;We use a [HasMany] attribute to represent a one-to-many relationship, attributing the collection on the parent class i.e. [HasMany(typeof(Post), Table=&amp;quot;Posts&amp;quot;, ColumnKey=&amp;quot;blogid&amp;quot;)]. We use the RelationType enumerated value to specify the type of the relationship i.e. RelationshipType.Set. We also set the Inverse parameter as part of the HasMany attribute if this is a bi-directional relationship to avoid generating the insert and update statement, and creating an insert only. We can indicate if this relationship should be lazy-loaded using the Lazy parameter on the HasMany attribute. As with XML mapping we can also set the action NHibernate should take when we update or delete the parent using the Cascade option. In addition, we can set the index if we use one of the ordered types for our relationship or the sort order.&lt;br /&gt;We use a [BelongsTo] attribute on the reverse side of the relationship to indicate a Many-To-One relationship. We need to pass the name of the foreign key column as a parameter to the attribute. Again there are options that reflect those available from the xml mapping file.&lt;/p&gt;
&lt;p&gt;ActiveRecord also provides support for more advanced scenarios that are outside the scope of this article (it is meant to be an introduction and most of this is documented elsewhere):&lt;/p&gt;
&lt;p&gt;HasAndBelongsToMany&lt;br /&gt;OneToOne&lt;br /&gt;Any and HasManyToAny&lt;/p&gt;
&lt;p&gt;ActiveRecord also supports inheritance, supporting both the table Table-per-class hierarchy and Table-per-subclass strategies. &lt;/p&gt;
&lt;p&gt;&lt;br /&gt;Mapping the Table-per-class hierachy strategy is straightforward, just set the parameters on the superclass ActiveRecord attribute to indicate the discriminator column to use i.e. [ActiveRecord(&amp;quot;companies&amp;quot;, DiscriminatorColumn=&amp;quot;type&amp;quot;, DiscriminatorType=&amp;quot;String&amp;quot;, DiscriminatorValue=&amp;quot;company&amp;quot;)] and then indicate the value for each of the sub-classes i.e. [ActiveRecord(DiscriminatorValue=&amp;quot;firm&amp;quot;)].&lt;br /&gt;Mapping the Table-per-subclass strategy requires us to use the JoinedBase attribute on the superclass ActiveRecord attribute i.e. [ActiveRecord(&amp;quot;entity&amp;quot;), JoinedBase] and then use the [JoinedKey] attribute on the shared key value of the sub-classes.&lt;/p&gt;
&lt;p&gt;ActiveRecord also provides support for fine grained object models. We declare the [Nested] attribute on the property declaration in the containing entity, and then only mark up the component class with [Property] attributes i.e. not with [ActiveRecord] or [PrimaryKey] attributes.&lt;/p&gt;
&lt;h3&gt;Configuring Active Record&lt;/h3&gt;
&lt;p&gt;Before using ActiveRecord we must invoke the method Initialize on ActiveRecordStarter to configure NHibernate for us.There are a range of options to use when configuring, depending on where your configuration information is found. Because we added our configuration to the app.config file we can use the ActiveRecordSectionHandler to retrieve our configuration information.&lt;br /&gt;ActiveRecordStarter also provides the functionality to generate our schema from our code.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; log4net.Config.XmlConfigurator.Configure();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IConfigurationSource config = ActiveRecordSectionHandler.Instance;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ActiveRecordStarter.Initialize(typeof(Company).Assembly, config);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ActiveRecordStarter.CreateSchema();&lt;/p&gt;
&lt;h2&gt;Switching from attributes to mapping files&lt;/h2&gt;
&lt;p&gt;Active Record generates XML mapping files at run-time from your attributes, so this is using the same mechanism as the XML configuration, the complexity is just hidden from you. If you want to see the mapping then you can set the Debug value to true on the active record configuration (see above). This will tell NHibernate to keep the files around when your application ends, instead of deleting them. &lt;br /&gt;This allows you to pursue a strategy of beginning development by using attributes, and then switching to .hbm.xml files later to fully utilize all options and keep your domain model clean of mapping information.&lt;br /&gt;&lt;/p&gt;
&lt;h2&gt;Active Record support for Session Management&lt;/h2&gt;
&lt;p&gt;Active Record removes the need to initialize a session factory explicitly, instead we use the ActiveRecordStarter.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IConfigurationSource config = ActiveRecordSectionHandler.Instance;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ActiveRecordStarter.Initialize(typeof(Company).Assembly, config);&lt;/p&gt;
&lt;p&gt;For a web based application best practice is that we initialize within the Application_Start method of the global HttpApplication object.&lt;/p&gt;
&lt;p&gt;Active Record operations try to get a session from the current thread, but create one if it is not extant, perform the operation and then release the session. So by default Active Record is session per operation. Active Record also gives us the ability to use a SessionScope to keep the session alive for the scope of our business transaction. Best practice is always to use a SessionScope.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (new SessionScope())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const string COMPANY_NAME = &amp;quot;CompanyOfWolves&amp;quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InsertNewCompany(COMPANY_NAME);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int companyId = FindInsertedCompany(COMPANY_NAME);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;For a web application the usual pattern is to create a &lt;a href="http://www.castleproject.org/activerecord/documentation/trunk/usersguide/web.html."&gt;SessionScope with request affinity&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Active Record and Repositories&lt;/h2&gt;
&lt;p&gt;The problem with the Active Record pattern, where the entity exposes CRUD methods is that it does not enforce a clean separation of concerns. (We have not shown this but to get Active Record working this way we need our entities to derive from ActiveRecordBase). Knowledge about persistence is coupled with knowledge about domain responsibilities. This increases complexity and thus makes maintenance harder. So good design strives for persistence ignorance within its domain model. The repository lives within the domain model and represents a collection of entities from an aggregate root.&lt;/p&gt;
&lt;p&gt; &lt;br /&gt;We call the repository from our domain level service to persist the object graph.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Support for Repository within Active Record&lt;/h3&gt;
&lt;p&gt;Active Record provides ActiveRecordMediator to allow you to use ActiveRecord to implement a repository.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; public class CompanyRepository&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected ActiveRecordMediator&amp;lt;Company&amp;gt; mediator;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Add(Company item)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ActiveRecordMediator&amp;lt;Company&amp;gt;.Save(item);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public virtual this[ int id]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; get { return ActiveRecordMediator&amp;lt;Company&amp;gt;.FindByPrimaryKey(id); }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Company[] Find(IActiveRecordQuery query)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (Company[])ActiveRecordMediator&amp;lt;Company&amp;gt;.ExecuteQuery(query);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Company[] Items()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ActiveRecordMediator&amp;lt;Company&amp;gt;.FindAll();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public virtual int Count()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ActiveRecordMediator&amp;lt;Company&amp;gt;.Count();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;A quick example of using this repository (domain services etc. elided to remove complexity) would be:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void Main(string[] args)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; log4net.Config.XmlConfigurator.Configure();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IConfigurationSource config = ActiveRecordSectionHandler.Instance;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ActiveRecordStarter.Initialize(typeof(Company).Assembly, config);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ActiveRecordStarter.CreateSchema();&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Comment out the session scope to see lazy load lack of scope issues&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (new SessionScope())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const string COMPANY_NAME = &amp;quot;CompanyOfWolves&amp;quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InsertNewCompany(COMPANY_NAME);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int companyId = FindInsertedCompany(COMPANY_NAME);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static int FindInsertedCompany(string companyName)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IActiveRecordQuery query = new SimpleQuery&amp;lt;Company&amp;gt;(&amp;quot;from Company org where Name = ?&amp;quot;, companyName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CompanyRepository companyRepository = new CompanyRepository();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Company[] companies = companyRepository.Find(query);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Company company = companies[0];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Out.WriteLine(company.Name);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (Customer customer in company.Customers)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Out.WriteLine();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Out.Write(&amp;quot;First Name: &amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Out.WriteLine(customer.Name.FirstName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Out.Write(&amp;quot;Surname: &amp;quot;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Out.WriteLine(customer.Name.Surname);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return company.Id;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void InsertNewCompany(string companyName)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Company company = new Company();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; company.Name = companyName;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Customer customer = new Customer();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; customer.Name.FirstName = &amp;quot;Neil&amp;quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; customer.Name.Surname = &amp;quot;Jordan&amp;quot;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; customer.DateOfBirth = new DateTime(1950, 2, 25);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; customer.Company = company;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; company.Customers.Add(customer);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CompanyRepository companyRepository = new CompanyRepository();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; companyRepository.Add(company); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=248066" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/NHibernate/default.aspx">NHibernate</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/.Net/default.aspx">.Net</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/DDD/default.aspx">DDD</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/Castle/default.aspx">Castle</category></item><item><title>AltNetConf UK London August 2009</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/05/15/altnetconf-uk-london-august-2009.aspx</link><pubDate>Fri, 15 May 2009 07:02:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:222182</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>14</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=222182</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/05/15/altnetconf-uk-london-august-2009.aspx#comments</comments><description>&lt;p&gt;It feels as though sufficient water has passed under-the-bridge for us to have another &lt;a href="http://altnetuk.com/"&gt;altnetconf&lt;/a&gt; in London. We tend to organize them when the &amp;#39;mood&amp;#39; seems right in the community. That usually means that we think folks have something to discuss. This time we are planning on the weekend of 1 August (31 JUL to 2 AUG). Registration should open on 12 May. Don&amp;#39;t be alarmed if you see an old version of the site before then.&lt;/p&gt;
&lt;p&gt;Numbers are still limited. The wider economy means that we are unlikely to get the sponsorship for a bigger venue this year. We&amp;#39;ll keep trying though. &lt;/p&gt;
&lt;p&gt;That said&amp;nbsp;&lt;a href="http://thoughtpad.net/alan-dean.html"&gt;Alan Dean&lt;/a&gt;, &lt;a href="http://blog.benhall.me.uk/"&gt;Ben Hall&lt;/a&gt;, and myself have been plotting in secret, and roped in &lt;a href="http://serialseb.blogspot.com/"&gt;Sebastian Lambla&lt;/a&gt; and &lt;a href="http://serialseb.blogspot.com/"&gt;Michelle Flynne&lt;/a&gt; to help so that we can hold a bigger event in terms of the amount we do. So this time the plan is:&lt;/p&gt;
&lt;p&gt;31 JUL Evening: Alt.Net Beers: Yes we are integrating Seb&amp;#39;s alt.net event to warm you up with a chance to relax with like-minded individuals&lt;/p&gt;
&lt;p&gt;1 AUG Day: Open Space Coding: Alan Dean&amp;#39;s &lt;a href="http://openspacecode.com/home.en.xhtml"&gt;Open Space Coding Day&lt;/a&gt; event joins our weekend. the emphasis is on writing code over jawing.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2 AUG Day: AltNetConf: Open Space discussion about the topics that have grabbed you today. Be prepare to be&amp;nbsp;surprised.&lt;/p&gt;
&lt;p&gt;UPDATE: We had a request from attendees at &lt;a href="http://skillsmatter.com/event/open-source-dot-net/progressive-dot-net-exchange"&gt;Progressive .NET&lt;/a&gt; to delay registration, as they are a key attendance group. I&amp;#39;ll update with the new time, likely to be Thursday lunchtime or evening.&lt;/p&gt;
&lt;p&gt;UPDATE: We have now opened registration: http://www.altnetuk.com/registration.en.html&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I&amp;#39;m looking forward to this one. It feels as though it has been long enough that we ought to have some things to talk about, not just re-hashing the old saws.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=222182" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/altnetconf/default.aspx">altnetconf</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/AltNetUK/default.aspx">AltNetUK</category></item><item><title>Finding out about London .NET events</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/05/06/finding-out-about-london-net-events.aspx</link><pubDate>Wed, 06 May 2009 08:47:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:215563</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=215563</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/05/06/finding-out-about-london-net-events.aspx#comments</comments><description>&lt;p&gt;We have a rich .NET development scene in London and the organizers of a number of communities and events are going to try and make sure everyone knows how to get the best out of the community.&lt;/p&gt;
&lt;p&gt;The first question for most people would be how to find out what is happening. For now the key site for you to bookmark is the &lt;a href="http://ukdotnet.ning.com/"&gt;UK .NET event site&lt;/a&gt;. The London communities are going to make sure that we all&amp;nbsp;advertise&amp;nbsp;our events their so that you can go to one place and see what is coming up.&lt;/p&gt;
&lt;p&gt;As some quick examples of what is happening there I wanted to show you two events that you can find there which I am involved in. &amp;nbsp;One is the &lt;a href="http://skillsmatter.com/event/open-source-dot-net/progressive-dot-net-exchange/wd-4"&gt;Progressive .NET tutorials&lt;/a&gt;, which you can find on the calendar &lt;a href="http://ukdotnet.ning.com/events/event/listByDate?date=2009-05-11"&gt;here&lt;/a&gt;. For those of you who can&amp;#39;t fly out to events like Alt.NET Seattle it is a great opportunity to catch people like Ayende, Hammet, Bellware (and me).&lt;/p&gt;
&lt;p&gt;On the 12th you can catch up with a lot of the same people down the pub as Seb has cunningly arranged the next &lt;a href="http://ukdotnet.ning.com/events/london-altnetbeers-8"&gt;Alt.NET beers&lt;/a&gt; to coincide with so many people being in town.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=215563" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/AltNetUK/default.aspx">AltNetUK</category></item><item><title>On Learning Boo</title><link>http://codebetter.com/blogs/ian_cooper/archive/2009/04/14/on-learning-boo.aspx</link><pubDate>Tue, 14 Apr 2009 03:18:00 GMT</pubDate><guid isPermaLink="false">d21fbbc9-c112-4f32-ad14-95939a2c53d4:193491</guid><dc:creator>Ian Cooper</dc:creator><slash:comments>22</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://codebetter.com/blogs/ian_cooper/rsscomments.aspx?PostID=193491</wfw:commentRss><comments>http://codebetter.com/blogs/ian_cooper/archive/2009/04/14/on-learning-boo.aspx#comments</comments><description>&lt;h2&gt;Learning Boo&lt;/h2&gt;
&lt;p&gt;As part of my commitment to The Pragmatic Programmer&amp;#39;s exhortation to learn a new language every year, I decided to tackle &lt;a href="http://boo.codehaus.org/"&gt;Boo&lt;/a&gt;. My interest has been piqued by the work &lt;a href="http://manning.com/rahien/"&gt;Oren is doing in DSLs with Boo&lt;/a&gt;. Learning Boo seemed to be an important first step to getting to grips with that.&lt;/p&gt;
&lt;p&gt;The first step was to get an environment in which I could write and compile Boo programs. Now this is possible using a decent text editor like Vim, and command line tools like booc and booish, but it is also possible to use an IDE for this. I downloaded &lt;a&gt;SharpDevelop&lt;/a&gt; which has support for authoring, building and debugging Boo projects.&lt;/p&gt;
&lt;p&gt;To give myself a starting point I have decided to work through the &lt;a href="http://boo.codehaus.org/Boo+Primer"&gt;Boo Primer&lt;/a&gt; as a way of getting to know the language&lt;/p&gt;
&lt;p&gt;One aspect that jumps out is why Boo is called &amp;#39;wrist-friendly&amp;#39;. There is a lot of effort expended on giving you less to type. Although it is a statically typed language, Boo does away with the need to declare types before use. Instead Boo infers the type. C# programmers will find this similar to te use of var, without the need for the var keyword.&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;greeting = &amp;quot;Hello World&amp;quot; //This declares a string&lt;br /&gt;houseNumber = 42 //This declares an integer&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;I&amp;#39;m always typing code of the form:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;var myString = string.Format(&amp;quot;Hello {0}&amp;quot;, name);&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;in C#. Boo makes this a lot easier with string interning. I get to skip the string format statement, along with the seperation of placeholder and variable for&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;myString = &amp;quot;Hello ${name}&amp;quot;&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;The use of whitespace (Boo has a Python inspired syntax) to indicate a block is one of the early aspects of the language that strikes me. It makes for great natural language syntax, because it requires no block markers, but coming from a curly brace language &amp;quot;{}&amp;quot; like C# it takes a little for the fingers to get used to.  I also seem to keep missing the colon off the end of the conditional&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;i = 5&lt;br /&gt;if i &amp;gt; 0:&lt;br /&gt;	print &amp;quot;i is greater than 0&amp;quot;&lt;br /&gt;	if (i &amp;lt; 10):&lt;br /&gt;		print &amp;quot;i is less than 10&amp;quot;&lt;br /&gt;		if (i==5):&lt;br /&gt;		      print &amp;quot;i equals 5&amp;quot;&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;One issue that hit me when working through the Boo Primer was that SharpDevelop disliked me trying to declare a list as follows:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;L = List(range(5))&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;which gave me the error&lt;/p&gt;
&lt;p&gt;
ERROR: Generic types without all generic parameters defined cannot be instantiated.
&lt;/p&gt;
&lt;p&gt;Some digging on the &lt;a href="http://groups.google.com/group/boolang"&gt;Boo Programming Language mailing list&lt;/a&gt; established that &lt;a href="http://groups.google.com/group/boolang/browse_thread/thread/ff5a4fa8166adc82/bbb42c9405e75e75?lnk=gst&amp;amp;q=generics#bbb42c9405e75e75"&gt;Boo now has generics&lt;/a&gt; and it looks like the Boo interpreter in SharpDevelop uses that type over the non-generic type. Switching to use the generic collection instead, removed the error messages&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;L = List[of int](range(5))&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;The built in list initializer syntax seems to work in SharpDevelop though:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;barfoo = [&amp;#39;abcdefghijkl&amp;#39;]&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;I like the provision of initializer syntax for arrys, lists, and hashes within the language which provides for concise syntax&lt;/p&gt;
&lt;p&gt;Overall I have spent an enjoyable half-a-day familiarizing myself with Boo&amp;#39;s syntax so far. One immediate advantage to learning Boo over say learning Ruby is that you are dealing with .NET libraries. So when you see Console.ReadKey(true) in a line of Boo code your existing knowledge tells you what it is doing. You are able to leverage existing framework skills and apply them to a new language. This speeds up the learning process, because having learnt the new syntax you can to put it to use fare more quickly.&lt;/p&gt;
&lt;p&gt;Next time I&amp;#39;ll play with Boo&amp;#39;s methods and classes. Looking forward to it.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://codebetter.com/aggbug.aspx?PostID=193491" width="1" height="1"&gt;</description><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/Object-Orientation/default.aspx">Object-Orientation</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/Boo/default.aspx">Boo</category><category domain="http://codebetter.com/blogs/ian_cooper/archive/tags/.Net/default.aspx">.Net</category></item></channel></rss>