Ioc Containers and dynamic languages (take 2)
I've been reading up a lot on Dependency Injection, Inversion of Control, and IoC containers. I al开发者_StackOverflow社区so primarily program in dynamic languages (PHP at work, Python at home). Here are the things I'm finding, but this leaves a lot of gaps for me to fill as I piece it all together:
- Why are IOC containers unnecessary with dynamic languages?
- Why do I need an IoC container as opposed to straightforward DI code?
- Advantages an IoC container provides beyond simple DI (blog post)
So what I'm reading is: IoC containers are a much bigger deal in static languages, because it's so much easier to perform DI in dynamic languages. But they also provide benefits far beyond DI, like managing dependencies for you and saving you from having to string together a dozen objects by hand. And, incidentally, they are complicated, so don't try to do them yourself (but no good ones exist for PHP).
I feel like this information leaves me kind of... stuck. What do I do with it? I work in a very large codebase, with very complicated dependencies (and probably a strong need for refactoring, but that's another parallel issue). We've done very poorly at implementing DI up till now, and I'm really trying to turn us in the right direction. There just seems to be nothing out there in regards to dynamic languages and IoC (or at least IoC containers).
Am I better off "hand-stringing" dependencies together for the time being, and worry about automating it in a container later, after I get a better handle on the principles? Is it worth implementing my own simple IoC container? Or is the benefit just not ultimately worth the cost in PHP?
For PHP try Symfony Dependency Injection. It's (supposedly - I've too little experience to validate that) based on how Java Spring works, but using a lot of PHP 'magic' too. AS a result it's quite lightweight and easy to use, while being able to do quite a lot.
First fix your dependency issues. If you use a IoC Container as a bag that deals with your dependencies for you it will bite you really hard not too far down the line.
IoC containers should give you an API/Vocabulary for talking about the system architecture.
Dependency injection leads you to use smaller decoupled classes that act as building blocks for subsystems. This is good as it lets you test your building blocks in isolation and reason about them it more easily. (You can think of them like electronic components in a circuit)
IoC Containers should give you a way to clearly express the composition of these building blocks. (the wiring diagram linking the components together)
Having this separation also lets you start thinking about the lifetimes of your subsystems.. when to use factories, registries, how to pass messages around the system without introducing coupling.. etc.
The point of IOC it to give you a place to explicitly state all this logic, not to magically solve it for you.
I hope this helps.
Martin Fowler wrote this article that is pretty much a bible for inversion of control and dependency injection. He explains how to implement an IoC container and discusses the merits of different injection mechanisms. http://martinfowler.com/articles/injection.html
No matter what language you are using "hand-stringing dependencies" is not scalable. It will be difficult to maintain, because other developers probably don't know where all the hand-stringing takes place, so when they change something they might not change the right thing. By contrast, putting all this in one place will make future changes much easier to implement. IoC helps to minimize repetitive code, and ensure a separation of concerns and consistent application architecture.
On the other hand, it sounds like you have a pretty large functioning application on your hands - and unless you also have a lot of time, if it's not broken, it might not be necessary to fix.
If you don't want to have an overdesigned DIC but one that delivers all that you need in a very compact way, try this one: Bucket (https://github.com/troelskn/bucket). A DI container does not need more. Beside Symfony's one is often used in a very dangerous way, as a service locator (the nicer alias global state).
If you think your IoC is/can be more lightweight then what other frameworks already have and if you have enough time to develop it then build your own. I personally use IoC in my MVC framework just for linking the View to the Controller. I manage the view and it's parameters from a registry (a standardized structure associative array).Models are handled as external services. I also found IoC and DI first time on Java so I tried to take what's best from both languages (Java and PHP) when I built mine.Of course it does not link anything to anything, but I do not need that for my case, so you might not either.
IoC is important for providing flexibility over time but how much flexibility? Do you work with many external components? Do you work with standard plugins and objects? PHP is not java, you do not have that sack of jars and libraries so well developed ready to implement any time by just loading it and replacing a directive in an XML to point at it, think about that.
I've found out excellent IoC implementation on an exceptional open source software called Alfresco (Document Management System). It is a product that brings together JSF,Spring,Hibernate and freemarker template, but as I said it is a product meant to be fit into thousands of business models, it is more like a highly advanced platform meant to be altered endlessly, so it needs to be highly flexible.
If you are developing a targeted application, meant for serving one business model and just a few customers, then plunging into IoC blossom will make things tougher rather than simpler.
Einstein said that things must be simple, but not simpler than they are.
精彩评论