Hacker News new | ask | show | jobs
by roam 4886 days ago
Don't use IoC if you don't need it, but I'll explain why we need it in our case: some customers require different implementations.

That's where the DI part comes from -- to enable us to load a different dependency based on the customer. Now, you could provide a different bootstrapper class per customer or start building a mega class with a lot of ifs-and-buts(elses), or you specify this kind of stuff in a configuration file.

We opt for configuration files. We opt for IDEs that can interpret Spring configuration files which means typos or incorrect dependencies do show up. This allows us to swap out implementations in case shit goes down without having to recompile, connect over a VPN to a remote desktop and hop through a few more hoops to get our class file on the other side. If you're not running your own apps on infrastructure you control (we should be so lucky), you have to take this sort of stuff into account. I'd love to be able to say "This is how stuff's set up. Deal with it."

(And when shit goes down, it is usually not at the place you were expecting it to happen, which means all kinds of configuration options for your bootstrapper would probably still fall short.)

4 comments

I agree with using IoC for different implementations, but I'm puzzled by those who want to use it everywhere, because it supposedly makes the code easier to test.

Guice is a nice IoC framework, but look at what they say on their website:

"Think of Guice's @Inject as the new new."

http://code.google.com/p/google-guice/

Testing is kind of a side effect. When you design your code with IoC in mind, you naturally will create more logical separations and avoid tight coupling -- which in turn will make your code easier to test. (Source: I wrote Ninject. :)
If your code has a hard-static dependencies to web-service call, you can't test it easily (and repeatedly). Especially when the actual service is down.

If your code has a hard-static dependencies to DB call, you now have excuses not to write test against it because "it's hard to prepare the environment to do such things."

Not all projects are as small as a Todo-List written using Rails.

Medium-to-Large size projects with large DB schemas exist in which it will take hours to run your Rails tests: "testing-my-active-record-models-as-unit-tests"

Exactly, you should really think about when and if you need IoC, just like with any other technique. It can be really useful. Unfortunately, if misused, it can lead to an absolute nightmare.

The problem is that when people learn about new techniques then they end up wanting to use those techniques in their next project. It reminds me of something a doctor said to me once, "Every time a new disease is identified there's an epidemic." Meaning that when doctors have something they can now identify as the new disease they are much more likely to do so since they've just heard about it, when before they would have identified it as "flu".

Or as a senior developer I know often said, "To the man with a hammer, everything looks like a nail."
Why not just split out the shared code into libraries and make your main() be different for each customer?
Then updates to the customer's configuration requires modifying code, compiling it, and shipping the result. It's easy to put an interface on configuration file modification and in many cases, updates can be applied without needing to restart a running system.
That's the problem with soft-coding, you trick yourself into believing that modifying a configuration file is not modifying code, but it is. It's code that isn't compiled, isn't regression tested.

As far as re-shipping, nearly every language nowadays has a method for automatic updates. Here is what Chrome uses: https://code.google.com/p/omaha/

It's absolutely modifying code.

But it's modifying code that your support team is allowed to modify in the field. By contrast, depending on the business policies in place any code that has to go through a compiler might also have to go through meetings, reviews, QA testing, a release cycle, IT department scheduling, acceptance testing, blah blah blah.

By this logic, every user is "programming" when they change their facebook account settings or configure the appearance of their desktop. Call it what you want, but configuration via "config files" of some sort (perhaps managed by a GUI) is a totally different beast from modifying 'main'.
There really isn't much difference between using a bootstrapper class or a spring xml file, they're still both configuration files and should be equally convenient to maintain.

One of the advantages spring gives you in your scenario is multiple options for configuring your app. So in your case you can use annotations for parts of the app that don't change and then specify the parts that are different for each customer using xml(I seem to recall you might even be able to wire up a spring container using vanilla java).

Spring actually brings a lot more to the table, properly qualifying it as an IOC container. It offers mechanisms for applying cross-cutting aspects such as transaction and security management.