<?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>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>4</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/about-readify"&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/about-readify/%20"&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/about-readify/careers/"&gt;http://readify.net/about-readify/careers/&lt;/a&gt;&amp;nbsp;&amp;nbsp;&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><item><title>Welcome to Hadi Hariri</title><link>http://devlicio.us/blogs/casey/archive/2009/10/14/welcome-to-hadi-hariri.aspx</link><pubDate>Wed, 14 Oct 2009 08:40:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:52656</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=52656</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=52656</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/10/14/welcome-to-hadi-hariri.aspx#comments</comments><description>&lt;p&gt;I am pleased to say that after a bit of gentle persuasion, &lt;a href="http://twitter.com/hhariri"&gt;one of my favourite Twitterers&lt;/a&gt;, &lt;a href="http://hadihariri.com"&gt;general top notch blogger&lt;/a&gt; and all around good egg Hadi Hariri is joining us as a new blogger on devlicio.us&lt;/p&gt;
&lt;p&gt;He has a wealth of experience, but I kept forgetting to visit his blog - and felt that devlicio.us could really benefit from his thoughts and advice - so I am really pleased he agreed to join the crew. &lt;/p&gt;
&lt;p&gt;Welcome Hadi!&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=52656" width="1" height="1"&gt;</description></item><item><title>Good Developers Write Good Code, Instinctively</title><link>http://devlicio.us/blogs/casey/archive/2009/10/06/good-developers-write-good-code-instinctively.aspx</link><pubDate>Tue, 06 Oct 2009 08:09:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:52215</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>11</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=52215</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=52215</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/10/06/good-developers-write-good-code-instinctively.aspx#comments</comments><description>&lt;p&gt;So &lt;a href="http://devlicio.us/blogs/casey/archive/2009/10/05/developer-myopia.aspx"&gt;my last post&lt;/a&gt; ruffled some feathers, but Steve hit the nail right on the head in his commments, and it was sort of the subtext of what I was saying:&lt;/p&gt;
&lt;p&gt;All this kerfuffle about &amp;quot;software craftsmen&amp;quot; and &amp;quot;code quality&amp;quot; and &amp;quot;best practice&amp;quot; misses the ultimate fundamental truth : &lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;em&gt;Good Developers Write Good Code, Instinctively&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let start with a funny statistic ... it certainly applies to drivers, I&amp;#39;m sure it applies to developers too (and almost any group of people) ...&lt;/p&gt;
&lt;p style="padding-left:30px;"&gt;&lt;em&gt;80% of developers think they are above average!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Our logical brains can&amp;#39;t help but admit that at least 30% of developers are therefore deluded. Our mathematical brains can&amp;#39;t help but admit that 50% of developers must be totally average or below average. And yet, most of us think we are above average developers. I would boldly go further, and put myself in the top 20% of developers - I like to think I at least have a damn good idea who the 20% above me are and why they are better.&lt;/p&gt;
&lt;p&gt;If you are a &amp;quot;good developer&amp;quot; you will write &amp;quot;good&amp;quot; code. It will probably use a dozen standard patterns, maybe without you even knowing what they are called, it will have low coupling, high cohesion, be easy to test, easy to extend, hard to modify, avoid duplication and abstract code behind well thought out interfaces. And yet despite all that - you may well have never heard of software patterns, OCP, ISP, DIP, unit Testing, DRY, YAGNI, etc etc etc&lt;/p&gt;
&lt;h3&gt;Before The Renaissance&lt;/h3&gt;
&lt;p&gt;There was a time, which sadly I am old enough to remember, when we didn&amp;#39;t have all these fancy names, and yet we pretty much did what all the enlightend are doing today. &lt;/p&gt;
&lt;p&gt;We may not have had &amp;quot;unit testing&amp;quot;, but we had &amp;quot;test harnesses&amp;quot;, and we may not have had automated tests running after every build, but we had QA people using our test harnesses to verify our code. &lt;/p&gt;
&lt;p&gt;We may not have had software patterns, but we all used factories, observers and singletons.&lt;/p&gt;
&lt;p&gt;We may not have has SOLID, but we wrote good decoupled code, well abstracted, easy to test and easy to maintain.&lt;/p&gt;
&lt;h3&gt;None of These Things Are New&lt;/h3&gt;
&lt;p&gt;While many like to go on almost holy crusades about these wonderful new inventions, some of us know that these are just evolutions of things good developers have been doing since programming began. Sure they are now formalised, they have great names, they have been refined to be more automated and more efficient - but at the end of the day - good developers already did this stuff.&lt;/p&gt;
&lt;p&gt;What concerns me more is how &amp;quot;new&amp;quot; these things seem to some of the holy crusaders. I remember code I wrote in 6502 assembler that had these principles applied (you try writing games in 3.5kb of RAM if you don&amp;#39;t apply DRY), I remember code I wrote in COBOL on a PDP/11 that had &amp;quot;factories&amp;quot;. &lt;/p&gt;
&lt;p&gt;I remember working on a RAD team in an investment bank, long before RAD had meaning. We delivered software fast, direct to the customers, with rapid feedback and weekly releases. We sat with the traders, we were &amp;quot;Agile&amp;quot; and &amp;quot;Lean&amp;quot; long before anyone thought of proper words.&lt;/p&gt;
&lt;p&gt;These great software practices were not invented, they were formalisations of things we were already doing.&lt;/p&gt;
&lt;h3&gt;All Of These Things Are Good&lt;/h3&gt;
&lt;p&gt;Before anyone decides to rip my head off and banish me to the pits of hell, let me state - all of these practices are good. More over, these practices are (probably) the pinnacle of our current understanding of development practices garnered over the last 30 or 40 years - and we should strive to write code with these things in mind. In 5 years I have no doubt all these things will have evolved, and there will be new best practices. Half of these things only apply to Java and C# anyway - in the world of F#, Erlang, Ruby and Python there are new principles and best practices.&lt;/p&gt;
&lt;p&gt;Formalisation of all these practices, principles and methodologies is good - it helps promote understanding and gives us a way of communicating.&lt;/p&gt;
&lt;p&gt;The thing is, the real &amp;quot;above average&amp;quot; developers were probably already doing this - and all that code they wrote for the past 30 years is probably still running your bank accounts, processing your taxes and helping keep your aircraft in the sky, precisely because they already did.&lt;/p&gt;
&lt;h3&gt;Below Average Developers Will Always Write Below Average Code&lt;/h3&gt;
&lt;p&gt;No way to avoid this I&amp;#39;m afraid - we can talk about the need to raise the bar, to raise the average, to help those below average developers write better code - but fundamentally, below average developers will always write below average code. The above average developers need to recognise this, and understand that they will always feel they are being held back by the lower 50%, and they are always fixing the code of the lower 50%, and they are always doing more than their share.&lt;/p&gt;
&lt;p&gt;And one last question... are you sure YOU are above average? I&amp;#39;m not sure myself, in fact my most common comment in interviews is that I am not the best C# developer in the world by a long way, I am rarely the best C# developer in my team for that matter. Am I in the top 20%? Probably by my own standards and measures - that doesn&amp;#39;t mean I am by everyone else&amp;#39;s measures.&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=52215" 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/Rants/default.aspx">Rants</category></item><item><title>Developer Myopia</title><link>http://devlicio.us/blogs/casey/archive/2009/10/05/developer-myopia.aspx</link><pubDate>Mon, 05 Oct 2009 12:07:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:52106</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>22</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=52106</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=52106</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/10/05/developer-myopia.aspx#comments</comments><description>&lt;p&gt;While &lt;a href="http://www.scottcreynolds.com/archive/2009/10/02/604.aspx"&gt;some may argue&lt;/a&gt; that TDD, BDD, SRP, ahderence to SOLID, use of Patterns, and many other development practices and principles are critical to achieving great software, these all seem to miss some core truths.&lt;/p&gt;
&lt;h3&gt;Most Software Has Not Been Developed This Way&lt;/h3&gt;
&lt;p&gt;Yep, sorry to disappoint, but the vast majority of software in production in the world today has had none of these principles and practices applied. Some of the software may have had some of these practices applied - but it is (I would guesstimate) an incredibly small percentage.&lt;/p&gt;
&lt;p&gt;And despite that (feel free to tell me I&amp;#39;m wrong) fact, most software works and continues to work. It processes your taxes correctly, makes sure your airplane doesn&amp;#39;t blow up on take off, scans your body for cancer, lets you bill your customers, tells you what you are doing tomorrow, and lets you keep in touch with friends and family.&lt;/p&gt;
&lt;h3&gt;Most Software &amp;quot;Mistakes&amp;quot; Are Not Development Practices&lt;/h3&gt;
&lt;p&gt;Steve McConnell, he of &lt;a href="http://cc2e.com/"&gt;Code Complete&lt;/a&gt; and &lt;a href="http://www.stevemcconnell.com/rd.htm"&gt;Rapid Development&lt;/a&gt; fame (books everyone in development or management should read) has just published his &amp;quot;&lt;a href="http://blogs.construx.com/blogs/stevemcc/archive/2008/05/13/Software_2700_s-Classic-Mistakes_2D002D00_2008.aspx"&gt;Software&amp;#39;s Classic Mistakes&lt;/a&gt;&amp;quot; list for 2008, and none of these things we developer&amp;#39;s like to refer to as &amp;quot;best practice&amp;quot; or &amp;quot;the right way&amp;quot; feature on the list - not in their specific forms, mnor even in their general forms.&lt;/p&gt;
&lt;p&gt;In fact - all of the classic mistakes (which cause software projects to be delayed or fail) are process mistakes, they are failures of people, not of coding constructs and practices.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Unrealistic Expectations&lt;/li&gt;
&lt;li&gt;Overly Optimistic Schedules&lt;/li&gt;
&lt;li&gt;Shortchanged Quality Assurance&lt;/li&gt;
&lt;li&gt;Wishful Thinking&lt;/li&gt;
&lt;li&gt;Confusing Estimates With Targets&lt;/li&gt;
&lt;li&gt;Excessive Multi Tasking&lt;/li&gt;
&lt;li&gt;Feature Creep&lt;/li&gt;
&lt;li&gt;Noisy Crowded Offices&lt;/li&gt;
&lt;li&gt;Abandoning Planning Under Pressure&lt;/li&gt;
&lt;li&gt;Insufficient Risk management&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We can certainly look at this list and see how Agile, Lean and similar processes can help alleviate many of these, but where do you see &amp;quot;TDD&amp;quot;, &amp;quot;BDD&amp;quot;, &amp;quot;SOLID&amp;quot; or even &amp;quot;Automated Testing&amp;quot; resolving any of them? The closest we will come is to see &amp;quot;Shortchanged Quality Assurance&amp;quot; as being ticked off the list, but this still doesn&amp;#39;t remove the need for real QA on a project, and real QA people.&lt;/p&gt;
&lt;h3&gt;Developer Myopia&lt;/h3&gt;
&lt;p&gt;While as developer&amp;#39;s we see great value in many of these practices, we need to admit that we are actually a very small part of the equation, and sometimes developer myopia sneaks in - we think that what we do at a code level matters, substantially more than it does in the grand scheme of things.&lt;/p&gt;
&lt;p&gt;By all means, apply and practice these things that create &amp;quot;quality&amp;quot; software, but bear in mind, there are much bigger and more important problems to resolve too.&lt;/p&gt;
&lt;p&gt;Or to paraphrase (and bastardize)&amp;nbsp;the Agile manifesto: While we see value in software patterns and practices, there is more value in solving process problems first&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=52106" 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/Rants/default.aspx">Rants</category></item><item><title>Ship it, or Ship Out</title><link>http://devlicio.us/blogs/casey/archive/2009/09/25/ship-it-or-ship-out.aspx</link><pubDate>Fri, 25 Sep 2009 08:38:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:51716</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>27</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=51716</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=51716</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/09/25/ship-it-or-ship-out.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://www.joelonsoftware.com/"&gt;Joel&lt;/a&gt;, in his inimitable way, &lt;a href="http://www.joelonsoftware.com/items/2009/09/23.html"&gt;posted the flame bait of all flame bait posts yesterday&lt;/a&gt;, explaining the role of the Duct Tape Programmer.&lt;/p&gt;
&lt;p&gt;To my surprise, the Twitterverse started to reverberate with commentary, but weirdly, almost all of it was very negative about the post, many claiming that Joel was just creating straw men and knocking them down, or was characterising developers who care about quality as being poor developers.&lt;/p&gt;
&lt;p&gt;I was surprised, because I read the article totally the other way around - and had said so earlier in the day to someone on Twitter, saying I largely agreed with it. It seems that there were two ways of reading the article, and mine differed substantially to most people I follow on Twitter.&lt;/p&gt;
&lt;p&gt;I was quite pleased to see Michael Neel post last night in a &lt;a href="http://devlicio.us/blogs/vinull/archive/2009/09/24/being-a-duct-tape-programmer.aspx"&gt;semi-defence of Joel&amp;#39;s standpoint&lt;/a&gt;, and I thought the 140 char limit of Twitter wasn&amp;#39;t enough for me to post my opinions.&lt;/p&gt;
&lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;Joel has a bit of a record on this, he isn&amp;#39;t best liked by a large proportion of the developer community who see their focus and remit as producing high quality, well tested and highly maintainable software. His &lt;a href="http://blog.stackoverflow.com/2009/01/podcast-38/"&gt;original tirades in a podcast&lt;/a&gt; about his deep distrust of Test Driven Development and of Unit Testing in &lt;a href="http://blog.objectmentor.com/articles/2009/01/31/quality-doesnt-matter-that-much-jeff-and-joel"&gt;general brought uproar&lt;/a&gt;. And on that matter he was so far off the mark, it was understandable why he had riled so many people - he really just didn&amp;#39;t understand or &amp;quot;get&amp;quot; TDD or testing in general.&lt;/p&gt;
&lt;p&gt;But, what he had done, in conjunction with &lt;a href="http://www.codinghorror.com/blog/"&gt;Jeff Atwood&lt;/a&gt;, was to deliver a website, &lt;a href="http://stackoverflow.com/"&gt;stackoverflow.com&lt;/a&gt;, that was proving hugely successful, and was being used extensively by all those same developers who railed against his podcasts and blogs.&lt;/p&gt;
&lt;p&gt;That website, as Joel and Jeff explained, was not done with TDD, was not well tested (via Unit Tests), was badly hacked together in places, and used &amp;quot;old&amp;quot; technologies like TSQL over &amp;quot;modern&amp;quot; solutions like ORMs&lt;/p&gt;
&lt;p&gt;Whether Joel &amp;quot;got&amp;quot; TDD wasn&amp;#39;t important, what he and Jeff had done was to ship a product, get it to market, and build upon that release to make stackoverflow the massive success it is today. It&amp;#39;s so successful, that soon after stackoverflow was released, they used the same code and model to release other Q&amp;amp;A sites, and they continue to do so.&lt;/p&gt;
&lt;h3&gt;The Duct Tape Programmer&lt;/h3&gt;
&lt;p&gt;So with all of that in mind, it was sort of obviously flame bait for Joel to make a post that basically boiled down to &amp;quot;shipping it way more important than fancy patterns and great tools&amp;quot; - he certainly has a way of putting such a simple message that can antagonise the meekest of individuals (and some not so meek). &lt;/p&gt;
&lt;p&gt;It was a terrible choice of label, but I guess &amp;quot;Pragmatic Programmer&amp;quot; had already been taken.&lt;/p&gt;
&lt;h3&gt;Time, Quality, Functionality&lt;/h3&gt;
&lt;p&gt;I read the article slight differently - I read it as an urge to maintain your highest priority as shipping the product your business wants you to ship.&lt;/p&gt;
&lt;p&gt;There are three factors involved in a project (if you exclude Resourcing, which falls under Brooks Law):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Time&lt;/li&gt;
&lt;li&gt;Quality&lt;/li&gt;
&lt;li&gt;Functionality (or Scope)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you try and maintain all three factors as fixed, your project is doomed to fail. Something will, unless you are really lucky, break. And then one of those factors will suffer, and it will be luck as to which it is. At best you can fix two of those factors, and then the third has to be allowed to slip when the unexpected happens (as it always does).&lt;/p&gt;
&lt;p&gt;But, the important part here, is that which of those factors is fixed, and which is allowed to slip is NOT a developer decision - it is a business decision.&lt;/p&gt;
&lt;p&gt;Much of the outrage about Joel&amp;#39;s article stated that he isn&amp;#39;t a developer - and they are correct - he is a business owner, and prior to that a project manager. His focus is therefore on shipping his product, and inevitably from that perspective, the instinct is to fix Time and Functionality (ship as soon as possible, with as much functionality as possible) and to let Quality suffer to achieve that objective.&lt;/p&gt;
&lt;p&gt;This is a TOTALLY VALID business decision - it is just one that developers don&amp;#39;t like, it offends their sense of code quality and high standards.&lt;/p&gt;
&lt;h3&gt;Why Do Developers Care So Much About Quality?&lt;/h3&gt;
&lt;p&gt;I&amp;#39;ll start with the cynical view: development is only fun while you are trying new things, trying to perfect a tricky algorithm, or make some great new OSS component do some magic. By nature, the developers who care deeply about quality are also perfectionists, they like to make sure they have done a good job, and have written the best code they can.&lt;/p&gt;
&lt;p&gt;Go on, admit it, if developers just did routine coding all day long, our jobs would be boring. We like new toys, new language features, we like to play.&lt;/p&gt;
&lt;p&gt;And we know that better code will be easier to maintain - and developers HATE bug fixing duty, so we want to ensure we don&amp;#39;t have to do much of it.&lt;/p&gt;
&lt;p&gt;To a developer, the most important factor in any project is Quality, followed by Time (because we know our bosses will be mad if we miss our deadlines), but we are happy to slip Functionality because it matters little to us if a new feature isn&amp;#39;t included in the release.&lt;/p&gt;
&lt;h3&gt;Fundamentally We Are Not Aligned&lt;/h3&gt;
&lt;p&gt;Developers and business owners are not aligned in their goals - we prioritise the three factors very differently, and for different reasons.&lt;/p&gt;
&lt;p&gt;Only two things can happen here, your developers need to align with their business objectives, or the business needs to align with the developers - or they can both compromise.&lt;/p&gt;
&lt;p&gt;Agile is all about the compromise, making both sides aware of the issues involved, and then coming to an agreement, but fundamentally - it is STILL A BUSINESS DECISION.&lt;/p&gt;
&lt;p&gt;While it is the responsibility of a professional developer to explain all the problems they see with low quality code, and to make their boss aware of all the potential future issues this may cause, it is also their professional responsibility to go with the decision their boss makes.&lt;/p&gt;
&lt;p&gt;They have one other option - resign and go somewhere that is more closely aligned with their values.&lt;/p&gt;
&lt;h3&gt;Ship It or Ship Out&lt;/h3&gt;
&lt;p&gt;Whatever your opinions of Joel and Jeff&amp;#39;s understandings of TDD, Unit testing, maintainable code or just code in general (and I&amp;#39;m sure yours aren&amp;#39;t too far from mine), you have to admit they delivered a product to market (many in fact), and have turned it into a huge success. They may have to pay for that speed to market later, but that was a business decision they were willing to take.&lt;/p&gt;
&lt;p&gt;Never underestimate the value to a business of being fast to market - there is a risk the product will be so bugged it will backfire - but there is a chance they could steal the march on their competitors, and gain critical traction. Business is all about assessing risk, that is what a business owner has to do, and if they do it right their business flourishes.&lt;/p&gt;
&lt;p&gt;If your boss wants a product shipped by a particular date, and that is their highest priority, you have a responsibility to ship it. If they won&amp;#39;t sacrifice functionality to achieve that goal, then code quality will have to suffer - in that case do the best you can do with the restraints you are under. And if all that fails, quit, go somewhere that appreciates your values and dedication to your art - you do not have a right to hold your employer to ransom.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So, Ship It or Ship Out.&lt;/strong&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=51716" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/TDD/default.aspx">TDD</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><category domain="http://devlicio.us/blogs/casey/archive/tags/Twitter/default.aspx">Twitter</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Testing/default.aspx">Testing</category></item><item><title>Make It Easy To Refactor</title><link>http://devlicio.us/blogs/casey/archive/2009/09/21/make-it-easy-to-refactor.aspx</link><pubDate>Mon, 21 Sep 2009 15:17:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:51578</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=51578</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=51578</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/09/21/make-it-easy-to-refactor.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;m currently looking at a code base that could do with some refactoring, overall it&amp;#39;s a pretty good code base, and the test coverage is pretty good too. But looking through it gave me some ideas on what makes a code base tricky to safely refactor. Here are some tips to make sure your code is in a good state to be refactored with safety and confidence.&lt;/p&gt;
&lt;h3&gt;Provide Good Test Names&lt;/h3&gt;
&lt;p&gt;Test methods should have good, meaningful names; this is of course exactly the same as all code - naming is very important to give context and meaning. I am looking at a lot of tests that make sense to the original developer, and within reason make sense to me, but they do not properly describe what the test tries to do and what it expects.&lt;/p&gt;
&lt;p&gt;A test named &amp;quot;ValidHardware()&amp;quot; is less than ideal for telling me the intent of the test.&amp;nbsp; If the method had been correctly named it would have been called:&lt;/p&gt;
&lt;p style="PADDING-LEFT:30px;"&gt;ensure_that_hardware_detector_returns_true_when_valid_hardware_is_present()&lt;/p&gt;
&lt;p&gt;Now you tell me, which is easier to understand? And which is going to give me more confidence in refactoring that hardware detector?&lt;/p&gt;
&lt;h3&gt;Make Sure Variables Are Well Named&lt;/h3&gt;
&lt;p&gt;Probably blindingly obvious given the above section, but if you use poor variable names, I am probably going to waste a lot of time trying to figure out exactly which thing is which, and worse still, I am probably going to miss subtle bugs.&lt;/p&gt;
&lt;h3&gt;Cover The Right Things&lt;/h3&gt;
&lt;p&gt;Beware of high coverage that does not actually test either all the aspects of a component, or that makes a lot of assumptions. &lt;/p&gt;
&lt;p&gt;Getting 100% coverage is likely to be impossible, and probably your return on investment over 75% is going to be low, but don&amp;#39;t achieve the 75% by testing the trivial and easy to test things only - it&amp;#39;s going to be those tricky to test components that will cause most bugs when refactoring.&lt;/p&gt;
&lt;p&gt;If something is tricky to test, perhaps you have the wrong level of abstraction applied, or perhaps the test is trying to tell you something. Skipping it and going for some simpler tests may pay off in the short term, but in the long term will hurt you.&lt;/p&gt;
&lt;h3&gt;Avoid Fragile Tests&lt;/h3&gt;
&lt;p&gt;There is a lot of debate between the &amp;quot;classicist and mockist schools&amp;quot; about what to test, and personally I veer towards state based testing for most components - but regardless of where your personal impulses lie, avoid creating fragile tests. Any test that is likely to break with trivial refactoring could be considered fragile, and those tests are going to cost you a lot of time and cause many potential bugs when refactoring.&lt;/p&gt;
&lt;p&gt;One of the main causes of fragile tests are an overreliance on mocks, and specifically using mocks over stubs. &amp;nbsp;By all means mock where necessary, but try to limit mock usage to very specific test cases, and try to favour stubs over mocks and favour &amp;quot;Setup.ResultFor&amp;quot; over &amp;quot;Expect.Call&amp;quot; type semantics.&lt;/p&gt;
&lt;h3&gt;Avoid [Setup] and [Teardown]&lt;/h3&gt;
&lt;p&gt;Yes, I know they make it easier to create lots of similar tests, but they make your tests fragile and interdependent.&lt;/p&gt;
&lt;p&gt;James Newkirk (who was on the original NUnit team) made a &lt;a href="http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html"&gt;good blog post on this&lt;/a&gt; when he moved to writing xUnit, where Setup and Teardown were removed. &lt;/p&gt;
&lt;p&gt;They make it hard to read your tests (you have to read code in two or three locations to understand what the test does) and can cause Setup/Teardown getting too many responsibilities, leading to fragility or code bloat.&lt;/p&gt;
&lt;p&gt;Either switch to setup within the individual test, or favour a Context based testing approach such as with BDD&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Tests are code, and code has to be maintained too. Make sure your tests are of a similar or higher standard than the rest of your codebase, make sure they test the right things, in the right way, and you will make your life much easier, and that of the guy who comes after you much easier too&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=51578" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/TDD/default.aspx">TDD</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Mocking/default.aspx">Mocking</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Unit+Tests/default.aspx">Unit Tests</category><category domain="http://devlicio.us/blogs/casey/archive/tags/Testing/default.aspx">Testing</category></item><item><title>The Largest Wicked Problem in Software is Politics and Management</title><link>http://devlicio.us/blogs/casey/archive/2009/08/25/the-largest-wicked-problem-in-software-is-politics-and-management.aspx</link><pubDate>Tue, 25 Aug 2009 11:40:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:50714</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=50714</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=50714</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/08/25/the-largest-wicked-problem-in-software-is-politics-and-management.aspx#comments</comments><description>&lt;p&gt;I previously wrote a post stating that &lt;a href="http://devlicio.us/blogs/casey/archive/2009/08/04/software-is-a-wicked-problem.aspx"&gt;Software is a Wicked Problem&lt;/a&gt;, and indeed it is.&lt;/p&gt;
&lt;p&gt;There is a bigger Wicked Problem that affects software projects though, that of Politics and Management.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;While there are at least technical solutions to most software problems, and even wicked problems can be cracked eventually, it is a much harder and more time consuming issue to deal with political and managerial problems, and they largely turn out to be wicked problems in of themselves.&lt;/p&gt;
&lt;p&gt;And, as with all wicked problems, it is faster to fix the problem than it is to estimate how long it will take to fix - it also happens that with politics and managerial issues, it is often nearly impossible to estimate, or to actually fix the problems, so software developers spend most of their time trying to work around these problems rather than addressing them.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Wicked_problem"&gt;http://en.wikipedia.org/wiki/Wicked_problem&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.poppendieck.com/wicked.htm"&gt;http://www.poppendieck.com/wicked.htm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=50714" 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/wicked+problem/default.aspx">wicked problem</category></item><item><title>Software is a Wicked Problem</title><link>http://devlicio.us/blogs/casey/archive/2009/08/04/software-is-a-wicked-problem.aspx</link><pubDate>Tue, 04 Aug 2009 13:06:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:49828</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=49828</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=49828</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/08/04/software-is-a-wicked-problem.aspx#comments</comments><description>&lt;p&gt;A Wicked Problem, roughly speaking, has a number of properties:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The problem is not understood until after the 
formulation of a solution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Wicked problems have no stopping 
rule.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Solutions to wicked problems are not right or 
wrong.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Every wicked problem is essentially novel and 
unique.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Every solution to a wicked problem is a &amp;#39;one 
shot operation&amp;#39;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Wicked problems have no given alternative 
solutions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Software development is largely a Wicked Problem,&lt;strong&gt; &lt;/strong&gt;or in headline 
terms:&lt;/p&gt;
&lt;h3&gt;It is faster to create a solution to the problem than to estimate how 
long it will take to create that solution with any degree of accuracy, and the 
estimate will still be wrong.&lt;/h3&gt;
&lt;p&gt;
&lt;a href="http://en.wikipedia.org/wiki/Wicked_problem"&gt;http://en.wikipedia.org/wiki/Wicked_problem&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.poppendieck.com/wicked.htm"&gt;http://www.poppendieck.com/wicked.htm&lt;/a&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=49828" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/casey/archive/tags/Rants/default.aspx">Rants</category></item><item><title>We Are Not Doing DDD – Part Two - CQS</title><link>http://devlicio.us/blogs/casey/archive/2009/06/22/we-are-not-doing-ddd-part-two-cqs.aspx</link><pubDate>Mon, 22 Jun 2009 16:32:58 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:48438</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=48438</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=48438</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/06/22/we-are-not-doing-ddd-part-two-cqs.aspx#comments</comments><description>&lt;p&gt;From the beginning of my current project we have been working under some horrible constraints, many imposed by legacy systems, many by late decisions that would have speeded things immensely if made earlier, and many imposed by decisions that are outside of my control.&lt;/p&gt;  &lt;p&gt;This lead us early on to make decisions on architecture that eliminated any possibility of using DDD heavily, and as I mentioned in my original post about this project it is also essentially a glorified CRUD system - we read data from databases, we modify it a bit, and we put it back again.&lt;/p&gt;  &lt;h3&gt;What We Are Doing – Command Query Separation&lt;/h3&gt;  &lt;p&gt;The first architectural choice that I made, and in hindsight got accepted with relative ease, was to employ &lt;a href="http://dddstepbystep.com/wikis/ddd/blogged-command-query-separation-as-an-architectural-concept.aspx" target="_blank"&gt;CQS&lt;/a&gt; to simplify the system.&lt;/p&gt;  &lt;p&gt;Earlier projects had suffered quite badly from being abstractions of legacy systems with new functionality bolted on. As &lt;/p&gt;  &lt;p&gt;far as possible I wanted to eliminate this problem from our project, as I was all too aware that this was an easy trap for the team to fall into, and would burn a lot of development time very fast.&lt;/p&gt;  &lt;p&gt;To make the system simpler I chose to separate our query mechanisms from the &amp;quot;domain&amp;quot; type stuff, our commands and data writing/updating code.&lt;/p&gt;  &lt;p&gt;CQS is a pretty simple concept. One path through your system is responsible for querying of anything much more than &amp;quot;Get By ID&amp;quot; type calls. This side of our system is responsible for reading data from legacy systems, reading data from legacy web services, and for reading data from our application database.&lt;/p&gt;  &lt;h4&gt;Querying&lt;/h4&gt;  &lt;p&gt;The Query side deals largely in DataTables, DataSets and a very very limited number of DTOs. This data is largely and essentially used for display purposes, it is the contents of search results, the results of postcode lookups, the information to populate dropdown lists and tables. &lt;/p&gt;  &lt;p&gt;The Query side of CQS does not need strongly typed entities, nor does it require strongly typed DTOs - as it is largely ad-hoc data maintaining these entities and DTOs would consume a disproportionate amount of development time for something a DataTable can deal with more than adequately.&lt;/p&gt;  &lt;p&gt;Our Query side actually uses the Query Object pattern, most of which encapsulate a call to an Oracle DB, some of which wrap simple NHibernate criteria and a few of which sit around web services. These are fronted by a WCF facade, which allows us to put these queries out of process, and to cache them aggressively should be need.&lt;/p&gt;  &lt;p&gt;What we do not have in the system anywhere, and especially in the Query side, is any big entity model – we have two very small entity models (5 entities in total) used for very specific functions within our application.&lt;/p&gt;  &lt;h4&gt;Command&lt;/h4&gt;  &lt;p&gt;The Command side of the CQS equation is a little different. Firstly, it deals with anything that is essentially a request to &amp;quot;go do something&amp;quot;. In our case these are commands like &amp;quot;SaveDraft&amp;quot; and &amp;quot;CancelPolicy&amp;quot; &lt;/p&gt;  &lt;p&gt;The Command side can write data to the databases, the Query side is not allowed to.&lt;/p&gt;  &lt;p&gt;If we were doing DDD, this is where our Domain would sit - and in fact we have been referring to this as &amp;quot;the domain&amp;quot; for most of this project. But, we aren’t using DDD and we don&amp;#39;t really have a Domain Model. It is however where most stuff we could describe as &amp;quot;logic&amp;quot; lives. This is primarily a bunch of application services, most of which operate in response to messages fired over MSMQ using NServiceBus.&lt;/p&gt;  &lt;p&gt;This side of the architecture has a number of listeners that are responsible for pulling messages from various MSMQs and for dealing with the specific requests, for example pushing data back to our legacy systems, for logging, and eventually for notifications.&lt;/p&gt;  &lt;h4&gt;Benefits&lt;/h4&gt;  &lt;p&gt;Early on, the use of CQS paid for itself easily. By removing the complications of maintaining read and write models together, we quickly managed to get working prototype up and running, with no need for a &amp;quot;domain&amp;quot; or entity model up front.&lt;/p&gt;  &lt;p&gt;As the project has progressed, this decision has helped simplify decisions that otherwise would have involved structural or fundamental changes to the architecture – but more importantly, it has helped all of the developers think in terms of a command driven system, rather than viewing the system as CRUD over a database.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=48438" width="1" height="1"&gt;</description><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/CQS/default.aspx">CQS</category></item><item><title>Commercial Suicide - Integration at the Service Level</title><link>http://devlicio.us/blogs/casey/archive/2009/05/19/commercial-suicide-integration-at-the-service-level.aspx</link><pubDate>Tue, 19 May 2009 07:03:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:46913</guid><dc:creator>Jak Charlton</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/rsscomments.aspx?PostID=46913</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/casey/commentapi.aspx?PostID=46913</wfw:comment><comments>http://devlicio.us/blogs/casey/archive/2009/05/19/commercial-suicide-integration-at-the-service-level.aspx#comments</comments><description>&lt;p&gt;In my previous post I described &lt;a href="http://devlicio.us/blogs/casey/archive/2009/05/14/commercial-suicide-integration-at-the-database-level.aspx"&gt;the problems with trying to integrate your organisation at the database level&lt;/a&gt;, and the fallacies surrounding the idea of the One True Authority Database. I also alluded to this being a problem with services too.&lt;/p&gt;
&lt;p&gt;When you try to create a monolithic and authoritarian database that knows all, sees all, and brings everything into a single coherrent whole, you are heading down a slippery slope. Different applications have different requirements, and even within the same job role, the meaning of Customer can have a totally different meaning in two different contexts. I also argued that data has no value without context, and the context is the application that is meeting the business requirements, be these user interaction, system interaction, or reporting.&lt;/p&gt;
&lt;h3&gt;SOA to the Rescue!&lt;/h3&gt;
&lt;p&gt;I&amp;#39;m not arguing without ample evidence behind me here - the idea of integration at a database level was one that was well discredited many years ago. I grant you many organisations haven&amp;#39;t got the message yet, and that many vested interests still keep trying to make the magic solution work, but fundamentally a long time back we in IT recognised that the One True Authority Database (OTADB)&amp;nbsp;was a &amp;quot;bad thing&amp;quot; - and this lead us to the promised land - initially Web Services and then on to Service Oriented Architectures.&lt;/p&gt;
&lt;p&gt;SOA is an attempt to resolve the OTADB issue - take all those database calls, and even calls to different databases, and unify them through a set of coherrent and cohesive services - SOA can provide us with the abstraction over out data stores that is required - and now we can have the One True Authority Service Layer.&lt;/p&gt;
&lt;p&gt;With SOA we can define services to wrap our databases, services to update data, service to read and query data, and even services to unify those &amp;quot;different&amp;quot; Customers into a&amp;nbsp;single coherrent and canonical data model.&lt;/p&gt;
&lt;p&gt;And that&amp;#39;s where it all goes wrong again.&lt;/p&gt;
&lt;h3&gt;Anti-Pattern: The&amp;nbsp;Canonical Data Model&lt;/h3&gt;
&lt;p&gt;Back when our database guys were trying to integrate all this information, what they were trying to achieve, but maybe didn&amp;#39;t realise, was a canonical data model - this is the &amp;quot;holy grail&amp;quot; of SOA. &lt;a href="http://www.amazon.com/Enterprise-Integration-Patterns-Designing-Addison-Wesley/dp/0321200683/"&gt;Martin Fowler describes&lt;/a&gt; it thus:&lt;/p&gt;
&lt;p style="PADDING-LEFT:30px;"&gt;&lt;span class="Apple-style-span" style="TEXT-ALIGN:left;WIDOWS:2;TEXT-TRANSFORM:none;TEXT-INDENT:0px;BORDER-COLLAPSE:separate;WHITE-SPACE:normal;ORPHANS:2;LETTER-SPACING:normal;COLOR:#000000;WORD-SPACING:0px;-webkit-border-horizontal-spacing:0px;-webkit-border-vertical-spacing:0px;-webkit-text-decorations-in-effect:none;-webkit-text-size-adjust:auto;-webkit-text-stroke-width:0;"&gt;How can you minimize dependencies when integrating applications that use different data formats? &amp;hellip;Design a Canonical Data Model that is independent from any specific application. Require each application to produce and consume messages in this common format&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Sounds perfect! We now have a way of abstracting our systems from each other, and our canonical data model will pull this information all together at the end.&lt;/p&gt;
&lt;p&gt;So, I&amp;#39;m going out on a limb here, disagreeing with Martin Fowler is rarely a smart move.&lt;/p&gt;
&lt;p&gt;Except I&amp;#39;m not disagreeing with Martin Fowler so much as I am disagreeing with those that try to implement his ideas and principles. I don&amp;#39;t recollect anywhere that Martin says that all data can be squeezed into this model, or that this model is the &amp;quot;one true view&amp;quot;. In fact, later evolutions of Martin&amp;#39;s work have included things like Domain Driven Design, which is almost the opposite of a canoncial data model - DDD says that you have a different model for every domain or context, each specifically engineered to solve the problem at hand. Given the choice, I am certainly in the DDD camp here - after all data without context is worthless, and it is the domain (and&amp;nbsp;DDD) that provides the context.&lt;/p&gt;
&lt;p&gt;The key and important part of a canonical data model is it provides a mapping between inconsistent formats and differing views of data.&lt;/p&gt;
&lt;p&gt;So as an ideal, the canonical data model is fine - in practice it is often a major anti-pattern.&lt;/p&gt;
&lt;p&gt;There is still no One True Authority, and SOA really never promised this, nor did the canonical data model - what they promised was enough abstraction to allow applcaitions to work independently, and to fulfill their specific requirements independently. And then to leave it to the service layers to unify this data.&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;So Service Oriented Architectures HAVE Come to the Rescue?&lt;/h3&gt;
&lt;p&gt;Not quite - again my argument here isn&amp;#39;t so much about SOA, or any of the things around it, but more the people who try to implement it, often&amp;nbsp;without understanding what they are trying to achieve, the problems that SOA or a service layer solves,&amp;nbsp; or even the amount of effort that is required to get a canonical data model right.&lt;/p&gt;
&lt;p&gt;The key part here is that a canonical data model is a massive excercise to do right. Essentially it means analysing every applciation, every service and every database within your organisation and extracting their individual requirements and current functionality, and trying to distill that down to a set of common definitions.&lt;/p&gt;
&lt;p&gt;While this may be eventually achievable, in practice it is almost never the case. This &amp;quot;holy grail&amp;quot; of SOA is much like the &amp;quot;holy grail&amp;quot; of integration at the database level, eventually it boils down to &amp;quot;the problem is too complex, too fast moving and too indeterminate to define&amp;quot;. In development we figured out long ago that we needed Agile to help us move quickly as requirements shifted and changed, but the OTADB and the SOA canonical data model do not allow this to happen, they seek to solidify the design early.&lt;/p&gt;
&lt;p&gt;SOA done &amp;quot;right&amp;quot; may well make this problem smaller, but SOA is rarely done right.&lt;/p&gt;
&lt;h3&gt;Can Domain Driven Design Help?&lt;/h3&gt;
&lt;p&gt;DDD was largely an attempt to address these problems - by identifying that individual applications and contexts required different data, DDD allowed us to recognise that square pegs and round holes do not match. Eventually with a big enough hammer you may be able to force it through, but there is going to&amp;nbsp;be a lot of effort and a lot of collaterel damage.&lt;/p&gt;
&lt;p&gt;Domain Driven Design includes terms like &amp;quot;Domain&amp;quot;, &amp;quot;Bounded Context&amp;quot; and&amp;nbsp;&amp;quot;Anti Corruption Layer&amp;quot;&amp;nbsp;specifically to deal with the issues around trying to use a &amp;quot;one solution fits all&amp;quot; hammer to crack what is quite a simple nut. &lt;/p&gt;
&lt;p&gt;DDD is largely unconcerned with what other things Domains talk to, or even how, all that matters is that within a Domain there is one logical view of the world, tailored to the requirements of that specific Domain. Beyond that Domain, there may be a large central database, there may be a perfect canonical data model, but at application level, we have the Domain, Bounded Contexts and Anot Corruption Layers to protect us from all of that.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;DDD gives us a loosely coupled way of thinking.&lt;/p&gt;
&lt;h3&gt;So SOA is Evil and&amp;nbsp;the One True Authority Database is Evil?&lt;/h3&gt;
&lt;p&gt;Well hardly, but unfortunately we live in an imperfect world, and the people implementing these noble ideas are often far from perfect. They do not have mystical powers of future vision, and they do make mistakes.&lt;/p&gt;
&lt;p&gt;By creating properly decoupled systems, and in this I certainly do not mean &amp;quot;systems that use web services&amp;quot;, we can isolate our applications from external change and influence, and ensure we meet the requirements we have today, and can react quickly to future requirements as they appear.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;Big Design Up Front is still BDUF, whether it is done at a database level, a service level, or in a canonical data model.&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=46913" 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></channel></rss>