Is it better to use facades or dependency injection?

By @ralphjsmit · 2021-11-09 09:12 (edited)

Is it better to use facades or dependency injection?

This week I came across a package called Laravel Optimus, which allows you to encode your model id's to a longer integer, in order to hide the original id's.

One of the things that picqued my curiousity was the following statement:

Dependency Injection If you prefer to use dependency injection over facades like me, then you can inject the manager (...)

That made me wondering: is dependency injection better than facades?

Personally dependency injection feels a little bit 'messy', because it clutters the parameters in the constructor, which in turn distracts from the parameters in the constructor that really need to be injected manually.

After some searching I found this StackOverflow question, where someone said that he 'would much much rather see a constructor with 6 or 7 dependencies than a parameterless one and a bunch of static calls hidden throughout the methods.

Why? Purely because the static facade calls are 'hidden' in the code?

What is your opinion on this? What is 'best practice'?

  • By @davorminchorov · 2021-11-21 01:53

    I personally prefer to use dependency injection because it allows for a better object oriented design and better usage for design patterns when there’s complex code overall.

    When working on a long term project, let’s say more than a year and add a ton of features over time, your code will get messy and you can’t avoid that part but what you can do to fix it is to refactor it using some of the design patterns if they are applicable in the specific use case.

    I know that most people in the Laravel community promote simplicity over complexity but that can cause more issues in the long term if the structure of the project is not properly planned from the start. It becomes a nightmare to maintain the codebase and increases the chance of huge amount of bugs, as well as time to research how things work and/ or debug issues. One change can fix one thing but break another one.

    It can be demotivating to work on such a project where no one really cares for the codebase.

    If it’s a small short term project with a small team, it shouldn’t be a big deal, but if it’s something bigger for the long term, design patterns, modular structure and design principles can be very useful if applied properly.

    • By @ralphjsmit · 2021-11-22 06:57

      Thanks for your reply! So because you are injecting dependencies into constructors, this allows for a better object oriented design? Because facades are more 'hidden' throughout your code?

  • By @samuel · 2021-11-09 13:49

    I almost never use DI. The only exception is packages, in specific classes that are bound to the service container (for instance here although looking at that now it ideally wouldn't inject Application itself).

    One of the main arguments for DI was that it lets you change implementation by binding a class that extends the parent into the service container, like:

    class MyDatabaseManager extends DatabaseManager
    {
        // ...
    }
    
    app()->bind(DatabaseManager::class, MyDatabaseManager::class);
    

    However, Laravel's facades and helpers forward the calls to the service container anyway. So the behavior is identical, and you don't lose any features by using facades or helpers (I personally prefer helpers over facades).

    Then the only remaining benefit (of the ones that are commonly mentioned) is that the class lists its dependencies. I can see the logic behind that, but don't really care about that in general.

    • By @ralphjsmit · 2021-11-09 14:36

      Yes, so this is a highly developer-specific thing. I was asking because I got the idea that DI was widely seen as best practice, but that's then not the case :)