<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com/blog/</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2012 (c) 2012</copyright><ttl>60</ttl><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/AyendeRahien" /><feedburner:info uri="ayenderahien" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>Limit your abstractions: Application Events&amp;ndash;Proposed Solution #2&amp;ndash;Cohesion</title><description>&lt;p&gt;In my previous post, I spoke about ISP and how we can replace the following code with something that is easier to follow:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Limit-your-abstractions_41F4/image_thumb3_thumb_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image_thumb3_thumb" border="0" alt="image_thumb3_thumb" src="http://ayende.com/blog/Images/Windows-Live-Writer/Limit-your-abstractions_41F4/image_thumb3_thumb_thumb.png" width="907" height="180"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I proposed something like:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IHappenOn&amp;lt;T&amp;gt;
{
   &lt;span class="kwrd"&gt;void&lt;/span&gt; Inspect(T item);
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;Which would be invoked using:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;container.ExecuteAll&amp;lt;IHappenOn&amp;lt;Cargo&amp;gt;&amp;gt;(i=&amp;gt;i.Inspect(cargo));&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;Or something like that. &lt;/p&gt;
&lt;p&gt;Which lead us to the following code:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CargoArrived : IHappenedOn&amp;lt;Cargo&amp;gt;
{
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Inspect(Cargo cargo)
  {
    &lt;span class="kwrd"&gt;if&lt;/span&gt;(cargo.Delivery.UnloadedAtDestination == &lt;span class="kwrd"&gt;false&lt;/span&gt;)
      &lt;span class="kwrd"&gt;return&lt;/span&gt;;
      
    &lt;span class="rem"&gt;// handle event&lt;/span&gt;
  }
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CargoMisdirected : IHappenedOn&amp;lt;Cargo&amp;gt;
{
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Inspect(Cargo cargo)
  {
    &lt;span class="kwrd"&gt;if&lt;/span&gt;(cargo.Delivery.Misdirected == &lt;span class="kwrd"&gt;false&lt;/span&gt;)
      &lt;span class="kwrd"&gt;return&lt;/span&gt;;
      
    &lt;span class="rem"&gt;// handle event&lt;/span&gt;
  }
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CargoHandled : IHappenOn&amp;lt;HandlingEvent&amp;gt;
{
   &lt;span class="rem"&gt;// etc&lt;/span&gt;
}

&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; EventRegistrationAttempt : IHappenedOn&amp;lt;HandlingEventRegistrationAttempt&amp;gt;
{
  &lt;span class="rem"&gt;// etc&lt;/span&gt;
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;But I don’t really like this code, to be perfectly frank. It seems to me like there isn’t really a good reason why CargoArrived and CargoMisdirected are located in different classes. It is likely that there is going to be a lot of commonalities between the different types of handling events on cargo. We might as well merge them together for now, giving us:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; CargoHappened : IHappenedOn&amp;lt;Cargo&amp;gt;
{
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Inspect(Cargo cargo)
  {
    &lt;span class="kwrd"&gt;if&lt;/span&gt;(cargo.Delivery.UnloadedAtDestination)
      CargoArrived(cargo);
      
    
    &lt;span class="kwrd"&gt;if&lt;/span&gt;(cargo.Delivery.Misdirected)
      CargoMisdirected(cargo);
      
  }
  
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CargoArrived(Cargo cargo)
  {
    &lt;span class="rem"&gt;// handle event&lt;/span&gt;
  }
  
  &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CargoMisdirected(Cargo cargo)
  {
    &lt;span class="rem"&gt;//handle event&lt;/span&gt;
  }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;This code put a lot of the cargo handling in one place, making it easier to follow and understand. At the same time, the &lt;em&gt;architecture&lt;/em&gt; gives us the option to split it to different classes at any time. We aren’t going to end up with a God class for Cargo handling. But as long as it make sense, we can keep them together. &lt;/p&gt;
&lt;p&gt;I like this style of event processing, but we can probably do better job at if if we actually used event processing semantics here. I’ll discuss that in my next post.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/vaIUbluiTB4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/vaIUbluiTB4/limit-your-abstractions-application-eventsndash-proposed-solution-2ndash-cohesion</link><guid isPermaLink="false">http://ayende.com/blog/154017/limit-your-abstractions-application-eventsndash-proposed-solution-2ndash-cohesion</guid><pubDate>Thu, 09 Feb 2012 00:41:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/154017/limit-your-abstractions-application-eventsndash-proposed-solution-2ndash-cohesion</feedburner:origLink></item><item><title>Limiting your abstractions: Reflections on the Interface Segregation Principle</title><description>&lt;p&gt;I have found two definitions for ISP (in this post, I assume that you know what ISP is, if you don’t, look at the links below).&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.objectmentor.com/resources/articles/isp.pdf"&gt;This one&lt;/a&gt; I can fully agree with:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Clients should not be forced to depend upon interfaces that they don't use.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;And &lt;a href="http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf"&gt;this one&lt;/a&gt; I strongly disagree with: &lt;blockquote&gt; &lt;p&gt;Many client specific interfaces are better than one general purpose interface&lt;br&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;For fun, both of those links are from Object Mentor.  &lt;p&gt;It would be more accurate to say that I don’t so much disagree with the &lt;em&gt;intent&lt;/em&gt; of the second statement, but that I disagree with the wording. One (literal) way of understanding the second statement is to say that we want specific interfaces over generic ones. And I would strongly disagree. An interface is an abstraction (for the most part), and I want to reduce the amount that I have in my system.  &lt;p&gt;Let us look at an example, based on my recent posts in this series. &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Reflections-on-the-Interface-Segregation_388F/image_thumb%5B3%5D_thumb_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image_thumb[3]_thumb" border="0" alt="image_thumb[3]_thumb" src="http://ayende.com/blog/Images/Windows-Live-Writer/Reflections-on-the-Interface-Segregation_388F/image_thumb%5B3%5D_thumb_thumb.png" width="907" height="180"&gt;&lt;/a&gt; &lt;p&gt;In my previous post, I said that I want to remove both CargoWasHandled and CargoWasMisdirected in favor of IHappenOnCargoInspection. But what about the two other methods?&lt;/p&gt; &lt;p&gt;Would ISP force me to have IHappenOnEventRegistrationAttempt and IHappenOnCargoHandling?&lt;/p&gt; &lt;p&gt;Sure, those are many specific interfaces, but are they really better than something like IHappenOn&amp;lt;T&amp;gt;? Is there something truly meaningful that gets lost when we have the generic interface?&lt;/p&gt; &lt;p&gt;I would say that this isn’t the case, further more, I would actually state that having a single interface will lead to more maintainable code, because there are less abstractions in the code. There is a codebase that is more cohesive and easier to understand.&lt;/p&gt; &lt;p&gt;But I’ll talk more about cohesion on my next post.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/aKBtJv3edAs" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/aKBtJv3edAs/limiting-your-abstractions-reflections-on-the-interface-segregation-principle</link><guid isPermaLink="false">http://ayende.com/blog/153985/limiting-your-abstractions-reflections-on-the-interface-segregation-principle</guid><pubDate>Wed, 08 Feb 2012 07:35:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153985/limiting-your-abstractions-reflections-on-the-interface-segregation-principle</feedburner:origLink></item><item><title>Send me a patch for that</title><description>&lt;p&gt;
	This post is in reply to &lt;a href="http://devlicio.us/blogs/hadi_hariri/archive/2012/02/06/submit-a-patch.aspx"&gt;Hadi&amp;rsquo;s post&lt;/a&gt;. Please go ahead and read it.&lt;/p&gt;
&lt;p&gt;
	Done? Great, so let me try to respond, this time, from the point of view of someone who &lt;em&gt;regularly &lt;/em&gt;asks for patches / pull requests.&lt;/p&gt;
&lt;p&gt;
	Here are &lt;a href="http://groups.google.com/group/ravendb/browse_thread/thread/e41be56d64ab17b1/8329434c8f5dca1f"&gt;a&lt;/a&gt; &lt;a href="http://groups.google.com/group/ravendb/browse_thread/thread/bb70cab7a459e57/a72da650336a6a85?lnk=gst&amp;amp;q=%22pull+request%22#a72da650336a6a85"&gt;few&lt;/a&gt; &lt;a href="http://groups.google.com/group/ravendb/browse_thread/thread/98b2ab69677c7ea/5eeb8b08064c1124?lnk=gst&amp;amp;q=pull+request#5eeb8b08064c1124"&gt;examples&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;
	To make things more interesting, the project that I am talking about now is RavenDB which is both Open Source and commercial. Hadi says:&lt;/p&gt;
&lt;blockquote&gt;
	&lt;p&gt;
		Numerous times I&amp;rsquo;ve seen reactions from OSS developers, contributors or merely a simple passer by, responding to a complaint with: &lt;strong&gt;&lt;em&gt;submit a patch &lt;/em&gt;&lt;/strong&gt;or &lt;strong&gt;&lt;em&gt;well if you can do better, write your own framework. &lt;/em&gt;&lt;/strong&gt;In other words, put up or shut up.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
	Hadi then goes on to explain exactly why this is a high barrier for most users.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
		You need to familiarize yourself with the codebase.&lt;/li&gt;
	&lt;li&gt;
		You need to understand the source control system that is used and how to send a patch / pull request.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
	And I would fully agree with Hadi that those are stumbling blocks. I can&amp;rsquo;t speak for other people, but in our case, that is the &lt;em&gt;intention&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote&gt;
	&lt;p&gt;
		Nitpicker corner here: I am speaking explicitly and only about &lt;em&gt;features &lt;/em&gt;here. Bugs gets fixed by us (unless the user already submitted a fix as well).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
	Put simply, there is an issue of priorities here. We have a certain direction for the project that we want to take it. And in many cases, users want things that are out of scope for us for the foreseeable future. Our options then become:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
		Sorry, ain&amp;rsquo;t going to happen.&lt;/li&gt;
	&lt;li&gt;
		Sure, we will push aside all the work that we intended to do to do your thing.&lt;/li&gt;
	&lt;li&gt;
		No problem, we added that to the queue, expect it in 6 &amp;ndash; 9 months, if we will still consider it important then.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
	None of which is an acceptable answer from our point of view.&lt;/p&gt;
&lt;p&gt;
	Case in point, facets support in RavenDB was something that was requested a few times. We never did it because it was out of scope for our plan, RavenDB is a &lt;em&gt;database&lt;/em&gt; server, not a &lt;em&gt;search&lt;/em&gt; server and we weren&amp;rsquo;t really sure how complex this would be and how to implement this. Basically, this was an expensive feature that wasn&amp;rsquo;t in the major feature set that we wanted. The answer that we gave people is &amp;ldquo;send me a pull request for that&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;
	To be clear, this is basically an opportunity to affect the direction of the project in a way you consider important. What ended up happening is that Matt Warren took up the task and created an initial implementation. Which was then subject to intense refactoring and finally got into the product. You can see the &lt;a href="http://groups.google.com/group/ravendb/browse_thread/thread/76908832b1e2a0ae/f1d0ab9a2422b96d"&gt;entire conversation about this here&lt;/a&gt;. The major difference along the way is that Matt did all the research for this feature, and he had working code. From there the balance change. It was no longer an issue of expensive research and figuring out how to do it. It was an issue of having working code and refactoring it so it matched the rest of the RavenDB codebase. &lt;em&gt;That &lt;/em&gt;wasn&amp;rsquo;t expensive, and we got a new feature in.&lt;/p&gt;
&lt;p&gt;
	Here is another story, a case where &lt;em&gt;I flat out didn&amp;rsquo;t think it was possible&lt;/em&gt;. About two years ago &lt;a href="http://codeofrob.com/"&gt;Rob Ashton&lt;/a&gt; had a feature suggestion (ad hoc queries with RavenDB). Frankly, I thought that this was simply not possible, and after a bit of back and forth, &lt;a href="http://groups.google.com/group/ravendb/browse_thread/thread/792c90f28c2141e2/f0f39e1e24aea0be"&gt;I told Rob&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
	&lt;p&gt;
		Let me rephrase that.&lt;br /&gt;
		Dream up the API from the client side to do this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
	Rob went away for a few hours, and then came back with a &lt;em&gt;working code sample&lt;/em&gt;. I had to pick my jaw off the floor using both hands. &lt;em&gt;That &lt;/em&gt;feature got a lot of priority right away, and is a feature that I routinely brag about when talking about RavenDB.&lt;/p&gt;
&lt;p&gt;
	But let me come back again to the common case, a user request something that isn&amp;rsquo;t in the project plan. Now, remember, &lt;em&gt;requests are cheap&lt;/em&gt;. From the point of view of the user, it doesn&amp;rsquo;t cost anything to request a feature. From the point of view of the project, it can cost a lot. There is research, implementation, debugging, backward compatibility, testing and continuous support associated with just about any feature you care to name.&lt;/p&gt;
&lt;p&gt;
	And our options whenever a user make a request that is out of line for the project plan are:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
		Sorry, ain&amp;rsquo;t going to happen.&lt;/li&gt;
	&lt;li&gt;
		Sure, we will push aside all the work that we intended to do to do your thing.&lt;/li&gt;
	&lt;li&gt;
		No problem, we added that to the queue, expect it in 6 &amp;ndash; 9 months, if we will still consider it important then.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
	&lt;em&gt;Or&lt;/em&gt;, we can also say:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
		We don&amp;rsquo;t have the resources to currently do that, but we would gladly accept a pull request to do so.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
	And that point, the user is faced with a choice. He can either:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
		Oh, well, it isn&amp;rsquo;t important to me.&lt;/li&gt;
	&lt;li&gt;
		Oh, it is important to me so I have better do that.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
	In other words, it shift the prioritization to the user, based on how important that feature is.&lt;/p&gt;
&lt;p&gt;
	We recently got a feature request to support something like this:&lt;/p&gt;
&lt;blockquote&gt;
	&lt;pre class="csharpcode"&gt;
session.Query&amp;lt;User&amp;gt;()
   .Where(x=&amp;gt; searchInput.Name != &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; x.User == searcInput.Name)
   .ToArray();&lt;/pre&gt;
	&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }	&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;
	I&amp;rsquo;ll spare you the details of just how complex it is to implement something like that (especially when it can also be things like: (searchInput.Age &amp;gt; 18). But the simple work around for that is:&lt;/p&gt;
&lt;blockquote&gt;
	&lt;pre class="csharpcode"&gt;
var q = session.Query&amp;lt;User&amp;gt;();
&lt;span class="kwrd"&gt;if&lt;/span&gt;(searchInput.Name != &lt;span class="kwrd"&gt;null&lt;/span&gt;)
  q = q.Where(x=&amp;gt; x.User == searcInput.Name);

q.ToArray();&lt;/pre&gt;
	&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }	&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;
	Supporting the first one is &lt;em&gt;complex&lt;/em&gt;, there is a simple work around that the user can use (and I like the second option from the point of view of readability as well).&lt;/p&gt;
&lt;p&gt;
	That sort of thing get a &amp;ldquo;A pull request for this feature would be appreciated&amp;rdquo;. Because the alternative to that is to slam the door in the user&amp;rsquo;s face.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/VHkc-aSwfTc" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/VHkc-aSwfTc/send-me-a-patch-for-that</link><guid isPermaLink="false">http://ayende.com/blog/154305/send-me-a-patch-for-that</guid><pubDate>Tue, 07 Feb 2012 18:24:26 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/154305/send-me-a-patch-for-that</feedburner:origLink></item><item><title>Limit your abstractions: Application Events&amp;ndash;Proposed Solution #1</title><description>&lt;p&gt;In my previous post, I explained why I really don’t the following. &lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Limit-your-abstractions-Application-Even_3856/image_thumb%5B3%5D_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image_thumb[3]" border="0" alt="image_thumb[3]" src="http://ayende.com/blog/Images/Windows-Live-Writer/Limit-your-abstractions-Application-Even_3856/image_thumb%5B3%5D_thumb.png" width="907" height="180"&gt;&lt;/a&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; CargoInspectionServiceImpl : ICargoInspectionService 
{
  &lt;span class="rem"&gt;// code redacted for simplicity&lt;/span&gt;

 &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; InspectCargo(TrackingId trackingId)
 {
    Validate.NotNull(trackingId, &lt;span class="str"&gt;"Tracking ID is required"&lt;/span&gt;);

    Cargo cargo = cargoRepository.Find(trackingId);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (cargo == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    {
      logger.Warn(&lt;span class="str"&gt;"Can't inspect non-existing cargo "&lt;/span&gt; + trackingId);
      &lt;span class="kwrd"&gt;return&lt;/span&gt;;
    }

    HandlingHistory handlingHistory = handlingEventRepository.LookupHandlingHistoryOfCargo(trackingId);

    cargo.DeriveDeliveryProgress(handlingHistory);

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (cargo.Delivery.Misdirected)
    {
      applicationEvents.CargoWasMisdirected(cargo);
    }

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (cargo.Delivery.UnloadedAtDestination)
    {
      applicationEvents.CargoHasArrived(cargo);
    }

    cargoRepository.Store(cargo);
 }
}&lt;/pre&gt;
&lt;p&gt;Now, let us see one proposed solution for that. We can drop the IApplicationEvents.CargoHasArrived and IApplicationEvents.CargoWasMisdirected, instead creating the following:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;interface&lt;/span&gt; IHappenOnCargoInspection
{
   &lt;span class="kwrd"&gt;void&lt;/span&gt; Inspect(Cargo cargo);
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;We can have multiple implementations of this interface, such as this one:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MidirectedCargo : IHappenOnCargoInspection
{
   &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Inspect(Cargo cargo)
   {
        &lt;span class="kwrd"&gt;if&lt;/span&gt;(cargo.Delivery.Misdirected == &lt;span class="kwrd"&gt;false&lt;/span&gt;)
             &lt;span class="kwrd"&gt;return&lt;/span&gt;;

        &lt;span class="rem"&gt;// code to handle misdirected cargo.&lt;/span&gt;
   }
}&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;In a similar fashion, we would have a CargoArrived implementation, and the ICargoInspectionService would be tasked with managing the implementation of IHappenOnCargoInspection, probably through a container. Although I would probably replace it with something like:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre class="csharpcode"&gt;container.ExecuteOnAll&amp;lt;IHappenOnCargoInspection&amp;gt;(i=&amp;gt;i.Inspect(cargo));&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;All in all, it is a simple method, but it means that now the responsibility to detect and act is centralized in each cargo inspector implementation. If the detection of misdirected cargo is changed, we know that there is just one place to make that change. If we need a new behavior, for example, for late cargo, we can do that by introducing a new class, which implement the interface. That gives us the Open Closed Principle. &lt;/p&gt;
&lt;p&gt;This is better, but I still don’t like it. There are better methods than that, but we will discuss them in another post.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/fYUlKhYyGrI" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/fYUlKhYyGrI/limit-your-abstractions-application-eventsndash-proposed-solution-1</link><guid isPermaLink="false">http://ayende.com/blog/153953/limit-your-abstractions-application-eventsndash-proposed-solution-1</guid><pubDate>Tue, 07 Feb 2012 07:30:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153953/limit-your-abstractions-application-eventsndash-proposed-solution-1</feedburner:origLink></item><item><title>Limit your abstractions: Application Events&amp;ndash;what about change?</title><description>&lt;p&gt;
	In my previous post, I showed an example of application events and asked what is wrong with them.&lt;/p&gt;
&lt;p&gt;
	&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Limit-your-abstractions-Application-Even_3557/image_2.png"&gt;&lt;img alt="image" border="0" height="180" src="http://ayende.com/blog/Images/Windows-Live-Writer/Limit-your-abstractions-Application-Even_3557/image_thumb_3.png" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" width="907" /&gt;&lt;/a&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; CargoInspectionServiceImpl : ICargoInspectionService 
{
  &lt;span class="rem"&gt;// code redacted for simplicity&lt;/span&gt;

 &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; InspectCargo(TrackingId trackingId)
 {
    Validate.NotNull(trackingId, &lt;span class="str"&gt;&amp;quot;Tracking ID is required&amp;quot;&lt;/span&gt;);

    Cargo cargo = cargoRepository.Find(trackingId);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (cargo == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    {
      logger.Warn(&lt;span class="str"&gt;&amp;quot;Can&amp;#39;t inspect non-existing cargo &amp;quot;&lt;/span&gt; + trackingId);
      &lt;span class="kwrd"&gt;return&lt;/span&gt;;
    }

    HandlingHistory handlingHistory = handlingEventRepository.LookupHandlingHistoryOfCargo(trackingId);

    cargo.DeriveDeliveryProgress(handlingHistory);

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (cargo.Delivery.Misdirected)
    {
      applicationEvents.CargoWasMisdirected(cargo);
    }

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (cargo.Delivery.UnloadedAtDestination)
    {
      applicationEvents.CargoHasArrived(cargo);
    }

    cargoRepository.Store(cargo);
 }
}&lt;/pre&gt;
&lt;p&gt;&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &amp;quot;Courier New&amp;quot;, courier, monospace;
	background-color: #ffffff;
	/&lt;em&gt;white-space: pre;&lt;/em&gt;/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;
&lt;p&gt;
	This is very problematic code, from my point of view, for several reasons. Look at how it allocate responsibilities. IApplicationEvents is supposed to execute the actual event, but &lt;em&gt;deciding&lt;/em&gt; when to execute the event is left for the caller. I said several reasons, but this is the main one, all other flows from it.&lt;/p&gt;
&lt;p&gt;
	What happen when the rules for invoking an event change? What happen when we want to add a new event?&lt;/p&gt;
&lt;p&gt;
	The way this is handled is broken. It violates the Open Closed Principle, it violates the Single Responsibility Principle and it frankly annoys me.&lt;/p&gt;
&lt;p&gt;
	Can you think about ways to improve this?&lt;/p&gt;
&lt;p&gt;
	I&amp;rsquo;ll discuss some in my next post.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/SZ9LroWPIJ4" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/SZ9LroWPIJ4/limit-your-abstractions-application-eventsndash-what-about-change</link><guid isPermaLink="false">http://ayende.com/blog/153921/limit-your-abstractions-application-eventsndash-what-about-change</guid><pubDate>Mon, 06 Feb 2012 12:47:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153921/limit-your-abstractions-application-eventsndash-what-about-change</feedburner:origLink></item><item><title>RavenDB workshop in NDC, Oslo 4-5th June</title><description>&lt;p&gt;
	The RavenDB workshop is coming to Oslo, Norway in June!&lt;/p&gt;
&lt;p&gt;
	Join us to an intensive RavenDB hands-on workshop just before the great NDC conference starts.&lt;/p&gt;
&lt;p&gt;
	During the first day of this workshop we will get to know RavenDB and its core concepts, get comfortable with its API, learn how to build and customize indexes, and how to correctly model data for use in a document database.&lt;/p&gt;
&lt;p&gt;
	After getting familiar with all the basics in the first day, during the second day we will build on that knowledge to properly grok Map&amp;frasl;Reduce, Multi&amp;ndash;maps and other advanced usages of indexes, learn how to extend RavenDB and the various options of scaling out.&lt;/p&gt;
&lt;p&gt;
	More details on the workshop and the conference can be found &lt;a href="http://www.ndcoslo.com/Workshop/ravendb"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/8FVedGXIJOY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/8FVedGXIJOY/ravendb-workshop-in-ndc-oslo-4-5th-june</link><guid isPermaLink="false">http://ayende.com/blog/153857/ravendb-workshop-in-ndc-oslo-4-5th-june</guid><pubDate>Sun, 05 Feb 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153857/ravendb-workshop-in-ndc-oslo-4-5th-june</feedburner:origLink></item><item><title>Limit your abstractions: Application Events&amp;ndash;the wrong way</title><description>&lt;p&gt;In my previous post, I have taken a few interfaces from a &lt;a href="http://dddsample.sourceforge.net/index.html"&gt;DDD sample application&lt;/a&gt; and called the application procedural and hard to maintain. In this post, I want to show you exactly why.&lt;/p&gt; &lt;p&gt;We will start with examining this interface, and how it is used:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Limit-your-abstractions-Application-Even_33F1/image_thumb%5B3%5D_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image_thumb[3]" border="0" alt="image_thumb[3]" src="http://ayende.com/blog/Images/Windows-Live-Writer/Limit-your-abstractions-Application-Even_33F1/image_thumb%5B3%5D_thumb.png" width="907" height="180"&gt;&lt;/a&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; CargoInspectionServiceImpl : ICargoInspectionService 
{
  &lt;span class="rem"&gt;// code redacted for simplicity&lt;/span&gt;

 &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; InspectCargo(TrackingId trackingId)
 {
    Validate.NotNull(trackingId, &lt;span class="str"&gt;"Tracking ID is required"&lt;/span&gt;);

    Cargo cargo = cargoRepository.Find(trackingId);
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (cargo == &lt;span class="kwrd"&gt;null&lt;/span&gt;)
    {
      logger.Warn(&lt;span class="str"&gt;"Can't inspect non-existing cargo "&lt;/span&gt; + trackingId);
      &lt;span class="kwrd"&gt;return&lt;/span&gt;;
    }

    HandlingHistory handlingHistory = handlingEventRepository.LookupHandlingHistoryOfCargo(trackingId);

    cargo.DeriveDeliveryProgress(handlingHistory);

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (cargo.Delivery.Misdirected)
    {
      applicationEvents.CargoWasMisdirected(cargo);
    }

    &lt;span class="kwrd"&gt;if&lt;/span&gt; (cargo.Delivery.UnloadedAtDestination)
    {
      applicationEvents.CargoHasArrived(cargo);
    }

    cargoRepository.Store(cargo);
 }
}&lt;/pre&gt;
&lt;p&gt;Can you see what I find painful in this code?&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/EMS7JIJtEf0" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/EMS7JIJtEf0/limit-your-abstractions-application-eventsndash-the-wrong-way</link><guid isPermaLink="false">http://ayende.com/blog/153890/limit-your-abstractions-application-eventsndash-the-wrong-way</guid><pubDate>Fri, 03 Feb 2012 07:45:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153890/limit-your-abstractions-application-eventsndash-the-wrong-way</feedburner:origLink></item><item><title>Limit your abstractions: Analyzing a DDD application</title><description>&lt;p&gt;Abstractions have a cost. You should limit them. That seems like an obvious statement, but in a &lt;a href="https://plus.google.com/117570489094161918692/posts/KdwJdSm4jXm"&gt;recent discussion&lt;/a&gt; I had, I realized that I didn’t articulate things in quite the proper way before. &lt;/p&gt; &lt;p&gt;Let me see if I can explain better now. One of the problems in typical applications is that we don’t really think before we introduce abstractions. For the purpose of this discussion, an abstraction in an interface. Let us take a look at a sample DDD application.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Nitpicker corner: No, I am not saying avoid using interfaces.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;I took all the interesting interfaces out of the application, you can see them here:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Limit-your-abstractions_2687/image_4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Limit-your-abstractions_2687/image_thumb_1.png" width="1075" height="509"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Take a look at those interfaces. They bother me. They bother me because each of them represent an abstraction that is specific for a particular problem. In other words, it represent an non-abstracted abstraction, if that make any sense.&lt;/p&gt; &lt;p&gt;As I said, this is taken a &lt;a href="http://dddsample.sourceforge.net/index.html"&gt;DDD sample application&lt;/a&gt;. It isn’t a big one (and no, I didn’t review the actual code to see if it is a good one), but the interfaces that it has reveal a common problem, namely, interface explosion, or over abstraction. I removed any infrastructure / persistence stuff that was in the app, so you are looking just at the business interfaces, mind.&lt;/p&gt; &lt;p&gt;The problem is that the way this application is structured, it is highly procedural and had to maintain.&lt;/p&gt; &lt;p&gt;Huh?! I can hear you say, procedural? This is a DDD app, just look at the names, we have services and facades and events and… those are all &lt;em&gt;good things&lt;/em&gt;. This design is pretty much text book. How can you say that this design is hard to maintain?&lt;/p&gt; &lt;p&gt;I’ll answer this question (and propose answers) in this series of posts. In the meantime, feel free to look at the code (it is Java, in its origin, and I simply modified it to C# for easier working) and make your own conclusions. &lt;/p&gt; &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/-ZBB9zUnjvo" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/-ZBB9zUnjvo/limit-your-abstractions-analyzing-a-ddd-application</link><guid isPermaLink="false">http://ayende.com/blog/153889/limit-your-abstractions-analyzing-a-ddd-application</guid><pubDate>Thu, 02 Feb 2012 07:43:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153889/limit-your-abstractions-analyzing-a-ddd-application</feedburner:origLink></item><item><title>Embracing RavenDB</title><description>&lt;p&gt;
	&lt;img align="right" alt="RavenDBliconBurgandy" src="http://ayende.com/blog/Images/Windows-Live-Writer/RavenDB--NHibernate-Training_DCA7/RavenDBliconBurgandy_6.png" style="display: inline; float: right" /&gt;In fact, for over 30 years or so, the Database Wars have been settled, the relational databases have won the fight, and the decision left was &lt;i&gt;which&lt;/i&gt; relational database to use. Everyone &amp;ldquo;knows&amp;rdquo; that NoSQL is something that Google invented to handle the amount of data and users they have, and that is it somehow related to scaling to Google or Facebook levels.&lt;/p&gt;
&lt;p&gt;
	And since most of us aren&amp;rsquo;t working on applications that have millions of users, we get to keep using the tried and true methods, no need to bother with something that is only relevant at extreme high scale. The relational database has served us well, and can continue serving us in the future. Learning SQL &lt;i&gt;was&lt;/i&gt; a very smart investment, after all.&lt;/p&gt;
&lt;p&gt;
	Let us go back a bit to those Database Wars that I mentioned. In the 70s there were actually quite a lot of different types of databases competing with each other, anything from ISAM to DBase to relational databases. And as you can see, the relational database has won such a decisive victory that it rules undisputed for over a generation.&lt;/p&gt;
&lt;p&gt;
	But one thing that we have to remember is that those Database Wars were fought on a drastically different ground than the one we have today.&lt;/p&gt;
&lt;h4&gt;
	1980 vs. 2012&lt;/h4&gt;
&lt;p&gt;
	In 1980, a 10 MB hard disk (that is in &lt;i&gt;mega&lt;/i&gt;bytes, about 2 songs or 3 pictures) cost around 4,000 $ US. Adjusting for inflation, that comes at about 11,000 $ US in today&amp;rsquo;s dollars. Just to compare, today a 10 MB of disk space would cost you about half a &lt;strike&gt;dollar&lt;/strike&gt; cent. And those aren&amp;rsquo;t the only changes, of course. Computation speed, memory sizes and networks are all many orders of magnitude faster and cheaper than they were in the 80s.&lt;/p&gt;
&lt;p&gt;
	Even more interesting is the differences in the type of applications being built. In the 80s, a typical application had exactly one user. Multi users&amp;rsquo; applications had to support&amp;hellip; 3 users. All of them at the same time! The UI paradigms were drastically different, as well. At the time, the master &amp;ndash; details form was the top of the hill, the uncontested king of good UI design. But today&amp;hellip; there are usually so many items and active elements on a single web page today as there were in entire applications then.&lt;/p&gt;
&lt;p&gt;
	Why the history lesson, you ask? Why, to give you some perspective on the design choices that led to the victory of the relational databases. Space was at a premium, the interaction between the user and the application closely modeled the physical layout of the data in the database. That made &lt;i&gt;sense&lt;/i&gt;, because there really were no other alternatives given the environment that existed at the time.&lt;/p&gt;
&lt;p&gt;
	That environment is no longer here, and the tradeoffs made when 30 MB would cost as much as an annual salary are no longer relevant. In particular, one immensely annoying aspect of relational database is very much a problem today. Relational databases trade off read speed in favor of write speed. Because it made perfect sense to make this trade off when disk space was so costly, and making users wait an extra second was no big deal.&lt;/p&gt;
&lt;p&gt;
	In separate studies conducted by both Google and Amazon, they found that even additional 100ms added to the latency of a page severely impacted their bottom line. And yet relational database tradeoff read speed (having to do joins and extra loads) for write speed (having to write small amount of data).&lt;/p&gt;
&lt;p&gt;
	Another problem that pops up frequently with relational database is their inability to handle complex data types, such as collections or nested objects. Oh, you can certainly map that to a relational database, but that requires additional tables, and each additional table is going to make it that much more complex to query the data, work with it and display it to the user.&lt;/p&gt;
&lt;p&gt;
	For many years, I have been working with customers on optimizing their applications using relational databases, and I&amp;rsquo;ve seen the same problems occur over and over again. That led me to the belief that the NoSQL databases aren&amp;rsquo;t suitable just for extremely scalable scenarios. NoSQL databases make sense for a wide range of options, and this realization led me to RavenDB.&lt;/p&gt;
&lt;p&gt;
	In my company, we are using RavenDB as the backend database for everything from a blog, our ordering and purchasing systems, the daily build server and many more.&lt;/p&gt;
&lt;p&gt;
	The major advantages that we found weren&amp;rsquo;t the ability to scale (although that exists), it is the freedom that it gives us in terms of modeling our data and changing our minds.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/7g5gAqz28ys" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/7g5gAqz28ys/embracing-ravendb</link><guid isPermaLink="false">http://ayende.com/blog/153026/embracing-ravendb</guid><pubDate>Wed, 01 Feb 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153026/embracing-ravendb</feedburner:origLink></item><item><title>Ask Ayende: What about the QA env?</title><description>&lt;p&gt;&lt;a&gt;Matthew Bonig&lt;/a&gt; asks, with regards to &lt;a href="http://ayende.com/blog/152738/bug-hunt-what-made-this-blog-slow"&gt;a bug&lt;/a&gt; in RavenDB MVC Integration (RavenDB Profiler) that caused major slow down on this blog.: &lt;blockquote&gt; &lt;p&gt;I'd be very curious to know how this code got published to a production environment without getting caught. I would have thought this problem would have occurred in any testing environment as well as it did here. Ayende, can you comment on where the process broke down and how such an obvious bug was able to slip through?&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Well, the answer for that comes in two parts. The first part&amp;nbsp; is that no process broke down. We use our own assets for final testing of all our software, that means that whenever there is a stable RavenDB release pending (and sometimes just when we feel like it) we move our infrastructure to the latest and greatest. &lt;p&gt;&lt;em&gt;Why? &lt;/em&gt; &lt;p&gt;Because as hard as you try testing, you will never be able to catch everything. Production is the final test ground, and we have obvious incentives of trying to make sure that everything works.&amp;nbsp; It is dogfooding, basically. Except that if we get a lemon, that is a very public one. &lt;p&gt;It means that whenever we make a stable release, we can do that with high degree of confidence that everything is going to work, not just because all the tests are passing, but because our production systems had days to actually see if things are right. &lt;p&gt;The second part of this answer is that this is neither an obvious bug nor one that is easy to catch. Put simply, things &lt;em&gt;worked&lt;/em&gt;. There wasn’t even an infinite loop that would make it obvious that something is wrong, it is just that there was a lot of network traffic that you would notice only if you either had a tracer running, or were trying to figure out why the browser was suddenly so busy. &lt;p&gt;Here is a challenge, try to devise some form of an automated test that would catch something like this error, but do so without actually testing for &lt;em&gt;this specific issue&lt;/em&gt;. After all, it is unlikely that someone would have written a test for this unless they run into the error in the first place. So I would be really interested in seeing what sort of automated approaches would have caught that.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/9ZrTQ8wqZZA" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/9ZrTQ8wqZZA/ask-ayende-what-about-the-qa-env</link><guid isPermaLink="false">http://ayende.com/blog/153825/ask-ayende-what-about-the-qa-env</guid><pubDate>Tue, 31 Jan 2012 07:33:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153825/ask-ayende-what-about-the-qa-env</feedburner:origLink></item><item><title>Bug Hunt: What made this blog slow?</title><description>&lt;p&gt;A while ago the blog start taking 100% CPU on the client machines. Obviously we were doing something very wrong there, but what exactly was it?&lt;/p&gt; &lt;p&gt;We tracked down the problem to the following code:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Bug-Hunt-What-made-this-blog-slow_FB72/image_thumb_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image_thumb" border="0" alt="image_thumb" src="http://ayende.com/blog/Images/Windows-Live-Writer/Bug-Hunt-What-made-this-blog-slow_FB72/image_thumb_thumb.png" width="587" height="224"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Bug-Hunt-What-made-this-blog-slow_FB72/image_thumb%5B1%5D_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image_thumb[1]" border="0" alt="image_thumb[1]" src="http://ayende.com/blog/Images/Windows-Live-Writer/Bug-Hunt-What-made-this-blog-slow_FB72/image_thumb%5B1%5D_thumb.png" width="392" height="113"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;As you can probably guess, the problem is that we have what is effective an infinite loop. On any Ajax request, we will generate a new Ajax request. And that applies to &lt;em&gt;our own requests as well&lt;/em&gt;.&lt;/p&gt; &lt;p&gt;The fix was pretty obvious when we figured out what was going on, but until then…&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Bug-Hunt-What-made-this-blog-slow_FB72/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Bug-Hunt-What-made-this-blog-slow_FB72/image_thumb_3.png" width="538" height="142"&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/r1r1wix5boQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/r1r1wix5boQ/bug-hunt-what-made-this-blog-slow</link><guid isPermaLink="false">http://ayende.com/blog/152738/bug-hunt-what-made-this-blog-slow</guid><pubDate>Mon, 30 Jan 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/152738/bug-hunt-what-made-this-blog-slow</feedburner:origLink></item><item><title>Bug Hunt: What made this blog slow?</title><description>&lt;p&gt;A while ago the blog start taking 100% CPU on the client machines. Obviously we were doing something very wrong there, but what exactly was it?&lt;/p&gt; &lt;p&gt;We track down the problem to the following code, can you figure out what the problem?&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Bug-Hunt-What-made-this-blog-slow_FB38/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Bug-Hunt-What-made-this-blog-slow_FB38/image_thumb.png" width="587" height="224"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Bug-Hunt-What-made-this-blog-slow_FB38/image_4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Bug-Hunt-What-made-this-blog-slow_FB38/image_thumb_1.png" width="392" height="113"&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/WTgxRBf_nh8" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/WTgxRBf_nh8/bug-hunt-what-made-this-blog-slow</link><guid isPermaLink="false">http://ayende.com/blog/152737/bug-hunt-what-made-this-blog-slow</guid><pubDate>Fri, 27 Jan 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/152737/bug-hunt-what-made-this-blog-slow</feedburner:origLink></item><item><title>Northwind Starter Kit Review: Conclusion</title><description>&lt;p&gt;This is a review of the &lt;a href="http://nsk.codeplex.com/"&gt;Northwind Starter Kit project&lt;/a&gt;, this review revision &lt;a href="http://nsk.codeplex.com/SourceControl/changeset/changes/94815"&gt;94815&lt;/a&gt; from Dec 18 2011.  &lt;p&gt;A while ago I said:  &lt;blockquote&gt; &lt;p&gt;Seriously?!&amp;nbsp; 22(!) projects to do a sample application using Northwind?&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;And people took me up to task about it. The criticism was mostly focused on two parts:  &lt;ul&gt; &lt;li&gt;I didn’t get that the project wasn’t about Northwind, but about being a sample app for architectural design patterns.  &lt;li&gt;I couldn’t actually decide that a project was bad simply by looking at the project structure and some minor code browsing.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;I am sad to say that after taking a detailed look at the code, I am even more firmly back at my original conclusion.&amp;nbsp; I started to do a review of the UI code, but there really is no real need to do so.&lt;/p&gt; &lt;p&gt;The entire project, as I said in the beginning, is supposed to be a sample application for Northwind. Northwind is a CRUD application. Well, not exactly, it is supposed to be an example of an Online Store, which is something much bigger than just Northwind. But it isn’t. &lt;/p&gt; &lt;p&gt;Say what you will, the Northwind Starter Kit is a CRUD application. It does exactly that, and nothing else. It does so in an incredibly complicated fashion, mind, but that is what it does.&lt;/p&gt; &lt;p&gt;Well, it doesn’t do updates, or deletes, or creates. So it is just an R application (I certainly consider the codebase to be R rated, not for impressionable developers).&lt;/p&gt; &lt;p&gt;If you want to have a sample application to show off architectural ideas, make sure that the application can actually, you know, show them. The only thing that NSK does is loading stuff from the database, try as I might, I found no real piece of business logic, no any reason why it is so complicated.&lt;/p&gt; &lt;p&gt;So, to the guys who commented on that, it isn’t a good project. If you like it, I am happy for you, there are also people who loves &lt;a href="http://ugliestdogs.net/ugliestdogwinners.html"&gt;this guy&lt;/a&gt;:&lt;/p&gt; &lt;p&gt;&lt;img src="http://ugliestdogs.net/sitebuilder/images/Picture_144_1_-387x251.jpg"&gt;&lt;/p&gt; &lt;p&gt;Personally, I would call pest control.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/hAxud30AzzY" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/hAxud30AzzY/northwind-starter-kit-review-conclusion</link><guid isPermaLink="false">http://ayende.com/blog/153062/northwind-starter-kit-review-conclusion</guid><pubDate>Thu, 26 Jan 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153062/northwind-starter-kit-review-conclusion</feedburner:origLink></item><item><title>Ask Ayende: Handling filtering</title><description>&lt;p&gt;With regards to my quests against repositories, Matt &lt;a href="http://ayende.com/blog/153058/northwind-starter-kit-review-data-access-review-thoughts?key=852c1fa5de554460b9a8b4fbc2e2843a#comment4"&gt;asks&lt;/a&gt;: &lt;blockquote&gt; &lt;p&gt;…if my aggregate root query should exclude entities that have, for example, and IsActive = false flag, I also don't want to repeatedly exclude the IsActive = false entities. Using the repository pattern I can expose my Get method where internally it ALWAYS does this.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The problem with this question is that it make a false assumption, then go ahead and follow on that false assumption. The false assumption here is that the only way to handle the IsActive = false in by directly querying that. But that is wrong.&lt;/p&gt; &lt;p&gt;With NHibernate, you can define that with a where condition, or as a filter. With RavenDB, you can define that inside a query listener. You can absolutely set those things up as part of your infrastructure, and you won’t need to create any abstractions for that.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/bMvKdLsTT64" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/bMvKdLsTT64/ask-ayende-handling-filtering</link><guid isPermaLink="false">http://ayende.com/blog/153702/ask-ayende-handling-filtering</guid><pubDate>Wed, 25 Jan 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153702/ask-ayende-handling-filtering</feedburner:origLink></item><item><title>Northwind Starter Kit Review: That CQRS thing</title><description>&lt;p&gt;This is a review of the &lt;a href="http://nsk.codeplex.com/"&gt;Northwind Starter Kit project&lt;/a&gt;, this review revision &lt;a href="http://nsk.codeplex.com/SourceControl/changeset/changes/94815"&gt;94815&lt;/a&gt; from Dec 18 2011. &lt;p&gt;It is obvious from reading the code that there was some attention given to CQRS. Unfortunately, I can’t really figure out what for. &lt;p&gt;To start with, both the Read Model and the Domain Model are actually sitting &lt;em&gt;on the same physical location&lt;/em&gt;. If you are doing that, there is a 95% chance that you don’t need CQRS. If you have that, you are going to waste a lot of time and effort and are &lt;em&gt;very&lt;/em&gt; unlikely to get anything from it.  &lt;p&gt;In the case of NSK, here is the domain model vs. the read model for the customer. &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit_11A1/image_2.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit_11A1/image_thumb.png" width="357" height="448"&gt;&lt;/a&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit_11A1/image_4.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit_11A1/image_thumb_1.png" width="382" height="279"&gt;&lt;/a&gt;  &lt;p&gt;I marked the difference.&lt;/p&gt; &lt;p&gt;I am sorry, there is nothing that justify a different model here. Just needless complexity.&lt;/p&gt; &lt;p&gt;Remember, our job is to make things &lt;strong&gt;simpler&lt;/strong&gt;, not make it hard to work with the application.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/pb6OFheoa2k" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/pb6OFheoa2k/northwind-starter-kit-review-that-cqrs-thing</link><guid isPermaLink="false">http://ayende.com/blog/153154/northwind-starter-kit-review-that-cqrs-thing</guid><pubDate>Tue, 24 Jan 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153154/northwind-starter-kit-review-that-cqrs-thing</feedburner:origLink></item><item><title>Northwind Starter Kit Review: It is all about the services</title><description>&lt;p&gt;This is a review of the &lt;a href="http://nsk.codeplex.com/"&gt;Northwind Starter Kit project&lt;/a&gt;, this review revision &lt;a href="http://nsk.codeplex.com/SourceControl/changeset/changes/94815"&gt;94815&lt;/a&gt; from Dec 18 2011.  &lt;p&gt;Okay, enough about the data access parts. Let us see take a look at a few of the other things that are going on in the application. In particular, this is supposed to be an application with…  &lt;blockquote&gt; &lt;p&gt;Domain logic is implemented by means of a Domain Model, onto a layer of services adds application logic. The model is persisted by a DAL designed around the principles of the "Repository" patterns, which has been implemented in a LINQ-friendly way.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Let us try to figure this out one at a time, okay?  &lt;p&gt;The only method in the domain model that have even a hint of domain logic is the CalculateTotalIncome method. Yes, you got it right, that is &lt;em&gt;a &lt;/em&gt;method, as in singular. And that method should be replaced with a query, it has no business being on the domain model. &lt;p&gt;So let us move to the services, okay? Here are the service definitions in the entire project: &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/0ae6875d1b24_71A7/image_6.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/0ae6875d1b24_71A7/image_thumb_2.png" width="885" height="690"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Look at the methods carefully. Do you see any &lt;em&gt;action&lt;/em&gt; at all? You don’t, the entire thing is just about &lt;em&gt;queries&lt;/em&gt;. &lt;/p&gt; &lt;p&gt;And queries should be &lt;em&gt;simple&lt;/em&gt;, not abstracted away and made very hard to figure out.&lt;/p&gt; &lt;p&gt;The rule of the thumb is that you try hard to not abstract queries, it is operations that you try to abstract. Operations is where you usually actually find the business logic.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/45UuPFlVt4g" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/45UuPFlVt4g/northwind-starter-kit-review-it-is-all-about-the-services</link><guid isPermaLink="false">http://ayende.com/blog/153061/northwind-starter-kit-review-it-is-all-about-the-services</guid><pubDate>Mon, 23 Jan 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153061/northwind-starter-kit-review-it-is-all-about-the-services</feedburner:origLink></item><item><title>Northwind Starter Kit Review: From start to finishing&amp;ndash;tracing a request</title><description>&lt;p&gt;This is a review of the &lt;a href="http://nsk.codeplex.com/"&gt;Northwind Starter Kit project&lt;/a&gt;, this review revision &lt;a href="http://nsk.codeplex.com/SourceControl/changeset/changes/94815"&gt;94815&lt;/a&gt; from Dec 18 2011.&lt;/p&gt; &lt;p&gt;One of the things that I repeatedly call out is the forwarding type of architecture, a simple operation that is hidden away by a large number of abstractions that serves no real purpose. &lt;/p&gt; &lt;p&gt;Instead of a controller, let us look at a web service, just to make things slightly different. We have the following:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-From-start-_72A0/image_8.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-From-start-_72A0/image_thumb_3.png" width="650" height="497"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Okay, let us dig deeper:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-From-start-_72A0/image_12.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-From-start-_72A0/image_thumb_5.png" width="451" height="121"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I &lt;em&gt;really &lt;/em&gt;like the fact that this repository actually &lt;em&gt;have&lt;/em&gt; have FindById method, which this service promptly ignores in favor of using the IQueryable&amp;lt;Customer&amp;gt; implementation. If you want to know how that is implemented, just look (using the EF Code First repository implementations, the others are fairly similar):&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-From-start-_72A0/image_14.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-From-start-_72A0/image_thumb_6.png" width="501" height="376"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;All in all, the entire thing only serves to make things harder to understand and maintain. &lt;/p&gt; &lt;p&gt;Does anyone really think that this abstraction adds anything? What is the &lt;strong&gt;&lt;em&gt;point&lt;/em&gt;&lt;/strong&gt;?!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/H9P3EavZcEk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/H9P3EavZcEk/northwind-starter-kit-review-from-start-to-finishingndash-tracing-a-request</link><guid isPermaLink="false">http://ayende.com/blog/153060/northwind-starter-kit-review-from-start-to-finishingndash-tracing-a-request</guid><pubDate>Fri, 20 Jan 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153060/northwind-starter-kit-review-from-start-to-finishingndash-tracing-a-request</feedburner:origLink></item><item><title>Ask Ayende: Life without repositories, are they worth living?</title><description>&lt;p&gt;With regards to my quests against repositories, Matt &lt;a href="http://ayende.com/blog/153058/northwind-starter-kit-review-data-access-review-thoughts?key=852c1fa5de554460b9a8b4fbc2e2843a#comment4"&gt;asks&lt;/a&gt;:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;For example, you dismiss the repository pattern, but what are the alternatives? For example, in an &lt;a href="http://asp.net/"&gt;ASP.NET&lt;/a&gt; web application you have controllers. I do NOT want to see this code in my controllers:  &lt;p&gt;var sessionFactory = CreateSessionFactory();  &lt;p&gt;using (var session = sessionFactory.OpenSession()) { using (var transaction = session.BeginTransaction()) { // do a large amount of work&lt;pre&gt;&lt;code&gt;// save entities
session.SaveOrUpdate(myEntity);

transaction.Commit();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;} } 
&lt;p&gt;That is ugly, repetitive code. I want in my service methods to Get, update, save, and not have to worry about the above. &lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;This is a straw dummy. Set up the alternative as nasty and unattractive as possible, then call out the thing you have just set up as nasty and unattractive. It is a good tactic, except that this isn’t the alternative at all. &lt;/p&gt;
&lt;p&gt;If you go with the route that Matt suggested, you are going to get yourself into problems. Serious ones. But that isn’t what I recommend. I talked about this scenario specifically in &lt;a href="http://ayende.com/blog/4101/do-you-need-a-framework"&gt;this post&lt;/a&gt;. This is how you are supposed to set things up. In a way that doesn’t get in the way of the application. Everything is wired in the infrastructure, and we can just rely on that to be there. And in your controller, you have a Session property that get the current property, and that is &lt;em&gt;it&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For bonus points, you can move your transaction handling there as well, so you don’t need to handle that either. It makes the code so much easier to work with, because you don’t care about all those external concerns, they are handled elsewhere.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/7zxp_001Ntk" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/7zxp_001Ntk/ask-ayende-life-without-repositories-are-they-worth-living</link><guid isPermaLink="false">http://ayende.com/blog/153701/ask-ayende-life-without-repositories-are-they-worth-living</guid><pubDate>Thu, 19 Jan 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153701/ask-ayende-life-without-repositories-are-they-worth-living</feedburner:origLink></item><item><title>Northwind Starter Kit Review: If you won&amp;rsquo;t respect the database, there will be pain</title><description>&lt;p&gt;This is a review of the &lt;a href="http://nsk.codeplex.com"&gt;Northwind Starter Kit project&lt;/a&gt;, this review revision &lt;a href="http://nsk.codeplex.com/SourceControl/changeset/changes/94815"&gt;94815&lt;/a&gt; from Dec 18 2011.&lt;/p&gt; &lt;p&gt;The database is usually a pretty important piece in your application, and it likes to remind you that it should be respected. If you don’t take care of that, it will make sure that there will be a lot of pain in your future. Case in point, let us look at this method:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-Data-Access_60A8/image_10.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-Data-Access_60A8/image_thumb_4.png" width="559" height="263"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;It looks nice, it is certainly something that looks like a business service. So let us dig down and see how it works.&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-Data-Access_60A8/image_12.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-Data-Access_60A8/image_thumb_5.png" width="847" height="459"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;It seems like a nice thing, the code is clear, and beside the bug where you get 100% discount if you buy enough and the dissonance between the comment and the code, fairly clear. And it seems that we have service logic and entity logic, which is always nice.&lt;/p&gt; &lt;p&gt;Except that this piece of code issues the following queries (let us assume a customer with 50 orders).&lt;/p&gt; &lt;p&gt;1 Query to load the customer, line 34 in this code. And now let us look at line 35… what is actually going on here:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-Data-Access_60A8/image_14.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-Data-Access_60A8/image_thumb_6.png" width="450" height="185"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Okay, so we have an additional query for loading the customer’s orders. Let us dig deeper.&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-Data-Access_60A8/image_16.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-Data-Access_60A8/image_thumb_7.png" width="336" height="138"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;And for each order, we have &lt;em&gt;another &lt;/em&gt;query for loading all of that order’s items. Does it gets worse?&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-Data-Access_60A8/image_8.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="image" border="0" alt="image" src="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review-Data-Access_60A8/image_thumb_3.png" width="507" height="356"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Phew! I was worried here for a second. &lt;/p&gt; &lt;p&gt;But it turns out that we only have a Select N+2 here, where N is the number of orders that a customer has.&lt;/p&gt; &lt;p&gt;What do you want, calculating the discount for the order is &lt;em&gt;complicated&lt;/em&gt;, it is supposed to take a lot of time. Of course, the entire thing can be expressed in SQL as:&lt;/p&gt; &lt;blockquote&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;SELECT&lt;/span&gt; 
  &lt;span class="kwrd"&gt;SUM&lt;/span&gt;((UnitPrice * Quantity) * (1 - Discount) Income
&lt;span class="kwrd"&gt;FROM&lt;/span&gt; OrderItems o
&lt;span class="kwrd"&gt;WHERE&lt;/span&gt; o.OrderID &lt;span class="kwrd"&gt;in&lt;/span&gt; (
  &lt;span class="kwrd"&gt;SELECT&lt;/span&gt; Id &lt;span class="kwrd"&gt;FROM&lt;/span&gt; Orders
  &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; CustomerId = @CustomerId
)&lt;/pre&gt;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;/blockquote&gt;
&lt;p&gt;But go ahead and try putting that optimization in. The architecture for the application will actively fight you on that.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/qHRwSm4vADQ" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/qHRwSm4vADQ/northwind-starter-kit-review-if-you-wonrsquo-t-respect-the-database-there-will-be-pain</link><guid isPermaLink="false">http://ayende.com/blog/153059/northwind-starter-kit-review-if-you-wonrsquo-t-respect-the-database-there-will-be-pain</guid><pubDate>Wed, 18 Jan 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153059/northwind-starter-kit-review-if-you-wonrsquo-t-respect-the-database-there-will-be-pain</feedburner:origLink></item><item><title>Ask Ayende: Repository for abstracting multiple data sources?</title><description>&lt;p&gt;&lt;img style="display: inline; float: right" align="right" src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/8b/%E7%84%A1-still.svg/167px-%E7%84%A1-still.svg.png"&gt;With regards to my recommendation to not use repositories, Remyvd &lt;a href="http://ayende.com/blog/153028/northwind-starter-kit-review-data-access-and-the-essence-of-needless-work-part-i?key=a3c7969445fd4efba2ee8b2b4a3f11c6"&gt;asks&lt;/a&gt;:  &lt;blockquote&gt; &lt;p&gt;… if you have several kind of data sources in different technologies, then it would be nice if you have one kind of interface. Also when an object (like Customer) is combined from data out of different data sources, the repository is for me a good place to initialize the object and return it. How would you solve this cases?&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;My answer is: System.ArgumentException: Question assumes invalid state. &lt;p&gt;More fully, this is one of those times where, in order to actually answer the question, we have to correct the question. Why do I say that? &lt;p&gt;Well, the question makes the assumption that actually combining the customer entity out of different data stores is desirable. Having made that assumption, it proceed to see what is the best way to do that. I am not going to recommend a way to do that, because the underlying assumption is wrong. &lt;p&gt;If your Customer information is stored in multiple data stores, you have to ask yourself, is it actually the same thing in all places? For example, we may have Customer entity in our main database, Customer Billing History in the billing database, Customer credit report accessible over a web service, etc. Note what happens when we start actually drilling down into the entity design. It suddenly becomes clear that that information is in different data stores for a reason. &lt;p&gt;Those aren’t the druids you are looking for might be a good quote here. The fact that the information is split usually means that there is a reason for that. The information is handled differently, usually by different teams and applications, it deals with different aspects of the entity, etc. &lt;p&gt;Trying to abstract that away behind a repository layer loses that very important distinction. It also forces us to do a lot of additional work, because we have to load the customer entity from all of the different data stores every time we need it. Even if most of the data that we need is not relevant for the operation at hand. &lt;p&gt;If would be much easier, simpler and maintainable to actually expose the idea of the multiple data stores to the application at large. You don’t end up with a leaky abstraction and it is easy to see when and how you actually need to combine the different data stores, and what the implications of that are for the specific scenarios that requires it.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/AyendeRahien/~4/19-6FodbMSg" height="1" width="1"/&gt;</description><link>http://feedproxy.google.com/~r/AyendeRahien/~3/19-6FodbMSg/ask-ayende-repository-for-abstracting-multiple-data-sources</link><guid isPermaLink="false">http://ayende.com/blog/153699/ask-ayende-repository-for-abstracting-multiple-data-sources</guid><pubDate>Tue, 17 Jan 2012 10:00:00 GMT</pubDate><feedburner:origLink>http://ayende.com/blog/153699/ask-ayende-repository-for-abstracting-multiple-data-sources</feedburner:origLink></item></channel></rss>

