• fuck_u_spez@lemmy.fmhy.mlOP
    link
    fedilink
    arrow-up
    3
    arrow-down
    2
    ·
    edit-2
    1 year ago

    I still haven’t really understood the use (and use case) of “dependency injection” (and it feels to me I read now everything about dependency injection I could find), to me it seems to be yet another ProblemFactory.

    • CodeBlooded@programming.dev
      link
      fedilink
      arrow-up
      9
      ·
      edit-2
      1 year ago

      Single responsibility principle: is your GetData() function responsible for getting data? Or is it responsible for creating a new database connection and also using that to go get the data?

      Start naming your functions by what they really do. When you see the word “and” in your function name, you know your function is responsible for too much.

      Dependency injection is the difference between CreateDatabaseConnectionAndGetData() and GetData(connection ConnectionType).

      In the first example, that function will always connect to the specific db that you hard coded in it. It probably has to also read in a config file to get the connection details. Maybe you should name it ReadConfigAndCreateDatabaseConnectionAndGetData()?

      In the second example, I can pass in a MySQL connection or PostgreSQL connection, or some dummy connection for testing.

      Keep all that nasty dirty untestable code in one place and spare your business logic from owning all of that.

      • fuck_u_spez@lemmy.fmhy.mlOP
        link
        fedilink
        arrow-up
        2
        arrow-down
        3
        ·
        1 year ago

        Thanks for the write up, but as I said, I know and I’ve read all about that already. I still cannot see, why a simple function argument and an interface isn’t enough (you can probably already call that “dependency injection” if you want to get fancy)

        I guess I have just divorced with OOP and the “necessary” “design patterns”…

        Things are more simple and less boilerplaty now for me :).

        • bjornsno@lemm.ee
          link
          fedilink
          arrow-up
          12
          ·
          1 year ago

          My brother in Christ, that is dependency injection. Just because you don’t want to call the spade a spade anymore doesn’t make it not so.

            • bjornsno@lemm.ee
              link
              fedilink
              arrow-up
              5
              ·
              1 year ago

              You’re gonna have a tough time talking to others about your code if you don’t agree on common terminology. Function invocation is just function invocation, it doesn’t say anything about the form of the parameters or composition. Dependency injection is a well known and commonly understood method of facilitating decoupling and composition by passing a function’s dependencies as parameters. From your comments you’re talking about the second, but refusing the name, for… reasons?

              • philm@programming.dev
                link
                fedilink
                arrow-up
                2
                ·
                1 year ago

                I guess I’m a little bit too long already in the functional/data-driven world (after being a decade in OO languages (IMO too long…)). In OOP you may need a separate term for that.

                But I think it’ just not really necessary in functional programming, it’s just another parameter when calling a function, that may be a somewhat type-constrained generic (for testing e.g. with a mock implementation).

                I mean function parameters are somewhat dependencies anyway, so should I call all my parameters now dependencies and invocation “injection”?

                • bjornsno@lemm.ee
                  link
                  fedilink
                  arrow-up
                  2
                  ·
                  1 year ago

                  Thought you were OP for a second there, as they were talking about composability. Whether it’s dependency injection or not depends on what shape your parameters take. If you’re doing functional programming and you’re passing handlers and connections etc. as params, that’s dependency injection. If you’re only passing strings and objects and such and the function has to do a bunch of logic to decide how to handle its params, that’s not dependency injection.

                  • dreugeworst
                    link
                    fedilink
                    arrow-up
                    1
                    ·
                    1 year ago

                    I think the main reason OOP has a well-known term and pattern for dependency injection is to differentiate these two (out of multiple) options:

                    • the constructor of my object creates other objects it depends on itself
                    • I construct the dependencies of my object elsewhere and pass them in to the constructor and use an interface to make it easy to swap behaviour

                    However, this becomes less of a pattern in functional programming as you wouldn’t make such objects to begin with. In FP, you pass all parameters where a function is invoked, and DI just becomes using generic parameters. You wouldn’t instantiate a dependency on each function call after all.

                    As this is such a minor change, it’s not really talked about much and it’s not really a pattern,

            • jvisick@programming.dev
              link
              fedilink
              arrow-up
              3
              ·
              1 year ago

              “Dependency injection” is just a term for providing a function or method with its dependencies rather than making the function go and gather them itself.

              It’s (typically) done through parameters, but it’s still more specific than just invoking a function. It describes how that function was written and the reasoning for certain parameters. To the other commenter’s point, you’ll have a hard time communicating about your code with other developers if you refuse to use the term dependency injection just because you don’t like OOP.

            • dudinax@programming.dev
              link
              fedilink
              arrow-up
              2
              ·
              edit-2
              1 year ago

              Di is just good functional practice. I’m not sure it’s a super importent idea to someone who knows how to write a good function.

              Edit: “a function should do one thing and its operands should be passed as arguments” for the OO world.

              • MrShankles@reddthat.com
                link
                fedilink
                arrow-up
                4
                ·
                1 year ago

                I’m just lurking around, so don’t mind me. But I gotta say, it really does sound like y’all are just making shit up sometimes lol. Like a mechanic trying to charge you an extra 50 bucks because your jindle shaft needed an alignment

        • Smallletter@lemmy.world
          link
          fedilink
          arrow-up
          1
          ·
          1 year ago

          I’ve tried studying CSa d programming, both formally and informally, for long enough to know most of what y’all are talking about, but failed terribly enough that I still have no idea how people can actually build code. Syntax is easy enough, I always started a class like oh cool I can do this. And then they drop me off the deep end and I fail, every time. I work in IT infrastructure now and I’m happy to say I never have to worry about coding, though my foundational knowledge is useful for troubleshooting.

          • fuck_u_spez@lemmy.fmhy.mlOP
            link
            fedilink
            arrow-up
            1
            arrow-down
            2
            ·
            1 year ago

            It’s all about experience IMHO, just start small projects (and in my experience ignore all these “design patterns”, I learned quite a lot of patterns, but I’m not really using any of them nowadays, maybe sometimes intuitively, (as this thread shows, “dependency injection” which can be a fancy term for generic function parameters).

            Well maybe learn them, but take everything with a grain of salt, I think. Intuitively thinking is often better (with the drive to do it better). Try to write code such that it’s easily readable exactly focused on the problem that it’s trying to solve, not anything fancier (this is actually a very simple but effective Mantra). Otherwise it often leads to overengineering (all these “design patterns” for example…), or premature optimization. (E.g. something like the popular book “Clean code” is IMHO full of antipatterns, like the examples are definitely not something I would do, they are inefficient, boilerplate, and often make the code unreadable).

    • offbyone@reddthat.com
      link
      fedilink
      arrow-up
      2
      ·
      1 year ago

      Generally speaking the use case is writing tests. If your tests just call all the dependencies and new directly then it’s harder to write tests for your specific component while avoiding setting up a whole bunch of stuff (to make all those other classes work). By requiring all the dependencies to be provided to the class, you can swap them out at test time for something else that’s easier to work with.

      That said, IMO it’s a symptom of problems in language design. Using DI is only necessary because languages like C# don’t make it easy to mock out new or classes used directly, so we resort to wrapping everything in interfaces and factories to avoid those features and replace them with ones that are easier to mock. If the language was designed such that those features were easy to replace during testing then DI probably wouldn’t be a thing.

      • fuck_u_spez@lemmy.fmhy.mlOP
        link
        fedilink
        arrow-up
        1
        arrow-down
        2
        ·
        1 year ago

        It’s probably a general symptom of what people call OOP nowadays, in a more functional composeable world (where I’m living in currently). You just use function parameters and interfaces (or as Rust calls it “Traits”). But I still think in OOP, this is enough as well and the dataflow is more clear.