6 ms·
From dependency injection to dependency rejection
- pmarreck 10y agoMore evidence that functional programming is a useful simplification/complexity reduction on a number of older paradigms.
- yawaramin 10y agoFunctional programming is actually the older paradigm (if you're comparing to OOP), but I get your point.
- kornish 10y agoThis reminds me a lot of Gary Bernhardt's Boundaries talk and the associated idea of "functional core, imperative shell". For anyone who found this article interesting, you might also like this: https://www.destroyallsoftware.com/talks/boundaries https://www.destroyallsoftware.com/talks/boundaries
- charlieflowers 10y agoThanks for sharing that. That's a great link, and I agree, they are talking about the same thing and reaching pretty much the same conclusion. The talk is well worth checking out.
- charlieflowers 10y agoVery good article. If you think about it, you will see this pattern in many places. Simply because it is the outcome of emphasizing pure functions. For example, it's the heart of the virtual DOM in React. Pure functions create an entirely new (no mutation) virtual DOM, and then something at the "impure boundary" applies this to the actual, messy, mutable DOM of the browser. With a little thought you can probably find several other well-known examples.
- obstinate 10y agoIt's interesting -- this is not what I generally end up using DI for. The point of DI, a lot of the time, is to put seams into the program where you can test units of a limited size. If you don't have some way of injecting behavior, you end up having some serious trouble when you have a module that brings together the behavior of many sub-modules (how do you test it?). That's something these short code example style articles never seem to capture for me.
- DenisM 10y agoWhy not test the whole thing together? That's what it was meant to be - a whole.
- solipsism 10y agoPlease don't ever work for NASA!
- bbcbasic 10y ago1. Speed of automated tests. 2. Often it is good to test the semantics of a sub system are solid before integrating it so that edge cases are routed out and at the very least it's easy to find where a break occurred.
- marvin 10y ago3. You might have external dependencies that are difficult or impossible to duplicate in your testing environment. Yes, stuff like this exists -- e.g. a medium-size retail bank will have at least a dozen, typically multiple-dozens of external contractors, each with their own APIs and testing environments.
- DenisM 10y agoThis is the only answer that speaks to me. Although I would think most often you would have such dependencies be API calls over network. It would me more prudent in such case to create a mock server rather than use DI. But yeah, in general API from a third party might call for DI. Thanks.
- daxfohl 10y agoTwo things: 1. This is overly simplistic. What happens if your IO and logic are by necessity interleaved? Grab X out of DB, grab Y or Z out of DB depending on X's value, etc.? The whole thing just reeks of "ideal case". 2. This is overly complex. All that really needs to be said here is "pull out your pure code when possible". There's nothing special about F# to enable that. The logic in "tryAcceptComposition" is just a function calling other functions; you can do that in C# or even C. The only advantage F# adds here is the piping syntax, which to me only serves to make the code more obtuse. But I guess you couldn't write a three-part series about a single "extract pure function" op. (This brings up an interesting thought: ReSharper should come up with a way to let you highlight a function and extract the "obviously pure" tidbits automatically).
- yawaramin 10y agoYou may find it interesting to go over a similar conversation I had with the post author a few days ago https://github.com/ploeh/ploeh.github.com/commit/f89c405e92b69c4dfcc65c336a0ff4528f50f029#commitcomment-20681176 https://github.com/ploeh/ploeh.github.com/commit/f89c405e92b...
- daxfohl 10y agoI'll have to learn more about free monads. In general I love F# for doing domain modeling and logic, but I still find OO-style DI better for organizing "services". I've followed ploeh and scott wlaschin for some time and all my attempts to use their DI concepts in my own real-world code have led to code that's less intelligible than IoC with no tangible benefit. It's not for lack of trying, and I think not for lack of intelligence. It just never worked for me. If free monads could provide something better than standard DI, and (and this is a big caveat) still retain decent editor integration (autocomplete, go-to-declaration/implementation), then I'd check it out. But my gut feeling says that it'll end up being a leaky abstraction that will need undue patching up just to maintain it.
- willtim 10y agoF# uses .NET classes and objects for a module system, so your use of Objects for "services" is not surprising. An OCaml programmer is much less likely to miss Objects and DI frameworks, as OCaml has a powerful module system (i.e. module functors). Free Monads can reify an effectful computation, giving flexibility on how it is interpreted. But they are not really a substitute for a good module system.
- JackMorgan 10y agoNice! An alternative is to try something like SimpleMock http://deliberate-software.com/simplemock-unit-test-mocking/ http://deliberate-software.com/simplemock-unit-test-mocking/ which strikes a balance between useful and easy to test. Also there's examples in F# http://deliberate-software.com/f-number-unit-testing/ http://deliberate-software.com/f-number-unit-testing/
- edem 10y agoThe key part about why dependency injection with partial application is not functional: > When you inject impure operations into an F# function, that function becomes impure as well. Dependency injection makes everything impure, which explains why it isn't functional.
- henriquelimao 10y agoIt seems that in the end the initial function Post(ReservationRequestDto dto) has to call the tryAcceptComposition which has its dependencies hard coded there. So how exactly this solved the issue? If you pass the dependencies as parameters in the tryAcceptComposition function, the Post would have to know its dependencies and we would be back to the initial state. I would like to know the whole example he showed before using this model to see how this scale for more than one function.