[HN Gopher] Inversion of Control Containers and the Dependency I...
___________________________________________________________________
Inversion of Control Containers and the Dependency Injection
pattern (2004)
Author : Tomte
Score : 37 points
Date : 2024-02-20 12:10 UTC (1 days ago)
(HTM) web link (martinfowler.com)
(TXT) w3m dump (martinfowler.com)
| TheAlchemist wrote:
| It's a very good article. I wish I knew how to find this at the
| time when it was written.
|
| I remember when I first discovered the pattern, at a job I took
| 10 years after this article. The codebase seemed so clean, easy
| to evolve and test, even for a newbie and 'half programmer' as me
| - my mind was blown. I was thinking - what kind of black magic is
| this ?!
|
| Say you're new to programming. What's the best place today to
| learn about design patterns (with python examples, since it's the
| most used language for beginners) in an easy and accessible way ?
| mcnichol wrote:
| Head First Design Patterns. It's a recent and very friendly
| introduction to the popular Gang of 4 - Object Oriented
| Programming book.
|
| I love this part of the journey for folks because it opens the
| door to a world of possibilities that has dramatically more
| structure and form. Thoughts and ideas become less "what if.."
| and more puzzling together the best interactions between
| certain design implementations.
|
| At risk of rattling on endlessly in my excitement for you, TDD
| became a very interesting and enjoyable way (for me at least)
| to implement these patterns and gain a better understanding. I
| think you'll find Martin Fowler, TDD, and IoC/DI are peas in a
| pod.
|
| (I realize you said Python and this was Java. I'll see if I can
| find something Python friendly. If you'd like to try your hand
| with Java....I highly highly recommend Spring Framework and
| more specifically Spring Boot. Spring is an IoC Container
| Framework where the Dependency Injection is done for you on the
| fly. So much to throw at someone but if you'd like to connect
| on it, I'd be more than happy to give you a running start.)
| uptownhr wrote:
| I would love to pair with someone that works through TDD. I
| personally tried it a few times in the past and constantly
| got stuck for one reason or another. My conclusion is that
| testing is hard and guides and articles online don't do it
| justice. Anyone love and practice TDD and want to help
| another engineer out, please reach out :)
| bb86754 wrote:
| Dependency Injection Principles, Practices, and Patterns by
| Mark Seemann.
|
| Examples are in C# but it's a great book about OOP in general.
| ayhanfuat wrote:
| If you are a beginner and you are coding in Python, I'd say
| hold off on the design patterns (as defined by the gang of
| four) but instead focus on idiomatic Python. The reason is many
| of the design patterns are baked into the language. It may
| create more confusion. For idiomatic Python, I can recommend
| two books that I've found really helpful: 1. Python Cookbook by
| David Beazley (it doesn't have the latest features like pattern
| matching but the 3rd edition uses Python 3 and it is still very
| relevant) 2. Fluent Python by Luciano Ramalho (the book itself
| is very good but it is also very valuable for the list of
| suggested readings at the end of each chapter).
| tester756 wrote:
| >hat's the best place today to learn about design patterns
| (with python examples, since it's the most used language for
| beginners) in an easy and accessible way ?
|
| https://en.wikipedia.org/wiki/Result_type
|
| https://github.com/rustedpy/result
| nicklecompte wrote:
| I would second ayhanfuat's comment[1] - if the programming
| beginner is at the level that we'd prefer to show them Python
| over Java or C#, then they probably aren't ready for
| understanding these design patterns.
|
| The other thing is that Python doesn't actually seem like a
| good language to discuss these abstractions compared to Java or
| C#: it's dynamically/gradually typed and in general
| dependencies are handled in a more "UNIX"-y way. In particular
| Python doesn't have first-class interfaces (at least last I
| checked, maybe mypy has something?). But statically-checked
| first-class interfaces are critical for why e.g. the service
| locator pattern works "seamlessly"[2] in real-life Java/C#
| codebases with lots of people doing lots of different things.
|
| My gut is that a lot of inversion-of-control design patterns
| don't actually work so well in _practical_ Python compared to
| just throwing things in a dictionary /etc and using strings +
| careful unit testing. I do see there are some service locator
| Python packages so maybe I am being too closed-minded. But for
| _teaching_ C# /Java is probably a better choice.
|
| [1] https://news.ycombinator.com/item?id=39459732
|
| [2] I have been mystified by too many null pointers to say this
| with a straight face. But when the bugs are squashed it really
| does manage a "magical" level of complexity.
| polotics wrote:
| Wow, are you really sure you've updated your priors? This
| notion that Python is for programming beginners as opposed to
| Java/C# has aged quite a bit has it not?
|
| In other news, ten years on the game's been up a while now,
| Fowler's profusion of wordage plastered onto simple
| functional concept, eg. in the present case: partial function
| application, doesn't really fly so well, even in the
| enterprise.
| bobfromhuddle wrote:
| If you're new to programming, steer clear of design patterns.
| If you're a working python programmer who's curious about how
| other ecosystems use design patterns, try
| https://www.cosmicpython.com/
| Veserv wrote:
| Dependency injection has always been such a bad name for the
| concept. It is just passing dependencys as arguments.
|
| Though the funniest part about it is that the things we use every
| day, programming languages and build systems, still do not
| generally use this concept. Your imports are dependencies, you
| should just pass them in. Wham bam, no more environment
| variables, ambiguity, lookups, multiple version ambiguity,
| rewiring challenges, naming conflicts, etc.
|
| Well, you still need somebody to know so they can instantiate the
| correct dependency versions in the first place (which you could
| implement as a snazzy automatic dependency resolver), but all of
| the internal ambiguitys disappear. Replacing a library (with a
| drop-in compatible one) would be just instantiating a different
| codebase into the same symbol name which will get passed in
| exactly the same way as the old one.
| peheje wrote:
| This has become so seeped into how we develop dotnet c# past
| couple of years. Just using Microsoft built in ServiceCollection.
|
| Honestly I think this is the most important pattern in my line of
| work. It has become so common for me. That when I see c# code not
| using it. It almost looks like another language.
|
| Testing becomes so easy because everything is easy to mock out.
| Be it in a unit test using some mock framework. Or a real
| 'integration-test' where you write a small in memory queue mock
| by hand to easy your tests.
|
| Object lifetime is easy to change and manage. Just how you
| register the dependency. As scoped (to http request for example)
| as transient (every time you ask) or singleton?
|
| Want to do something before/after with some hook? Just Decorate
| the dependency and register it to the container.
|
| Nothing feels tangled. Just inject the service. Call the method.
| Do the thing. No need to worry about cleanup or how to create the
| dependency. It's already setup.
| tester756 wrote:
| >That when I see c# code not using it. It almost looks like
| another language.
|
| On the other hand
|
| While I see the value of DI containers in web apps (ASP.NET)
|
| Then I don't really see the value of it in console apps (tools)
| (yea, asp app is console too, ik.)
|
| You may ask what's the difference and in my opinion the
| difference is: input/output flow model
|
| In web app you run your app with some args/envs, and then
| you're receiving request and return them results.
|
| In console app your run your app with some args/envs and then
| you're doing stuff until you complete (ofc unless you're
| listening/waiting for things... like in web app)
|
| In this 2nd model DI containers seem to not give me anything
| useful. You even were writing about this here:
|
| >"Just how you register the dependency. As scoped (to http
| request for example) as transient (every time you ask) or
| singleton?"
|
| It fits asp request/response model very well, but for other
| things? I dont feel it
| nh23423fefe wrote:
| The value was always the implicit object graph. I don't see
| what IO has to do with it. DI lets you label nodes and the
| container toposorts and makes edges for you.
| tester756 wrote:
| >I don't see what IO has to do with it.
|
| ASP web framework creates instances of Controllers
| (handlers) on request basis, that's when they need to
| resolve dependencies in order to create them, so it fits it
| very well.
|
| But when I need to create instance of some repository, some
| background job handler and some csv writer, then why would
| I want to do it via DI container?
|
| >DI
|
| I'm talking about containers, just containers.
|
| DI != DI containers
| behnamoh wrote:
| Genuine question: What design pattern works best here:
|
| Let's say I want to write small functions that do one thing very
| well: args = {LLM parameters, e.g., prompt}
| 1. foo(args): calls the LLM API with args 2. goo
| (foo(args)): uses backoff (retry) and makes sure the output is
| JSON 3. hoo(goo(foo(args))): extracts and desers the JSON
|
| At any point, things could go wrong. I could use a monadic
| approach and turn each of these functions into a monad:
| 1. foo: args -> Maybe(API_res) 2. goo: Maybe(API_res) ->
| Maybe(JSON) 3. hoo: Maybe(JSON) -> Maybe(dict)
|
| But before I knew about monads, I thought: wouldn't be cool if
| when a function goes wrong and needs to be called again, it had
| access to its "parent" function which called it? Like:
|
| Currently args is only passed to foo. What if, depending on how
| things went wrong, goo needed to see args?
|
| One approach is to make foo pass its args as well:
| foo: args -> args, output
|
| Then goo would take that and do something with it. But what if
| now hoo also needed to know about args to make sure the extracted
| JSON conforms to the JSON schema mentioned in args? Now we'd have
| to do: foo: args -> args, output goo:
| args, output -> args, output, JSON goo: args, output,
| JSON -> dict (deserialized JSON)
|
| I think this is not "elegant". Is there any better solution?
| nh23423fefe wrote:
| foo should hold the args and be a command object, not a result
| type
|
| goo should take foo as argument and delegate to the command in
| its loop
|
| hoo shouldn't be a Maybe. if you want that function then lift
| hoo instead of writing it, that's fmap hoo
| jauntywundrkind wrote:
| I wish we were seeing better hope for IoC in webdev today!
|
| I feel like there's a general feeling that:
|
| > _It is just passing dependencys as arguments._
|
| (And: oh no, magic!)
|
| That's often what consumers see, sure.
|
| But it's also managed repositories of objects and factories. It's
| also injection logic, with scope and conditional logic. It's also
| runtime assembleable interception layers for objects. It's also
| awareness methods to observe and track your managed repositories
| & objects.
|
| There's simple things we see. But zooming out from the trees I
| think the forest here is something more than the sun of these
| pieces. Programs are mostly here to juggle entities of various
| sorts. Mostly we programmers write code that imperatively creates
| & modifier objects & their references...
|
| And Dependency Injection and Inversion of Control is having
| explicit tooling & stable patterns for this construction. Having
| actual places & tools for managing runtime objects.
|
| I think it's so damned cool. It's so enticing to me, of being
| expanded beyond a programmer tool. It could & should pioneer
| waves of general systems research! This tech should offer
| external hooks beyond the app, be integrated into repls & hosting
| apis that let us talk to the computing objects of our world.
|
| Invert the control! I cannot wait for us to stop doing all coding
| bottom up, instantiating and passing everything from the
| bottom.up, and starting to create some top down tools that manage
| the entities of the runtime!
___________________________________________________________________
(page generated 2024-02-21 23:01 UTC)