﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2021 (c) 2026</copyright><ttl>60</ttl><item><title>Mr Simple commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>@evereq
&gt;Because people in .NET community really tend to overcomplicate things for some reason where it is not required... but it does not mean they are stupid... it just mean they are too smart :)

Amen brother.  You're the kinda guy I hire instead of propellor heads who are more concerned about which pattern they are going to use instead of fixing my problems with simple code.  Too often they end up fixing their patterns instead.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment79</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment79</guid><pubDate>Wed, 18 Jan 2012 14:41:38 GMT</pubDate></item><item><title>Ayende Rahien commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Karep,
Do that in a child actions, then. </description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment78</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment78</guid><pubDate>Tue, 17 Jan 2012 21:09:37 GMT</pubDate></item><item><title>Karep commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Regarding dropdowns. I can't imagine how you fill them with separate calls to other controllers. First you risk displaying a page with combos empty for a second or two or worse longer. Also you make more hits to a server instead of just one. From previous posts you seem to take care not to hit db/server more than you need to. But that would be the case when getting data to dropdowns using AJAX.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment77</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment77</guid><pubDate>Tue, 17 Jan 2012 20:41:28 GMT</pubDate></item><item><title>Karep commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>everequ: "I watch carefully to avoid leaky abstractions to not lose performance" 
I think you are wrong. In order to not loose performance you need leaky abstractions.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment76</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment76</guid><pubDate>Tue, 17 Jan 2012 19:54:39 GMT</pubDate></item><item><title>Karep commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>When I see code like this I think "Oh the person just learned LINQ".</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment75</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment75</guid><pubDate>Tue, 17 Jan 2012 18:03:31 GMT</pubDate></item><item><title>Ayende Rahien commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Scott,
No, it wouldn't, because the inner query is going to eval only when the outer is executed.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment74</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment74</guid><pubDate>Tue, 17 Jan 2012 17:58:04 GMT</pubDate></item><item><title>Scott commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>@Ayende, but before you call .First(), you've called .ToList() when defining 'q'. That won't cause the full query to execute even thought the inner query has dependency on p.Category? Are you positive you have full deferred execution until you call q.First()? </description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment73</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment73</guid><pubDate>Tue, 17 Jan 2012 17:56:42 GMT</pubDate></item><item><title>Ayende Rahien commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Daniel,
There is no reusing this piece, it is made to order. And while I understand that some people find this uncomfortable, I find this style of code highly readable, even for large amount of code.
</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment72</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment72</guid><pubDate>Tue, 17 Jan 2012 17:37:34 GMT</pubDate></item><item><title>Ayende Rahien commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Allan,
Caching is not a cross cutting concern, and you want to do that in the place with the most context. That is in the outer layers of the system.
You can do that with adding a Cache() method to the query on the controller, very easy and simple, or by caching the actual output from the server, so your code doesn't even run.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment71</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment71</guid><pubDate>Tue, 17 Jan 2012 17:36:33 GMT</pubDate></item><item><title>Ayende Rahien commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>dmitry,
Yes, I would put the SQL directly in the controller if I was using a mini ORM</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment70</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment70</guid><pubDate>Tue, 17 Jan 2012 17:34:34 GMT</pubDate></item><item><title>Ayende Rahien commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Scott,
Yes, but we only have 1, so it is okay</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment69</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment69</guid><pubDate>Tue, 17 Jan 2012 17:34:11 GMT</pubDate></item><item><title>Ayende Rahien commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Spaten,
In this case, just a class that expose NHibernate's session.Query[Product]()</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment68</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment68</guid><pubDate>Tue, 17 Jan 2012 17:33:58 GMT</pubDate></item><item><title>Karep commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>OutputCache varybyparam none on method that takes parameter. Ok.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment67</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment67</guid><pubDate>Tue, 17 Jan 2012 16:59:46 GMT</pubDate></item><item><title>Karep commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>You gotta be kidding that this is clean code? Have you read about Composed method?</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment66</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment66</guid><pubDate>Tue, 17 Jan 2012 16:58:30 GMT</pubDate></item><item><title>Rich commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>I think the bigger question is, why the hell are they using an ORM for this type of "read model"?</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment65</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment65</guid><pubDate>Tue, 17 Jan 2012 13:40:43 GMT</pubDate></item><item><title>Allan commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Philip - Output caching won't help if I want the cached result elsewhere, i.e. a different view.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment64</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment64</guid><pubDate>Tue, 17 Jan 2012 10:07:23 GMT</pubDate></item><item><title>Daniel commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>@Oren/Ayende

Mike said:
"When giant LINQ queries don't do what you expect, in my experience they're not so easy to debug without breaking them into smaller chunks,"

I second this. I consider single line linq/fluent style statements as an anti-pattern. "Elegant" - perhaps, as long as it runs. How many different places of a null pointer exception do you see here?

I would break it into 3-4 chunks. Those chunks *could* be refactored out into individual methods for re-usage once I see the point.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment63</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment63</guid><pubDate>Tue, 17 Jan 2012 09:03:18 GMT</pubDate></item><item><title>Phillip commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Allan - He's already using output caching, theres no need for 2nd level caching like with NH.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment62</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment62</guid><pubDate>Tue, 17 Jan 2012 08:47:18 GMT</pubDate></item><item><title>Allan commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Ayende, how would you go about second level caching with your solution?

I think we'ed definitely end up with queries being duplicated unless extension methods or specifications were used from the beginning, I mean working in a team your not going to know someone else has written the query you need using an inline query or your a new starter on a legacy project, whereas repository.GetMeSomething is clear.

But yes I see your point and it is very annoying having to update your Repository and IRepository whenever a new query is needed, more work but I guess most large scale application will need some abstraction, say we had some new requirement which we needed to introduce a web service (This is fairly common) in this case we'ed be trawling through UI code gathering queries we need and placing them in a central location, anyway, or we could be lazy and not refactor existing code and just copy and paste :) If this were a brownfield project I was working on I would be frustrated and wish a repository was used.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment61</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment61</guid><pubDate>Tue, 17 Jan 2012 08:35:16 GMT</pubDate></item><item><title>Dmitry commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Ayende, if you were to use a mini ORM that requires an SQL query string or even straight ADO .NET, would you still do it inside the controller?

I do not see why LINQ-to-external data source is any different.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment60</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment60</guid><pubDate>Tue, 17 Jan 2012 06:57:23 GMT</pubDate></item><item><title>Scott commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Does EF not collapse the expression for and execute the N+1 sub select on RelatedProducts to resolve p.Category?</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment59</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment59</guid><pubDate>Tue, 17 Jan 2012 04:59:27 GMT</pubDate></item><item><title>SPATEN commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Oren,

Just out of curiosity, what would the Database class look like to enable the Products property as you've shown?

Regards,
Stephen  </description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment58</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment58</guid><pubDate>Tue, 17 Jan 2012 03:22:52 GMT</pubDate></item><item><title>Ryan commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>@hpcd - But code reuse across applications is not an immediate up front requirement for most apps. When you need it you can refactor to it. Plus your mobile app might only show a subset of data, or have different pagination requirements, etc. It's futile to try to guess all these up front. It's best to refactor later.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment57</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment57</guid><pubDate>Tue, 17 Jan 2012 01:27:08 GMT</pubDate></item><item><title>Mike commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Considering that your solution is essentially one single LINQ statement, I'm not sure I agree with this statement: "It is all inline, so it is possible to analyze, optimize and figure out what the hell is going on easily."

When giant LINQ queries don't do what you expect, in my experience they're not so easy to debug without breaking them into smaller chunks, etc.

Also on an unrelated note, unless I need the result to be mutable I generally prefer .ToArray() over .ToList(), but that's just personal preference.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment56</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment56</guid><pubDate>Tue, 17 Jan 2012 00:40:01 GMT</pubDate></item><item><title>hpcd commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Hi Ayende: I agree that there was way too much abstraction going on in the code you reviewed. However, I think you might have gone too far on the other side. I believe that even you read should be in a service- basically not in the controller. The reason, we can't reuse what you have in a non mvc app. You could have a web app serve different devices, but it is not inconceivable that we want to provide a UI more native to the device and reuse the service and view model. 

Case in point: Android UI and IOS UI. 

But what you have done is valid-but it breaks reuse scenarios. This is not a theoretical argument- I have seen and been involved in dev for both devices.

</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment55</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment55</guid><pubDate>Mon, 16 Jan 2012 23:02:18 GMT</pubDate></item><item><title>Roland commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Compare to the original code:

http://ayende.com/blog/Images/Windows-Live-Writer/6a03ddd05a08_46EE/image_8.png</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment54</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment54</guid><pubDate>Mon, 16 Jan 2012 19:07:27 GMT</pubDate></item><item><title>João Bragança commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>@Darren, then you should capture that business logic on the command side, i.e. trying to put a product whose cost is less than $5 on sale throws an exception. But that would require a domain that was more than getters and setters.

Reuse? Really how hard would it be to move all these extension methods of IQueryable[of T] to a separate assembly? Now you can reuse it.

Another thing I like about extension methods for this is that they better capture the UL. You can chain them together. You can compose them.

Where else would you build the view model but in the controller? Who knows more about the requirements of the view? The controller or a service behind WCF?

What's more maintainable? 2 lines of code as above or a bunch more scattered throughout multiple assemblies? What ever happened to the simplest possible thing that could work?</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment53</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment53</guid><pubDate>Mon, 16 Jan 2012 18:38:48 GMT</pubDate></item><item><title>Bunter commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Superb sample to show where to NOT use layering. I can already imagine architecture astronauts jumping up and down realizing that since example contains two business rules, tons of strategies, factories, mappers and injections can be thrown in. All to

a) select a product by ID from allowed set
b) add related products from same category in given order
c) map query result to a view model

Arguments of reuse: if such piece of code needs to be called twice duplication is already introduced somewhere up the chain.

</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment52</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment52</guid><pubDate>Mon, 16 Jan 2012 17:55:58 GMT</pubDate></item><item><title>SteveR commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>@Matt - If you're talking about a mobile web application I would have thought that it could be the same application just using responsive design to deliver a layout optimized for smaller screens. A platform native mobile app might be a different proposition but my experience of those has been that they often differ in their informational requirements quite a lot. Where there is some commonality, like for example a search feature, then that might even deserve to be an entirely separate application in it's own right. In other words more vertical service partition than horizontal DAO service sharing because it promotes better composition.

It's really not that odd that different applications have very different data requirements or different models of the same data source, and having the freedom to allow them diverge in response to business needs and change at different rates is the main point. </description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment51</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment51</guid><pubDate>Mon, 16 Jan 2012 15:58:19 GMT</pubDate></item><item><title>Wayne M commented on Northwind Starter Kit Review: Refactoring to an actual read model</title><description>Thanks, Ayende.  I would much rather have Massive or PetaPoco myself (well I would prefer NHibernate of course) but was just curious as at work we are basically forced to use sprocs and DataSets everywhere and trying to use something else gets shot down, but maybe we could use some kind of abstraction layer to avoid having that mess in code-behind.</description><link>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment50</link><guid>http://ayende.com/153153/northwind-starter-kit-review-refactoring-to-an-actual-read-model#comment50</guid><pubDate>Mon, 16 Jan 2012 15:50:02 GMT</pubDate></item></channel></rss>