Когда в коде куча new, перед глазами картина: человек стоит посреди горящей свалки, льёт бензин и думает: «Да норм, зато быстро работает». Нет, не норм. new в лоб — это как сварить суп, зацементировав в кастрюле ингредиенты. Потом попробуй поменяй мясо на курицу. Да, можно, но проще выбросить кастрюлю.

Dependency Injection (DI) — это не модное слово из конференций, а единственный шанс, что твой проект не превратится в монстра, который жрёт время и силы. DI — это про тесты, про гибкость, про то, чтобы завтра ты не матерился на свой же код. Если, конечно, проект не какой-то говнокод и позволяет это сделать.

1. Тестируемость или «а как это вообще протестить?»

Представь, у тебя контроллер сам делает new StripePaymentGateway(). Красиво? Хрен там.
В тесте тебе придётся дёргать реальный Stripe. Удачи с этим.

DI говорит: «Брат, не парься, я подложу тебе что хочешь». В тестах ты пихаешь мок — и живёшь спокойно. Код не знает, что там под капотом. Для теста — подставка из картона, для прода — реальный сервис.

Без DI твой тест будет выглядеть как ритуал вуду, с моками в 10 строк на каждый вызов. С DI — подменил в контейнере, готово.

2. Гибкость или «не хочешь Stripe — бери PayPal»

Сегодня у тебя Stripe, завтра менеджеру вздумалось: «Давайте PayPal».
Если ты хардкодил new StripePaymentGateway, то добро пожаловать в веселую игру «поменяй 100500 строк кода».

С DI меняешь одну строчку в провайдере:

$this->app->bind(PaymentGateway::class, PayPalPaymentGateway::class);

и всё. Код даже не заметил подмены. Вот это называется гибкость, а не тот цирк, когда ты grep-ом по проекту ищешь, где ты опять нафигачил new Stripe....

3. Повторное использование или «перестань копипастить»

Класс, который жрёт Stripe, тебе понадобится и в контроллере, и в сервисе, и в очереди. Если ты везде пихаешь new StripePaymentGateway(), то поздравляю — ты изобрёл Copy-Paste Driven Development.

С DI ты один раз прописал зависимость, дальше она разъезжается по проекту сама. И ты наконец перестаёшь чувствовать себя клоуном, который тащит один и тот же код по разным папкам.

4. Управляемость или «когда проект разросся до размеров мамонта»

Если у тебя три класса — new ещё может прокатить. Но когда код разрастается до ста сервисов, у которых связи как у родственников на даче после третьей бутылки — всё, приехали.

DI-контейнер позволяет держать всё в одном месте. Захотел обновить сервис — пошёл в одно место, поправил, поехали дальше. Без DI это превращается в прогулку по минному полю: в одном месте забыл поменять — бац, всё легло.

5. Снижение связности или «почему твой код напоминает сиамских близнецов»

Жёсткие new связывают код так, что отделить один кусок от другого невозможно. Это как сиамские близнецы, только без шансов на операцию.
DI делает компоненты самостоятельными. Хочешь заменить кусок? Пожалуйста. Хочешь протестить отдельно? Без проблем.

Пример на Laravel

Чтобы не быть голословным. Laravel сам за тебя тащит DI, если ты не ломаешь систему.

Регистрация зависимости:

$this->app->bind(PaymentGateway::class, StripePaymentGateway::class);

Внедрение в контроллер:

class OrderController extends Controller
{
    protected $paymentGateway;

    public function __construct(PaymentGateway $paymentGateway)
    {
        $this->paymentGateway = $paymentGateway;
    }

    public function placeOrder($amount)
    {
        $this->paymentGateway->charge($amount);
    }
}

Тут контроллеру вообще насрать, Stripe там или PayPal. Ему главное — чтобы был кто-то, у кого есть метод charge.

Тест:

$mock = $this->createMock(PaymentGateway::class);
$mock->expects($this->once())->method('charge')->with(100);

$this->app->instance(PaymentGateway::class, $mock);

$response = $this->post('/order', ['amount' => 100]);
$response->assertStatus(200);

Без DI ты бы уже страдал, пытаясь отключить реальный платежный шлюз. С DI — тест прошёл, нервы целы.

Итог

new в коде — это как пить водку на работе: вроде весело, но последствия неизбежны. DI — это скучный, но надёжный способ не превращать код в кладбище костылей.

Хочешь код, который живёт дольше недели и тестируется без шаманства? Забудь про new в бизнес-логике. Пусть всем рулит DI.