besogonskiy
@besogonskiy
работаю php laravel разработчиком.

Почему целесообразнее не использовать new для работы с классами, а предпочесть DI?

на проекте, куда попал, принято каждый сервис вызывать внутри функций других классов в виде
(new MyService())->getData() - к примеру.

Но у меня было убеждение, что тогда уж лучше в конструктор класса прокинуть его:
private readonly MyService $service;

или прям в метде контроллера:
public function store(Request $request,  Myservice $service)
{
   $newData = $service->getData($request->all());
}


в общем можете мне с точки зрения целесообразности объяснить как правильнее?
  • Вопрос задан
  • 108 просмотров
Решения вопроса 3
alexey-m-ukolov
@alexey-m-ukolov Куратор тега PHP
Вот почему: PHPunit замокать класс внутри тестируемого класса?
Бонус-раунд: DI упрощает работу с зависимостями зависимостей. Если ваш MyService принимает какой-нибудь логер в зависимостях, который в свою очередь ожидает какой-нибудь драйвер файловой системы, вы задолбаетесь собирать их через new.
Ответ написан
Комментировать
DmitriyEntelis
@DmitriyEntelis
Думаю за деньги
Главные аргументы против new.
1. Невозможно написать unit-тест на класс
2. Нельзя сделать то что написал devian3000 в своем примере
3. По коду непонятно от чего зависит класс.
4. Хорошие контейнеры обеспечивают переиспользование уже созданных классов, что может давать выигрыш в скорости
Ответ написан
Комментировать
@devian3000
Правильнее через внедрение зависимости (в частности DI).
В конструктор нужно передавать интерфейс.
Простой пример, в зависимости от настроек нам нужно отправить сообщение или через email или просто записать в файл для отладки, тогда

interface MessageProviderInterface {
    public function sendMessage($from, $to, $text);
}

class Email implements MessageProviderInterface{}
class File implements MessageProviderInterface{}

class NewService {
   private MessageProviderInterface $provider;
   public function __construct(MessageProviderInterface $provider) {
      $this->provider = $provider;
  }
}

$provider = getenv('ENV') === 'DEBUG' ? new FileProvider() : new EmailProvider();
$service = new NewService($provider);

Это буквы I и D в принципе SOLID.
DI контейнер просто позволяет проще регистрировать эти зависимости (не только но в основном)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы