> the factory/provider/whatever pattern, comes in real handy when 2 years from now, a crucial ODE library that your air-defense system uses, absolutely has to be replaced by something else.

Hmm; that's the point where your enterprise experience and mine diverge. Here are what I consider the key observations from the organisations I've seen:

The majority of uses of dependency injection seem to be an attempt by a developer to not commit to a technology choice, or to build and preserve some feeling of control over the selection of platforms and technologies. Often I think this is a result of technology platform choices being taken away from the developer, typically by some kind of architecture function. So we abstract away from databases, ORMs, XML binding libraries, network transports, messaging systems, basically anything that's not part of the core application. See Java Enterprise Edition deployment descriptors for an industrialised example.

At the same time, in any sufficiently complex enterprise environment, the chances of any of the platform technology choices changing rapidly is tiny because of the basic risk avoidance culture. And even if you do decide to try migrating to a new technology platform (e.g. database, app server, messaging platform etc), none of the existing deployed applications will migrate because the cost of retesting the application on the new platform is too high relative to the business benefit you can demonstrate.

It doesn't matter if you say "it's just a 20 line configuration change": the result of your configuration change is to switch from one implementation containing thousands of lines of code to another implementation containing thousands of lines of different code. Your ops team simply won't trust you to put that configuration change live without as much testing as when you put the original application into production. And if it's several months since the last production change, good luck getting hold of the people who can carry out the testing - they'll all be off doing other things.

So the developer is building abstractions to insulate from changes in technology that never happen, but at the same time the one kind of change that's guaranteed to come along over the lifetime of a deployed application is a change in business requirements. And this is typically the exact type of change that all the abstraction and configuration frameworks don't tackle, because it usually results in changes in the way that components interact with each other, not just substituting one interchangeable part for another.

So, who can gain from abstracting away from the technology platform? Well the main benefit comes when you want the same code to run in many different environments. So the main uses in descending order of likelihood:

* You might sell the same piece of software into multiple customers and want to support the variation in environments you'll find. Hello, IBM, Oracle and SAP, as you point out.

* You might have different configurations of your software for different environments (development, test, staging, production and so on), but you need to be careful to make sure your test results from one configuration are actually valid for another.

* You might actually need to run the same code in production in more than one environment. There are cases where this happens (e.g. in a desktop app vs. a web app, or a mobile app), but often its just as easy to build an API around the code and invoke it over the network.

So, in my experience the effort of implementing all this configurable decoupling is very rarely rewarded by a significant reduction in downstream effort.