Хорошая архитектура symfony app?

Что значит "Хорошо спроектированное приложение с применением Symfony2"?

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

А вы, {{ user.name }}, как думаете?

UPD: Появился (по ходу) еще вопрос. А что тогда значит "Хорошо организованный сервисный слой приложения"?

UPD2: из ответов ув-х keltanas и Nikolas Lindemann, как бы не двусмысленно следует, что всетки, хорошее приложение имеет слой работы с данными непосредственно (доктрина, например, которая поставляет данные в модели), но, так как приложение в самом верхнем слое может имеет разные интерфейсы с внешним миром, то логику самого приложения лучше таки скрыть в еще одном слое между ними. Этот слой (сервисный?) и будет взаимодействовать с слоем работы с данными по запросам из интерфейсов (верхнего слоя), обеспечивая тем самым единую логику работы приложения в целом. Но на слой логики не стоит возлагать операции сохранения данных, а лишь манипуляции (собственно, реализацию самой логики)

UPD3: Замечено, что многие смотрят на архитектуру по своему :) Для кого-то, хорошая архитектура -- это удобство с которым можно покрыть код и функционал тестами; для кого-то это возможность внесения изменений без ущерба для окружающих компонентов. Может из этого следует сделать вывод, что к хорошей архитектуре относится та, которая состоит из независимых, но сильно связных компонент?

UPD4: ADR (https://habrahabr.ru/post/260769/).

UPD5: SOLID
  • Вопрос задан
  • 3613 просмотров
Решения вопроса 1
lexxpavlov
@lexxpavlov
Программист, преподаватель
Хорошая архитектура - это очень понятная архитектура, когда для каждого типа задачи созданы логичные и понятные средства. Когда приложение построено таким образом, то его получится и тестировать, и изменять/расширять. Если нужно добавить новый класс, то в хорошей архитектуре понятно, куда его нужно добавить.

Всего существует не так много типов задач:
1) хранение данных приложения - модель. Модель ничего не должна знать о базе данных.
2) слой доступа к БД - репозиторий. Вся работа с БД - здесь, и всё, что связано с одной сущностью - в репозитории этой сущности. Если нужно взаимодействие нескольких сущностей, то, скорее всего, репозиторий одной из сущностей не подойдёт, эта задача пойдёт в сервис.
3) бизнес-логика - сервисы. Сервисы умеют получать данные (модели), обращаясь к репозиториям или лучше к другим сервисам (служебным).
4) служебные задачи - сервисы. Например, кэширование данных реализуется в специальном сервисе.
5) отображение данных - шаблоны. Весь html - только в шаблоне, а также логика отображения тоже в нём (вывод списков, некоторые фильтры)
6) подготовка данных к отображению - контроллер. Запрос пользователя приходит в контроллер, контроллер же обращается к сервису (или в простом случае к репозиторию) за данными. Возможно, для обработки запроса нужно получить данные из нескольких сервисов/репозиториев, а скорее, правильный сервис сам подготовит все данные для запроса.

Получается, контроллер вызывает сервис, который предоставит готовые данные, и будет очень простым - "тонким". Основной код, отвечающий за работу задач приложения - в сервисах. Один и тот же сервис часто будет вызываться из разных контроллеров. Работа с БД - не в сервисе и уж точно не в контроллере, для этого нужен репозиторий.
Если структура БД изменится, то в хорошей архитектуре поменять придётся только репозиторий, но не сервисы/контроллеры. С другой стороны, изменение схемы БД чаще всего связаны с новыми фичами, поэтому придётся добавить новый сервис или изменить существующий.
Модель же умеет не так много - выводить свои данные, возможно, в разных форматах (данные, возвращаемые моделью не обязаны совпадать с полями сущности - см. пример в комментарии keltanas в ответе Владимир Балин).

Модели, репозитории, контроллеры, шаблоны обычно расположены в особых специальных папках проекта. А вот сервисы могут быть расположены в совершенно разных папках проекта, созданных специально для них. Как пример, сервисы кэширования можно поместить в папку Persistance - отдельный сервис для получения сущностей и отдельные сервисы для получения агрегированных данных (полученных из разных сущностей). При изменении способа кэширования поменяются только сервисы, связанные с кэшированием, но не остальные части проекта.

Получается, контроллеры "тонкие", модели "тонкие", а репозитории гораздо толще. Сервисы тоже "толстые", но их хорошо разбивать на отдельные сервисы, чтобы не было вся логика проекта в одном классе, и тогда каждый сервис уже не такой уж "толстый".

P.S. Я вот написал, что модель не должна ничего не знать о базе данных, получается, что неправильно использовать аннотации для маппинга полей сущности на поля таблиц. После ответа на этот вопрос я, скорее всего, пересмотрю свои взгляды на @ОRМ-аннотации в моделях.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
Если все приложение можно без проблем покрыть юнит тестами, если у вас тонкие контроллеры и довольно тонкие сервисы и жирные модели, если вы соблюдаете принципы SOLID и т.д... то у вас выходит код который очень легко поддерживать и расширять. Для проектов посложнее есть всякие там DDD, CQRS, есть гексагональная архитектура...

Короче все сводится к такому параметру как maintainability.

https://github.com/phptodayorg/php-must-watch#arch...

updated
если интересно, есть пример "хорошей" архитектуры (ну или основы для нее), ну или как минимум интересной:
https://github.com/qandidate-labs/broadway

Конечно этот пример не подходит для всех предметных областей, но как один из вариантов "посмотреть как люди делают" - как по мне неплохо.
Ответ написан
krocos
@krocos Автор вопроса
Php-dev
Судя из обсуждения, понятно, что приложение должно быть, как минимум, хорошо тестируемым и готовым для легкого расширения и/или изменений. А это достигается хранением бизнес логики в сервисах, которые подключены к контейнеру, но не в моделях, потому, что слой БД может (потенциально) поменяться.

Делаем вывод: тонкие контроллеры, толстый сервисный слой и тонкие (или не очень) модели.

Вроде все правильно?
Ответ написан
Наверное многие вообще не хотят понять для чего вообще нужна служба (service), какого её главная цель?! Большинство её приравнивают, как ещё один вид абстрактного слоя, где можно отгородить некую, а бывают случаи что и всю логику приложения, то есть модель и служба по сути одно и тоже, и отдают предпочтение именно службе. Судя по всему, сколько я слышал и читал, сделав вывод, что это аргументируется тем, что это просто круче звучит: это же СЕРВИС, а не какая то там модель, значит что-то стоящее, и в глазах коллег, или падших наших пользователей это считается и расценивается как превосходство... Вообще ничего хорошего от этого нету!
Возвращаюсь к самой теме, служба - это всего лишь некий функционал, который может работать на уровне всего приложения. Разумеется, что на уровне всего приложения захочется сделать не только какой то безобидный функционал, а какую то услугу, но делать такое надо с умом, ибо это не основная задача службы, в результате чего, может пасть производительность.
К вопросу автора:
1. Использование шаблона проектирования MVC.
2. Проектирование на сервис-ориентированной архитектуре.
3. Проектирование на событийно-ориентированной архитектуре.
Есть ещё много вариантов, но копировать-вставить нету никакого смысла и желания, достаточно найти в поисковике "архитектура программного обеспечения".
В любом случае надо исходить из задачи, и подбирать лучшее инструменты для её решения.
Ответ написан
Ваш ответ на вопрос

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

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