﻿<?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>Daniel Martin commented on Ask Ayende: Aggregates and repositories</title><description>I do not understand the business requirement here, but we use domain events (see Udi Dahan) for communication between aggregates and do not need any dependencies or delegates in our aggregates and entities. 
</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment46</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment46</guid><pubDate>Tue, 27 Mar 2012 11:23:36 GMT</pubDate></item><item><title>Stan commented on Ask Ayende: Aggregates and repositories</title><description>@Ayende, thanks for an answer. I was out here for some weeks and only now saw this blogpost.
I think I got your point but cant agree with you. I dont like this solution. Its unclear what method should be passed and where to look for it. It smells bad.
In my case I do not pass repository into a method. Following given example I inject IRepository&lt;BirthPlace&gt; into Person in NH load event listener when it's fetched. It will be very ugly starting to register loads of delegates in DI container aspecialy when some of them will have same signature. Also it will be much harder to automate registration proccess of delegates than repositories.
Injecting some sort of IGetBirthPlaceFordateQuery instead of repository seems better than injecting delegate. I'll think about it.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment45</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment45</guid><pubDate>Tue, 20 Mar 2012 21:38:03 GMT</pubDate></item><item><title>Bill commented on Ask Ayende: Aggregates and repositories</title><description>Using delegates in this way actually reduces clarity. You seem to have a delegate fetish Ayende as this kind of thing is all over the RavenDB Codebase. I personally prefer classes for most things (there are exceptions), much easier to track and much more explicit.

The reason both the original and proposed solutions seems wrong is that in this case you would probably be better of just moving the birthplace resolution logic out of this class.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment44</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment44</guid><pubDate>Fri, 02 Mar 2012 18:02:59 GMT</pubDate></item><item><title>degorolls commented on Ask Ayende: Aggregates and repositories</title><description>@Falhar,

Does it make you more comfortable with this shift if instead of this signature:

void CorrectBirthDate(Func{DateTime, BirthPlace} getBirthPlaceFordate, 
        DateTime date);

we have something like this one:

delegate BirthPlace BirthPlaceRetriever(DateTime d);

void CorrectBirthDate(BirthPlaceRetriever getBirthPlaceFordate, 
        DateTime date);

Structurally it is identical and will work identically as far as the compiler is concerned (i.e. you can pass repository method group, lambda, etc.) but is converying the same semantics as the interface would do, except in a much  more granular fashion. . 


</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment43</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment43</guid><pubDate>Thu, 01 Mar 2012 07:44:12 GMT</pubDate></item><item><title>gunteman commented on Ask Ayende: Aggregates and repositories</title><description>I don't see how

public void CorrectBirthDate(IRepository&lt;BirthPlace&gt; birthPlaces, DateTime date)

is any less confusing than

public void CorrectBirthDate(Func&lt;DateTime, BirthPlace&gt; getBirthPlaceFordate, DateTime date)

If anything, the latter is more explicit.

</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment42</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment42</guid><pubDate>Wed, 29 Feb 2012 22:07:27 GMT</pubDate></item><item><title>J commented on Ask Ayende: Aggregates and repositories</title><description>I have to agree with Rafal on this one, using delegates in this case seem very wrong to me, it makes the code unclear and confusing for the user.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment41</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment41</guid><pubDate>Wed, 29 Feb 2012 03:03:45 GMT</pubDate></item><item><title>gunteman commented on Ask Ayende: Aggregates and repositories</title><description>@Sla

Spot on!

The delegate solution is no more and no less abstract than the IRepository solution, and it's no more and no less enforceable. 

The objective was to show how a data accessing double dispatch can be made, without an unnecessary IRepository and without injecting an "ISession" into the method. The delegate itself can be as loosy lambdaish or as strongly typed and as testable as you'd like. </description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment40</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment40</guid><pubDate>Wed, 29 Feb 2012 01:01:45 GMT</pubDate></item><item><title>Ayende Rahien commented on Ask Ayende: Aggregates and repositories</title><description>Rafal,
If you had 10 operations going on, you are doing it wrong.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment39</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment39</guid><pubDate>Tue, 28 Feb 2012 23:21:44 GMT</pubDate></item><item><title>Rafal commented on Ask Ayende: Aggregates and repositories</title><description>Imagine that in the example you have not one but ten delegates for performing various queries 
How is such set of delegates called? An Interface!
But don't you ever try to name it IRepository - it's bad practice. Name it something like ISetOfEntityOperations...
</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment38</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment38</guid><pubDate>Tue, 28 Feb 2012 23:18:21 GMT</pubDate></item><item><title>Daniel Marbach commented on Ask Ayende: Aggregates and repositories</title><description>Jimmy bogards presentation covers this very well!

https://github.com/jbogard/presentations/tree/master/WickedDomainModels

Daniel</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment37</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment37</guid><pubDate>Tue, 28 Feb 2012 21:54:25 GMT</pubDate></item><item><title>Sla commented on Ask Ayende: Aggregates and repositories</title><description>How about mathematical proof that both approaches are complete dual of each other and we can prove it by bringing it into pull/push analogy.
Meanings you put into those are totally human related and its all about your team and your target audience.

This would means both ways do provide similar guarantees and do provide similar modularity. 
Please go ahead and prove otherwise.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment36</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment36</guid><pubDate>Tue, 28 Feb 2012 21:27:05 GMT</pubDate></item><item><title>Sony Mathew commented on Ask Ayende: Aggregates and repositories</title><description>Business rules being expected to live within the boundary of an Aggregate is a fallacy in my opinion.  Business rules are conjured up in the minds of humans and can span any number of entities and can change at any time to use altogether new entities and/or additional attributes. This is why in my opinion DDD is not a valid approach. I'm sure there are many exceptional workarounds for this in DDD but it is fundamentally flawed in this regard.

As for access to a Repository (or Store or DAO) instance. It is best to use Injection (IoC) of the Repository which is then controlled from a central IoC binding for your module.  Specifically for the case of repository like functionality - the Interface/Class approach is better than a Delegate function due to many reasons: first of many methods might require to interact with the same repository (if 2 entities are used in one business rule, likely it will be used together under more rules in the same service), second: the Delegate's function signature will cause a nasty ripple effect as each caller tries to fulfil up the call-chain.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment35</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment35</guid><pubDate>Tue, 28 Feb 2012 19:41:50 GMT</pubDate></item><item><title>Karep commented on Ask Ayende: Aggregates and repositories</title><description>@Fahlar
With repository, you ensure 2 things: You select from all BirthPlaces, that exist and you select the correct one.

You don't ensure anything by using repository. You only have interface in method signature. You don't know what is passed! So there is no difference between delegate and ISomeRepository.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment34</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment34</guid><pubDate>Tue, 28 Feb 2012 18:45:14 GMT</pubDate></item><item><title>Rohland commented on Ask Ayende: Aggregates and repositories</title><description>In cases where you need to cross aggregate boundaries, I usually use an extension method. This is useful as the entity is relatively persistence ignorant but has the capability to execute business rules using data it needs. Going with this approach means that your root entities don't reference each other directly, but when they need each other, the code to retrieve the data isn't duplicated.

The downside with this approach is the abstraction which Ayende is trying to hammer away. The approach cited in this example means the developer is in full control. That being said, I prefer the extension approach. If it's common practice with a specific development team, I think it works quite well and keeps your code neat. I agree with the folk saying that the delegate approach would create confusion in future.

If it's not clear what I'm suggesting, here is an extension method on a user entity to grab the user's orders. If you're using DI, you could use your object factory to instantiate the repository. Testing nuts will tell you that this approach isn't a good one, however, I think the overhead of mocking the repository in your test setup is worth the gain in simplicity when actually consuming the code.

public static class UserExtensions
{
	public static IEnumerable&lt;Orders&gt; GetOrders(this User user)
	{
		return new OrderRepository().GetOrders(user.Id);
	}
}
</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment33</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment33</guid><pubDate>Tue, 28 Feb 2012 18:02:01 GMT</pubDate></item><item><title>Jeff Sternal commented on Ask Ayende: Aggregates and repositories</title><description>If the Person class really needs birth places to do its job, why not make it member data (and include birth places in the OR/M mappings)?</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment32</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment32</guid><pubDate>Tue, 28 Feb 2012 16:05:55 GMT</pubDate></item><item><title>Scott commented on Ask Ayende: Aggregates and repositories</title><description>@Joseph, that's a joke. I always design my application around the "stupidity" of future developers, because 90% of the time, that stupid developer is me. 

I would never want to come back to this example code after 6 months, especially if the getBirthPlaceForDate logic was different in each place it was used. </description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment31</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment31</guid><pubDate>Tue, 28 Feb 2012 15:57:28 GMT</pubDate></item><item><title>Markus commented on Ask Ayende: Aggregates and repositories</title><description>@Wayne M
Where is the abstraction? I never mentioned any ICorrectBirthDateService. If anything, it is adding (perhaps overkill) *specifics*, not abstractions.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment30</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment30</guid><pubDate>Tue, 28 Feb 2012 15:44:19 GMT</pubDate></item><item><title>Wayne M commented on Ask Ayende: Aggregates and repositories</title><description>@Markus 

"I would probably use a CorrectBirthDateService for this; the repository gets injected in the service constructor and the Person object gets passed as an argument to CorrectBirthDate."

That would be my first instinct but the whole point of these posts is to **limit** the abstractions, not add additional ones ;-)  I think the whole underlying point here is that a `CorrectBirthDateService` is overkill, having a separate repository is overkill.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment29</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment29</guid><pubDate>Tue, 28 Feb 2012 15:16:52 GMT</pubDate></item><item><title>Markus commented on Ask Ayende: Aggregates and repositories</title><description>@Falhar, I think you are spot on with your last comment. I try to use types to provide more information to me and to developers around me. For that reason I always create Id-classes for objects instead of using ints. I also create LatLon structs instead of using Point or Vector.

Moreover, I don't like passing around repositories like in the example either.. Repositories are infrastructure and I get a bad feeling when I pass infrastructure around. A couple of options:

I would probably use a CorrectBirthDateService for this; the repository gets injected in the service constructor and the Person object gets passed as an argument to CorrectBirthDate. 

If there was a direct mapping from DateTime to BirthPlace I might have gone with a variant of Ayende's solution: passing IDictionary&lt;DateTime, BirthPlace&gt; instead of a Func&lt;-,-&gt;. Bit less generic though, but that is what I would have come up with.

For me, part of the reason to use static typing is to remind (rather than force) myself of what objects are needed so that I can go look for the information I need.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment28</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment28</guid><pubDate>Tue, 28 Feb 2012 15:00:29 GMT</pubDate></item><item><title>Falhar commented on Ask Ayende: Aggregates and repositories</title><description>@Joseph: That is not idiocy. That is when developer, which didn't wrote the code, tries to use that code. Which is common practice. Unless you are only one doing whole project.

Generic delagates are too general as abstraction. Noone will know WHAT should be passed into it, unless some other source tells them.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment27</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment27</guid><pubDate>Tue, 28 Feb 2012 14:59:42 GMT</pubDate></item><item><title>Falhar commented on Ask Ayende: Aggregates and repositories</title><description>@Shane: No, no, no. Where do I get the MyMethod? How do I know what should it implement? Didn't someone already implement it? Is the implementation correct?
It is not MyMethod, but IRepository&lt;BirthPlace&gt;.GetForDate , no other method can be passed, othervise you change the domain logic.

And there should already be infrastructure to create concrete implementation of IRepository from anywhere where you call it from. Just like Ayende's ExecuteCommand from few articles back.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment26</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment26</guid><pubDate>Tue, 28 Feb 2012 14:57:01 GMT</pubDate></item><item><title>Melle commented on Ask Ayende: Aggregates and repositories</title><description>I see that depending from person onto the  birthplaces repository is bad and depending on a method might be better. But would that not just pull the birthplacesrepository up a level? What does the caller of this method look like, does it not need that repository?</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment25</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment25</guid><pubDate>Tue, 28 Feb 2012 14:54:52 GMT</pubDate></item><item><title>Joseph Daigle commented on Ask Ayende: Aggregates and repositories</title><description>Falher, That's a fallacy. You shouldn't be designing your application around assumptions about the stupidity of your developers. You should be designing based on solid principals.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment24</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment24</guid><pubDate>Tue, 28 Feb 2012 14:54:49 GMT</pubDate></item><item><title>Falhar commented on Ask Ayende: Aggregates and repositories</title><description>Also, lets look at it from point of some other developer, who needs to use it.

void CorrectBirthDate(IRepository&lt;BirthPlace&gt; birthPlaces, DateTime date)

"So, to change date, I need to give it correct date and this repository. Sure." Because Repository is general term and developer knows what it means, they can easily tell what the method wants and how to get the repository.

 void CorrectBirthDate(Func&lt;DateTime, BirthPlace&gt; getBirthPlaceFordate, DateTime date)

"So, to change date, I need to give it date and .. how do I get BirthPlaceForDate ??" This needs developer to look for more information, probably by asking someone or looking at other usages of this method, so they can call this method.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment23</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment23</guid><pubDate>Tue, 28 Feb 2012 14:51:37 GMT</pubDate></item><item><title>Shane Courtrille commented on Ask Ayende: Aggregates and repositories</title><description>@Falhar: Why do you think it would be easier?  

person.CorrectBirthDate(myRepository);

vs.

person.CorrectBirthDate(MyMethod);

They both require I go somewhere else.. and that assumes that MyMethod isn't so simple that I can just inline it.  In fact myRepository is worse because I need to go find the actual implementor.  If we're talking typical IoC this means back tracking it based on my conventions.
</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment22</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment22</guid><pubDate>Tue, 28 Feb 2012 14:50:26 GMT</pubDate></item><item><title>Falhar commented on Ask Ayende: Aggregates and repositories</title><description>@Ayende: But it is easier to ensure correct repository is used, than ensuring correct method is passed as parameter.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment21</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment21</guid><pubDate>Tue, 28 Feb 2012 14:40:02 GMT</pubDate></item><item><title>Ayende Rahien commented on Ask Ayende: Aggregates and repositories</title><description>Falhar,
You mean, in the same sense that I can give you CheatingRepository : IRepository ?</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment20</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment20</guid><pubDate>Tue, 28 Feb 2012 14:29:56 GMT</pubDate></item><item><title>Falhar commented on Ask Ayende: Aggregates and repositories</title><description>@Apostol: But with Repository, the logic is still a domain logic. Or at least, can be enforced as such. With delegate, I can give it any method. Not only the one containing domain logic. And noone is gona ensure me, that the correct method will be used.

If someone else will want to change BirthDate, then it is not obvious to know what kind of method they should pass in.
With Repository, this is obvious. Because there is only one in whole application. (either one specific, or one generic)</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment19</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment19</guid><pubDate>Tue, 28 Feb 2012 14:28:19 GMT</pubDate></item><item><title>Apostol  commented on Ask Ayende: Aggregates and repositories</title><description>@Falhar But you cannot *Enforce* The Repository to have the correct domain logic either.

The meaning of the repository in this case is to get the proper BirthPlace by date. The meaning of the delegate is the same.
With the repository you just include a unnecessary abstraction which makes the code harder to use.

You basically trade more lines of code for a *feeling* that the code is properly structured. You can't even *enforce* that the code would be properly structured.

If you want the code to be properly structured - make a Coding Style document and follow it. Don't write more code.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment18</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment18</guid><pubDate>Tue, 28 Feb 2012 14:15:53 GMT</pubDate></item><item><title>Falhar commented on Ask Ayende: Aggregates and repositories</title><description>@Apostol:
No. This is not implementation detail. This is doman detail.

With repository, the method says:
- if date changed
- from all BirthPlaces
- select the one by date

With delagate, the method says:
-if date changed
-get BirthPlace with date parametter

You cannot enforce, that the delegate passed will have correct domain logic. And slecting correct BirthPlace IS domain logic. Not implementation detail.

This whole thing asumes, the one who will use this code, will not change the meaning of IRepository. When I have repository, I know I work over all persisted entities with specific domain logic. 

This refactoring changed the meaning of the method.</description><link>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment17</link><guid>http://ayende.com/153700/ask-ayende-aggregates-and-repositories#comment17</guid><pubDate>Tue, 28 Feb 2012 13:50:19 GMT</pubDate></item></channel></rss>