I have done proper dependency injection with constructors, but that makes my main method look like this:
MyModel myModel = MyModelFileReader.getModel(Config.getDefaultFile());
MyApp myApp = new MyApp(myModel, new View(new SubView(myModel), new SubView(myModel, new CustomChart(Config.getChartOptionOne(), Config.getChartOptionTwo)));
myApp.start();
All the constructing gets piled here, and it looks bad. What the proper way to do this?
To expand on the comment from #Nkosi, new has to called somewhere. Objects are instantiated by invoking their constructors, and dependency injection doesn't change that.
If you apply a DI framework, that framework will take on the responsibility of instantiating objects, so you won't necessarily see the new keywords; but they are just hidden rather than eliminated.
If you apply your own DI, then you implement a composition root yourself (which will be filled with new keywords). Your main method is exactly the right place to implement a composition root.
Note the advantage of the composition root pattern is that it consolidates object instantiation (and thereby new keywords) in a single location. If you think of creating objects as a "single responsibility" then consolidating that work into main makes your codebase more cohesive.
No pattern will eliminate the need to new up objects. By injecting dependencies through constructors, you're doing DI the right way.
Here are some of the things you can do:
Instantiate every object on the separate line. It will improve readability of your code.
Use "Builder" creational design pattern to extract object construction from main method to a "Builder" class where you can manage it better. https://refactoring.guru/design-patterns/builder
Use some of the IoC container/Dependency injection frameworks. Core module from Spring framework contains a good solution. Also you have "guice" framework from Google and a lot more.
Related
In Effective Java (book), static factories are recommended.
On the other hand, keeping dependencies explicit, for example by using DI, is recommended.
But when I want to use a static factory, this explicitness will be skipped, because object instances will be received by calling the static factory method. With static factory methods, I won't have to pass in the object containing the static factory.
How can these two things go together?
Really good question.
Static factories have indeed this drawback (among others): they are not explicit and consequently they cannot be used as switchable dependencies.
I don't think that you can make the two things work together as a static method is associated to the class while the dependency injection is associated to instances.
So it is a choice of design.
Personally, I use the factory method as I don't want to allow to set explicitly the dependency returned by the factory.
It is the case as you want to master the objects creation : consistency, caching, and so for... and you want to provide a clear API.
It is a very straight way to guarantee that.
Setting an object with dependency injection will not provide that.
Generally, I did it for classes that I don't want neither to provide alternative implementations nor to mock during unit tests.
It is the case of business/model classes which I want to master the creation and also for some "utility" classes.
But as soon as the need to explicitly set the dependency happens, I refactor the static factory in something that allows to set the dependency explicitly.
If the master of the objects creation is always necessary, I transform the static factory into an instance factory that I inject.
Otherwise I inject directly the object that was returned by the factory.
There are two sides of the problem:
The object that is being created.
The object that is doing the
creating.
Factories, constructors, and auto-resolving containers are means of changing the way an object can be created (problem 2). That is entirely separate from how an object allows itself to be created (problem 1).
As a general heuristic:
Objects that are being created should be as flexible as possible in terms of how they can be constructed, and should explicitly advertise all their dependencies in their constructors (even if the constructors are made private and a factory is used by creators).
Creators should be as decoupled from the objects they created as your application needs to maintain its flexibility. Highly stable dependencies can be depended on directly. Dependencies that may change or be replaced should not
Differences between static factories, instance factories, constructors, and auto-resolution by container are largely just syntax. The biggest differences are semantic expression (what it communicates to a developer about the structure of the program) and the ability to resolve different implementations at runtime.
To answer your core question, the two things can go together because they are solutions to separate halves of the problem. You can use them both together.
I have the below classes:
class Validator {
private final SchemaFetcher schemaFetcher;
#Inject
Validator(SchemaFetcher schemaFetcher) {...}
}
class DatabaseSchemaFetcher implements SchemaFetcher {
#Override
Schema loadSchema(final SchemaDefinition schemaDef);
#Override
boolean compareSchemaWithSource(final SchemaDefinition schemaDef, final Schema updatedSchema);
}
This is just one of the examples, I have some other classes like this which I inject into other classes as dependencies. But it makes my SchemaFetcher class like a singleton and I keep passing the schemaDefinition to every single method of it. This seems very procedural and I want to actually make SchemaDefinition an instance variable to the DatabaseSchemaFetcher class but in that case I would not be able to inject a SchemaFetcher Object into my Validator class and instead I should be doing
validate(String schemaName) {
SchemaDefinition schemaDef = buildSchemaDefinitionFrom(schemaName);
SchemaFetcher fetcher = new DatabaseSchemaFetcher(schemaDef);
}
But this makes me tightly coupled to the fetcher which is why I wanted to use Dependency Injection in the first place.
I can see that I could possibly have a default constructor for DatabaseSchemaFetcher and then a setSchemaDefintion() setter to acheive this but that violates the principle of building your object completely using the constructor.
How do I improve this to not have a procedural style fetcher but also inject my dependencies into the constructor? I prefer constructor injection because it clearly defines my dependencies without anyone looking into the implementation of the class to figure out the dependencies the class uses if I use a factory or service locator.
Dependency Injection is one of those very good ideas that seems so good that it gets badly overused. I would not inject the Fetcher into the Validator using the DI framework. Rather, I'd have the DI framework inject a factory into "main". The factory creates the Fetcher with the appropriate SchemaDefinition and passes it to the Validator.
Remember that we want a boundary separating "main" from the rest of the application, and all dependencies should point from "main" to the application. The application should not know about "main". i.e. "main" is a plugin to the application.
In general, DI should be used to inject into "main", and then main uses more traditional techniques to pass factories, strategies, or just regular old abstract interfaces into the application.
Why do you say you're tightly coupled to SchemaFetcher in your 2nd solution?
You're providing there an interface, so you're not coupled to any specific implementation, but only to the definition of what SchemaFetcher is (i.e - the contract of the SchemaFetcher)
You may consider to have a Validator class which takes into its CTOR the SchemaDefinition, and your DatabaseSchemaFetcher can hold a field to it. This way you will also be able to extend the Validator class change the validation logic if required.
But once again, the question of how to pass the schema definition object rises. Not sure injection should be used here - consider altering your design.
I'm not exactly sure what the use of Dependecy Injection and Procedural have to do with each other in this instance.
I think the real issue is that the way you've chosen to model you're objects does not reflect the stated goal.
In the code you've supplied Validator serves no purpose that I can see. If its purpose is to validate SchemaFetcher objects then it probably should have no state beyond the rules for validation then accept arbitary SchemaFetcher objects to validate.
As for DataBaseSchemaFetcher I once again struggle to understand what this does. If its stated purpose is only to fetch schemas then it requires no state in regards to DatabaseSchema objects and as such should accept DatabaseSchema for the methods in which it is charged with acting on a DatabaseSchema. Any internal state should only be related to the classes's fetching behavior.
One tried and true way to get past these painted in a corner situations is to sit down and try really hard to assign each class a single responsibility and keep in mind the following:
Thing really hard about the domain of the exact problem you are trying to solve.
Do not solve any problems you don't have.Take your dreams of extensibility and throw them away. They will almost always be wrong and will just be a huge time sink.
Accept that your design is necessarily deficient and you will have to change it later.
It's common to have an object used application wide.
What are the different patterns / models / ways to share an object through an application?
Is defining a "main class", then setting a member variable and extending all other classes from this "main class" a good way? Is creating a static class probably the better and cleaner way? What's your prefered pattern?
It's common to have an object used application wide. What are the different patterns / models / ways to share an object through an application?
One common way is to use the singleton pattern. I would avoid that though.
Is defining a "main class", then setting a member variable and extending all other classes from this "main class" a good way
Absolutely not. Aside from anything else, if it's an instance variable then it wouldn't be "shared" with instances of your other classes anyway. It's also a complete abuse of inheritance which would certainly bite you hard in any application of significant size - your other classes wouldn't logically have an inheritance relationship with your "main" class, would they? As a general rule, inheritance should only be used when it's really appropriate - not to achieve a quick fix.
What's your prefered pattern?
Dependency injection. When your application starts up, create all the appropriate objects which need to know about each other, and tell them (usually in the constructor) about their dependencies. Several different objects can all depend on the same object if that's appropriate. You can use one of the many dependency injection frameworks available to achieve this easily.
Dependency injection generally works better than using singletons because:
The class itself doesn't know whether or not the dependency is actually shared; why should it care?
Global state makes unit testing harder
Each class makes its dependencies clearer when they're declared - it's then easier to navigate around the application and see how the classes relate to each other.
Singletons and global factories are more appropriate when they're for things like logging - but even then, it means it's relatively hard to test the logging aspects of a class. It's a lot simpler to create a dependency which does what you need it to, and pass that to the object under test, than it is to add ways of messing around with a singleton (which usually remains "fixed" after initialization).
If you use a framework like Spring which has dependency injection, you can get all the benefits of "global" objects for free without needing to explicitly define them. You just create a reference to them in your application context and you can inject them into any object you'd like without worrying about issues with synchronizing.
Singleton pattern, AFAIK the preferable way in software engineering.
I believe what you are looking for is the Singleton Pattern. With this pattern you are ensured that only one instance of a class can be created in memory.
Example:
public class mySingletonClass {
private static mySingletonClass singleObject;
// Note that the constructor is private to prevent more than one
//instance of the class
private SingletonObjectDemo() {
// Optional Code
}
public static mySingletonClass getSingletonObject() {
if (singleObject == null) {
singleObject = new mySingletonClass();
}
return singleObject;
}
}
That said, you should try to avoid using it; but there are some acceptable cases, one of which is here.
Can you briefly explain: What mainly differs Dependency Injection from Factory Design pattern?
Additionally: Is it possible to demonstrate the difference very simply by a code example?
Thanks
With Factory (or any other Creation pattern), the caller has to know how to get the object and has to "explicitly" ask for it before consuming it.
Car car = CarFactory.getCarByModel(LUXURY);
Whereas when using DI, the responsibility to pass the desired object is delegated to some external (container mostly) entity which knows how to create the object (by reading the config already defined) and make it available to the caller silently.
Car car = getCar();
void setCar(Car car){..} // container sets the car fromoutside
The factory pattern is typically useful to repeatedly create instances of an object with possibly complex instantiation logic. This way, your classes knows of the factory and requests instances.
Dependency injection goes one step further to completely abstract away instantiation logic as far as your classes are concerned. All your code needs to care about is to declare the dependencies they need, without bothering where they come from.
For a nice in-depth guide, see Inversion of Control Containers and the Dependency Injection pattern.
Same goals are achieved with both patterns, it's just that with the factory design pattern you have to write code whereas with DI you use an existing DI framework to do the job for you and simply do the configuration of the dependencies. With the factory pattern you have to write factories for you classes.
What is the difference between creating a new object and dependency injection? Please explain in detail.
Well, they're not exactly comparable. You will always have to create a new object by instantiating a class at some point. Dependency injection also requires creating new objects.
Dependency injection really comes into play when you want to control or verify the behavior of instances used by a class that you use or want to test. (For Test Driven Development, dependency injection is key for all but the smallest example).
Assume a class Holder which requires an object of class Handle. The traditional way to do that would be to let the Holder instance create and own it:
class Holder {
private Handle myHandle = new Handle();
public void handleIt() {
handle.handleIt();
}
}
The Holder instance creates myHandle and no one outside the class can get at it. In some cases, unit-testing being one of them, this is a problem because it is not possible to test the Holder class without creating the Handle instance which in turn might depend on many other classes and instances. This makes testing unwieldy and cumbersome.
By injecting the Handle instance, for example in the constructor, someone from the outside becomes responsible for the creation of the instance.
class Holder {
private Handle myHandle;
public Holder(Handle injectedHandle) {
myHandle = injectedHandle;
}
public void handleIt() {
handle.handleIt();
}
}
As you can see the code is almost the same, and the Handle is still private, but the Holder class now has a much loser coupling to its outside world which makes many things simpler. And when testing the Holder class a mock or stub object can be injected instead of a real instance making it possible to verify or control the interaction between the Holder, its caller and the handle.
The actual injection would take place at some other place, usually some "main" program. There are multiple frameworks that can help you do that without programming, but essentially this is the code in the "main" program:
...
private Handle myHandle = new Handle(); // Create the instance to inject
private Handler theHandler = new Handler(myHandle); // Inject the handle
...
In essence, the injection is nothing more than a fancy set method. And of course, you can implement the injection mechanism using that instead of in the constructor like the simple example above.
Of course, both create objects. The difference is in who is responsible for the creation. Is it the class that needs its dependencies or a container like Spring for example, which wires the component's dependencies? You configure the dependencies in a separate(typically XML) configuration file.
It is really a separation of concerns. The class says I need this, this, and this component to function properly. The class doesn't care how it gets its components. You plug them into the class with a separate configuration file.
To give you an example let's consider having a shopping class that needs a payment module. You don't want to hardcode which payment module will be used. To achieve this you inverse the control. You can change the used payment module with a few keystrokes in the configuration file of the container. The power is that you aren't touching any Java code.
Well,
creating a new object is as explicit as it can get - you create a new instance of the desired class.
Dependency injections is a mechanism that provides you with references where you need them.
Imagine a class that represents a connection pool to your database - you usually only have one instance of that class. Now you need to distribute that reference to all the classes that use it.
Here is where Dependency Injection comes in handy - by using a DI framework such as Spring you can define that the one instance of your pool will be injected into the classes that need it.
Your question itself is not easy to answer since the creation of an object and dependency injection can't be compared that easily...
Dependency injections adds a layer of configurability into your application. In the sense, when you hard code object construction, you need to re-build and re-deploy your app, but when you use dependency injection, you can re configure the XML and change the behavior without re-building and re-deploying. There are a large variety of use cases where this can save a lot of tie and effort.
When using an inversion-of-control container to perform dependency injection, the container creates the objects, and not the developer. This is done so that the container can "inject" these objects into other objects.
The answer to the following question may also give the answer you are looking for: Why is the new operator an anti-pattern? Well, the simple answer is that using the new operator may create a hidden, inaccessible dependency within the containing class. This makes testing the containing class more difficult because it involves testing the hidden dependency at the same time (barring MOCK frameworks of course). However, you can avoid this situation by not using the new operator and injecting the dependent object instead. This also has the following advantages:
For test purposes you can inject a different object.
The resulting containing class is more reusable because it can support different implementations of the dependent object.