Вот уже полтора года я использую Symfony 2 для разработки web-приложений. За это время я трижды начинал новый проект, еще в трех проектах работал с унаследованным кодом, а также провел ревью около 15 тестовых заданий на знание фреймворка.
Наверное, было бы здорово иметь возможность вернуться на полтора года назад и дать себе несколько советов перед стартом своего первого проекта. Увы, это невозможно. Но может быть, мои советы могут пригодятся другим начинающим разработчикам на Symfony?
Соблюдай кодстайл и конвенции по наименованию
Я не стану в тысячный раз говорить о важности кодстайла, но большинство начинающих девелоперов его не соблюдают.
К счастью эту проблему легко исправить. Современные IDE могут автоматичеси форматировать код по выбранным правилам. Сейчас я использую PHPStorm. Тут есть и предустановленные настройки для Symfony, и автоматическое добавление оператора use, и еще много вкусностей.
Если говорить о стандартах кодирования, нельзя не упомянуть о PHP CS Fixer от Fabien Potencier. PHP CS Fixer станет для тебя обязательным инструментом через некоторое время.
Небольшое лирическое отступление. В социологии, существует Теория разбитых окон, которая говорит о том, что игнорирование общепринятых правил одними людьми провоцирует других людей так же игнорировать эти и другие правила. Исправляй ошибки кодстайла в проекте, не оставляйте “разбитых окон” в своем коде.
Не делай толстых контроллеров
Толстые тупые уродливые контроллеры (ТТУК), вторая по популярности ошибка, которая встречается в коде начинающего девелопера. Про толстые контроллеры написано немало. Если в двух словах, то контроллеры не являются переиспользуемыми программными модулями в общем случае. Поэтому не стоит тут держать бизнес логику. Логика в контроллерах приводит к нарушению принципе DRY и провоцирует на копипаст. Выноси бизнес логику в слой сервисов, в модель, куда угодно. Не стесняйся создавать новый класс, сервис, метод, стесняйся делать ТТУКи.
Не делай сервисы зависимые от контейнера
Лучше всего забудь, что такая возможность вообще существует. В момент, когда ты создашь зависимый от контейнера сервис, ты перестанешь контролировать, что в нем происходит. А если тебе хочется внедрить в сервис весь контейнер, только потому что он “распухает” от зависимостей, то, скорее всего, что у тебя проблемы с архитектурой. Контейнер в сервисе будет провоцировать тебя на нарушение Single responsibility principle и уж никак не будет способствовать созданию правильного дизайна. Container aware сервисы будет тяжело тестировать. А если завдешь себе иерархию на основе такого класса, то это еще и будет тяжело отрефакторить.
Посмотри на Service Container с другой стороны. Это в первую очередь инструмент для конфигурации зависимостей, а не место откуда ты можешь дернуть любой сервис. Не используй контейнер в других классах, кроме контроллеров. А еще лучше приучи себя и контроллеры делать сервисами. Тебе же самому будет легче понимать и контролировать, то что происходит в твоем коде.
Пиши код максимально просто
Во-первых, перестань делать лишние интерфейсы. Не вводи интерфейс лишь для того, чтобы не делать зависимость от конкретного класса. Твоя единственная конкретная реализация интерфейса, возможно, так и будет жить в проекте годами. Не бойся делать зависимости на конкретный класс. Ты легко сможешь отрефакторить код и добавить интерфейс тогда, когда увидишь в нем необходимость.
Во-вторых, делай публичный API классов как можно проще. Другими словами, не стоит делать публичных методов у класса, которые ты не будешь использовать прямо сейчас.
В-третьих, методы и свойства, которые не являются публичным API класса делай приватными по дефолту. Ты всегда сможешь изменить область видимости, если появится необходимость перекрыть метод или свойство. Но когда другой программист будет читать твой код, он будет на сто процентов уверен, что этот метод не используется нигде больше.
В-четвертых, не стоит имплементить сейчас то, что будет использоваться завтра. Практика показывает, что это призрачное завтра может никогда и не наступить. Да, ты никогда не сможешь точно сказать, как изменятся требования к проекту. Так зачем же усложнять проект сейчас? Зачем тебе делать лишнюю работу?
Ну и, в-пятых, не включай в проект целые бандлы, ради одной маленькой фичи. Например, тебе же не нужен FOSRestBundle, чтобы в одном из контроллеров вернуть JSON.
Не злоупотребляй комментариями
Не комментируй то, что очевидно. Не добавляй комментарии к методам, только потому что твоя IDE умеет это делать автоматически. Если ты удачно выбрал названия классов, методов, переменных и свойств у тебя вообще никогда не должно возникнуть желание добавить комментарий в код.
Впрочем, иногда комментарии просто необходимы. Не забывай комментировать код, когда логика сложна или не очевидна. Добавляй комментарии только к ключевым методам, т.е. к тем, которые делают самую важную работу. Всегда покрывай комментариями и тестами методы в которых используются сложные регулярки.
Хорошо разберись в том, как работает Doctrine
Чаще всего твои собственные ошибки, а не ORM будут причиной медленной работы приложения с БД. Правильно определяй тип и направленность отношений между сущностями. Не злоупотребляй наследованием в сущностях. Постоянно заглядывай в профайлер, чтобы контролировать как быстро работает слой доступа к данным и какие запросы создает ORM. Избегай вложенных транзакций. Вызывай flush только в контроллере. Прочти еще раз документацию по Doctrine, хотя бы по диагонали.
Используй все возможности Twig
Twig очень хороший шаблонизатор. Со временем ты это поймешь. Его очень легко расширять при необходимости. Но и того, что есть в стандартной поставке с головой хватит, чтобы перестать дублировать код в шаблонах. Перечитай еще раз документацию, там немного. И с пользуйся всеми возможностями этого инструмента.
Грамотно пользуйся исключениями
Всегда определяй кастомный тип для исключений, которые могут возникнуть на продакшене. Пиши четкие сообщения для тех исключений, которые могут возникнуть в разработке. Обрабатывай исключения в одном месте, а не пытайся ловить из в каждом контроллере.
Не делай конфиги громоздкими
Symfony дает тебе все инструменты, чтобы организовать конфигурационные файлы так, как нужно именно тебе. Большие конфиги не удобны. Их стоит разбивать на более мелкие так, чтобы любой разработчик в проекте мог легко ориентироваться в конфигах.
Почаще обновляй зависимости в проекте
Используй стабильные версии бандлов, если есть такая возможность. А если нет, то обновляй зависимости как можно чаще. Ошибки лучше всего исправлять по мере их появления. Когда ты насобираешь много обновлений, то и устранить все проблемы несовместимости, будет намного сложнее.
Пиши тесты
Пиши приемочные тесты на Behat с первого дня проекта. Потом будет тяжелее покрыть весь функционал. Создание тестового окружения требует определенного времени. Но на начальных этапах это время будет размазываться между другими задачами. А в дальнейшем эти тесты будут часто тебя выручать.
Пиши модульные тесты на PHPUnit. Хотя бы на сложные и наиболее важные методы. Пиши тесты перед кодом, это позволит создавать более качественный дизайн. Профит от модульных тестов будет в отсутствии багов и регрессий в коде.
Ну, а самый главный совет, который я бы хотел себе дать: “Не бойся делать ошибки, но стремись работать в команде с более оптыными разработчиками, которые тебе на них укажут. Ну, а если у тебя сейчас нет такой возможности в коммерческом проекте, ищи таких людей в OSS.”
Немного ссылок:
- Кодстайл Symfony
- Теория разбитых окон
- ТТУКи
- Хорошая статья о «правильном» использовании DI
- Видео доклада о «правильном» использовании Doctrine
Автор: tyomo4ka