16

This is more of a nomenclature (technical writing) rather than a purely technical question. I am trying to write a refactoring proposal (and get it assigned to myself) centered around expanding dependency injection in our application. While we do use Spring for autowiring beans, there are still instances that instantiate beans using MyClass obj = new MyClass(...), which could totally be injected. I would like to make my proposal use elegant nomenclature and refer to the design pattern opposite of DI with a proper term.

Is "tight coupling" an adequate term that stands as an antonym to DI?

8
  • 1
    Yes, coupling describes both the act of using explicit class names in other classes and the resulting state of a code base. Commented Sep 30, 2016 at 14:33
  • 11
    No, tight coupling only describes the property of the resulting code, not the opposite of DI. You can use DI and still have tight coupling for completely different reasons.
    – Doc Brown
    Commented Sep 30, 2016 at 14:44
  • 1
    Agreed that DI and tight coupling are not opposites.
    – Eric King
    Commented Sep 30, 2016 at 19:16
  • 1
    "Dependency suction". Commented Oct 1, 2016 at 4:13
  • 1
    The opposite of dependency injection is called 'programming'.
    – mrr
    Commented Oct 4, 2016 at 23:02

5 Answers 5

32

Is "tight coupling" an adequate term that stands as an antonym to DI?

No. Tight coupling is much more than what dependency injection deals with.

Dependency injection externalizes a decision of implementation. This goes a long way to decouple but coupling is more than just this.

Technical term to denote opposite of dependency injection?

A good antonym for dependency injection is hard coding a dependency. When you construct (use new or directly use some factory) inside a behavior object you've smushed together two different concerns. A service locator helps decouple but leaves you coupled to the service locator itself.

Coupling is more than just separating construction and behavior. If I have 101 methods that have to be called in some particular order from class A to class B I'm tightly coupled. Doesn't matter how wonderfully separated construction and behavior are.

Coupling is a measure the interdependence of the two objects. Anything that contributes to making it difficult to make changes in one without impacting the other is contributing to coupling. Dependency injection helps with this but it is not all of this.

15
  • Yes, hard coding (a dependency), as opposed to injecting it (at runtime) is exactly what I was going to suggest, too, you just were a little bit quicker than me.
    – Doc Brown
    Commented Sep 30, 2016 at 14:48
  • 7
    @DocBrown I sometimes wish this place didn't put so much emphasis on being fast. I'd like to hear how you'd put it. Commented Sep 30, 2016 at 14:50
  • Good answer - dependency injection does not imply decoupling. Believing otherwise leads down a bad road
    – Ant P
    Commented Sep 30, 2016 at 15:36
  • 1
    @CandiedOrange Maybe someone should suggest in meta that answers be remain hidden for a period of time. And/Or that votes be hidden from public view for N hours... Or until an answer is selected. I know I'm not entirely objective when one answer already has 10 votes and the other 5 answers have none!
    – svidgen
    Commented Sep 30, 2016 at 15:45
  • 2
    @svidgen search "fastest gun in the west" on meta. The issue already has a long history. Commented Sep 30, 2016 at 15:48
6

Strictly speaking, Dependency Injection only really opposes NOT Dependency Injection -- and therefore any dependency management strategy that isn't Dependency Injection.

[Unwanted] coupling, though not exactly an orthogonal issue, can either occur or be mitigated either way. These are both coupled to DependencyClass:

public DependencyInjectedConstructor(DependencyClass dep) {
  dep.do();
}

public DependencyLookupConstructor() {
  var dep = new DependencyClass();
  dep.do();
}

DependencyLookupConstructor is coupled to a particular DependencyClass in this case. But, they're both coupled to DependencyClass. The real evil, if there is one here, isn't the coupling necessarily, it's that DependencyLookupConstructor needs to change if DependencyClass suddenly needs its own dependencies injected1.

However, this constructor/class is even more loosely coupled:

public DependencyLocatingConstructor() {
  var dep = ServiceLocator.GetMyDoer();
  dep.do();
}

If you're working in C#, the above will permit your ServiceLocator to return anything when GetMyDoer() is invoked, as long as it has can do() what DependencyLocatingConstructor has it do(). You get the benefit of compile-time signature validation without even being coupled to a complete interface2.

So, pick your poison.

But basically, if there's a concrete "opposite" of Dependency Injection, it would be something else in the realm of "Dependency Management Strategies." Amongst others, if you used any of the following in conversation, I'd recognize it as being NOT Dependency Injection:

  • Service Locator Pattern
  • Dependency Locator / Location
  • Direct object/dependency construction
  • Hidden dependency
  • "Not Dependency Injection"

1. Ironically, some of the problems that DI solves at higher levels are sort of a result of [over-]using DI in the lower levels. I've had the pleasure of working on codebases with unnecessary complexity all over as a result of accommodating the handful of places where that complexity actually helped ... I'm admittedly biased by bad exposure.

2. Using service location also permits you to easily specify different dependencies of the same type by their functional role from the invoking code, while still being largely agnostic about how the dependency is built. Suppose you need to resolve User or IUser for different purposes: E.g., Locator.GetAdministrator() versus Locator.GetAuthor() -- or whatever. My code can ask for what it needs functionally without even knowing what interfaces it supports.

6
  • 2
    The salvation for DependencyInjectedConstructor(DependencyClass dep) is that DependencyClass could be an interface or abstract class. This is why it makes me sad that C# coders use an interface prefix, as in IDependency. As the client, It's really not my business what this Dependency thing is. As long as I don't construct it, all I have to know is how to talk to it. What it is is someone else's problem. Commented Sep 30, 2016 at 17:25
  • Points being, DI still couples you to that interface, and it doesn't require that DependencyClass be an abstract interface at all. It only requires that the construction/configuration/location logic existing "somewhere else." ... Well, and more pertinently to the question, the point is that DI isn't "the opposite of tight coupling" :)
    – svidgen
    Commented Sep 30, 2016 at 17:38
  • Actually ... I may be slightly out of bounds in saying DI necessarily couples you to an interface, even in C#. Though, I've avoided them in C#, I'm under the impression I could also accept dynamic parameters. (But not var parameters, if memory serves.) So, with DI in C#, I think I either have to code against an interface, or I have to totally forgo the compile-time validation.
    – svidgen
    Commented Sep 30, 2016 at 17:41
  • Objects are coupled to the interfaces. Whether you use the interface keyword or not. That's what a proper interface is. Everything you HAVE to be coupled to. What you boil away are implementation details and extra stuff you don't need. We can formalize this by using the interface keyword to let the client tell the world, "All I need is this". But we don't have to. Heck we can do duck typing, well in some languages. Commented Sep 30, 2016 at 17:50
  • I'm not sure we're in total disagreement. But, to clarify ... Objects are internally coupled to their own interfaces, yes. But, the interface itself only imposes dependency-coupling if the interface is explicitly named. In C#, using dynamic or var and getting an object from a locator let's you ignore the interface and use any class that can do() what you need, regardless of whether that class implements some IDoer interface. In other words, if we have A->B<-C, DI decouples A from C, but it requires both A and C to be coupled to B, and prevents use of D, even if D will do().
    – svidgen
    Commented Sep 30, 2016 at 18:32
3

I don't know that there's specific, widely accepted industry terminology, but alternatives that come to mind include internal instance creation, internal dependency creation, local dependencies, or locally scoped dependencies.

1
  • 2
    i like instance creation but it is not specific enough. DI creates instances but by the means of controller and not at the application level. maybe internal instance creation
    – amphibient
    Commented Sep 30, 2016 at 14:41
2

Direct Dependency

Wow asked 6 years ago! I came to do this page searching for the same answer, and ultimately decided to use the term Direct Dependency instead of Hard Coding.

This decision was made because it describes what the injection avoids, by creating an indirect dependency. And after coming up with that definition, I decided to also start using the term indirect dependency to describe the general case of injection.

Reasoning

If i was to provide an object containing functions to a system, this would function as form of injection. The host or controller would have a direct dependency to the target, and the method would be invoked without a dependency from the target to either.

Target

export default {
  setName(name){ }  
}

So the common denominator between either exposing a method, or having some method accept an injected parameter by various means, is that the dependency is indirect, and removed from the target. The target has either a direct dependency or an indirect dependency on something. Injection is a form of indirect dependency.

Now let's look at the ideal coupling of dependencies, using the mediator pattern. Using this pattern, we have both direct and indirect dependencies:

Target

useMediator().callback = (name) => { myName = name }

Host

useMediator().callback('foobar')

In this example, our target has a direct dependency to the mediator, but publishes its callback to be used an indirect dependency. The host of our target will also have a direct dependency to the mediator, but an indirect dependency to the client method. In code-speak, the client and host include the mediator, but not each other.

The bottom line is that there are many ways to implement indirect dependencies, including but not limited to method parameter injection, but only 1 way to implement direct dependencies: by explicitly including them.

1

I would go with dependency encapsulation. This expresses the dependency is locked in rather than visiting and leaving again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.