Как правильно реализовать архитектуру для связанных объектов с сервисом, коллекцией и репозиторием? Добрый день. Есть таблица в бд, в ней хранится сущность: Post. Сама по себе эта сущность не используется, в зависимости от некоторых строк в таблице, создается дочерняя сущность News, Article и.т.д, у которых есть одинаковые методы, но могут быть дополнительные разные методы. Хотелось бы реализовать все это с репозиториями и интерфейсами, чтобы можно было менять при необходимости Набросал пример, чтобы было хоть немного понятно, чего я хочу:interface PostContract { public function getId(); public function getTitle(); } interface NewsContract extends PostContract { public function getCountry(); } interface ArticleContract extends PostContract { public function getTags(); } abstract class Post implements PostContract { public function getId() { } public function getTitle() { } } class News extends Post implements NewsContract { public function getCountry() { } } class Article extends Post implements ArticleContract { public function getTags() { } } interface NewsCollectionContract { public function push(NewsContract $item); } interface ArticleCollectionContract { public function push(ArticleContract $item); } class NewsCollection implements NewsCollectionContract { public function push(PostContract $item) { } } class ArticleCollection implements ArticleCollectionContract { public function push(ArticleContract $item) { } } interface PostRepositryContract { public function getList(); } interface NewsRepositryContract extends PostRepositryContract { public function getList() : NewsCollectionContract; public function get($id) : NewsContract; } interface ArticleRepositryContract extends PostRepositryContract { public function getList() : ArticleCollectionContract; public function get($id) : ArticleContract; } abstract class PostRepositry { // Общие методы } class NewsRepository extends PostRepository implements NewsRepositryContract { public function getList() : NewsCollectionContract { return new NewsCollection; } public function get($id) : NewsContract { return new News; } } class ArticleRepositry extends PostRepository implements PostRepositryContract { public function getList() : ArticleCollectionContract { new ArticleCollection; } public function get($id) : ArticleContract { new Article; } } interface NewsServiceContract { public function getList(array $params) : NewsCollectionContract; } interface ArticleServiceContract { public function getList(array $params) : ArticleCollectionContract; } class NewsService implements NewsServiceContract { private $repo; public function __construct(NewsRepositryContract $repo) { $this->repo = $repo; } public function getList(array $params) : NewsCollectionContract { return $this->repo->getList(); } } class ArticleService implements ArticleServiceContract { private $repo; public function __construct(ArticleRepositryContract $repo) { $this->repo = $repo; } public function getList(array $params) : ArticleCollectionContract { return $this->repo->getList(); } } Как все это реализовать правильно?
У вас уже весьма неплохой набросок архитектуры для связанных объектов с сервисом, коллекцией и репозиторием. Однако, есть несколько моментов, которые стоит улучшить или обратить внимание:
Применение интерфейсов на уровне сервисов (NewsServiceContract, ArticleServiceContract) дает возможность легко подменять репозитории или сами сервисы в будущем. Таким образом, соблюдается принцип инверсии зависимостей (Dependency Inversion Principle).Нет необходимости вводить различные коллекции (NewsCollection, ArticleCollection). Вы можете использовать одну универсальную коллекцию и передавать в неё разные типы объектов. Например, можно создать общий класс PostCollection и передавать в него объекты News или Article.При объявлении методов get() в репозиториях NewsRepository и ArticleRepository, следует вернуть результат операции, например, return new News(); вместо простого создания объекта.Разумно обрабатывать ошибки, например, проверкой на существование объекта перед его возвратом из репозитория.
Кроме того, стоит также уделить внимание названиям классов (например, PostRepository вместо PostRepositry) и также пересмотреть методы, возвращающие коллекции (getList()) в репозиториях, возможно, они могут быть модифицированы для работы с параметрами.
В целом, ваш подход к созданию архитектуры с использованием интерфейсов, абстрактных классов и разделением ответственностей сервисов, репозиториев и коллекций вполне правильный и позволит легко расширить функционал и поддерживать проект в будущем.
У вас уже весьма неплохой набросок архитектуры для связанных объектов с сервисом, коллекцией и репозиторием. Однако, есть несколько моментов, которые стоит улучшить или обратить внимание:
Применение интерфейсов на уровне сервисов (NewsServiceContract, ArticleServiceContract) дает возможность легко подменять репозитории или сами сервисы в будущем. Таким образом, соблюдается принцип инверсии зависимостей (Dependency Inversion Principle).Нет необходимости вводить различные коллекции (NewsCollection, ArticleCollection). Вы можете использовать одну универсальную коллекцию и передавать в неё разные типы объектов. Например, можно создать общий класс PostCollection и передавать в него объекты News или Article.При объявлении методов get() в репозиториях NewsRepository и ArticleRepository, следует вернуть результат операции, например, return new News(); вместо простого создания объекта.Разумно обрабатывать ошибки, например, проверкой на существование объекта перед его возвратом из репозитория.Кроме того, стоит также уделить внимание названиям классов (например, PostRepository вместо PostRepositry) и также пересмотреть методы, возвращающие коллекции (getList()) в репозиториях, возможно, они могут быть модифицированы для работы с параметрами.
В целом, ваш подход к созданию архитектуры с использованием интерфейсов, абстрактных классов и разделением ответственностей сервисов, репозиториев и коллекций вполне правильный и позволит легко расширить функционал и поддерживать проект в будущем.