Why are IOC containers unnecessary with dynamic languages

后端 未结 9 1461
慢半拍i
慢半拍i 2020-12-04 12:13

Someone on the Herding Code podcast No. 68, http://herdingcode.com/herding-code-68-new-year-shenanigans/, stated that IOC containers had no place with Python or Javascript,

9条回答
  •  情书的邮戳
    2020-12-04 12:49

    I agree with the answers above, but I thought I'd chip in a little bit here too regarding testing:

    In complex systems where there are interactions between sub-systems dependency injection is the best way that I'm aware of to do unit testing.

    If you have a logic unit X, that has known interactions with logic unit Y, you can create a MockY that has a predefined behaviour and explicitly test the logic of X.

    Without dependency injection, writing tests is a nightmare. You cannot get good code coverage. Some frameworks (eg. django) work around this problem by spinning up mock database instances to talk to for tests, etc. but it's basically a poor solution to the problem.

    There should be two sorts of tests:

    • Unit tests that run in ANY environment and test the logic of individual code units.
    • Integration / functional tests that test the combined application logic.

    Now to the question: IoC. What is IoC good for? It's handy for a few things, but its really really good for making it easier to use dependency injection:

    // Do this every time you want an instance of myServiceType
    var SystemA = new SystemA()
    var SystemB = new SystemB()
    var SystemC = new SystemC(SystemA, "OtherThing")
    var SystemD = new SystemD(SystemB, SystemC)
    var IRepo = new MySqlRepo()
    var myService = new myServiceType(SystemD, IRepo)
    

    Into this logic:

    // Do this at application start
    Container.Register(ISystemA, SystemA)
    Container.Register(ISystemB, SystemB)
    Container.Register(ISystemC, SystemC)
    Container.Register(ISystemD, SystemD)
    Container.Register(IRepo, MySqlRepo)
    Container.Register(myServiceType)
    
    // Do this any time you like
    var myService = Container.resolve(myServiceType)
    

    Now, why don't we see IOC in many dynamic languages?

    I'd say the reason is that we don't see much dependency injection in those languages.

    ...and that would be because typically the testing done in them is non-existent.

    I've heard all kinds of excuses for this; interacting with the DOM makes tests hard, my code is simple enough it doesn't require tests, dynamic languages don't need unit tests because they're awesome and expressive.

    It's all nonsense.

    There is no excuse for a project without unit tests or unit tests with poor code coverage.

    ...but it's amazing the number of javascript and python projects I've seen (picking on these two specifically only because they're an area of interest and I've seen more projects of this type than others) with no IoC, no DI, and unsurprisingly, no tests.

    There is an excellent article on DI on the guice website here: http://code.google.com/p/google-guice/wiki/Motivation

    There is nothing about dynamic languages that solves any of these problems.

    Summary:

    • IoC is useful for things, but primarily for implementing DI
    • IoC is NOT xml config files. >_<
    • DI is useful for tests
    • Absence of IOC is indicative of the absence of DI, which is indicative of the absence of good testing.
    • Use IoC.

提交回复
热议问题