# What is Dependency Injection?

This chapter will introduce you to the basic programming practices that you should follow when writing any application. These are the fundamentals needed for writing clean, understandable, and maintainable code.

If you learn and follow these rules, Nette will be there for you every step of the way. It will handle routine tasks for you and provide maximum comfort, so you can focus on the logic itself.

The principles we will show here are quite simple. You don't have to worry about anything.

We don't know what language you wrote it in, but if it was PHP, it might have looked something like this:

``````function addition(float \$a, float \$b): float
{
return \$a + \$b;
}

echo addition(23, 1); // prints 24
``````

A few trivial lines of code, but so many key concepts hidden in them. That there are variables. That code is broken down into smaller units, which are functions, for example. That we pass them input arguments and they return results. All that's missing are conditions and loops.

The fact that a function takes input data and returns a result is a perfectly understandable concept, which is also used in other fields, such as mathematics.

A function has its signature, which consists of its name, a list of parameters and their types, and finally the type of the return value. As users, we are interested in the signature, and we usually don't need to know anything about the internal implementation.

Now imagine that the function signature looked like this:

``````function addition(float \$x): float
``````

``````function addition(): float
``````

Now that's really weird, right? How is the function used?

``````echo addition(); // what does it prints?
``````

Looking at such code, we would be confused. Not only would a beginner not understand it, but even an experienced programmer would not understand such code.

Are you wondering what such a function would actually look like inside? Where would it get the summands? It would probably somehow get them by itself, perhaps like this:

``````function addition(): float
{
\$a = Input::get('a');
\$b = Input::get('b');
return \$a + \$b;
}
``````

It turns out that there are hidden bindings to other functions (or static methods) in the body of the function, and to find out where the addends actually come from, we have to dig further.

## Not This Way!

The design we just showed is the essence of many negative features:

• the function signature pretended that it didn't need the summands, which confused us
• we have no idea how to make the function calculate with two other numbers
• we had to look at the code to find out where the summands came from
• we found hidden dependencies
• a full understanding requires examining these dependencies as well

And is it even the job of the addition function to procure inputs? Of course it isn't. Its responsibility is only to add.

We don't want to encounter such code, and we certainly don't want to write it. The remedy is simple: go back to basics and just use parameters:

``````function addition(float \$a, float \$b): float
{
return \$a + \$b;
}
``````

## Rule #1: Let It Be Passed to You

The most important rule is: all data that functions or classes need must be passed to them.

Instead of inventing hidden ways for them to access the data themselves, simply pass the parameters. You will save time that would be spent inventing hidden paths that certainly won't improve your code.

If you always and everywhere follow this rule, you are on your way to code without hidden dependencies. To code that is understandable not only to the author but also to anyone who reads it afterward. Where everything is understandable from the signatures of functions and classes, and there is no need to search for hidden secrets in the implementation.

This technique is professionally called dependency injection. And those data are called dependencies. It's just ordinary parameter passing, nothing more.

Please do not confuse dependency injection, which is a design pattern, with a “dependency injection container”, which is a tool, something diametrically different. We will deal with containers later.

## From Functions to Classes

And how are classes related? A class is a more complex unit than a simple function, but rule #1 applies entirely here as well. There are just more ways to pass arguments. For example, quite similar to the case of a function:

``````class Math
{
public function addition(float \$a, float \$b): float
{
return \$a + \$b;
}
}

\$math = new Math;
``````

Or through other methods, or directly through the constructor:

``````class Addition
{
public function __construct(
private float \$a,
private float \$b,
) {
}

public function calculate(): float
{
return \$this->a + \$this->b;
}

}

``````

Both examples are completely in compliance with dependency injection.

## Real-Life Examples

In the real world, you won't be writing classes for adding numbers. Let's move on to practical examples.

Let's have a `Article` class representing a blog post:

``````class Article
{
public int \$id;
public string \$title;
public string \$content;

public function save(): void
{
// save the article to the database
}
}
``````

and the usage will be as follows:

``````\$article = new Article;
\$article->title = '10 Things You Need to Know About Losing Weight';
\$article->content = 'Every year millions of people in ...';
\$article->save();
``````

The `save()` method will save the article to a database table. Implementing it using Nette Database will be a piece of cake, were it not for one hitch: where does `Article` get the database connection, i.e., an object of class `Nette\Database\Connection`?

It seems we have plenty of options. It can take it from a static variable somewhere. Or inherit from a class that provides a database connection. Or take advantage of a singleton. Or use so-called facades, which are used in Laravel:

``````use Illuminate\Support\Facades\DB;

class Article
{
public int \$id;
public string \$title;
public string \$content;

public function save(): void
{
DB::insert(
'INSERT INTO articles (title, content) VALUES (?, ?)',
[\$this->title, \$this->content],
);
}
}
``````

Great, we've solved the problem.

Or have we?

Let's recall rule #1: Let It Be Passed to You: all the dependencies the class needs must be passed to it. Because if we break the rule, we have embarked on a path to dirty code full of hidden dependencies, incomprehensibility, and the result will be an application that will be painful to maintain and develop.

The user of the `Article` class has no idea where the `save()` method stores the article. In a database table? Which one, production or testing? And how can it be changed?

The user has to look at how the `save()` method is implemented, and finds the use of the `DB::insert()` method. So, he has to search further to find out how this method obtains a database connection. And hidden dependencies can form quite a long chain.

In clean and well-designed code, there are never any hidden dependencies, Laravel facades, or static variables. In clean and well-designed code, arguments are passed:

``````class Article
{
public function save(Nette\Database\Connection \$db): void
{
\$db->query('INSERT INTO articles', [
'title' => \$this->title,
'content' => \$this->content,
]);
}
}
``````

An even more practical approach, as we will see later, will be through the constructor:

``````class Article
{
public function __construct(
private Nette\Database\Connection \$db,
) {
}

public function save(): void
{
\$this->db->query('INSERT INTO articles', [
'title' => \$this->title,
'content' => \$this->content,
]);
}
}
``````

If you are an experienced programmer, you might think that `Article` should not have a `save()` method at all; it should represent a purely data component, and a separate repository should take care of saving. That makes sense. But that would take us far beyond the scope of the topic, which is dependency injection, and the effort to provide simple examples.

If you write a class that requires, for example, a database for its operation, don't invent where to get it from, but have it passed. Either as a parameter of the constructor or another method. Admit dependencies. Admit them in the API of your class. You will get understandable and predictable code.

``````class Logger
{
public function log(string \$message)
{
\$file = LOG_DIR . '/log.txt';
file_put_contents(\$file, \$message . "\n", FILE_APPEND);
}
}
``````

What do you think, did we follow rule #1: Let It Be Passed to You?

We didn't.

The key information, i.e., the directory with the log file, is obtained by the class itself from the constant.

Look at the example of usage:

``````\$logger = new Logger;
\$logger->log('The temperature is 23 °C');
\$logger->log('The temperature is 10 °C');
``````

Without knowing the implementation, could you answer the question of where the messages are written? Would you guess that the existence of the `LOG_DIR` constant is necessary for its functioning? And could you create a second instance that would write to a different location? Certainly not.

Let's fix the class:

``````class Logger
{
public function __construct(
private string \$file,
) {
}

public function log(string \$message): void
{
file_put_contents(\$this->file, \$message . "\n", FILE_APPEND);
}
}
``````

The class is now much more understandable, configurable, and therefore more useful.

``````\$logger = new Logger('/path/to/log.txt');
\$logger->log('The temperature is 15 °C');
``````

## But I Don’t Care!

“When I create an Article object and call save(), I don't want to deal with the database; I just want it to be saved in the one I have set in the configuration.”

“When I use Logger, I just want the message to be written, and I don't want to deal with where. Let the global settings be used.”

These are valid points.

As an example, let's look at a class that sends newsletters and logs how it went:

``````class NewsletterDistributor
{
public function distribute(): void
{
\$logger = new Logger(/* ... */);
try {
\$this->sendEmails();
\$logger->log('Emails have been sent out');

} catch (Exception \$e) {
\$logger->log('An error occurred during the sending');
throw \$e;
}
}
}
``````

The improved `Logger`, which no longer uses the `LOG_DIR` constant, requires specifying the file path in the constructor. How to solve this? The `NewsletterDistributor` class doesn't care where the messages are written; it just wants to write them.

The solution is again rule #1: Let It Be Passed to You: pass all the data that the class needs.

So does that mean we pass the path to the log through the constructor, which we then use when creating the `Logger` object?

``````class NewsletterDistributor
{
public function __construct(
private string \$file, // ⛔ NOT THIS WAY!
) {
}

public function distribute(): void
{
\$logger = new Logger(\$this->file);
``````

No, not like this! The path doesn't belong among the data that the `NewsletterDistributor` class needs; in fact, the `Logger` needs it. Do you see the difference? The `NewsletterDistributor` class needs the logger itself. So that's what we'll pass:

``````class NewsletterDistributor
{
public function __construct(
private Logger \$logger, // ✅
) {
}

public function distribute(): void
{
try {
\$this->sendEmails();
\$this->logger->log('Emails have been sent out');

} catch (Exception \$e) {
\$this->logger->log('An error occurred during the sending');
throw \$e;
}
}
}
``````

Now it is clear from the signatures of the `NewsletterDistributor` class that logging is also part of its functionality. And the task of exchanging the logger for another, perhaps for testing, is completely trivial. Moreover, if the constructor of the `Logger` class changes, it will not affect our class.

## Rule #2: Take What's Yours

Don't be misled and don't let yourself pass the dependencies of your dependencies. Just pass your own dependencies.

Thanks to this, the code using other objects will be completely independent of changes in their constructors. Its API will be more truthful. And above all, it will be trivial to replace these dependencies with others.

## New Family Member

The development team decided to create a second logger that writes to the database. So we create a `DatabaseLogger` class. So we have two classes, `Logger` and `DatabaseLogger`, one writes to a file, the other to a database … doesn't the naming seem strange to you? Wouldn't it be better to rename `Logger` to `FileLogger`? Definitely yes.

But let's do it smartly. We create an interface under the original name:

``````interface Logger
{
function log(string \$message): void;
}
``````

… which both loggers will implement:

``````class FileLogger implements Logger
// ...

class DatabaseLogger implements Logger
// ...
``````

And because of this, there will be no need to change anything in the rest of the code where the logger is used. For example, the constructor of the `NewsletterDistributor` class will still be satisfied with requiring `Logger` as a parameter. And it will be up to us which instance we pass.

That's why we never add the `Interface` suffix or `I` prefix to interface names. Otherwise, it would not be possible to develop the code so nicely.

## Houston, We Have a Problem

While we can get by with a single instance of the logger, whether file-based or database-based, throughout the entire application and simply pass it wherever something is logged, it's quite different for the `Article` class. We create its instances as needed, even multiple times. How to deal with the database dependency in its constructor?

An example can be a controller that should save an article to the database after submitting a form:

``````class EditController extends Controller
{
public function formSubmitted(\$data)
{
\$article = new Article(/* ... */);
\$article->title = \$data->title;
\$article->content = \$data->content;
\$article->save();
}
}
``````

A possible solution is obvious: pass the database object to the `EditController` constructor and use `\$article = new Article(\$this->db)`.

Just as in the previous case with `Logger` and the file path, this is not the right approach. The database is not a dependency of the `EditController`, but of the `Article`. Passing the database goes against rule #2: take what's yours. If the `Article` class constructor changes (a new parameter is added), you will need to modify the code wherever instances are created. Ufff.

Houston, what do you suggest?

## Rule #3: Let the Factory Handle It

By eliminating hidden dependencies and passing all dependencies as arguments, we have gained more configurable and flexible classes. And therefore, we need something else to create and configure those more flexible classes for us. We will call it factories.

The rule of thumb is: if a class has dependencies, leave the creation of their instances to the factory.

Factories are a smarter replacement for the `new` operator in the world of dependency injection.

Please do not confuse with the factory method design pattern, which describes a specific way of using factories and is not related to this topic.

## Factory

A factory is a method or class that creates and configures objects. We will name the class producing `Article` as `ArticleFactory`, and it could look like this:

``````class ArticleFactory
{
public function __construct(
private Nette\Database\Connection \$db,
) {
}

public function create(): Article
{
return new Article(\$this->db);
}
}
``````

Its usage in the controller will be as follows:

``````class EditController extends Controller
{
public function __construct(
private ArticleFactory \$articleFactory,
) {
}

public function formSubmitted(\$data)
{
// let the factory create an object
\$article = \$this->articleFactory->create();
\$article->title = \$data->title;
\$article->content = \$data->content;
\$article->save();
}
}
``````

At this point, if the signature of the `Article` class constructor changes, the only part of the code that needs to react is the `ArticleFactory` itself. All other code working with `Article` objects, such as the `EditController`, will not be affected.

You might be wondering if we have actually made things better. The amount of code has increased, and it all starts to look suspiciously complicated.

Don't worry, soon we will get to the Nette DI container. And it has several tricks up its sleeve, which will greatly simplify building applications using dependency injection. For example, instead of the `ArticleFactory` class, you will only need to write a simple interface:

``````interface ArticleFactory
{
function create(): Article;
}
``````