tag:blogger.com,1999:blog-15136575.post4606623339199526233..comments2023-10-17T12:00:16.772+01:00Comments on Code rant: Delegates make great container componentsMike Hadlowhttp://www.blogger.com/profile/16441901713967254504noreply@blogger.comBlogger15125tag:blogger.com,1999:blog-15136575.post-4776173131294795892011-02-17T16:58:28.754+00:002011-02-17T16:58:28.754+00:00Nick,
"I was just digging a bit deeper, wond...Nick,<br /><br />"I was just digging a bit deeper, wondering if it gets a bit easy to start relying on the container when maybe you shouldn't?"<br /><br />Well of course the whole application structure relies on the container to wire it together. In this example we're registering functions with the container so that they can be passed by the container to components that depend on them.<br /><br />The magic is that we never see any direct reference to the container in our code (apart from the component registration and single call to resolve buried deep in our framework).Mike Hadlowhttps://www.blogger.com/profile/16441901713967254504noreply@blogger.comtag:blogger.com,1999:blog-15136575.post-73451454039494124972011-02-17T16:35:06.775+00:002011-02-17T16:35:06.775+00:00No, no it does seem a good way to do things and pe...No, no it does seem a good way to do things and perfectly explained. <br /><br />I was just digging a bit deeper, wondering if it gets a bit easy to start relying on the container when maybe you shouldn't?nickhttp://nick@NTCODING.CO.UKnoreply@blogger.comtag:blogger.com,1999:blog-15136575.post-46679253812396434282011-02-16T22:55:09.731+00:002011-02-16T22:55:09.731+00:00Richard, sorry, sense of humour bypass :p
I'm...Richard, sorry, sense of humour bypass :p<br /><br />I'm so into my currying I forget how stupid it sounds.Mike Hadlowhttps://www.blogger.com/profile/16441901713967254504noreply@blogger.comtag:blogger.com,1999:blog-15136575.post-51543501119749810222011-02-16T22:53:32.290+00:002011-02-16T22:53:32.290+00:00Hi Mike,
Once again a great post. The currying co...Hi Mike,<br /><br />Once again a great post. The currying containers was me trying to be funny (obviously it failed!<br /><br /> I'll try to be less humorous in the future!Richard ODhttps://www.blogger.com/profile/13855706515612188950noreply@blogger.comtag:blogger.com,1999:blog-15136575.post-14426212593720283372011-02-16T21:46:34.438+00:002011-02-16T21:46:34.438+00:00Thanks for the kind words Nick.
Yes, scattering c...Thanks for the kind words Nick.<br /><br />Yes, scattering calls to container.Resolve() around your code is an anti-pattern.<br /><br />Here I'm simply pointing out that delegates can define service contracts in the same way as interfaces.<br /><br />Does this make no sense?Mike Hadlowhttps://www.blogger.com/profile/16441901713967254504noreply@blogger.comtag:blogger.com,1999:blog-15136575.post-41132163252730743372011-02-16T19:37:12.555+00:002011-02-16T19:37:12.555+00:00Mike,
You talked in a previous post about relying...Mike,<br /><br />You talked in a previous post about relying on the container, and making calls to the container as "a bit of an anti-pattern".<br /><br />Could you possibly elaborate on how that would, or wouldn't, apply in conjunction with this?<br /><br />Good to learn new tricks. Cheers mate.Nickhttp://www.ntcoding.co.uknoreply@blogger.comtag:blogger.com,1999:blog-15136575.post-12154427635240520912011-02-16T08:50:00.338+00:002011-02-16T08:50:00.338+00:00"I look forward to your posts on 'curryin..."I look forward to your posts on 'currying containers'." - Didn't you notice, the last sentence was a link to the post on currying containers :)Mike Hadlowhttps://www.blogger.com/profile/16441901713967254504noreply@blogger.comtag:blogger.com,1999:blog-15136575.post-27941537736878102762011-02-16T05:07:12.585+00:002011-02-16T05:07:12.585+00:00+1 on currying containers+1 on currying containersJeffhttp://www.agilification.comnoreply@blogger.comtag:blogger.com,1999:blog-15136575.post-64458689589024966322011-02-15T22:37:24.100+00:002011-02-15T22:37:24.100+00:00Mike,
Yes the downside to the static Func is the ...Mike,<br /><br />Yes the downside to the static Func is the fact it returns the new value after assignment! I was going to add that! I'm sure that could lead to people writing unrepeatable tests if they were not careful! Yikes!<br /><br />TBH I'm not happy with any of the approaches 100%, but I still think the interface based approach is the most common and pragmatic, and that is the approach I always use in situations like this (until I'm convinced otherwise).<br /><br />The thing I don't like about this:<br />container.Register(<br />Component.For().Instance(() => DateTime.Now),<br /><br />Is it isn't obvious to call DateTime.Now either- this is even less obvious to me than having to add teardown behaviour to the static Func example I described earlier! <br /><br />Also how would it work if you are storing container configuration in a config file (I'm not familar with Windsor- but can't imagine this is possible/desirable?)<br /><br />I've always thought of delegates as being the equivalent to a single method interface (obviously it is not that simple, you can't do Interface.BeginInvoke!) but a useful comparision sometimes.<br /><br />I look forward to your posts on 'currying containers'.Richard ODhttps://www.blogger.com/profile/13855706515612188950noreply@blogger.comtag:blogger.com,1999:blog-15136575.post-11493300680479304962011-02-15T21:39:37.203+00:002011-02-15T21:39:37.203+00:00After a few seconds' more thought... The reaso...After a few seconds' more thought... The reason I don't like the static Func<DateTime> field is because there's some vagueness about what its value might be. In my tests I'd have to set it to some stubbed value, but then set it back to it's original value afterwards, which I'd have to be aware of. The test would be expected to know far too much about the mechanics of CurrentTime.Now. By passing a delegate in as a dependency we're being explicit about it's implementation for that particular instance of the client component.Mike Hadlowhttps://www.blogger.com/profile/16441901713967254504noreply@blogger.comtag:blogger.com,1999:blog-15136575.post-23693319855607446632011-02-15T21:34:22.676+00:002011-02-15T21:34:22.676+00:00Hi Richard,
Well, the whole point of the post is ...Hi Richard,<br /><br />Well, the whole point of the post is that interfaces are too much ceremony in many cases. In any case, you can think of delegates as method interfaces, except that they're more flexible in some ways. Like the fact that you don't have to declare a method or lambda as implementing a particular delegate.<br /><br />I don't like the smell of your static field 'Now', but TBH, I can't see any benefit of using the container over it currently. Of course if I had my 'currying container' then the compositional possibilities would steer me back towards the container based delegate, but you've got me thinking, thanks :)Mike Hadlowhttps://www.blogger.com/profile/16441901713967254504noreply@blogger.comtag:blogger.com,1999:blog-15136575.post-89864274071364923532011-02-15T20:31:04.003+00:002011-02-15T20:31:04.003+00:00Mike,
Sorry, just realised CurrentTime should be:...Mike,<br /><br />Sorry, just realised CurrentTime should be:<br /><br /> public static class CurrentTime<br /> {<br /> public static Func Now = () => DateTime.Now;<br /> }Richard ODhttps://www.blogger.com/profile/13855706515612188950noreply@blogger.comtag:blogger.com,1999:blog-15136575.post-11063808279113210872011-02-15T20:21:35.679+00:002011-02-15T20:21:35.679+00:00Mike,
Didn't think about the container not wo...Mike,<br /><br />Didn't think about the container not working- good point. In which case I'd probably stick to using interfaces!<br /><br />Another option, would be to define a class as follows:<br /><br /> public static class CurrentTime<br /> {<br /> public static Func Now = () => new DateTime();<br /> }<br /><br />This can then be used as follows:<br /> DateTime now = CurrentTime.Now();<br /> Console.WriteLine(CurrentTime.Now());<br /> CurrentTime.Now = () => new DateTime(2010, 2, 15);<br /><br /> Console.WriteLine(CurrentTime.Now());<br />Console.ReadLine();<br /><br />Sorry about the code formatting!<br /><br />Yet another option would be to use TypeMock isolator or Moles.Richard ODhttps://www.blogger.com/profile/13855706515612188950noreply@blogger.comtag:blogger.com,1999:blog-15136575.post-42234265495623873052011-02-15T19:48:22.141+00:002011-02-15T19:48:22.141+00:00Hi Richard,
Sorry, I disagree. In this case it...Hi Richard,<br /><br />Sorry, I disagree. In this case it's definitely best to declare your own delegates. Of course you could use Func<DateTime> in my example, in fact that's how I started out implementing these things. But say you wanted some other service that provided say, next weekend. Then you'd have two Func<DateTime> and no way to for the container to differentiate between them, because you can only have one instance defined for a single service.<br /><br />It's also more intention revealing. Better to have a dependency on 'Now' than 'Func<DateTime>', there's no clue with the latter about what that DateTime represents.Mike Hadlowhttps://www.blogger.com/profile/16441901713967254504noreply@blogger.comtag:blogger.com,1999:blog-15136575.post-54238075332698952242011-02-15T19:15:17.150+00:002011-02-15T19:15:17.150+00:00Interesting idea, however it is best practise not ...Interesting idea, however it is best practise not to declare your own delegates- use Func and Action instead.Richard ODhttps://www.blogger.com/profile/13855706515612188950noreply@blogger.com