Как стать автором
Обновить

Повышаем читаемость Symfony DI

Уровень сложностиПростой
Время на прочтение3 мин
Количество просмотров2.8K

Привет! Я разрабатываю приложения на Symfony и хочу поделиться проблемами, с которыми сталкивался при использовании Symfony DI, а также дать несколько советов которые, как мне кажется, будут полезны при разработки больших приложений. Кратко я упоминал о них в этой статье, и здесь хочу развернуть мысль и поговорить подробнее.

Есть давно известная it мудрость, а том что код мы намного чаще читаем, чем пишем. На крупных проектах, работу над которыми ведёт не один разработчик или даже не одна команда, это наиболее актуально. Проект меняется быстро, следить за всеми изменениями невозможно, постоянно появляются новые классы, неймспейсы, решения, добавляются зависимости, создаются бандлы. В такой атмосфере во главу угла развития проекта я ставлю читаемость и гибкость написанного кода и di его важная часть.

Autowire

Первое препятствие на пути к этой цели это autowire. Автовайринг полезен при быстром прототипировании, так как ускоряет написание di, но в долгой перспективе скорее вредит, приведу небольшие примеры:

services:
    _defaults:
        autowire: true
        
App\Service\Service: ~

App\Component\LockInterface:  
   class: App\Component\Lock 
final class Service {
	public function __construct(private readonly LockInterface $locker)  
	{  
	}
}

Реализация успешно подтягивается в класс сервиса. Дальше сервис растёт, растёт service.yaml, возможно разбивается на более мелкие yaml, появляются новые реализации LockInterface (иначе зачем мы создавали интерфейс). И со временем взглянув на класс при чтении кода становится довольно не просто найти, а какая конкретно реализация сейчас используется.
Ситуация значительно упрощается, если явно указать реализацию: добавив всего одну строчку di при написании, мы облегчаем себе её чтение в будущем.

App\Service\Service:
	arguments:  
	    $locker: '@App\Component\Lock'

Ещё одна опасность это возможные ошибки, так как изменения реализации могут происходить неявно:

App\Component\LockInterface:  
   class: App\Component\MyCustomLock 

Так мы одним махом меняем реализацию во всех местах использования, удобно на маленьком приложении, где мы держим в голове все места использования. Но в большой кодовой базе такое изменение может задеть места, о котором мы не подумали/забыли/не знали. Явное изменение строки di в используемом классе как минимум подсветит это. Да мы потратим больше времени, но зато изменения будет явными.
Не используйте автовайринг.

Классы вместо алиасов

В di лучше придерживаться одного стиля написания, это упрощает чтение и выбор собственно между двумя вариантами:

App\Component\Consumer:

app.component.consumer:
	class: App\Component\Consumer: ~

Я предпочитаю второй, хоть он и более многословный. Причина в том, что это позволяет переиспользовать классы с разными аргументами, например так:

app.component.consumer.email_queue:
	class: App\Component\Consumer:
		arguments: 
			$queueName: 'mail'
			
app.component.consumer.sms_queue:
	class: App\Component\Consumer:
		arguments: 
			$queueName: 'sms'

Так не придётся добавлять новый дублирующий код или что страшнее использовать наследование. Использование обоих способов именования одновременно по необходимости вносит лишний шум в di и мешает чтению.
Используйте алиасы.

Интерфейс вместо реализации

Ещё один странный способ указания зависимостей в di, который я часто встречаю:

app.component.consumer:
	class: App\Component\Consumer:
		arguments: 
			$executor: '@App\Component\ExecutorInterface'

Есть явное указание в аргументах класса, но указание интерфейса. DI container - это про сборку проекта, то место, где мы указываем конкретные реализации интерфейсов, описанных в коде и указание здесь интрфейса просто заставляет разработчика дополнительно тратить время на чтение di в поисках реализации, а сама по себе такая строчка не несёт никакой полезной информации, то что $executor это интерфейс видно и так глядя на код.
Не делайте так.

Правила эти очень субъективные и возможно спорные, они заставляют более дисциплинированно и многословно подходить к написанию di, но по моему мнению упрощают его чтение, что приносит много пользы в долгосрочной перспективе.

Теги:
Хабы:
Всего голосов 3: ↑3 и ↓0+5
Комментарии5

Публикации

Истории

Работа

PHP программист
187 вакансий

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань