Skip to main content
added 213 characters in body
Source Link

I have to say that in my opinion, the entire notion of Dependency Injection is overrated.

The example below shows how to achieve the exact same result for testing purposes as using DI, but with no additional baggage or requirements.

DI is the modern day equivalent of global values. The things you are injecting are global singletons and pure code objects, otherwise, you couldn't inject them. And the reason you Most uses of DI are injecting them is becauseforced on you don't have an architecture that allows accessin order to them any other way - all you have isuse a ton o' beans built on masses of boilerplate codegiven library (JPA, Spring Data, etc). For the most part, DI provides the perfect environment for nurturing and cultivating spaghetti.

The result is exactly equivalent to using DI - that is, the ClassUnderTest is configured for testing. The

The only differences are that this code is moreutterly concise, completely encapsulated, easier to code, easier to understand, faster, uses less memory, does not require an alternate configuration, does not require any frameworks, will never be the cause of a 4 page (WTF!) stack tracestrace that includeincludes exactly ZERO (0) classes which you wrote, and is completely obvious to everyoneanyone with even the slightest OO knowledge, from beginner to Guru (you would think, but would be mistaken). That

That being said, of course we can't use it - it's too obvious and not trendy enough.

InAt the meantimeend of the day, for us advanced guysthough, real injection means choosing and instantiatingmy biggest concern with DI is that of the desired class at run-time. That means we use interfacesprojects I have seen fail miserably, all of them have been massive code bases where DI was the way they were meant to be usedglue holding everything together. DI is not an architecture - to specifyit is really only relevant in a familyhandful of related classessituations, not as an alternatemost of which are forced on you in order to newuse another library (JPA, Spring Data, etc). For the most part, in a well designed code base, most uses of DI would occur at a level below where your daily development activities take place.

I have to say that the entire notion of Dependency Injection is overrated.

The example below shows how to achieve the exact same result for testing purposes as using DI, but with no additional baggage or requirements.

DI is the modern day equivalent of global values. The things you are injecting are global singletons and pure code objects, otherwise, you couldn't inject them. And the reason you are injecting them is because you don't have an architecture that allows access to them any other way - all you have is a ton o' beans built on masses of boilerplate code.

The result is exactly equivalent to using DI - that is, the ClassUnderTest is configured for testing. The only differences are that this is more concise, easier to code, easier to understand, faster, uses less memory, does not require an alternate configuration, does not require any frameworks, will never be the cause of 4 page (WTF!) stack traces that include exactly ZERO (0) classes which you wrote, and is completely obvious to everyone from beginner to Guru (you would think, but would be mistaken). That being said, of course we can't use it - it's too obvious and not trendy enough.

In the meantime, for us advanced guys, real injection means choosing and instantiating the desired class at run-time. That means we use interfaces the way they were meant to be used - to specify a family of related classes, not as an alternate to new.

I have to say that in my opinion, the entire notion of Dependency Injection is overrated.

DI is the modern day equivalent of global values. The things you are injecting are global singletons and pure code objects, otherwise, you couldn't inject them. Most uses of DI are forced on you in order to use a given library (JPA, Spring Data, etc). For the most part, DI provides the perfect environment for nurturing and cultivating spaghetti.

The result is exactly equivalent to using DI - that is, the ClassUnderTest is configured for testing.

The only differences are that this code is utterly concise, completely encapsulated, easier to code, easier to understand, faster, uses less memory, does not require an alternate configuration, does not require any frameworks, will never be the cause of a 4 page (WTF!) stack trace that includes exactly ZERO (0) classes which you wrote, and is completely obvious to anyone with even the slightest OO knowledge, from beginner to Guru (you would think, but would be mistaken).

That being said, of course we can't use it - it's too obvious and not trendy enough.

At the end of the day, though, my biggest concern with DI is that of the projects I have seen fail miserably, all of them have been massive code bases where DI was the glue holding everything together. DI is not an architecture - it is really only relevant in a handful of situations, most of which are forced on you in order to use another library (JPA, Spring Data, etc). For the most part, in a well designed code base, most uses of DI would occur at a level below where your daily development activities take place.

I wanted to clarify based on the comments...
Source Link

You are not injecting dependencies - the dependency is explicity stated in all cases, whether injecting or not. ForThe example, you will always declare a variable of the desired type, hence you are stating below shows how to achieve the dependency explicity, whetherexact same result for testing purposes as using DI, but with no additional baggage or notrequirements.

TheDI is the modern day equivalent of global values. The things you would like to be able to inject, but can't, are anything that involves more than instance - can you have multiple Orders - can't inject it. Can you have more than one Invoice - can't inject that.

Most (all) injection involves injecting singleton instances - i.e. classes which have only one instance ever and are injected wherever desired. These instances are all created at startup timeglobal singletons and cached for the duration of your application run, increasing startup timespure code objects, increasing memory usageotherwise, and forgoing GC for all injectablesyou couldn't inject them.

Also, as some And the reason you are injecting them is because you don't have referredan architecture that allows access to above, injecting only creates the dependencythem any other way - if you want to fill the dependency with a mocked object,all you will need to have is a completely different configuration available which provides the mock definition for every single instanceton o' beans built on masses of injection in yourboilerplate code. This means auto-wiring (which most injectors are using because it was the only way they got it to work) is not an option.

Then you instantiate the Test class and put it throughtest all its pacesmethods. This won't be clear to some of you - the methods you are testing are the ones belonging to the class under test. And all of these method tests occur in a single class file - the unit testing class associated with the class under test. There is zero overhead here - this is how unit testing works.

class SomeClassClassUnderTest { ADependencyprotected aDependency;final ADependency; AnotherDependencyprotected anotherDependency;final AnotherDependency;   // Call from a factory or use an initializer  public void initializeDependencies() { aDependency = new ADependency(); anotherDependency = new AnotherDependency(); } } class TestSomeClassTestClassUnderTest extends SomeClassClassUnderTest { @Override public void initializeDependencies() { aDependency = new ATestDependencyMockitoObject(); anotherDependency = new AnotherTestDependencyMockitoObject(); }    // Unit tests go here... // Unit tests call base class methods } 

ThatThe result is the exactexactly equivalent ofto using DI - withthat is, the ClassUnderTest is configured for testing. The only differences beingare that itthis is more concise, easier to code, easier to understand, faster, uses less memory, does not require an alternate configuration, does not require any frameworks, will never be the cause of 4 page (WTF!) stack traces that include exactly ZERO (0) classes which you wrote, and is completely obvious to everyone from beginner to Guru (you would think, but would be mistaken).

The only thing That being said, of course we can't use it requires is a little discipline in class design - Ohh crap, that's it, this will never work!it's too obvious and not trendy enough.

Actually, if you create a TestableObject interfaceIn the meantime, which defines a method initializeDependencies()for us advanced guys, then you could implement that interface in anyreal injection means choosing and instantiating the desired class you want to testat run-time. Even a dummy could figure out how to That means we use thatinterfaces the way they were meant to be used - to specify a family of related classes, I thinknot as an alternate to new.

If you did that, then at test time, you could inject instances of every class that implements that interface using a DI framework (grin)!

You are not injecting dependencies - the dependency is explicity stated in all cases, whether injecting or not. For example, you will always declare a variable of the desired type, hence you are stating the dependency explicity, whether using DI or not.

The things you would like to be able to inject, but can't, are anything that involves more than instance - can you have multiple Orders - can't inject it. Can you have more than one Invoice - can't inject that.

Most (all) injection involves injecting singleton instances - i.e. classes which have only one instance ever and are injected wherever desired. These instances are all created at startup time and cached for the duration of your application run, increasing startup times, increasing memory usage, and forgoing GC for all injectables.

Also, as some have referred to above, injecting only creates the dependency - if you want to fill the dependency with a mocked object, you will need to have a completely different configuration available which provides the mock definition for every single instance of injection in your code. This means auto-wiring (which most injectors are using because it was the only way they got it to work) is not an option.

Then you instantiate the Test class and put it through its paces.

class SomeClass { ADependency aDependency; AnotherDependency anotherDependency; public void initializeDependencies() { aDependency = new ADependency(); anotherDependency = new AnotherDependency(); } } class TestSomeClass extends SomeClass { public void initializeDependencies() { aDependency = new ATestDependency(); anotherDependency = new AnotherTestDependency(); } } 

That is the exact equivalent of DI - with the only differences being that it is more concise, easier to code, easier to understand, faster, uses less memory, does not require an alternate configuration, does not require any frameworks, will never be the cause of 4 page (WTF!) stack traces that include exactly ZERO (0) classes which you wrote, and is completely obvious to everyone from beginner to Guru.

The only thing it requires is a little discipline in class design - Ohh crap, that's it, this will never work!

Actually, if you create a TestableObject interface, which defines a method initializeDependencies(), then you could implement that interface in any class you want to test. Even a dummy could figure out how to use that, I think.

If you did that, then at test time, you could inject instances of every class that implements that interface using a DI framework (grin)!

The example below shows how to achieve the exact same result for testing purposes as using DI, but with no additional baggage or requirements.

DI is the modern day equivalent of global values. The things you are injecting are global singletons and pure code objects, otherwise, you couldn't inject them. And the reason you are injecting them is because you don't have an architecture that allows access to them any other way - all you have is a ton o' beans built on masses of boilerplate code.

Then you instantiate the Test class and test all its methods. This won't be clear to some of you - the methods you are testing are the ones belonging to the class under test. And all of these method tests occur in a single class file - the unit testing class associated with the class under test. There is zero overhead here - this is how unit testing works.

class ClassUnderTest { protected final ADependency; protected final AnotherDependency;   // Call from a factory or use an initializer  public void initializeDependencies() { aDependency = new ADependency(); anotherDependency = new AnotherDependency(); } } class TestClassUnderTest extends ClassUnderTest { @Override public void initializeDependencies() { aDependency = new MockitoObject(); anotherDependency = new MockitoObject(); }    // Unit tests go here... // Unit tests call base class methods } 

The result is exactly equivalent to using DI - that is, the ClassUnderTest is configured for testing. The only differences are that this is more concise, easier to code, easier to understand, faster, uses less memory, does not require an alternate configuration, does not require any frameworks, will never be the cause of 4 page (WTF!) stack traces that include exactly ZERO (0) classes which you wrote, and is completely obvious to everyone from beginner to Guru (you would think, but would be mistaken). That being said, of course we can't use it - it's too obvious and not trendy enough.

In the meantime, for us advanced guys, real injection means choosing and instantiating the desired class at run-time. That means we use interfaces the way they were meant to be used - to specify a family of related classes, not as an alternate to new.

added 373 characters in body
Source Link

I have to say that the entire notion of Dependency Injection is overrated.

You are not injecting dependencies - the dependency is explicity stated in all cases, whether injecting or not. For example, you will always declare a variable of the desired type, hence you are stating the dependency explicity, whether using DI or not.

The things you would like to be able to inject, but can't, are anything that involves more than instance - can you have multiple Orders - can't inject it. Can you have more than one Invoice - can't inject that.

Most (all) injection involves injecting singleton instances - i.e. classes which have only one instance ever and are injected wherever desired. These instances are all created at startup time and cached for the duration of your application run, increasing startup times, increasing memory usage, and forgoing GC for all injectables.

Also, as some have referred to above, injecting only creates the dependency - if you want to fill the dependency with a mocked object, you will need to have a completely different configuration available which provides the mock definition for every single instance of injection in your code. This means auto-wiring (which most injectors are using because it was the only way they got it to work) is not an option.

In all honesty, the easiest way to test a class is to ensure that all dependencies are created in a method that can be overridden. Then create a Test class derived from the actual class and override that method.

Then you instantiate the Test class and put it through its paces.

In code, this concept looks like this...

class SomeClass { ADependency aDependency; AnotherDependency anotherDependency; public void initializeDependencies() { aDependency = new ADependency(); anotherDependency = new AnotherDependency(); } } class TestSomeClass extends SomeClass { public void initializeDependencies() { aDependency = new ATestDependency(); anotherDependency = new AnotherTestDependency(); } } 

That is the exact equivalent of DI - with the only differences being that it is more concise, easier to code, easier to understand, faster, uses less memory, does not require an alternate configuration, does not require any frameworks, will never be the cause of 4 page (WTF!) stack traces that include exactly ZERO (0) classes which you wrote, and is completely obvious to everyone from beginner to Guru.

The only thing it requires is a little discipline in class design - Ohh crap, that's it, this will never work!

Actually, if you create a TestableObject interface, which defines a method initializeDependencies(), then you could implement that interface in any class you want to test. Even a dummy could figure out how to use that, I think.

If you did that, then at test time, you could inject instances of every class that implements that interface using a DI framework (grin)!

I have to say that the entire notion of Dependency Injection is overrated.

You are not injecting dependencies - the dependency is explicity stated in all cases, whether injecting or not. For example, you will always declare a variable of the desired type, hence you are stating the dependency explicity, whether using DI or not.

The things you would like to be able to inject, but can't, are anything that involves more than instance - can you have multiple Orders - can't inject it. Can you have more than one Invoice - can't inject that.

Most (all) injection involves injecting singleton instances - i.e. classes which have only one instance ever and are injected wherever desired. These instances are all created at startup time and cached for the duration of your application run, increasing startup times, increasing memory usage, and forgoing GC for all injectables.

Also, as some have referred to above, injecting only creates the dependency - if you want to fill the dependency with a mocked object, you will need to have a completely different configuration available which provides the mock definition for every single instance of injection in your code. This means auto-wiring (which most injectors are using because it was the only way they got it to work) is not an option.

In all honesty, the easiest way to test a class is to ensure that all dependencies are created in a method that can be overridden. Then create a Test class derived from the actual class and override that method.

Then you instantiate the Test class and put it through its paces.

In code, this concept looks like this...

class SomeClass { ADependency aDependency; AnotherDependency anotherDependency; public void initializeDependencies() { aDependency = new ADependency(); anotherDependency = new AnotherDependency(); } } class TestSomeClass extends SomeClass { public void initializeDependencies() { aDependency = new ATestDependency(); anotherDependency = new AnotherTestDependency(); } } 

That is the exact equivalent of DI - with the only differences being that it is more concise, easier to code, easier to understand, faster, uses less memory, does not require an alternate configuration, does not require any frameworks, will never be the cause of 4 page (WTF!) stack traces that include exactly ZERO (0) classes which you wrote, and is completely obvious to everyone from beginner to Guru.

The only thing it requires is a little discipline in class design - Ohh crap, that's it, this will never work!

I have to say that the entire notion of Dependency Injection is overrated.

You are not injecting dependencies - the dependency is explicity stated in all cases, whether injecting or not. For example, you will always declare a variable of the desired type, hence you are stating the dependency explicity, whether using DI or not.

The things you would like to be able to inject, but can't, are anything that involves more than instance - can you have multiple Orders - can't inject it. Can you have more than one Invoice - can't inject that.

Most (all) injection involves injecting singleton instances - i.e. classes which have only one instance ever and are injected wherever desired. These instances are all created at startup time and cached for the duration of your application run, increasing startup times, increasing memory usage, and forgoing GC for all injectables.

Also, as some have referred to above, injecting only creates the dependency - if you want to fill the dependency with a mocked object, you will need to have a completely different configuration available which provides the mock definition for every single instance of injection in your code. This means auto-wiring (which most injectors are using because it was the only way they got it to work) is not an option.

In all honesty, the easiest way to test a class is to ensure that all dependencies are created in a method that can be overridden. Then create a Test class derived from the actual class and override that method.

Then you instantiate the Test class and put it through its paces.

In code, this concept looks like this...

class SomeClass { ADependency aDependency; AnotherDependency anotherDependency; public void initializeDependencies() { aDependency = new ADependency(); anotherDependency = new AnotherDependency(); } } class TestSomeClass extends SomeClass { public void initializeDependencies() { aDependency = new ATestDependency(); anotherDependency = new AnotherTestDependency(); } } 

That is the exact equivalent of DI - with the only differences being that it is more concise, easier to code, easier to understand, faster, uses less memory, does not require an alternate configuration, does not require any frameworks, will never be the cause of 4 page (WTF!) stack traces that include exactly ZERO (0) classes which you wrote, and is completely obvious to everyone from beginner to Guru.

The only thing it requires is a little discipline in class design - Ohh crap, that's it, this will never work!

Actually, if you create a TestableObject interface, which defines a method initializeDependencies(), then you could implement that interface in any class you want to test. Even a dummy could figure out how to use that, I think.

If you did that, then at test time, you could inject instances of every class that implements that interface using a DI framework (grin)!

Source Link
Loading