<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devlicio.us/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>Jak Charlton - Insane World</title><link>http://devlicio.us/blogs/casey/default.aspx</link><description>Hang the code, and hang the rules. They&amp;#39;re more like guidelines anyway</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Avoiding Prescriptive Requirements</title><link>http://devlicio.us/blogs/casey/archive/2012/02/09/avoiding-prescriptive-requirements.aspx</link><pubDate>Thu, 09 Feb 2012 03:50:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:69485</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=69485</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=69485</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2012/02/09/avoiding-prescriptive-requirements.aspx#comments</comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Core Requirements&lt;/h3&gt;
&lt;p class="MsoNormal"&gt;&lt;strong&gt;Requirements &lt;/strong&gt;should be given as
the &lt;strong&gt;Core Requirement&lt;/strong&gt;, and avoid the common pitfall of providing &lt;strong&gt;Prescriptive
Requirements&lt;/strong&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;As an example, a core requirement in an insurance system may be:&lt;/p&gt;
&lt;p style="padding-left:30px;" class="MsoNormal"&gt;&lt;strong&gt;&lt;span&gt;As a user of the Broker system, I want to create a Settlement Batch of Eligible Documents across Insurance Policies&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span&gt;This is eminently testable, is
clear and unambiguous, and has real business value, and it meets the general &lt;strong&gt;INVEST&lt;/strong&gt;
principle of good user stories (which is also a good maxim for any form of
requirements):&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoListParagraph"&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is &lt;strong&gt;Independent&lt;/strong&gt;
of other stories&lt;/li&gt;
&lt;li&gt;It is easily &lt;strong&gt;Negotiated&lt;/strong&gt;
as to priority and value&lt;/li&gt;
&lt;li&gt;It has real business
&lt;strong&gt;Value&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;It is small enough
to easily &lt;strong&gt;Estimate&lt;/strong&gt; with some degree of certainty&lt;/li&gt;
&lt;li&gt;It is of an
appropriate &lt;strong&gt;Size&lt;/strong&gt; for easy estimation, planning and prioritisation&lt;/li&gt;
&lt;li&gt;It is able to be &lt;strong&gt;Tested&lt;/strong&gt;
both manually and in an automated fashion with clear and unambiguous pass or
fail criteria, you can either do it or not&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;The stated requirement is not
prescriptive, it does not specify how the user triggers this action, what data
they need to provide, how they select the documents, nor does it specify what a &amp;quot;user of the Broker System&amp;quot; is within this context, nor what a Settlement Batch is, nor what an Eligible Document is. This
means the requirement can be documented very early on, with little analysis
work needed, allowing very quick comparison with other requirements, and very
quick verification from the business as to the validity of the story.&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span&gt;Later this placeholder can be
expanded in discussions between the technical teams and the business to include
the actual definitions and scenarios that define its acceptance criteria:&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoListParagraph"&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The user must
have the &amp;ldquo;Batch Creation&amp;rdquo; permission&lt;/li&gt;
&lt;li&gt;Eligible Documents are those which are awaiting Settlement&lt;/li&gt;
&lt;li&gt;A Settlement Batch is a group of Documents that will be dealt with together by the Claims Settlement system, so as to save managing on an individual policy level&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span&gt;This would lead to a requirement
with maybe a dozen test scenarios giving all the variations of user and
statuses that would allow or not allow the story to pass the test. All of these
stories and scenarios are now easily tested with automated and repeatable
testing.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span&gt;At this point it would probably
be obvious where within the UI this functionality should surface, and the
design of the UI interaction can be worked out. This UI work is actually a very
specific development skill within its own right - there is significant complexity in
designing UI interactions that mirror both the technical system and the user&amp;rsquo;s
mental model.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span&gt;Through all of these steps, the
original core requirement has not been changed, though its implementation and
business logic may have evolved, changed and adapted to line up with other
functionality.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span&gt;Good requirements are merely a
placeholder for a later conversation. Their level of completeness or accuracy
only dictates your certainty in implementing them accurately and efficiently,
but does not preclude moving forwards, and does not hold development up waiting
on &amp;ldquo;complete requirements&amp;rdquo;.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span&gt;As granularity increases, so
does complexity required to understand, verify and implement, but oddly so does
instability. By starting with core stories, you maintain a fairly stable set of
requirements, and only deal with complexity when you need to, and suffer the
instability only on individual scenarios.&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Which brings us neatly to
development&lt;/span&gt;&lt;/h3&gt;
&lt;p class="MsoNormal"&gt;&lt;span&gt;It is fairly well established
now that development must be iterative within short cycles to increase its
chance of being successful. Early feedback and revision saves massive amounts
of time and effort correcting incorrect assumptions and poor translation.&lt;/span&gt;&lt;/p&gt;
&lt;p class="MsoNormal"&gt;&lt;span&gt;The sooner a story enters
development, the sooner a basic version of it can be demonstrated to business
users, to verify against their assumptions, the faster it can be revised and
the more accurately it will reflect the actual requirements. In addition it
will expose underlying technical constraints and limitations earlier on.&lt;/span&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://devlicio.us/aggbug.aspx?PostID=69485" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Rants/default.aspx">Rants</category><category domain="http://devlicio.us/blogs/casey/archive/tags/development/default.aspx">development</category><category domain="http://devlicio.us/blogs/casey/archive/tags/requirements/default.aspx">requirements</category></item><item><title>Single Action per Controller in ASP.NET MVC</title><link>http://devlicio.us/blogs/casey/archive/2011/07/11/single-action-per-controller-in-asp-net-mvc.aspx</link><pubDate>Mon, 11 Jul 2011 01:08:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:67963</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=67963</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=67963</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2011/07/11/single-action-per-controller-in-asp-net-mvc.aspx#comments</comments><description>&lt;p&gt;As I keep doing this on MVC projects, thought I may as well blog it, so the next time I need it I can find it myself :)&lt;/p&gt;
&lt;p&gt;To keep ASP.NET MVC controllers clean and organised, I find it much easier to split them so they handle only a single action each. This helps significantly with maintaining some semblance of the Single Responsibility Principle, allowing each controller to deal with a single action, and not have concerns like Logon, Logoff and ChangePassword all start globbing together under a single controller called &amp;quot;Account&amp;quot;&lt;/p&gt;
&lt;p&gt;With a little bit of magic in the ControllerFactory you can tell ASP.NET MVC3 to resolve controllers from your own directory and class structure, meaning we can have controllers that look like:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; IndexController : Controller
{
   [Authorize]
   &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult Index()
   {
      &lt;span class="kwrd"&gt;return&lt;/span&gt; View();
   }
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/1075169"&gt;https://gist.github.com/1075169&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;The Controller Factory&lt;/h3&gt;
&lt;p&gt;I tend to use Castle Windsor to do this magic for me, though any IoC container would do, and you could even do it without a container if you were really masochistic!&lt;/p&gt;
&lt;p&gt;In Windsor the ControllerFactory looks like:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;pre class="csharpcode"&gt;  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; WindsorControllerFactory : DefaultControllerFactory
    {
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; IKernel kernel;

        &lt;span class="kwrd"&gt;public&lt;/span&gt; WindsorControllerFactory(IKernel kernel)
        {
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.kernel = kernel;
        }

        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ReleaseController(IController controller)
        {
            kernel.ReleaseComponent(controller);
        }

        &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IController GetControllerInstance(RequestContext context, Type controllerType)
        {
            var baseNs = &lt;span class="kwrd"&gt;typeof&lt;/span&gt;(SecureController).Namespace;

            var ns = context.RouteData.GetRequiredString(&lt;span class="str"&gt;&amp;quot;controller&amp;quot;&lt;/span&gt;).ToLower();
            var controllerName = context.RouteData.GetRequiredString(&lt;span class="str"&gt;&amp;quot;action&amp;quot;&lt;/span&gt;).ToLower() + &lt;span class="str"&gt;&amp;quot;controller&amp;quot;&lt;/span&gt;;
            &lt;span class="kwrd"&gt;try&lt;/span&gt;
            {
                var controller = kernel.Resolve&amp;lt;IController&amp;gt;(baseNs.ToLower() + &lt;span class="str"&gt;&amp;quot;.&amp;quot;&lt;/span&gt; + ns + &lt;span class="str"&gt;&amp;quot;.&amp;quot;&lt;/span&gt; + controllerName);
                &lt;span class="kwrd"&gt;return&lt;/span&gt; controller;
            }
            &lt;span class="kwrd"&gt;catch&lt;/span&gt; (ComponentNotFoundException ex)
            {
                &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; HttpException(404, &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;&amp;quot;The controller for path &amp;#39;{0}&amp;#39; could not be found.&amp;quot;&lt;/span&gt;, context.HttpContext.Request.Path));
            }
        }
    }
&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/1075171"&gt;https://gist.github.com/1075171&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;The Controller Installer&lt;/h3&gt;
&lt;p&gt;So that Windsor has some way of resolving our controllers, you need to register them in the container. This installer will scan for all classes implementing IController and add them into the container against a key matching their namespace:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Install(IWindsorContainer container, IConfigurationStore store)
{
     &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var type &lt;span class="kwrd"&gt;in&lt;/span&gt; Assembly.GetExecutingAssembly().GetTypes())
     {
      &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;typeof&lt;/span&gt;(IController).IsAssignableFrom(type) &amp;amp;&amp;amp; !type.IsAbstract)
      container.Register(Component.For(type).ImplementedBy(type).Named(type.FullName.ToLower()).LifeStyle.Transient);
     }
}
&lt;/pre&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/1075176"&gt;https://gist.github.com/1075176&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Which leaves your controller folder structure looking like:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/casey/controllers.png"&gt;&lt;img src="http://devlicio.us/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/casey/controllers.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;GET and POST&lt;/h3&gt;
&lt;p&gt;Where an action has a Get and a Post action, for example where you display a form, then take some actions based on the form, you just put the two actions in the same Controller, you aren&amp;#39;t breaking SRP here as both actions are inherently linked anyway:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;pre class="csharpcode"&gt;   &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ChangePasswordController : Controller
    {
        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; IUsersDB users;

        &lt;span class="kwrd"&gt;public&lt;/span&gt; ChangePasswordController(IUsersDB users)
        {
            &lt;span class="kwrd"&gt;this&lt;/span&gt;.users = users;
        }

        [Authorize]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult ChangePassword()
        {
            &lt;span class="kwrd"&gt;return&lt;/span&gt; View();
        }

        [Authorize]
        [HttpPost]
        &lt;span class="kwrd"&gt;public&lt;/span&gt; ActionResult ChangePassword(ChangePasswordViewModel model)
        {
            &lt;span class="kwrd"&gt;if&lt;/span&gt; (ModelState.IsValid)
            {
                &lt;span class="kwrd"&gt;try&lt;/span&gt;
                {
                    users.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword);
                    &lt;span class="kwrd"&gt;return&lt;/span&gt; RedirectToAction(&lt;span class="str"&gt;&amp;quot;ChangePasswordSuccess&amp;quot;&lt;/span&gt;);
                }
                &lt;span class="kwrd"&gt;catch&lt;/span&gt; (DataAccessException ex)
                {
                    ModelState.AddModelError(&lt;span class="str"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, &lt;span class="str"&gt;&amp;quot;The current password is incorrect or the new password is invalid.&amp;quot;&lt;/span&gt;);
                }
            }

            &lt;span class="kwrd"&gt;return&lt;/span&gt; View(model);
        }
    }&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=67963" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Windsor/default.aspx">Windsor</category><category domain="http://devlicio.us/blogs/casey/archive/tags/MVC/default.aspx">MVC</category><category domain="http://devlicio.us/blogs/casey/archive/tags/asp.net/default.aspx">asp.net</category></item><item><title>What is Domain Driven Design?</title><link>http://devlicio.us/blogs/casey/archive/2011/05/16/what-is-domain-driven-design.aspx</link><pubDate>Mon, 16 May 2011 02:15:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:67301</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=67301</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=67301</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2011/05/16/what-is-domain-driven-design.aspx#comments</comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span&gt;&amp;quot;... the key to expert performance in many fields
is domain knowledge rather than intelligence.&amp;quot; &lt;br /&gt;
&lt;/span&gt;&lt;span&gt;&lt;i&gt;Don Reinertsen&lt;/i&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Domain Driven Design
is a software development methodology, intended to achieve a software system
closely modelled on and aligned with real business processes.&lt;/p&gt;
&lt;p&gt;Traditionally
development tends to be a technically led process, where requirements are
passed from the business to the development teams, and then the development
teams go off and produce their best guesstimate at what the requirements said.&lt;/p&gt;
&lt;p&gt;In a waterfall
approach this leads to large requirements documents that are diligently
collated, analysed, reviewed and approved. These documents are then given to
development teams to turn into working software.&lt;/p&gt;
&lt;p&gt;Agile approaches can
also accept the requirements documents that waterfall tends to produce, but for
them to actually progress forwards they must be broken to small tasks and
stories which can then be queued ready for development.&lt;/p&gt;
&lt;p&gt;Domain Driven Design
to a large degree steps back from these two distinct ends of the spectrum, and
looks at how the requirements are gathered in the first place - if you like, it
bridges the gap between doing everything up front and everything at the last
minute.&lt;/p&gt;
&lt;p&gt;DDD understands that
requirements are never &amp;#39;done&amp;#39;, but exist as a living document. More
importantly, the living document in question is actually the software itself -
all other documents are an artefact and reflection of the code.&lt;/p&gt;
&lt;p&gt;As the software
system develops and grows, deeper understanding of the problem grows too - DDD
is all about the discovery of the solution through deeper understanding of the
problem.&lt;/p&gt;
&lt;p&gt;Where DDD really
differs though is that it sees the software system as a reflection of the
business process, an enabler rather than the driver. DDD is deeply concerned
about the business processes, business terminology and practices. Technical
concerns are largely secondary and a means to an end.&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://thinkddd.com/blog/2009/02/09/the-ubiquitous-language/"&gt;Ubiquitous Language&lt;/a&gt; is at the centre of DDD - this is a shared and growing language. A
negotiated language derived from the business terminology and enriched by the development teams. If a business person doesn&amp;#39;t understand a term in the UL,
then the chances are the UL needs an evolution. If a technical person doesn&amp;#39;t
understand a term in the UL then the chances are they need a conversation with
a Domain Expert.&lt;/p&gt;
&lt;p&gt;The Domain Experts
are the second essential component of DDD - people who deeply understand the
business domain, and the business itself. These people are integral to the
development process. They may not be required &amp;quot;full time&amp;quot; like the
traditional Product Owners of some Agile methodologies, but they must be
accessible continually, and be prepared to invest time in the process. Domain
Experts are not to be considered outsiders, but as the core of the DDD process
- they are as much a part of the development team as any developer or tester.&lt;/p&gt;
&lt;p&gt;DDD doesn&amp;#39;t begin
and end - it is a constant process of re-evaluation, refactoring, remodelling
and redesign - every conversation should bring you to a closer understanding of
the problem. At no point is DDD &amp;#39;done&amp;#39; - it is always there; the Ubiquitous Language
grows and develops, the Domain Models change as understanding changes, code is
restructured and refactored to better represent that understanding.&lt;/p&gt;
&lt;p&gt;Artefacts will come
and go, but only one really matters - the code base. It is the only expression
of the solution that is free of abstraction. While documents may try to explain
or describe the system, only the code does so without losing information. This
means that in DDD the code must remain of high quality, be clear and
expressive, be free of technical abbreviations or jargon, and as far as
possible should make at least some sense to a Domain Expert when explained to
them.&lt;/p&gt;
&lt;p&gt;Clever code doesn&amp;#39;t
work in DDD, nor do magical processes or &amp;quot;you don&amp;#39;t need to know&amp;quot;
components. Domain Experts shouldn&amp;#39;t need to become developers to understand
what the key parts of the software system is doing for them.&lt;span&gt;&amp;nbsp; &lt;/span&gt;They also shouldn&amp;#39;t need to think in terms of
databases or batch jobs or other technical concerns.&lt;/p&gt;
&lt;p&gt;DDD is the ultimate
expression of Agile - it is about dealing with a constantly shifting and
evolving set of requirements - because as anyone who has ever been involved
with a software project knows - it is very rare for a requirement to remain
intact from the beginning to the end of a project, and almost impossible for it
to do so as the business grows and changes.&lt;/p&gt;
&lt;p&gt;Through constant
conversations, DDD will guide you to an ever more accurate software
representation of your business process.&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://devlicio.us/aggbug.aspx?PostID=67301" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Rants/default.aspx">Rants</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://devlicio.us/blogs/casey/archive/tags/DDD/default.aspx">DDD</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Domain+Driven+Design/default.aspx">Domain Driven Design</category></item><item><title>Trust, Honesty, Openness, Cooperation and Friction-free Tooling</title><link>http://devlicio.us/blogs/casey/archive/2011/05/03/trust-honesty-openness-cooperation-and-friction-free-tooling.aspx</link><pubDate>Tue, 03 May 2011 22:59:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:67188</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=67188</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=67188</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2011/05/03/trust-honesty-openness-cooperation-and-friction-free-tooling.aspx#comments</comments><description>&lt;p&gt;There is an inherent danger in using electronic tools to manage a process like software development, and one that almost always comes true - the tool defines your process, it doesn&amp;#39;t enable it.&lt;/p&gt;
&lt;p&gt;When people encounter limitations in the software tool, they begin to accept that these are limitations of the process and these become ingrained in your methodology. If the tool doesn&amp;#39;t support the &amp;quot;thing you want to do&amp;quot; then it is far easier to change the &amp;quot;thing&amp;quot; rather than rewrite or change the software.&lt;/p&gt;
&lt;p&gt;Were any of the electronic tools to have got the process &amp;quot;right&amp;quot; this might not be such a bad thing, but it would be reasonable to assume that in a field as adaptive and evolutionary as software development there is no such thing as the &amp;quot;right&amp;quot; process for an individual team, let alone for such a widely disparate ecosystem as development.&lt;/p&gt;
&lt;p&gt;And this conflict between our tools and our actual practices and processes is what we refer to as &amp;quot;friction&amp;quot;, and as physics defines it;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;Friction is the &amp;quot;evil&amp;quot; of all motion. No matter which direction something moves in, friction pulls it the other way. Move something left, friction pulls right. Move something up, friction pulls down. It appears as if nature has given us friction to stop us from moving anything.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;We aim for &amp;quot;friction-free&amp;quot; tools to allow us to better get on with moving things, specifically developing software, which is a constantly moving and adaptive process.&lt;/p&gt;
&lt;p&gt;Some tools aim to allow endless configuration or programmability, in their objective of being a universal solution. These tools tend to actually make the problem worse, by either leaving you bogged down in configuration or customisation, or leaving the tool so generic that it solves no problem at all.&lt;/p&gt;
&lt;p&gt;Of course, some tools are better than others. Lightweight tools are obviously going to create less friction as they have less moving parts, and less touch points with your actual process.&amp;nbsp;&amp;nbsp;But these are the ones that some see as &amp;quot;lacking features&amp;quot;, or as being &amp;quot;too simplistic&amp;quot; - but it is these things specifically that enable the process of development to continue.&lt;/p&gt;
&lt;p&gt;And ultimately, these tools expose a greater problem - there is usually a disjoint between project management and the development teams here. A lack of trust and visibility leads managers to seek to control or monitor the process more tightly, and these tools promise to allow that to happen. Surely if we can tie everything into a database or a spreadsheet or something similar, we can then see exactly what is happening, who is doing what, when things will be done, and how long they will take?&lt;/p&gt;
&lt;p&gt;But it is not the tool that enables this to happen - it is serving here merely to try and enforce control upon people - which as any good manager knows, enforcement is a far blunter instrument than cooperation.&lt;/p&gt;
&lt;p&gt;What enables proper management of the software development process is trust, honesty, openness and cooperation. Tools should reflect and enable those objectives, rather than try to enforce them. And most importantly, they should stay out of the way of the development teams to allow them to get on with their real job - developing software.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=67188" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Practices+and+Principles/default.aspx">Practices and Principles</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Agile/default.aspx">Agile</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Rants/default.aspx">Rants</category></item><item><title>CQRS - The Cult of Shiny Things</title><link>http://devlicio.us/blogs/casey/archive/2010/10/29/cqrs-the-cult-of-shiny-things.aspx</link><pubDate>Fri, 29 Oct 2010 00:12:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:63137</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=63137</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=63137</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2010/10/29/cqrs-the-cult-of-shiny-things.aspx#comments</comments><description>&lt;p&gt;CQRS has become another casualty of the buzzword culture and the cult of &amp;#39;shiny things&amp;#39;&lt;/p&gt;
&lt;p&gt;What started as a collection of some reasonably good principles has now turned into an almost religious mantra for some, with more and more outrageous claims, and almost no basis in fact or experience.&lt;/p&gt;
&lt;h3&gt;Scalability&lt;/h3&gt;
&lt;p&gt;Claims like &amp;quot;almost infinitely scalable systems&amp;quot; associated to CQRS are ludicrous, especially as none of the currently &amp;quot;near infinitely scalable systems&amp;quot; use CQRS or have probably even heard of it. The largest systems on the planet have no need of CQRS, they use many tricks and techniques that have been associated with CQRS - but they don&amp;#39;t use it, nor are they ever likely to use it, because when you have really large systems, things like CQRS become totally irrelevant.&lt;/p&gt;
&lt;p&gt;The scaling benefits of CQRS come from understanding eventual consistency and messaging - concepts that were around long before CQRS, and that will be around long after it too.&lt;/p&gt;
&lt;h3&gt;Task Based UIs&lt;/h3&gt;
&lt;p&gt;Well, yes CQRS may require a task based UI, but task based UIs were again around long before CQRS, and will again outlast it. This is just a different way of thinking about how people interact with computers - this is a UX issue, not a technical one.&lt;/p&gt;
&lt;p&gt;In fact, if anything, CQRS can be a major cause of issues here - when you really have a CRUD style system, CQRS is going to cause you all sorts of issues you will need to resolve. And much as I dislike CRUD based UIs, the reality is we have abused users to work this way in many cases - so sometimes that is just how we have to make our next UI work.&lt;/p&gt;
&lt;h3&gt;Side Effect Free&lt;/h3&gt;
&lt;p&gt;Another aspect of CQS (and by extrapolation CQRS) is that functions employing CQS are side effect free - you don&amp;#39;t accidentally introduce subtle bugs by writing and reading in one operation.&lt;/p&gt;
&lt;p&gt;And while this is nice in theory, the scale of system where this preventative measure would have benefit is the one where this problem is just as easily solved by many other simpler means, like just writing smart code. Larger systems have so many points in them where read and write are already being mixed, CQRS here just lends an illusion of safety.&lt;/p&gt;
&lt;h3&gt;Denormalised Read Models&lt;/h3&gt;
&lt;p&gt;A valuable benefit of CQRS is the concept that the views have specific read models that are denormalised from the (presumably) complex domain model.&lt;/p&gt;
&lt;p&gt;This has a number of benefits, though these are largely boiled down to improved efficiency of querying (and action that tends to happen frequently). These models can also be extrapolated out to provide reporting and MI models too.&lt;/p&gt;
&lt;p&gt;But again, we have been doing this for many years already, and usually to account for overloaded database servers that we don&amp;#39;t wish to query against, particularly with MI.&lt;/p&gt;
&lt;p&gt;And querying these days, even with horribly complex joins on highly complex models is becoming faster and faster. Push querying to a slave server, and you gain all the benefits of a rich model, and fast queries. And for even more speed you can look to NoSQL solutions - which are effectively based on the principle that you denormalised your data anyway.&lt;/p&gt;
&lt;h3&gt;Performance Considerations&lt;/h3&gt;
&lt;p&gt;Part of the theoretical benefit of CQRS is that your queries will be faster as your denormalised datastores are updated at write time, so you don&amp;#39;t have to do horrible joins on queries (which in theory on most systems happen far more frequently than writes)&lt;/p&gt;
&lt;p&gt;These days, the performance of relational databases and especially NoSQL databases is advancing rapidly. The new breed of databases takes things like sharding and replication very seriously, and as first class features, not afterthoughts like the databases of old did.&lt;/p&gt;
&lt;p&gt;Replication in MySQL takes roughly 0.0002 of a second (see&amp;nbsp;&lt;a href="http://nr-content.s3.amazonaws.com/railslab/videos/17-ScalingRails-Scaling-Your-Database-Part-1.mp4"&gt;http://nr-content.s3.amazonaws.com/railslab/videos/17-ScalingRails-Scaling-Your-Database-Part-1.mp4&lt;/a&gt;&amp;nbsp;at 6 minutes in) - compare that with how long a message based approach like CQRS will take to push that to your secondary datastores and you are talking orders of magnitude faster for the dumb replication approach. Apparently it operates at this speed for up to 10 slave databases before degrading.&lt;/p&gt;
&lt;p&gt;Now, think about this bit, the 37 Signal systems (a huge system) operates on a single MySQL instance running with 105Gb of memory caching. And 37 Signal could be considered the archetype of an Active Record approach, after all it is the reason Ruby on Rails exists. Are you writing a system that big?&lt;/p&gt;
&lt;p&gt;Maybe you are so let&amp;#39;s examine a larger system - Wordnik stores over 12 billion documents, 3Tb of data per node, 500k requests per hour and 4 times that at peak load, and yet their fetch time is around 60ms. (&lt;a href="http://blog.wordnik.com/12-months-with-mongodb"&gt;http://blog.wordnik.com/12-months-with-mongodb&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s not even begin to discuss Twitter, Ebay, Facebook or other similar &amp;quot;mega systems&amp;quot; - they still respond in milliseconds with tens or hundreds of millions of users - think that&amp;#39;s down to CQRS?&lt;/p&gt;
&lt;h3&gt;Dealing with Complexity&lt;/h3&gt;
&lt;p&gt;Yep - CQRS deals with complexity to one degree - it forces you to explicitly think about what each call is doing - &amp;quot;Is this writing data or reading data?&amp;quot; - and that thought process is a good thing.&lt;/p&gt;
&lt;p&gt;But it introduces another layer of complexity that is more subtle and harder to deal with - the replication to secondary datastores is complex in itself - it effectively needs to do that horrible join you are trying to avoid in your queries so that it can update your denormalised tables. That in itself isn&amp;#39;t simple.&lt;/p&gt;
&lt;p&gt;But it also needs to be able to maintain those secondary datastores if, for example they are corrupted and need recreating or if they miss some messages. In normal replication this is trivial, drop the slave, add a new slave - wait a short while - someone already wrote all that for you on a database system - you are going to need to write it all yourself with CQRS.&lt;/p&gt;
&lt;h3&gt;So Why Have I Implemented CQRS Before?&lt;/h3&gt;
&lt;p&gt;Well, at the time I first implemented CQRS I had two reasons for doing so - and oddly neither had to do with any of the aforementioned technical aspects. In fact, one was a technical problem and one was a people problem.&lt;/p&gt;
&lt;p&gt;Firstly this was nearly two years back, and the system that we were writing a layer over was a very old and crumbling legacy database system. It had no real normalised schema, and was open to abuse from just about every development team in the organisation without warning to others - it was also horribly prone to outages.&lt;/p&gt;
&lt;p&gt;One project had just &amp;quot;failed&amp;quot; (though I&amp;#39;m sure some would say it was just a lesser success), primarily due to trying to put a domain model on top of the legacy database.&lt;/p&gt;
&lt;p&gt;So, the problem we had was to create a disconnected system that could operate independently of the legacy system, but also use the legacy system as it&amp;#39;s true authority for the information it used. Because of the horrible complexity in the legacy system, using CQRS allowed us to write what were frankly quite horrible SQL statements for reading data from legacy, while using a pseudo-document database for the daily operations. We then used horrible SQL statements to replicate this data back into legacy.&lt;/p&gt;
&lt;p&gt;Of course, what we were really writing was a standard message based architecture, but the term CQRS encompassed that quite nicely.&lt;/p&gt;
&lt;p&gt;We could have approached this without the CQRS badge - but it served as a useful political tool - a number of the existing team had heard of it and were quite enthusiastic, and management would be confounded enough by it to not get in the way too much. It also broke the mental model the development teams had with &amp;quot;put an ORM over the database&amp;quot;.&lt;/p&gt;
&lt;p&gt;So the secondary benefit of CQRS here was a people problem - it was a new buzzword - it got new enthusiasm from a team that was demotivated from the previous project - and more than anything - that motivation was going to be the key to the success or failure of the new project.&lt;/p&gt;
&lt;h3&gt;So Why Have I Presented On It Before?&lt;/h3&gt;
&lt;p&gt;Well two reasons really, the first being that I have always tried to dispel the mythology around CQRS and to explain the real benefits of a flexible and scalable architecture - it just so happens that people want the buzzword explaining - you have to admit it&amp;#39;s a pretty vague and fuzzy term with a myriad of definitions and explanations.&lt;/p&gt;
&lt;p&gt;The secondary reason being, as my last presentation at DDD Sydney explained - my objective was to make you think. There&amp;#39;s a lot of good things hiding under the CQRS banner, and I really would like people to think about better ways of writing software.&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In the few years since CQRS was &amp;quot;invented&amp;quot; it has got a bit of a cult buzzword status. It is talked about as though it fixes a multitude of problems.&lt;/p&gt;
&lt;p&gt;But in that time, NoSQL has really taken off. RBDMS&amp;#39; have got far more powerful. And memory and processing power has increased significantly. Database caching is exceptionally impressive. REST gives us proxy caching for near enough free. Memcached and Velocity make light of massive data loads. We even have the nefarious &amp;quot;cloud&amp;quot; now, where processing power and memory is cheaper than the effort involved in maintain complex architectures.&lt;/p&gt;
&lt;p&gt;Scaling systems is now a pretty commonplace business problem for most of the startups taking off&amp;nbsp;&amp;nbsp;-and they don&amp;#39;t need CQRS - there is a very good chance you don&amp;#39;t either. We are past that point in time where we had to prematurely optimise things like database queries.&lt;/p&gt;
&lt;p&gt;If it&amp;#39;s about thinking differently, then I can tell you all you need to know about CQRS in a simple paragraph:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;i&gt;Learn to think of systems as being inconsistent at all times, no matter what illusion they present of &amp;#39;real time&amp;#39;. Learn to embrace messaging, REST, caching, replication, sharding, and a hundred other techniques to solve these problems.&amp;nbsp;&amp;nbsp;Embrace user centric task based UIs, embrace strong UX, embrace strong domain driven design, embrace business led functionality and delivering systems that match real requirements. Embrace thinking differently.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;CQRS is no silver bullet, in fact it has almost now become a solution to a problem that doesn&amp;#39;t exist any more. If you can give me a problem that CQRS claims to solve, I&amp;#39;m fairly sure I can solve it more easily than I could have done 2 years ago when I started using CQRS. I&amp;#39;m sure I&amp;#39;ll still use a lot of the things that CQRS encapsulates, because they are after all very good principles - I&amp;#39;m just pretty much over playing buzzword bingo!&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://devlicio.us/aggbug.aspx?PostID=63137" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Rants/default.aspx">Rants</category><category domain="http://devlicio.us/blogs/casey/archive/tags/DDD/default.aspx">DDD</category><category domain="http://devlicio.us/blogs/casey/archive/tags/cqrs/default.aspx">cqrs</category></item><item><title>Ruby Is Scary</title><link>http://devlicio.us/blogs/casey/archive/2010/07/31/ruby-is-scary.aspx</link><pubDate>Sat, 31 Jul 2010 01:55:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:61330</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>38</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=61330</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=61330</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2010/07/31/ruby-is-scary.aspx#comments</comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Why is Ruby on Rails all the rage at the moment, and why do a lot of .NET people seem so defensive?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Undoubtedly, there is a buzz in development right now, things are changing rapidly, possibly more rapidly than they have for a good number of years. New languages are sprouting up all over it seems, with PHP and Python gaining massive popularity, F#, Erlang and Haskell suddenly being talked about as mainstream, Javascript evolving beyond that thing that makes &amp;quot;onClick&amp;quot; work in your browser, and Ruby (and especially Rails) becoming &amp;quot;flavour of the month&amp;quot; for web development. Ruby is even starting to invade the .NET mainstream space with evolutions like Rake, Cuke4Nuke and Nu muddying the divide that there once was. We even have IronRuby to make Ruby run on .NET&lt;/p&gt;
&lt;p&gt;And yet, many .NET people seem defensive, as though their safe world was being invaded by a parasite.&lt;/p&gt;
&lt;p&gt;I find this quite odd. As a developer who has been around for far too long, I have seen more than my fair share of languages and platforms come and go, none of them was perfect, and I would venture to say none of the ones we have now are either.&lt;/p&gt;
&lt;p&gt;It would appear that a large proportion of the uncertainty is in the C# development &amp;#39;community&amp;#39;, though that may be as I don&amp;#39;t really frequent circles that use VB.NET (and I&amp;#39;m fairly sure they are still busy being defensive about C# and probably haven&amp;#39;t noticed that&amp;#39;s *so* last year :) Somehow the introduction of new ideas is rocking the C# type safe world.&lt;/p&gt;
&lt;p&gt;Some people seem to be concerned about Ruby itself, some seem to have concerns about the lack of a statically typed safety net, and some seem to think that &amp;quot;the Enterprise&amp;quot; needs something more professional than toys like Ruby and Rails.&lt;/p&gt;
&lt;h3&gt;To The Static Typing Stalwarts&lt;/h3&gt;
&lt;p&gt;Yes, it&amp;#39;s nice to have that compile time checking that static typing gives you, it gives us all a warm sense of fuzziness knowing that the compiler told us that this code would run just fine when we dropped it onto our web server.&lt;/p&gt;
&lt;p&gt;Yes, we appreciate the great benefits that this has for things like Intellisense and for easily discoverable APIs, and even for automated documentation.&lt;/p&gt;
&lt;p&gt;And yet, none of these things seem to bother the Ruby (and PHP/Python/Javascript) crowd too much. Why is that?&lt;/p&gt;
&lt;p&gt;I would suggest that the static typing benefits a language like C# brings are illusory to a large degree.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The compiler isn&amp;#39;t telling us that this code will run correctly at all, it&amp;#39;s actually just telling us that the CLR won&amp;#39;t throw our code out before the application even starts up - but correctness is so much more important than that. The safety net static typing provides us with is just one part of the equation, and possibly the least important part - we really should be enforcing correctness upon our code.&lt;/p&gt;
&lt;p&gt;Correctness is verified by good automated testing, and static typed languages start to come back and bite us here - we trade that compile time security blanket for a much harder experience testing our code. Sure, tools like NUnit, xUnit, Rhino Mocks, Moq, SpecFlow, StorEvil et al ease away our pain, but still our application code is littered with constructs that are pretty much there to support SOLID (or SOLID is required due to the constraints of type safe OO languages), and they become most obvious when we start testing in languages like C# (I am *so* over Interfaces, IoC, Covariance, Contravariance and Generics !&lt;/p&gt;
&lt;p&gt;The testing experience in Ruby is a world apart from in C# and .NET, it is just easy and simple ... so simple in fact that it is almost harder to not write automated tests in Ruby - and that&amp;#39;s how it should be. In C# testing is often convoluted, complex, fragile and just plain hard work - I can&amp;#39;t think of the last time a C# developer described automated testing as fun ... and yet, in Ruby, it just seems like FUN!&lt;/p&gt;
&lt;p&gt;And yes, Ruby without automated testing leaves you open to all kinds of runtime errors that C# just wouldn&amp;#39;t - so in Ruby, you just make sure you test, and not only test your code will run, but also test it will run *correctly* - there is no safety net, but the trade off is you are ensuring correctness of code, not just compilation of it.&lt;/p&gt;
&lt;p&gt;Intellisense, sure it&amp;#39;s nice, but as RubyMine and even Visual Studio (under Javascript) demonstrate, you can do some form of Intellisense in dynamic languages, you just can&amp;#39;t always be certain what may or may not be available - but this is getting better. And honestly, is discovering which method you are meant to call though typing &amp;quot;.&amp;quot; all that great an idea anyway? Shouldn&amp;#39;t you as a competent developer know *in advance* what you wanted to call, rather than guessing it as you type?&lt;/p&gt;
&lt;h3&gt;To The Enterprise&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;Sure, Ruby doesn&amp;#39;t have the track record that C# has, nor does it have the exposure, or market reach, or backing of a company like Microsoft.&lt;/p&gt;
&lt;p&gt;But, is that what is really important?&lt;/p&gt;
&lt;p&gt;I would bet that a large part of the appeal for statically typed languages &amp;nbsp;in the &amp;quot;Enterprise&amp;quot; is actually a need to deal with a much lower skilled developer base overall. Compile time safety means that your developers don&amp;#39;t have to be top notch, the compiler can make up for their weaknesses (and in the case of C# and .NET, Visual Studio &amp;#39;drag and drop&amp;#39; tooling is trying to make up for a lot of the rest)&lt;/p&gt;
&lt;p&gt;Enterprises tend to see dollars and cents, not people and value. So anything that lets them hire cheaper developers to churn out more product must be good.&lt;/p&gt;
&lt;p&gt;Again, I would argue this is a false economy. Sure that team of 30 developers may give you a warmer fuzzier feeling inside than a team of 4. And sure, the quantity of code those 30 can type out will probably be much more.&lt;/p&gt;
&lt;p&gt;But this misses some real issues around productivity and value - a &amp;#39;good&amp;#39; developer is 10x as productive as an &amp;#39;average&amp;#39; developer, and more importantly, the &amp;#39;average&amp;#39; developer will never be able to create the same quality level as the &amp;#39;good&amp;#39; developer, even given a near infinite amount of time. No matter how much time a hobbyist painter spends with oil and canvas, he will never create a Leonardo. And as a Jackson Pollock will amply demonstrate, sometimes less is more.&lt;/p&gt;
&lt;p&gt;So are you measuring bodies or productivity? Surely it is the end result that matters, not the comfort factor of people looking busy.&lt;/p&gt;
&lt;p&gt;And, when you get a good developer, and let them have the freedom of a dynamic language, they can spend less time fighting compile time safety and language constructs that exist almost solely for that type safety, and more time concentrating on business logic and the end product.&lt;/p&gt;
&lt;p&gt;In fact, the best argument for why Ruby is not suited to the Enterprise is ... the Enterprise probably already has a large investment in one platform and one core language (or maybe two), and the cost of retraining all those developers, support staff, renegotiating supplier contracts, etc etc is just disproportionately expensive. Lethargy is rife in the Enterprise, and monoliths take a long time to move - sure it&amp;#39;s easier for startups to hop on new technologies and run with them, and often it&amp;#39;s why they quickly challenge the status quo. This isn&amp;#39;t really a technical issue, this is a political and management one.&lt;/p&gt;
&lt;p&gt;Maybe Ruby and Rails will gain traction here, maybe not. Things like functional programming are certainly starting to grow roots in financial services, and things like Javascript are prevalent in web apps in the Enterprise so maybe dynamic programming in things like Ruby isn&amp;#39;t so far off. It just takes one small faction to show how well they solved a particular problem with a new language or platform to plant that thought.&lt;/p&gt;
&lt;h3&gt;So Should We All Switch To Ruby Now?&lt;/h3&gt;
&lt;p&gt;Of course not, and maybe this is what the defensive people in .NET miss. The Ruby people aren&amp;#39;t saying &amp;quot;you guys have it all wrong, convert now&amp;quot;, they are just saying &amp;quot;hey, I found a really cool way of solving this problem&amp;quot;.&lt;/p&gt;
&lt;p&gt;Ruby is about choice, it&amp;#39;s another tool in your arsenal. As are Javascript, PHP, Python, Erlang, F#, Java, Groovy, C++ and a host of others.&lt;/p&gt;
&lt;p&gt;There is no &amp;quot;one right path&amp;quot;, so let&amp;#39;s all stop pretending there is.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;We don&amp;#39;t need to be defensive about any one language or platform, unless we are so unsure of our abilities as developers that we cannot learn and adapt - and if that is the case, maybe a new career is a better idea?&lt;/p&gt;
&lt;p&gt;As my recent presentation at DDDSydney said ... My Objective Today was to make you think ... &amp;quot;Maybe There Is A Better Way&amp;quot; - because it would just be depressing to think we are already doing things the best possible way.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=61330" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Rants/default.aspx">Rants</category><category domain="http://devlicio.us/blogs/casey/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/casey/archive/tags/ruby/default.aspx">ruby</category></item><item><title>My Objective Today is to Make You Think</title><link>http://devlicio.us/blogs/casey/archive/2010/07/19/my-objective-today-is-to-make-you-think.aspx</link><pubDate>Mon, 19 Jul 2010 00:08:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:61124</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=61124</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=61124</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2010/07/19/my-objective-today-is-to-make-you-think.aspx#comments</comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;quot;Maybe There is a Better Way&amp;quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I recently presented at DeveloperDeveloperDeveloper in Sydney, and although my talk was Stuff About CQRS, I opened with the slide&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;My Object Today Is to Make You Think ... &amp;#39;Maybe There is a Better Way&amp;#39;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;(&lt;a href="http://thinkddd.com/blog/2010/07/17/dddsydney-presentation-stuff-about-cqrs/"&gt;slides here&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;The real focus of this was around how normal people think, and how unlike normal people we developers really are. My role in development is all about enabling better communication, because fundamentally I believe the real value a developer brings to a project is not technical, but is in the way they interact with the team, and more importantly with the normal people they are actually creating software for.&lt;/p&gt;
&lt;p&gt;Obviously some of this has roots in DDD, the Ubiquitous Language is obviously an attempt to traverse this chasm that seems to exist between us.&lt;/p&gt;
&lt;p&gt;Then I touched on user interfaces, and how they are so rarely designed the way people think - normal people think about their objectives and goals, not in terms of data like we developers do. Inductive UIs are focused on tasks, unlike the traditional data driven UIs that we tend to throw at users - users and people don&amp;#39;t think in grids and columns and rows, they think &amp;quot;I want to change my address&amp;quot;, not &amp;quot;open my customer record, edit the three fields under address and save to the database&amp;quot; - only a sadist or a developer would think that way.&lt;/p&gt;
&lt;p&gt;And finally I touched on things like NoSQL databases, which neatly solve a communication problem - they stop us thinking about How to store information and let us focus on What we are storing and Why.&lt;/p&gt;
&lt;p&gt;And lastly I tried to show the link between CQRS and these business problems - how it made you focus on the language, on tasks and objectives and how it let you detach the How from the What and Why.&lt;/p&gt;
&lt;p&gt;But most importantly, what I was trying to do in that presentation was to throw some non-mainstream ideas out into the audience, to spark discussion and debate, and to get people to think - Maybe There is a Better Way &amp;nbsp;&lt;/p&gt;
&lt;p&gt;If only a few of those in the audience went away and Googled some of the ideas I was talking about, it will be another step towards moving development away from it&amp;#39;s heavy focus on technology and technological solutions - and towards a people and business driven focus, where technology is an artifact, not the deciding factor.&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://devlicio.us/aggbug.aspx?PostID=61124" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Rants/default.aspx">Rants</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://devlicio.us/blogs/casey/archive/tags/DDD/default.aspx">DDD</category><category domain="http://devlicio.us/blogs/casey/archive/tags/cqrs/default.aspx">cqrs</category></item><item><title>ThinkDDD Resource Site</title><link>http://devlicio.us/blogs/casey/archive/2010/05/04/thinkddd-resource-site.aspx</link><pubDate>Tue, 04 May 2010 00:08:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:58106</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=58106</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=58106</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2010/05/04/thinkddd-resource-site.aspx#comments</comments><description>&lt;p&gt;For a while now I have been wanting to replace the creaking DDDStepByStep.com site - I originally set it up using Community Server, but it soon became obvious after deployment that CS just wasn&amp;#39;t up to the job - the server regularly ran out of resources just running the vanilla product and became a pain to keep rebooting.&lt;/p&gt;
&lt;p&gt;So, to try yet again to sort out the information, I setup a new website&amp;nbsp;&lt;a target="_blank" href="http://thinkddd.com"&gt;thinkddd.com&lt;/a&gt; and used it as an opportunity to play with Ruby, and the &lt;a href="http://radiantcms.org/"&gt;Radiant CMS&lt;/a&gt;. Deployment to &lt;a href="http://heroku.com/"&gt;Heroku&lt;/a&gt;&amp;nbsp;for such a low bandwidth site also worked out as free - so the new site cost basically nothing except for time.&lt;/p&gt;
&lt;p&gt;The slides from my recent presentation to the Sydney alt.net user group are available &lt;a href="http://thinkddd.com/blog/2010/04/27/sydney-alt-net-presentation/"&gt;from here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Hopefully it is a lot clearer and easier to navigate, so if you are interested in Domain Driven Design - enjoy.&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://devlicio.us/aggbug.aspx?PostID=58106" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/DDD/default.aspx">DDD</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Domain+Driven+Design/default.aspx">Domain Driven Design</category></item><item><title>Agile is Performance, Feedback, Revision</title><link>http://devlicio.us/blogs/casey/archive/2010/04/15/agile-is-performance-feedback-revision.aspx</link><pubDate>Thu, 15 Apr 2010 02:45:08 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:57265</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=57265</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=57265</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2010/04/15/agile-is-performance-feedback-revision.aspx#comments</comments><description>&lt;p&gt;I came across a great video link yesterday, entitled “&lt;a href="http://blog.newhumanist.org.uk/2010/03/see-baba-brinkmans-rap-guide-to.html" target="_blank"&gt;Performance, Feedback, Revision&lt;/a&gt;”. It’s a Canadian rapper named Baba Brinkman covering the theory of evolution and the work of Charles Darwin, and he equates evolution with how he writes his lyrics, Performance, Feedback, Revision.&lt;/p&gt;  &lt;p&gt;As I listened to it, it struck me that this is Agile … we develop, we run retrospectives, and we revise what we have.&lt;/p&gt;  &lt;p&gt;Evolution may be more like waterfall, and take millions of years to evolve something as fundamentally pointless as the &lt;a href="http://www.talkorigins.org/faqs/vestiges/appendix.html" target="_blank"&gt;appendix&lt;/a&gt;, and in Agile we may look to have Performance, Feedback and Revision inside a week or two.&lt;/p&gt;  &lt;p&gt;I can’t quite believe I just showed this video to a client to explain Agile, but it seemed to get the idea across pretty well. I’m considering using it more often, but I promise to draw the line at learning to rap.&lt;/p&gt;  &lt;p&gt;But from now on, in big letters across the top of my white boards will go the words:&lt;/p&gt;  &lt;h3 align="center"&gt;Performance, Feedback, Revision&lt;/h3&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=57265" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Agile/default.aspx">Agile</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Rants/default.aspx">Rants</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Architecture/default.aspx">Architecture</category></item><item><title>Around the World in 90 Days</title><link>http://devlicio.us/blogs/casey/archive/2010/03/02/around-the-world-in-90-days.aspx</link><pubDate>Tue, 02 Mar 2010 06:38:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:55591</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=55591</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=55591</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2010/03/02/around-the-world-in-90-days.aspx#comments</comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Around 3 months ago, I packed up in the UK, and headed to the other side of the world, to Australia.&lt;/p&gt;
&lt;p&gt;Last Autumn I was chatting to &lt;a href="http://www.twitter.com/rbanks54"&gt;Richard Banks&lt;/a&gt; over Twitter, and he mentioned that &lt;a href="http://readify.net/AboutUs/"&gt;Readify &lt;/a&gt;were looking to hire good .Net developers in Australia. I joked that if they wanted to pay my air fare over I would certainly do an interview.&lt;/p&gt;
&lt;p&gt;Sadly Readify don&amp;#39;t pay for the air fare, but after a bit more joking I took Richard seriously and dropped them a copy of my CV. A few months later, after a fairly thorough interview (part of which took place over Skype and Live Meeting... sadly the reason for no free holiday), I took the decision to join Readify as a Senior Consultant.&lt;/p&gt;
&lt;p&gt;For the last 18 years I have been a self employed consultant / contractor in the UK, and have made a fairly good living at it. In fact this will be the first time I have been an employee since I was aged 22. So this was a fairly big decision.&lt;/p&gt;
&lt;p&gt;What swung it for me was the general positive attitude of the Readify people I spoke to, and their focus on technical excellence and good development practices. This is a company that is rapidly growing, and despite the general world economic conditions, Australia managed to avoid the vast majority of the financial crisis.&lt;/p&gt;
&lt;p&gt;As part of their expansion, Readify are still recruiting, and due to the shortage of good developers in Australia, they are willing to hire from overseas, and deal with all of the immigration and visa issues needed to get you into the country. So far at least one person I have chatted to over Twitter has applied, and if you look &lt;a href="http://twitter.com/rbanks54/readify"&gt;through the list of Readify employees&lt;/a&gt; you are likely to see a number of people who are highly respected in the .Net world - it&amp;#39;s a great bunch of people.&lt;/p&gt;
&lt;p&gt;Apparently only 1% of applicants to &lt;a href="http://readify.net/AboutUs/"&gt;Readify &lt;/a&gt;get through the interview process, so if you are looking for a new career, are open to moving, and are pretty darn hot around .Net and good development practices, maybe you should think of applying.&amp;nbsp;&lt;a href="http://readify.net/Careers/"&gt;http://readify.net/Careers/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;
&lt;span&gt;
&lt;/span&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://devlicio.us/aggbug.aspx?PostID=55591" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Readify/default.aspx">Readify</category><category domain="http://devlicio.us/blogs/casey/archive/tags/careers/default.aspx">careers</category></item><item><title>ASP.NET MVC in the Wild</title><link>http://devlicio.us/blogs/casey/archive/2010/02/09/asp-net-mvc-in-the-wild.aspx</link><pubDate>Tue, 09 Feb 2010 11:02:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:55322</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=55322</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=55322</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2010/02/09/asp-net-mvc-in-the-wild.aspx#comments</comments><description>&lt;p&gt;Just before I emigrated to Australia, I took on a small contract to build a website for a UK company who wanted to start up a new kind of UK recruitment site, one where employers could advertise directly, and more specifically one where recruitment agencies couldn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;The result was Empty Lemon (&lt;a href="http://www.emptylemon.co.uk"&gt;www.emptylemon.co.uk&lt;/a&gt;) &amp;ndash; I leave you to figure out why it is called Empty Lemon, took me a fair while to be honest!&lt;/p&gt;
&lt;p&gt;This site was built in around 4 weeks, using ASP.NET MVC2, NHibernate, Fluent NHibernate, Windsor, JQuery, Automapper, and a host of other great tools and libraries.&lt;/p&gt;
&lt;p&gt;The site is actually, despite the occasional bit of code I&amp;rsquo;m not too delighted with, a great example of how fast a site can be developed with ASP.NET MVC and the chosen tooling. In just four weeks we went from more or less nothing, to a full domain model (all be it a fairly simple one) running over a SQL Server 2008 database, using a combination of NH, Fulltext search and the Spatial services from SQL Server 2008.&lt;/p&gt;
&lt;p&gt;I also want to thank James Gregory, Steve Strong and Hadi Hariri for (sometimes unknowingly) helping me write the site, with useful snippets of code, and even in Steve&amp;rsquo;s case a lot of work on getting NH to play fair with the spatial services.&lt;/p&gt;
&lt;p&gt;So, if you are looking for a job in the UK, or if you are looking to employ someone, I strongly suggest you take a look at &lt;a href="http://www.emptylemon.co.uk"&gt;www.emptylemon.co.uk&lt;/a&gt;. It&amp;rsquo;s a little empty right now, but some large employers are coming on board soon, and other companies are signing up day by day &amp;ndash; these things are always chicken and egg, so if you like the site, feel free to tell others about it &amp;ndash; after all, who really likes recruitment agents anyway ;)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=55322" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/casey/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://devlicio.us/blogs/casey/archive/tags/JQuery/default.aspx">JQuery</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Castle/default.aspx">Castle</category><category domain="http://devlicio.us/blogs/casey/archive/tags/NHibernate/default.aspx">NHibernate</category></item><item><title>Solving Complexity with Message Based Architectures </title><link>http://devlicio.us/blogs/casey/archive/2010/02/04/solving-complexity-with-message-based-architectures.aspx</link><pubDate>Thu, 04 Feb 2010 07:55:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:55264</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=55264</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=55264</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2010/02/04/solving-complexity-with-message-based-architectures.aspx#comments</comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;Ultimately most complexity in software comes not from the
requirements, the business logic, or even the underlying systems. Most
complexity comes out of a poorly considered and managed architecture, and this
is commonly seen in tightly coupled systems that rapidly degrade into Big Balls
of Mud.&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;The key to simplifying architectures is to decouple their
component parts, making each more specialised and less dependent on the
others. This allows every component to focus on a specific task without risk of
those tasks becoming compromised by, or interfering with, others.&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;The basic premise of most architectures that succeed in
this way is that they are message based, rather than being glorified CRUD
systems pulling data to and from databases. Operations are central to the
system, data is ultimately just the storage for the results of those
operations.&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;This separation of concerns allows development teams to
concentrate on component parts with little impact upon other teams, and no more
reliance upon them than an agreement on the messages they will listen for and
those they will publish. While messages share some characteristics of service
interfaces, they differ mostly in their granularity and lack of dependence upon
one another. Messages allow true decoupling, where traditional service layers
only promise this and usually end up creating even more tightly coupled
systems.&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;&amp;quot;Message based&amp;quot; does not inherently mean SOA, and in many
ways differs substantially. Although both can be considered message based, SOA
brings significant overhead and generalisation, along with an organisation wide
remit. Simple message based systems operate on the basis of message within the application
rather than across an enterprise.&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;Poor software architecture ends up impacting more than
just the software system under development, and frequently the impact can be
felt across an organisation; in the way development teams approach problems, in
the way they respond to new requirements, and throughout the SDLC.&lt;/p&gt;
&lt;p class="MsoPlainText"&gt;More often than not, the SDLC is a reflection of the weaknesses
in software architecture, and is frequently trying to play &amp;#39;catch up&amp;#39; to attempt
to deal with the issues weak architecture brings. These compromises and aspects
of the SDLC then start to propagate and impact other areas of the development and
support process. Often decisions about software architecture become the underlying
drivers for the entire IT department, and the SDLC turns into a point of
conflict as it becomes more about trying to restrain and control a big ball of
mud than it does about providing a framework for providing business value.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=55264" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Practices+and+Principles/default.aspx">Practices and Principles</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://devlicio.us/blogs/casey/archive/tags/DDD/default.aspx">DDD</category><category domain="http://devlicio.us/blogs/casey/archive/tags/SOA/default.aspx">SOA</category></item><item><title>What Is The Difference Between an IoC Container and MEF?</title><link>http://devlicio.us/blogs/casey/archive/2009/12/18/what-is-the-difference-between-an-ioc-container-and-mef.aspx</link><pubDate>Fri, 18 Dec 2009 06:50:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:54625</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>13</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=54625</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=54625</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/12/18/what-is-the-difference-between-an-ioc-container-and-mef.aspx#comments</comments><description>&lt;p&gt;Today a conversation sparked off on Twitter, started by &lt;a target="_blank" href="http://www.twitter.com/jbogard"&gt;Jimmy Bogard&lt;/a&gt; and &lt;a target="_blank" href="http://www.twitter.com/mhinze"&gt;Matt Hinze&lt;/a&gt;, and then carried on by myself and &lt;a target="_blank" href="http://www.twitter.com/gblock"&gt;Glenn Block&lt;/a&gt;. The basic starting point was what the difference was between using an IoC container like &lt;a target="_blank" href="http://www.castleproject.org/container/index.html"&gt;Windsor&lt;/a&gt; or &lt;a target="_blank" href="http://structuremap.sourceforge.net/Default.htm"&gt;StructureMap&lt;/a&gt; and using MEF (the &lt;a target="_blank" href="http://www.codeplex.com/MEF"&gt;Managed Extensibility Framework&lt;/a&gt;)   &lt;/p&gt;
&lt;p&gt;I started off by answering a question from Jimmy, he wanted the one paragraph sales pitch for MEF that didn&amp;rsquo;t include technical terminology &amp;hellip; I guess he was asking why MEF is a better option than one of the IoC containers we all love and hopefully all use religiously.&lt;/p&gt;
&lt;p&gt;My key answers were:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;MEF allows you to write your application as a series of much simpler mini applications, and have those brought together to create a much great whole&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;IoC container = service level components, MEF = Autonomous Components. A MEF &amp;quot;part&amp;quot; will probably use an IoC container&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This sparked some comments from Glenn where he wanted to clarify that sometimes an IoC container is the right choice, sometimes MEF is, and sometimes both are. Luckily we are both pragmatic, so not much to disagree with there. He pointed to two of his blogs on the subject, I recommend reading them highly, they will do a much better job than I could at explaining the detail of the decision points, &lt;a target="_blank" href="http://codebetter.com/blogs/glenn.block/archive/2009/08/16/should-i-use-mef-for-my-general-ioc-needs.aspx"&gt;Should I use MEF for my general IoC needs?&lt;/a&gt; and &lt;a target="_blank" href="http://codebetter.com/blogs/glenn.block/archive/2009/10/31/should-i-use-mef-with-an-ioc-container.aspx"&gt;Should I use MEF with an IoC container?&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;What&amp;rsquo;s Wrong With IoC Containers?&lt;/h3&gt;
&lt;p&gt;What an IoC container is very good at is low level control of your code, your dependency graphs, your lifestyle management, and gives you great low level ways to deal with facilities, factories, decorators and AOP. In just about any code base that goes past spike stage, I use an IoC container of some sort, it is just a fools errand to try and write and application without one these days. The keyword &amp;ldquo;new&amp;rdquo; is in my code smells book.&lt;/p&gt;
&lt;p&gt;However, what an IoC container is pretty poor at is enforcing boundaries. Sure you could use an IoC container to write much larger applications, but as Glenn rightly pointed out, the central configuration becomes a headache. In fact, the central registration can rapidly become the equivalent of using global variables, you never really know what is using what as everything has access to everything else.&lt;/p&gt;
&lt;p&gt;Most of the containers give you the capability to have child containers to try and deal with this situation, and while they do limit the global access issue, they are pretty hard to manage in their own right, and you can without some proper thought end up with a spaghetti mess of containers replacing your spaghetti mess of components.&lt;/p&gt;
&lt;h3&gt;An Architectural Solution To The Problem&lt;/h3&gt;
&lt;p&gt;To me, MEF is an architectural solution, while an IoC container is a code level solution. They both have their places in an application, but what MEF is exceptionally good at is creating process boundaries.&lt;/p&gt;
&lt;p&gt;One of the core underlying principles of good use of an IoC container is that you only ever reference a container at a process boundary &amp;ndash; in most applications that means it is probably referenced in your bootstrapping code inside your web application (maybe Global.ascx), or inside an HttpModule around your web services, but from that point on, your code should never reference the container again &amp;ndash; the magic of an IoC container comes from relinquishing all object construction and dependency graph resolution to it.&lt;/p&gt;
&lt;p&gt;But this means in a larger application, you may end up with massive containers with hundreds of registered components, and in reality most operations will only use a small handful at a time. &lt;/p&gt;
&lt;p&gt;In most larger systems you would naturally have parts of the system you want to devolve into discrete components, or Autonomous Components. Doing this with an IoC container starts to lead you down an architectural design geared around the limitations of the IoC container, and not necessarily driven by good architectural principles.&lt;/p&gt;
&lt;p&gt;What MEF allows you to do is to break the system apart easily, or as Glenn referred to it, MEF allows you to easily create composite applications. These composite &lt;strong&gt;parts&lt;/strong&gt; can operate as Autonomous Components, in almost total isolation from the core application, and therefore they provide a natural boundary without having to use things like web of WCF service layers just for that purpose. Oddly the MEF terminology that Jimmy wanted to avoid in his original question was &amp;ldquo;part&amp;rdquo; and yet it fits naturally in this context.&lt;/p&gt;
&lt;h3&gt;Russian Dolls&lt;/h3&gt;
&lt;p&gt;As I started off by saying, I would almost always end up using an IoC container in any application I was to write, even a fairly small scale one. If we look at these MEF parts as now being Autonomous Components, and therefore operating as mini applications, it now becomes apparent that they will themselves need a way to create service components and dependency graphs, and while MEF could in theory do a lot of that, it&amp;rsquo;s just not the best fit for the job.&lt;/p&gt;
&lt;p&gt;So it&amp;rsquo;s pretty certain that inside your MEF part you will be using yet another IoC container for object resolution, but now you don&amp;rsquo;t have a massive central registry, but one specifically geared to the MEF part in question.&lt;/p&gt;
&lt;p&gt;And this pattern can recurse if needed, each time providing a clean boundary within your application.&lt;/p&gt;
&lt;h3&gt;A Real World Example&lt;/h3&gt;
&lt;p&gt;The last &amp;ldquo;large scale&amp;rdquo; system I worked on where I had the opportunity to put some of these ideas into practice was an insurance portal. This portal was responsible for providing insurance quotations, but across a massively diverse and inconsistent set of products.&lt;/p&gt;
&lt;p&gt;The solution we came to in the end was a combination of all of the above principles &amp;ndash; we had a web application that held a Castle Windsor container in Global.ascx, that container was responsible for instantiating everything from controllers backwards, and all of the service components they used.&lt;/p&gt;
&lt;p&gt;But some of those controllers needed to call our product plugins, and in this case we actually used Castle Windsor to use MEF to instantiate the plugins (MEF parts). Within each product plugin we had another set of bootstrapping code that had it&amp;rsquo;s own instance of a Castle Windsor container, and it&amp;rsquo;s own registry specific to that plugin.&lt;/p&gt;
&lt;p&gt;The plugins were actually used by a number of points in the application, some in process, and some out of process, either on other servers or just behind service or service bus boundaries &amp;ndash; what MEF allowed us to do was create an independently deployable package that was self contained and self sufficient, without the need for managing masses of registration information &amp;ndash; trying to use an IoC container for this would have been a mini-nightmare, but with MEF it was almost a pleasure.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=54625" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Practices+and+Principles/default.aspx">Practices and Principles</category><category domain="http://devlicio.us/blogs/casey/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Architecture/default.aspx">Architecture</category><category domain="http://devlicio.us/blogs/casey/archive/tags/ASP.NET+MVC/default.aspx">ASP.NET MVC</category><category domain="http://devlicio.us/blogs/casey/archive/tags/MEF/default.aspx">MEF</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Castle/default.aspx">Castle</category></item><item><title>Combining NHibernate, NH Spatial and SQL Server 2008 Fulltext Queries</title><link>http://devlicio.us/blogs/casey/archive/2009/11/22/combining-nhibernate-nh-spatial-and-sql-server-2008-fulltext-queries.aspx</link><pubDate>Sun, 22 Nov 2009 22:42:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:54016</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=54016</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=54016</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/11/22/combining-nhibernate-nh-spatial-and-sql-server-2008-fulltext-queries.aspx#comments</comments><description>&lt;p&gt;Following &lt;a target="_blank" href="http://www.kevinwilliampang.com/"&gt;Kevin Pang&amp;rsquo;s&lt;/a&gt; request on &lt;a target="_blank" href="http://devlicio.us/blogs/casey/archive/2009/11/13/53319.aspx"&gt;my last post regarding my problems getting NHibernate, NH Spatial and SQL Server Fulltext queries to work&lt;/a&gt;, I am finally getting around to giving some tips and pointers, and the code that &lt;a target="_blank" href="http://blogs.imeta.co.uk/sstrong/Default.aspx"&gt;Steve Strong&lt;/a&gt; of &lt;a target="_blank" href="http://www.imeta.co.uk/"&gt;iMeta&lt;/a&gt; knocked up for me.&lt;/p&gt;
&lt;p&gt;I needed to get these things working together as I was writing a recruitment website, and they had two basic requirements, the ability to search in candidates CVs and job descriptions for keywords, and the ability to search for those things within a certain distance &amp;ndash; so an obvious search would be &amp;ldquo;find me all the C# developers within 10 miles of Central London&amp;rdquo;&lt;/p&gt;
&lt;h3&gt;Step One &amp;ndash; NHibernate&lt;/h3&gt;
&lt;p&gt;Firstly, I&amp;rsquo;m not dumb, and at the beginning of the project I had decided to use NHibernate for all data access. The site didn&amp;rsquo;t have much of a domain model, but what it did have was ideally suited to a relational DB and simple persistence and querying by an ORM like NHibernate. What it also had going in it&amp;rsquo;s favour was the 2nd level caching capabilities of NHibernate, which would significantly reduce the workload on a site that was expected to grow quickly (or at least the owners hoped it would)&lt;/p&gt;
&lt;p&gt;Win for NHibernate there &amp;ndash; the icing on the cake was the excellent NHProfiler which would prove to make development a breeze over other options, and which also proved to make my querying a lot smarter and more bug free than my first horrid attempts.&lt;/p&gt;
&lt;h3&gt;Step Two &amp;ndash; Spatial Searching&lt;/h3&gt;
&lt;p&gt;MS SQL Server 2008 introduced Spatial searching to it&amp;rsquo;s list of features &amp;ndash; in fact it&amp;rsquo;s not just for searching, and not just by distance either, it can do a host of clever geographical type calculations and querying.&lt;/p&gt;
&lt;p&gt;My first tests were done with &amp;ldquo;old fashioned&amp;rdquo; T-SQL and within a short while I had a reasonable distance search working, roughly speaking it looked like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SET @from = geography::STGeomFromText(&amp;#39;POINT(-0.094693 51.520223)&amp;#39;, 4326); -- EC2M (London&lt;/p&gt;
&lt;p&gt;SELECT * FROM JobSlot j      &lt;br /&gt;WHERE j.Location.STDistance(@from)&amp;lt;=(@distance * 1609.344)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Step Three &amp;ndash; Fulltext Searching&lt;/h3&gt;
&lt;p&gt;Long ago, back in the age before the dawn of time, MS SQL Server had Fulltext searching, via the FREETEXT and CONTAINS syntax. Give it a keyword, or a list of them, and it will dig inside your text to find just what you want.&lt;/p&gt;
&lt;p&gt;To use it on the site I was writing, we needed to index the content of CVs (resumes to your foreigners!) and some of those were in docx format &amp;ndash; so my first step was to &lt;a target="_blank" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=60C92A37-719C-4077-B5C6-CAC34F4227CC&amp;amp;displaylang=en"&gt;download the Microsoft Office 2007 iFilters&lt;/a&gt;. SQL Server uses the (now) age old technology of iFilters to extract the text from documents, and this filter pack allows it to look inside Office 2007 documents &amp;ndash; if you want to index any other weird document formats, or even your own document format, there is probably an iFilter available, or you can write your own. With the iFilters installed, SQL Server could now index all of my content just fine.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;SELECT *      &lt;br /&gt;FROM Candidate       &lt;br /&gt;WHERE FREETEXT(*, N&amp;#39;c#&amp;#39;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Combining It All&lt;/h3&gt;
&lt;p&gt;So far, so good. SQL Server can do pretty much all I need it to do, and combining those two queries is simplicity in TSQL, but as I was using NHibernate for all my data access, I wanted to try an get it all working there too.&lt;/p&gt;
&lt;p&gt;NHibernate has support for the Spatial features of SQL Server 2008, along with other spatial databases, via the NHSpatial stuff in the NH Contrib project at &lt;a href="http://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/"&gt;http://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A download and compile of this will have you making HQL queries to do similar things to my TSQL spatial query above, in fact, the HQL query is remarkably similar to the TSQL:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;select j from JobSlot j where NHSP.Distance(j.Loc, :point) &amp;lt;= (:distance * 1609.344)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then I needed to get the Fulltext part working, after some chatting with Steve Strong, he came up with the following code:&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; WKTReader wtk = new WKTReader();    &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; IGeometry point = wtk.Read(&amp;quot;POINT( -0.123356 51.524142 )&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; point.SRID = 4326; &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; string 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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @&amp;quot;select j from JobSlot j     &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;&amp;nbsp;&amp;nbsp; from freetexttable(&amp;#39;JobSlot&amp;#39;, :keywords) ftt     &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;&amp;nbsp;&amp;nbsp; where NHSP.Distance(j.Loc, :point) &amp;lt;= (:distance * 1609.344)&amp;quot;; &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; var results = session.CreateQuery(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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .SetParameter(&amp;quot;point&amp;quot;, point, SpatialDialect.GeometryTypeOf(session))     &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; .SetParameter(&amp;quot;distance&amp;quot;, 1)     &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; .SetParameter(&amp;quot;keywords&amp;quot;, &amp;quot;hello world&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; .SetFirstResult(5)     &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; .SetMaxResults(10)     &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; .List();&lt;/p&gt;
&lt;p&gt;And to get this to work we need 2 more classes, though the FreeText class is more an example of how to create an ISqlFunction for NHibernate:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;	public class MyDialect : MsSql2008GeographyDialect
	{
		public MyDialect()
		{
			RegisterFunction(&amp;quot;freetext&amp;quot;, new FreeText());
			RegisterFunction(&amp;quot;freetexttable&amp;quot;, new StandardSQLFunction(&amp;quot;freetexttable&amp;quot;, null));
			RegisterFunction(&amp;quot;contains&amp;quot;, new StandardSQLFunction(&amp;quot;contains&amp;quot;, null));
		}
	}

	public class FreeText : ISQLFunction
	{
		public bool HasArguments
		{
			get { return true; }
		}

		public bool HasParenthesesIfNoArguments
		{
			get { return true; }
		}

		public virtual SqlString Render(IList args, ISessionFactoryImplementor factory)
		{
			SqlStringBuilder builder = new SqlStringBuilder();
			builder.Add(&amp;quot;freetext(&amp;quot;);

			if (args.Count == 1)
			{
				builder.Add(&amp;quot;*, &amp;quot;);
				builder.AddObject(args[0]);
			}
			else
			{
				builder.AddObject(args[0]);
				builder.Add(&amp;quot;, &amp;quot;);
				builder.AddObject(args[1]);
			}

			builder.Add(&amp;quot;)&amp;quot;);

			return builder.ToSqlString();
		}

		public virtual IType ReturnType(IType columnType, IMapping mapping)
		{
			return null;
		}
	}&lt;/pre&gt;
&lt;h3&gt;Why I&amp;rsquo;m Not Using The Above Code&lt;/h3&gt;
&lt;p&gt;Yep, in my usual fashion I go through explaining all of that, just to say, I&amp;rsquo;m not doing it that way.&lt;/p&gt;
&lt;p&gt;Eventually, I went back to another approach, that of using TSQL dynamically constructed in my code. I did this for a number of reasons, but primarily as it was easier for me to tune the query and add more options and variants in old fashioned SQL than in HQL by adding more extensions on to NHibernate. It also left the code base in a much easier to follow and extend state for the developers who would be maintaining the project &amp;ndash; with the amount of investigation it took me to get this far, I figured extending it could be a nightmare for my successors.&lt;/p&gt;
&lt;p&gt;The benefits I got from NHibernate I still retained, as this is a search function it was returning DTOs anyway, not entities, and these were just as efficient to read with a DataReader as with NHibernate (in fact a lot easier). When one of the results from the search is selected, the item is retrieved by NHibernate and we are back in ORM land.&lt;/p&gt;
&lt;p&gt;It was also little effort to cache my SQL query results, so I also had all that NH was offering me in that respect too &amp;ndash; a simple hash of the query parameters allowed me to cache the results object.&lt;/p&gt;
&lt;p&gt;So there ya go, how to use Spatial and Fulltext with NHibernate, and why I didn&amp;rsquo;t do it! :)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=54016" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Practices+and+Principles/default.aspx">Practices and Principles</category><category domain="http://devlicio.us/blogs/casey/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://devlicio.us/blogs/casey/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/casey/archive/tags/NHibernate/default.aspx">NHibernate</category></item><item><title>When NHibernate Won't Do What You Think It Should</title><link>http://devlicio.us/blogs/casey/archive/2009/11/02/when-nhibernate-won-t-do-what-you-think-it-should.aspx</link><pubDate>Mon, 02 Nov 2009 13:57:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:53319</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=53319</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=53319</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/11/02/when-nhibernate-won-t-do-what-you-think-it-should.aspx#comments</comments><description>&lt;p&gt;There are times, when you just think something should work, and one way or another it just doesn&amp;#39;t. I&amp;#39;ve been having one of those weeks with NHibernate. I have been&amp;nbsp;using MS SQL Server 2008 spatial searching, along with SQL Server Full text search, and using NHibernate for almost all my data access.&lt;/p&gt;
&lt;p&gt;The only problem is that NHibernate out of the box doesn&amp;#39;t like to play nicely with Spatial or Fulltext. After head scratching, head bashing, and general teeth grinding I figured better to cut my losses and ask some people that actually knew what they were doing.&lt;/p&gt;
&lt;p&gt;Firstly I fired a twitter off in the direction of Ayende to get a feel for whether I was doing something wrong - with CreateSqlQuery NHibernate didn&amp;#39;t want me to use the Spatial stuff - NHibernate uses a colon : to identify parameters, but in SQL 2008 Microsoft decided to use a double colon :: in it&amp;#39;s spatial bits, so for example to declare a point you would use:&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;geography::STGeomFromText(&amp;#39;POINT(51.520223 -0.094693 )&amp;#39;, 4326)&lt;/p&gt;
&lt;p&gt;That promptly causes NH to stop you from carrying on with a missing parameter. Ayende did indeed confirm it&amp;#39;s not right, and after a few helpful suggestions he ran out of quick wins and suggested I might want to take advantage of his &lt;a href="http://nhprof.com/commercialsupport"&gt;commercial support for NHibernate&lt;/a&gt;. I&amp;#39;m not adverse to such a solution, but felt this one might get complex, and Ayende&amp;#39;s payment structure didn&amp;#39;t fit my needs - this is a small project for a small client, and I could work around NH&amp;#39;s limitations by using stored procedures (yes, I know, heresy).&lt;/p&gt;
&lt;p&gt;After a bit more head scratching I remebered that &lt;a href="http://www.imeta.co.uk/"&gt;iMeta&lt;/a&gt; also &lt;a href="http://www.imeta.co.uk/professional_nhibernate_support.aspx"&gt;provide NH commecial support&lt;/a&gt; now, and having taken&amp;nbsp;a look at their pages, I figured it would work much better for my limited budget.&lt;/p&gt;
&lt;p&gt;After a&amp;nbsp; quick chat with &lt;a href="http://hadihariri.com/blogengine/"&gt;Hadi Hariri&lt;/a&gt;, he directed me on to &lt;a href="http://blogs.imeta.co.uk/sstrong/Default.aspx"&gt;Steve Strong&lt;/a&gt;, the man who wrote a great deal of the Linq to NHibernate stuff, and a bit of an expert on the parser.&lt;/p&gt;
&lt;p&gt;Steve ripped through my queries with lighning pace, and had me a viable solution that afternoon - now that&amp;#39;s what I call customer service. Today Steve has continued to sort out niggles with the problem, and it looks like we may have identified a few bugs in NHibernate Spatial and possibly the parser, which Steve will now push back into the NH trunk for future geenrations to benefit from.&lt;/p&gt;
&lt;p&gt;So, althought NHibernate is open source software, and in theory you can fix this stuff yourself, this is just a post to point out that sometimes the best use of your time and effort is in things you can deal with quickly, and sometimes it is worth paying some real specialists to help out - the cost saving could be immense. If you have problems with NHibernate, I encourage you to take a look at the offerings available, &lt;a href="http://www.imeta.co.uk/professional_nhibernate_support.aspx"&gt;especially the iMeta one&lt;/a&gt; :)&lt;/p&gt;
&lt;p&gt;Just because NHibernate is free - doesn&amp;#39;t mean it isn&amp;#39;t worth paying for!&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://devlicio.us/aggbug.aspx?PostID=53319" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/NHibernate/default.aspx">NHibernate</category></item></channel></rss>