﻿<?xml version="1.0" encoding="utf-8"?><rss 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><item><title>If you put tripwires in my paths, you won&amp;rsquo;t get my money</title><description>&lt;p&gt;Recently I updated several of my VS plugins, and immediately after that I noticed a changed in the way VS behaves.&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/If-you-put-tripwires-in-my-paths-you-won_CC03/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/If-you-put-tripwires-in-my-paths-you-won_CC03/image_thumb.png" width="660" height="428"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This is actually quite nice, and useful. (Although I was a bit confused for a time about when it shows and when it doesn’t, but that is beside the point).&lt;/p&gt; &lt;p&gt;the problem is that in many cases, like the first two example, it is actually quite easy to press on those notifications. And if you do that, you get:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/If-you-put-tripwires-in-my-paths-you-won_CC03/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/If-you-put-tripwires-in-my-paths-you-won_CC03/image_thumb_1.png" width="469" height="306"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;And that is &lt;em&gt;annoying&lt;/em&gt;. Sure, I get that you want to encourage people to buy your products, I even agree. But this sort of a feature is something that is &lt;em&gt;very &lt;/em&gt;easy to invoke by mistake, and it completely throws you out of your current context. &lt;/p&gt; &lt;p&gt;I have VSCommands installed for the simple reason that I really like the Reload All feature. But it isn’t worth it if I have to be careful where I put my mouse in VS.&lt;/p&gt; &lt;p&gt;This single feature is the reason that I uninstalled it.&lt;/p&gt;</description><link>http://ayende.com/blog/154657/if-you-put-tripwires-in-my-paths-you-wonrsquo-t-get-my-money?key=e0d422db-8bf5-4ca3-a059-41a7be2259d7</link><guid>http://ayende.com/blog/154657/if-you-put-tripwires-in-my-paths-you-wonrsquo-t-get-my-money?key=e0d422db-8bf5-4ca3-a059-41a7be2259d7</guid><pubDate>Mon, 21 May 2012 09:00:00 GMT</pubDate></item><item><title>When using the Task Parallel Library, Wait() is a BAD warning sign</title><description>&lt;p&gt;Take a look at 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;static&lt;/span&gt; Task ParseAsync(IPartialDataAccess source, IPartialDataAccess seed, Stream output, IEnumerable&amp;lt;RdcNeed&amp;gt; needList)
{
    &lt;span class="kwrd"&gt;return&lt;/span&gt; Task.Factory.StartNew(() =&amp;gt;
    {
        &lt;span class="kwrd"&gt;foreach&lt;/span&gt; (var item &lt;span class="kwrd"&gt;in&lt;/span&gt; needList)
        {
            &lt;span class="kwrd"&gt;switch&lt;/span&gt; (item.BlockType)
            {
                &lt;span class="kwrd"&gt;case&lt;/span&gt; RdcNeedType.Source:
                    source.CopyToAsync(output, Convert.ToInt64(item.FileOffset), Convert.ToInt64(item.BlockLength)).Wait();
                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;
                &lt;span class="kwrd"&gt;case&lt;/span&gt; RdcNeedType.Seed:
                    seed.CopyToAsync(output, Convert.ToInt64(item.FileOffset), Convert.ToInt64(item.BlockLength)).Wait();
                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;
                &lt;span class="kwrd"&gt;default&lt;/span&gt;:
                    &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotSupportedException();
            }
        }
    });
}&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;Do you see the problem in here?&lt;/p&gt;
&lt;p&gt;It is a result of a code review comment about improper use of async in a project. This resulted in a lot of Task showing up in the return methods, but not in any measurable improvement in the actual codebase use of asynchronicity.&lt;/p&gt;
&lt;p&gt;The problem is that when you need to work with such things in C# 4.0, you have to do some annoying things to get the code to work properly. In particular, this method was modified to be:&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;static&lt;/span&gt; Task ParseAsync(IPartialDataAccess source, IPartialDataAccess seed, Stream output, IList&amp;lt;RdcNeed&amp;gt; needList, &lt;span class="kwrd"&gt;int&lt;/span&gt; position = 0)
{
  &lt;span class="kwrd"&gt;if&lt;/span&gt;(position&amp;gt;= needList.Count)
  {
        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; CompletedTask();
  }
  var item = needList[position];
  Task task;
            
  &lt;span class="kwrd"&gt;switch&lt;/span&gt; (item.BlockType)
  {
        &lt;span class="kwrd"&gt;case&lt;/span&gt; RdcNeedType.Source:
            task = source.CopyToAsync(output, Convert.ToInt64(item.FileOffset), Convert.ToInt64(item.BlockLength));
            &lt;span class="kwrd"&gt;break&lt;/span&gt;;
        &lt;span class="kwrd"&gt;case&lt;/span&gt; RdcNeedType.Seed:
            task = seed.CopyToAsync(output, Convert.ToInt64(item.FileOffset), Convert.ToInt64(item.BlockLength));
            &lt;span class="kwrd"&gt;break&lt;/span&gt;;
        &lt;span class="kwrd"&gt;default&lt;/span&gt;:
            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; NotSupportedException();
  }

  &lt;span class="kwrd"&gt;return&lt;/span&gt; task.ContinueWith(resultTask =&amp;gt;
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (resultTask.Status == TaskStatus.Faulted)
            resultTask.Wait(); &lt;span class="rem"&gt;// throws&lt;/span&gt;
        &lt;span class="kwrd"&gt;return&lt;/span&gt; ParseAsync(source, seed, output, needList, position + 1);
    }).Unwrap();
}&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 is more complex, but it is actually making proper use of the TPL. We have changed the loop into a recursive function, so we can take advantage of ContinueWith to the next iteration of the loop.&lt;/p&gt;
&lt;p&gt;And no, I can’t &lt;em&gt;wait&lt;/em&gt; to get to C# 5.0 and have proper await work.&lt;/p&gt;</description><link>http://ayende.com/blog/155585/when-using-the-task-parallel-library-wait-is-a-bad-warning-sign?key=08f9a2f5-c34a-4961-8c19-e5782bcc39a1</link><guid>http://ayende.com/blog/155585/when-using-the-task-parallel-library-wait-is-a-bad-warning-sign?key=08f9a2f5-c34a-4961-8c19-e5782bcc39a1</guid><pubDate>Thu, 17 May 2012 09:00:00 GMT</pubDate></item><item><title>Non overlapping time periods&amp;ndash;because I like the pain of 2 AM wakeup calls</title><description>&lt;p&gt;
	This post is partly in response for &lt;a href="http://codebetter.com/johnvpetersen/2012/03/13/229-the-case-of-the-missing-data-point-and-the-curious-thing-a-leap-year-is/"&gt;this post&lt;/a&gt;, discussing the Azure problem with leap year. But it is actually a bit more general than that.&lt;/p&gt;
&lt;p&gt;
	In my code, here is how I define &amp;ldquo;one year from now&amp;rdquo;:&lt;/p&gt;
&lt;blockquote&gt;
	&lt;p&gt;
		DateTime.Today.AddYears(1).AddDays(3);&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;
	As it turned out, this tend to have a lot of implications on your business, most of them are actually pretty good ones.&lt;/p&gt;
&lt;p&gt;
	For a start, you will never get hit with a leap year bug, but more importantly, you are never going to have to deal with an immediate cutoff. This is important because it gives you time. Mostly, it gives you time to screw up, but having the time to do so without having an egg all of your face is a really nice thing.&lt;/p&gt;
&lt;p&gt;
	For example, all of our subscriptions are using a similar method of calculation, and this is why we can take the ordering system down for a few hours or even a day or two and no one will actually notice. We have a big grace period in which we can work things out.&lt;/p&gt;
&lt;p&gt;
	Sure, a user gets 3 &amp;ldquo;extra&amp;rdquo; days for free out of this, but frankly, I don&amp;rsquo;t give a damn. It is more important that I get the buffer, and most users like it much better when you don&amp;rsquo;t slam the doors in their faces on the first chance.&lt;/p&gt;
&lt;p&gt;
	One of the things that is important is &lt;em&gt;style&lt;/em&gt;, and giving a grace period for those sort of things is crucial.&lt;/p&gt;
</description><link>http://ayende.com/blog/155521/non-overlapping-time-periodsndash-because-i-like-the-pain-of-2-am-wakeup-calls?key=d3ef0b84-4bb5-4f6a-9679-6759e89eef46</link><guid>http://ayende.com/blog/155521/non-overlapping-time-periodsndash-because-i-like-the-pain-of-2-am-wakeup-calls?key=d3ef0b84-4bb5-4f6a-9679-6759e89eef46</guid><pubDate>Tue, 15 May 2012 09:00:00 GMT</pubDate></item><item><title>Security decisions: Separate Operations &amp;amp; Queries</title><description>&lt;p&gt;The question came up several times in the mailing list with regards to how the RavenDB Authorization Bundle operates, and I think it serves a broader discussion.&lt;/p&gt; &lt;p&gt;Let us imagine a system where we have contracts, which may be in several states: &lt;/p&gt; &lt;ul&gt; &lt;li&gt;Mine – Contracts that an employee signed.  &lt;li&gt;Done – Standard users can view, Lawyers assigned to the company can sign.  &lt;li&gt;Draft – Lawyers can view / edit, Partners can approve.  &lt;li&gt;Proposed – Lawyers can create / edit, but only the lawyer that created it can view it, Partners can accept.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;So far, fairly simple, right? Except the pure &lt;em&gt;hell&lt;/em&gt; that you are going to get into when you are trying to show the users all of the contracts that they can see, sorted by edit date and in the NDA category.&lt;/p&gt; &lt;p&gt;Why am I being so negative here? Well, let us look at what we are going to have to do in the most trivial of cases:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Security_9400/image_4.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 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/Security_9400/image_thumb_1.png" width="450" height="221"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;In this sort of system, we are going to have to show the user all of the contracts that they are allowed to see, and show them some indication what operations they can do on each.&lt;/p&gt; &lt;p&gt;The problem is that generating this sort of view is &lt;em&gt;expensive&lt;/em&gt;. Especially when you have large amount of data to work through. More interesting, from a UX perspective, it also doesn’t really work that well. Most users would want a better separation of the things that they can do, probably something like this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Security_9400/image_9.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/Security_9400/image_thumb_3.png" width="450" height="221"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This allows us to do a first level filtering on the data itself, rather than try to apply security rules to it.&lt;/p&gt; &lt;p&gt;In the first case, we need to get all the contracts that we are allowed to see. The security rules above are &lt;em&gt;really&lt;/em&gt; simple, mind. But trying to translate them into an efficient query is going to be pretty hard. Both in terms of the code requires and the cost to actually perform the query on the server. There are other things that are involved as well, such as paging and sorting in such an environment.&amp;nbsp; I have created several such systems in the past, Rhino Security is probably the most well known of them, and it gets really hard to optimize things and make sure that everything works when you start getting more complex security rules (especially when you have a user editable security system, which is a common request).&lt;/p&gt; &lt;p&gt;The second case is cheaper because we can limit the choices that we see in the query itself. We may still need to apply security concerns, but those goes through the query directly, rather than a security sub system. This kind of change usually force people to be more explicit in what they want, and it result in a system that tends to be simpler. The security rules aren’t just something arbitrary that can be defined, they are actually visible on the screen (My Contracts, Drafts, etc). Changing them isn’t something that is done on an administrator’s whim.&lt;/p&gt; &lt;p&gt;Yes, this is a way to manage the client and their expectations, but that is &lt;em&gt;important&lt;/em&gt;. But what about the complex security that they want? &lt;/p&gt; &lt;p&gt;That might still be there, certainly, but that would be active mostly for operations (stuff that happen on a single entity), not on things that happen over all entities. It is drastically easier to make a single entity security decisions work efficiently than make it work over the whole set inside the database.&lt;/p&gt;</description><link>http://ayende.com/blog/152929/security-decisions-separate-operations-amp-queries?key=dd5d38bf-cf0b-4233-b6c5-b75582e2e82f</link><guid>http://ayende.com/blog/152929/security-decisions-separate-operations-amp-queries?key=dd5d38bf-cf0b-4233-b6c5-b75582e2e82f</guid><pubDate>Tue, 10 Apr 2012 10:00:00 GMT</pubDate></item><item><title>Monika: A lesson in component based design</title><description>&lt;p&gt;I was giving a lecture on architecture recently, and the notion of components came in. The most important bit about that lecture was probably at the very end, when I discussed what it is that I consider to be a component. During that discussion, I introduced Monika, the payment processing component.&lt;/p&gt; &lt;p&gt;Monika has the following Service Level Agreement:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Payment initiation is done messages.&lt;/li&gt; &lt;li&gt;Notification about payment completion is handled via a callback REST call.&lt;/li&gt; &lt;li&gt;The SLA calls for 90% of all successful payments to be processed in 2 business days.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;So far, it doesn’t sound really complicated, right? And there isn’t even a hint of how Monika works in the SLA or the contracts.&lt;/p&gt; &lt;p&gt;This is Monica:&lt;/p&gt; &lt;p&gt;&lt;img src="http://blog.rounds.com/wp-content/uploads/2011/05/monica-friends.jpg"&gt;&lt;/p&gt;  &lt;p&gt;Well, not really, but it makes the point, doesn’t it.&lt;/p&gt; &lt;p&gt;Monica is a component in the system that respond to (SMTP) messages, does some work, and respond by clicking on a link in the email (REST call).&lt;/p&gt; &lt;p&gt;Monica has a really sucky SLA, since she has only 22% uptime over the course of the year, and then there are those two weeks when she has her yearly maintenance period (vacation), etc.&lt;/p&gt; &lt;p&gt;The most important thing about this is that we are able to abstract all of that away and treat this scenario as just another component in the system. &lt;/p&gt; &lt;p&gt;All too often, people hear components and they start thinking about things like this:&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.agilemodeling.com/images/models/componentDesign.JPG"&gt;&lt;/p&gt; &lt;p&gt;A component in a system is usually something much larger than a single class or a set of classes. It is an independent agent in the system that has its own behavior, resources, dedicated team and deployment schedule separate from all other components.&lt;/p&gt;</description><link>http://ayende.com/blog/152961/monika-a-lesson-in-component-based-design?key=7e93ac65-10fb-4375-9771-4f958d8dab9a</link><guid>http://ayende.com/blog/152961/monika-a-lesson-in-component-based-design?key=7e93ac65-10fb-4375-9771-4f958d8dab9a</guid><pubDate>Fri, 06 Apr 2012 10:00:00 GMT</pubDate></item><item><title>Got to debug is a bug, fix your error messages</title><description>&lt;p&gt;This is part of the RavenDB test suite.&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Got-to-debug-is-a-bug-fix-your-error-mes_137E2/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/Got-to-debug-is-a-bug-fix-your-error-mes_137E2/image_thumb.png" width="831" height="330"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;It has a bug.&lt;/p&gt; &lt;p&gt;Can you see it?&lt;/p&gt; &lt;p&gt;One of the things that I learned when working on the Castle project is that errors are &lt;em&gt;important&lt;/em&gt;. In fact, they are &lt;em&gt;really&lt;/em&gt; important, so it is worth the time to check them very carefully.&lt;/p&gt; &lt;p&gt;In this case, this code would fail but won’t tell me &lt;em&gt;why &lt;/em&gt;it is failing.&lt;/p&gt; &lt;p&gt;Changing it to this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Got-to-debug-is-a-bug-fix-your-error-mes_137E2/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/Got-to-debug-is-a-bug-fix-your-error-mes_137E2/image_thumb_1.png" width="804" height="54"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Means that I get the actual error message right there and then, no need to do anything special.&lt;/p&gt;</description><link>http://ayende.com/blog/153121/got-to-debug-is-a-bug-fix-your-error-messages?key=ba719b0e-0f5f-4aac-81c2-8fada6d609fc</link><guid>http://ayende.com/blog/153121/got-to-debug-is-a-bug-fix-your-error-messages?key=ba719b0e-0f5f-4aac-81c2-8fada6d609fc</guid><pubDate>Wed, 04 Apr 2012 10:00:00 GMT</pubDate></item><item><title>Performance implications of method signatures</title><description>&lt;p&gt;In my previous post, I asked: What are the performance implications of the two options?&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Performance-implications-of-method-signa_AE1F/image_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" border="0" alt="image_thumb" src="http://ayende.com/blog/Images/Windows-Live-Writer/Performance-implications-of-method-signa_AE1F/image_thumb_thumb.png" width="891" height="85"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Versus:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Performance-implications-of-method-signa_AE1F/image_thumb1_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_thumb1" border="0" alt="image_thumb1" src="http://ayende.com/blog/Images/Windows-Live-Writer/Performance-implications-of-method-signa_AE1F/image_thumb1_thumb.png" width="973" height="73"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;And the answer is quite simple. The chance to optimize how it works.&lt;/p&gt; &lt;p&gt;In the first example, we have to return an unknown amount of information. In the second example, we know how much data we need to return. That means that we can optimize ourselves based on that.&lt;/p&gt; &lt;p&gt;What do I mean by that?&lt;/p&gt; &lt;p&gt;Look at the method signatures, those requires us to scan a secondary index, and get the results back. From there, we need to get back to the actual data. If we knew what the size of the data that we need to return is, we could fetch just the locations from the index, then optimize our disk access pattern to take advantage of sequential reads. &lt;/p&gt; &lt;p&gt;In the first example, we have to assume that every read is the last read. Callers may request one item, or 25 or 713, so we don’t really have a way to optimize things. The moment that we have the amount that the caller wants, things change.&lt;/p&gt; &lt;p&gt;We can scan the index to get just actual position of the document on disk, and then load the documents from the disk based on the optimal access pattern in terms of disk access. It is a very small change, but it allowed us to make a &lt;em&gt;big&lt;/em&gt; optimization.&lt;/p&gt;</description><link>http://ayende.com/blog/154529/performance-implications-of-method-signatures?key=0c3cfa8b-83a7-487d-a30b-697972ad1b1c</link><guid>http://ayende.com/blog/154529/performance-implications-of-method-signatures?key=0c3cfa8b-83a7-487d-a30b-697972ad1b1c</guid><pubDate>Tue, 03 Apr 2012 10:00:00 GMT</pubDate></item><item><title>Compare and contrast: Performance implications of method signatures</title><description>&lt;p&gt;What are the performance implications of the two options?&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Compare-and-contrast-Performance-implica_AD35/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/Compare-and-contrast-Performance-implica_AD35/image_thumb.png" width="891" height="85"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Versus:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Compare-and-contrast-Performance-implica_AD35/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/Compare-and-contrast-Performance-implica_AD35/image_thumb_1.png" width="973" height="73"&gt;&lt;/a&gt;&lt;/p&gt;</description><link>http://ayende.com/blog/154497/compare-and-contrast-performance-implications-of-method-signatures?key=838a499a-dc07-43c7-89d6-726b970ac449</link><guid>http://ayende.com/blog/154497/compare-and-contrast-performance-implications-of-method-signatures?key=838a499a-dc07-43c7-89d6-726b970ac449</guid><pubDate>Mon, 02 Apr 2012 10:00:00 GMT</pubDate></item><item><title>What are you in for?</title><description>&lt;p&gt;There is a level of tension between what a developer wants and what the client wants. As a developer, I want to use the coolest technologies, the freshest methodologies, to be so far on the bleeding edge that they have an ER dedicated just for my team.&lt;/p&gt; &lt;p&gt;As a client? I want to be as conservative as possible, for the most part, I don’t care for new technologies unless they have some significant feature that I can’t get anywhere else. I value speed of development over having the devs geek out.&lt;/p&gt; &lt;p&gt;I spoke about before, the tendency of developers to start building castles in the sky in favor of getting things done. I call it Stealing From Your Client, because you are introducing additional things that aren’t necessary, won’t bring additional value or just plain make things hard. &lt;/p&gt; &lt;p&gt;For example, in just about any project that I have seen, putting an IRepository in front of an OR/M or putting an IRepository in front of RavenDB was a mistake. It created no value and actually made things harder to use.&lt;/p&gt; &lt;p&gt;Other pet peeves of mine was raised in a discussion about architecture in a recent lecture that I gave. One of the participants asked me for my opinion about CQRS. But when I asked him for what sort of an application, he answer was somewhere along the lines of: “I want to build my next application using CQRS and I like to hear your opinion.”&lt;/p&gt; &lt;p&gt;This sort of thinking drives me bananas. (Editor note: That sounds like a very painful thing, and I am not sure why I would do that, but it appears that this is an English expression that fit this location in the post).&lt;/p&gt; &lt;p&gt;Dictating the architecture of an application, before you even &lt;em&gt;have&lt;/em&gt; an application? Hell, making any decisions about the application (including what technologies to use) before you actually have a good idea about what is going on is a Big No! No!&lt;/p&gt; &lt;p&gt;Here is the most important piece of this post. For the most part, all those cool technologies that you hear about? They aren’t relevant for your scenario. And even if you are convinced that they are a perfect fit, there is a &lt;em&gt;cost&lt;/em&gt; associated with them, which you have to consider before attempting them. &lt;em&gt;Especially &lt;/em&gt;if this is the first time that you are using something.&lt;/p&gt; &lt;p&gt;The really annoying part? Most people who come up with these exciting new technologies spent an inordinate amount of their time saying not how to build apps using them, but when you &lt;em&gt;shouldn’t&lt;/em&gt;. Evans’ DDD book quite explicitly state that DDD shouldn’t be your default architecture, that it has a cost and should be carefully considered. The industry as a whole (me included) just ignored him and started to write DDD applications.&lt;/p&gt; &lt;p&gt;Greg Young just lectured in Oredev about why you &lt;em&gt;shouldn’t&lt;/em&gt; use CQRS. For much the same reason.&lt;/p&gt; &lt;p&gt;At the end, we are there to provide value to the customer. Yes, it is cool to work on the newest thing on the block, but that is why you have hobby projects.&lt;/p&gt;</description><link>http://ayende.com/blog/153377/what-are-you-in-for?key=4a40f285-f50e-415b-bff0-c2cf7196c604</link><guid>http://ayende.com/blog/153377/what-are-you-in-for?key=4a40f285-f50e-415b-bff0-c2cf7196c604</guid><pubDate>Wed, 29 Feb 2012 10:00:00 GMT</pubDate></item><item><title>Ask Ayende: Aggregates and repositories</title><description>&lt;p&gt;With regards to my recommendation to avoid the repository, Stan &lt;a href="http://ayende.com/blog/153029/northwind-starter-kit-review-data-access-and-the-essence-of-needless-work-part-ii?key=01a97aa23ec049839c3fb2dd91421e61"&gt;asks&lt;/a&gt;:  &lt;blockquote&gt; &lt;p&gt;You returned to explain why repository pattern is evil. Just interesting to know what are you doing when you need in your model to access another aggregate. Do you reference NH from your model? I prefer to leave my model POCOed and wrap DB calls by repository pattern. Sleeping good with it.&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;This is an interesting question. There are several ways to answer that. To start with, assuming that we are using DDD model (which the usage of a repository would imply), you don’t &lt;em&gt;have&lt;/em&gt; references between aggregates.&lt;/p&gt; &lt;p&gt;But let us assume that we somehow need that, Stan seems to suggest something like &lt;a href="http://stackoverflow.com/a/8273030/6366"&gt;this proposed solution&lt;/a&gt;:&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; Person 
{
    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;readonly&lt;/span&gt; DateTime ImportantDate;
    &lt;span class="kwrd"&gt;public&lt;/span&gt; BirthPlace BirthPlace { get; set; } 

    &lt;span class="kwrd"&gt;public&lt;/span&gt; DateTime BirthDate 
    { 
        get; &lt;span class="kwrd"&gt;private&lt;/span&gt; set;
    } 

    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; CorrectBirthDate(IRepository&amp;lt;BirthPlace&amp;gt; birthPlaces, DateTime date)
    {
        &lt;span class="kwrd"&gt;if&lt;/span&gt; (BirthPlace != &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; date &amp;lt; ImportantDate &amp;amp;&amp;amp; BirthPlace.IsSpecial) 
        { 
            BirthPlace = birthPlaces.GetForDate(date); 
        }
    }
}&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;Here we have a business rule that states that this is required.&lt;/p&gt;
&lt;p&gt;But do we actually need a repository here? What if we just said that whoever calls us need to provide us with a way to get the birth place by date?&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;void&lt;/span&gt; CorrectBirthDate(
        Func&amp;lt;DateTime, BirthPlace&amp;gt; getBirthPlaceFordate, 
        DateTime date)
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (BirthPlace != &lt;span class="kwrd"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; date &amp;lt; ImportantDate &amp;amp;&amp;amp; BirthPlace.IsSpecial) 
    { 
        BirthPlace = getBirthPlaceFordate(date); 
    }
}&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 can be done with a simple delegate, no need to introduce a heavy weight abstraction. This is a local solution for a local problem. It keeps the database out from your entities and more importantly, it allows you to actually craft the appropriate response to this &lt;em&gt;at the time of the call&lt;/em&gt;. &lt;/p&gt;</description><link>http://ayende.com/blog/153700/ask-ayende-aggregates-and-repositories?key=05eabb7e-380d-4a0a-a815-5539cfdf5d34</link><guid>http://ayende.com/blog/153700/ask-ayende-aggregates-and-repositories?key=05eabb7e-380d-4a0a-a815-5539cfdf5d34</guid><pubDate>Tue, 28 Feb 2012 10:00:00 GMT</pubDate></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;</description><link>http://ayende.com/blog/153062/northwind-starter-kit-review-conclusion?key=8b9a7e78-40f5-40f0-9ee4-ab82db0c68ee</link><guid>http://ayende.com/blog/153062/northwind-starter-kit-review-conclusion?key=8b9a7e78-40f5-40f0-9ee4-ab82db0c68ee</guid><pubDate>Thu, 26 Jan 2012 10:00:00 GMT</pubDate></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;</description><link>http://ayende.com/blog/153702/ask-ayende-handling-filtering?key=4c2392dd-c883-42de-9fb9-65392804f011</link><guid>http://ayende.com/blog/153702/ask-ayende-handling-filtering?key=4c2392dd-c883-42de-9fb9-65392804f011</guid><pubDate>Wed, 25 Jan 2012 10:00:00 GMT</pubDate></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;</description><link>http://ayende.com/blog/153061/northwind-starter-kit-review-it-is-all-about-the-services?key=7f5a17e7-68be-468a-8660-a83386aa31a4</link><guid>http://ayende.com/blog/153061/northwind-starter-kit-review-it-is-all-about-the-services?key=7f5a17e7-68be-468a-8660-a83386aa31a4</guid><pubDate>Mon, 23 Jan 2012 10:00:00 GMT</pubDate></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;</description><link>http://ayende.com/blog/153060/northwind-starter-kit-review-from-start-to-finishingndash-tracing-a-request?key=ed569a76-c10c-41a2-a602-27bb9bb06d04</link><guid>http://ayende.com/blog/153060/northwind-starter-kit-review-from-start-to-finishingndash-tracing-a-request?key=ed569a76-c10c-41a2-a602-27bb9bb06d04</guid><pubDate>Fri, 20 Jan 2012 10:00:00 GMT</pubDate></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;</description><link>http://ayende.com/blog/153701/ask-ayende-life-without-repositories-are-they-worth-living?key=33f415ae-fba1-46b9-a276-ce3710c784cc</link><guid>http://ayende.com/blog/153701/ask-ayende-life-without-repositories-are-they-worth-living?key=33f415ae-fba1-46b9-a276-ce3710c784cc</guid><pubDate>Thu, 19 Jan 2012 10:00:00 GMT</pubDate></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;</description><link>http://ayende.com/blog/153059/northwind-starter-kit-review-if-you-wonrsquo-t-respect-the-database-there-will-be-pain?key=fb89b714-2ffb-4cf4-b33d-7a524d70a8ae</link><guid>http://ayende.com/blog/153059/northwind-starter-kit-review-if-you-wonrsquo-t-respect-the-database-there-will-be-pain?key=fb89b714-2ffb-4cf4-b33d-7a524d70a8ae</guid><pubDate>Wed, 18 Jan 2012 10:00:00 GMT</pubDate></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;</description><link>http://ayende.com/blog/153699/ask-ayende-repository-for-abstracting-multiple-data-sources?key=4d781c8e-25b8-44f2-a060-d918bcae2ef0</link><guid>http://ayende.com/blog/153699/ask-ayende-repository-for-abstracting-multiple-data-sources?key=4d781c8e-25b8-44f2-a060-d918bcae2ef0</guid><pubDate>Tue, 17 Jan 2012 10:00:00 GMT</pubDate></item><item><title>Northwind Starter Kit Review: Refactoring to an actual read model</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;In my previous post, I talked about how the CatalogController.Product(id) action was completely ridiculous in the level of abstraction that it used to do its work and promised to show how to do the same work on an actual read model in a much simpler fashion. Here is the code.&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review_628/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-Review_628/image_thumb.png" width="849" height="538"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;img style="display: inline; float: right" align="right" src="http://psalmsinpurgatory.files.wordpress.com/2011/07/pitchfork-mob1.jpg"&gt;&lt;/p&gt; &lt;p&gt;There are several things that you might note about this code:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;It is all inline, so it is possible to analyze, optimize and figure out what the hell is going on easily.&lt;/li&gt; &lt;li&gt;It doesn’t got to the database to load data that it already has.&lt;/li&gt; &lt;li&gt;The code actually does something meaningful.&lt;/li&gt; &lt;li&gt;It only do one thing, and it does this elegantly.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;This is actually using a read model. By, you know, &lt;em&gt;reading&lt;/em&gt; from it, instead of abstracting it.&lt;/p&gt; &lt;p&gt;But there is a problem here, I hear you shout (already reaching for the pitchfork, at least let me finish this post).&lt;/p&gt; &lt;p&gt;Previously, we have hidden the logic of discontinued products and available products behind the following abstraction:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review_628/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-Review_628/image_thumb_1.png" width="507" height="96"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Now we are embedding this inside the query itself, what happens if this logic changes? We would now need to go everywhere we used this logic and update it.&lt;/p&gt; &lt;p&gt;Well, yes. Except that there are two mitigating factors.&lt;/p&gt; &lt;ul&gt; &lt;li&gt;This nice abstraction is &lt;strong&gt;never used elsewhere&lt;/strong&gt;.&lt;/li&gt; &lt;li&gt;It is easy to create our own abstraction.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Here is an example on how to do this without adding additional layers of abstractions.&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review_628/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/Northwind-Starter-Kit-Review_628/image_thumb_2.png" width="672" height="197"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Which means that our action method now looks like this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/Northwind-Starter-Kit-Review_628/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_628/image_thumb_3.png" width="680" height="541"&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Simple, easy, performant, maintainable.&lt;/p&gt; &lt;p&gt;And it doesn’t make my head hurt or cause me to stay up until 4 AM feeling like &lt;a href="http://xkcd.com/386/"&gt;an XKCD item&lt;/a&gt;.&lt;/p&gt;</description><link>http://ayende.com/blog/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model?key=4cc1a59d-3842-4154-a6c7-c4f85525e4b2</link><guid>http://ayende.com/blog/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model?key=4cc1a59d-3842-4154-a6c7-c4f85525e4b2</guid><pubDate>Mon, 16 Jan 2012 10:00:00 GMT</pubDate></item><item><title>Northwind Starter Kit Review: Data Access review thoughts</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;In my last few posts, I have gone over the data access strategy used in NSK. I haven’t been impressed. In fact, I am somewhere between horrified, shocked and amused in the same way you feel when you see a clown slipping on a banana peel.&amp;nbsp; Why do I say that? Let us trace a single call from the front end all the way to the back.&lt;/p&gt; &lt;p&gt;The case in point, CatalogController.Product(id) action. This is something that should just display the product on the screen, so it should be fairly simple, right? Here is how it works when drawn as UML:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/6a03ddd05a08_46EE/image_11.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/6a03ddd05a08_46EE/image_thumb.png" width="1025" height="826"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;To simplify things, I decided to skip any method calls on the same objects (there are more than a few).&lt;/p&gt; &lt;p&gt;Let me show you how this looks like in actual code:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/6a03ddd05a08_46EE/image_6.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 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/6a03ddd05a08_46EE/image_thumb_2.png" width="647" height="124"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Digging deeper, we get:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/6a03ddd05a08_46EE/image_8.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 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/6a03ddd05a08_46EE/image_thumb_3.png" width="826" height="488"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;We will deal with the first method call to CatalogServices now, which looks like:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/6a03ddd05a08_46EE/image_10.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 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/6a03ddd05a08_46EE/image_thumb_4.png" width="670" height="68"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I’ll skip going deeper, because this is just a layer of needless abstraction on top of Entity Framework and that is quite enough already.&lt;/p&gt; &lt;p&gt;Now let us deal with the second call to CatalogServices, which is actually more interesting:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/6a03ddd05a08_46EE/image_14.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 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/6a03ddd05a08_46EE/image_thumb_6.png" width="831" height="205"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Note the marked line? This is generating a query. This is interesting, because we have &lt;em&gt;already loaded the product. &lt;/em&gt;There is no way of optimizing that, of course, because the architecture doesn’t let you.&lt;/p&gt; &lt;p&gt;Now, you need all of this &lt;em&gt;just to show a single product on the screen&lt;/em&gt;. I mean, &lt;strong&gt;seriously.&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;You might have noticed some references to things like Read Model in the code. Which I find highly ironic. Read Models are about making the read side of things &lt;em&gt;simple&lt;/em&gt;, not drowning the code in abstraction on top of abstraction on top of abstraction.&lt;/p&gt; &lt;p&gt;In my next post, I’ll show a better way to handle this scenario. A way that is actually simpler and make use an of actual read model and not infinite levels of indirection.&lt;/p&gt;</description><link>http://ayende.com/blog/153058/northwind-starter-kit-review-data-access-review-thoughts?key=852c1fa5-de55-4460-b9a8-b4fbc2e2843a</link><guid>http://ayende.com/blog/153058/northwind-starter-kit-review-data-access-review-thoughts?key=852c1fa5-de55-4460-b9a8-b4fbc2e2843a</guid><pubDate>Fri, 13 Jan 2012 10:00:00 GMT</pubDate></item><item><title>Northwind Starter Kit Review: The parents have eaten sour grapes, and the children&amp;rsquo;s teeth are set on edge</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;In my previous posts, I focused mostly on the needlessness of the repositories implementation and why you want to avoid that (especially implementing it multiple times). In this post, I want to talk about other problems regarding the data access. In this case, the sudden urge to wash my hands that occurred when I saw this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://ayende.com/blog/Images/Windows-Live-Writer/The-parents-have-eaten-sour-grapes-and-t_43DD/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/The-parents-have-eaten-sour-grapes-and-t_43DD/image_thumb_6.png" width="857" height="319"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;I mean, you are &lt;em&gt;already using an OR/M&lt;/em&gt;. I don’t like the Repository implementation, but dropping down to SQL (and unparapetrized one at that) seems uncalled for.&lt;/p&gt; &lt;p&gt;By the way, the most logical reason for this to be done is to avoid mapping the Picture column to the category, since the OR/M in use here (EF) doesn’t support the notion of lazy properties.&lt;/p&gt; &lt;p&gt;Again, this is a problem when you are trying to use multiple OR/Ms, and that is neither required nor really useful.&lt;/p&gt; &lt;p&gt;Okay, enough about the low level data access details. On my next post I’ll deal with how those repositories are actually being used.&lt;/p&gt;</description><link>http://ayende.com/blog/153057/northwind-starter-kit-review-the-parents-have-eaten-sour-grapes-and-the-childrenrsquo-s-teeth-are-set-on-edge?key=92f4042c-ece0-4777-8256-64b6346caec1</link><guid>http://ayende.com/blog/153057/northwind-starter-kit-review-the-parents-have-eaten-sour-grapes-and-the-childrenrsquo-s-teeth-are-set-on-edge?key=92f4042c-ece0-4777-8256-64b6346caec1</guid><pubDate>Thu, 12 Jan 2012 10:00:00 GMT</pubDate></item></channel></rss>
