Статья опубликована в рамках: LXI Международной научно-практической конференции «Вопросы технических и физико-математических наук в свете современных исследований» (Россия, г. Новосибирск, 22 марта 2023 г.)
Наука: Информационные технологии
Секция: Математическое и программное обеспечение вычислительных машин, комплексов и компьютерных сетей
Скачать книгу(-и): Сборник статей конференции
дипломов
ПРИМЕНЕНИЕ АРХИТЕКТУРНОГО ПАТТЕРНА «ВНЕДРЕНИЕ ЗАВИСИМОСТЕЙ» ДЛЯ ЗАГРУЗКИ ФАЙЛОВ В ПРИЛОЖЕНИИ НА ЯЗЫКЕ PHP
USING THE DEPENDENCY INJECTION ARCHITECTURAL PATTERN TO LOAD FILES IN A PHP APPLICATION
Dmitrii Kuzin
Candidate of Science, Associate Professor of Automation and Computer Systems Department, Surgut State University,
Russia, Surgut
АННОТАЦИЯ
Целью работы является исследование возможности и преимуществ применения архитектурного паттерна «внедрение зависимостей» при реализации загрузки файлов на сервер в приложении на PHP. Автором была предложена структура классов приложения, которая демонстрирует преимущества проектирования с применением внедрения зависимостей в объект на примере использования различных способов загрузки файлов на сервер. Результатом работы является веб-приложение, реализованное в соответствии с предложенной архитектурой и размещенное в открытом git-репозитории.
ABSTRACT
The aim of the work is to study the possibility and advantages of using the "dependency injection" architectural pattern when implementing file uploads to the server in a PHP application. The author proposed an application class structure that demonstrates the advantages of designing using dependency injection into an object using various methods of uploading files to a server as an example. The result of the work is a web application implemented in accordance with the proposed architecture and hosted in an open git repository.
Ключевые слова: внедрение зависимостей, PHP, веб-приложение.
Keywords: dependency injection, PHP, web application.
Внедрение зависимостей (Dependency Injection - DI) [1] один из паттернов объектно-ориентированного проектирования, в основе которого лежит простой принцип – любой объект не создает сам другие объекты, от которых зависит (зависимости), а получает их при создании.
Преимущества использования внедрения зависимостей:
1. Повышение изолированности кода. Если зависимость создается внутри кода класса, то в случае изменения метода создания придется менять код этого класса. Кроме того, возможно, что это придется делать во множестве зависимых классов. Внедрение зависимости избавляет от этого недостатка, если все зависимости при изменении продолжают имплементировать один и тот же интерфейс.
2. Облегчение тестирования. Одним из методов unit-тестирования является замена реальных объектов-зависимостей на их mock (макеты), участвующие в тестировании. Если класс создает зависимость внутри, то протестировать его невозможно, так как замена реальной зависимости на mock невозможно без изменения кода класса. Смысла тестировать измененный код нет. Если же используется паттерн DI, то замена реальных объектов на mock происходит прозрачно для тестируемых методов.
3. Более простое переиспользование. Внедрение зависимостей в класс повышает возможность переиспользования класса. Если в другом контексте требуется другая реализация или конфигурация какой-либо зависимости, достаточно передать в класс измененную зависимость без изменения кода класса.
Основным способом внедрения зависимости в объект является передача зависимости через параметр конструктора объекта при его инициализации. Наряду с этим для внедрения зависимости могут использоваться методы класса, обычно методы-сетеры.
При использовании паттерна DI возникает вопрос: как организовать архитектуру приложения с точки зрения того, где именно будут создаваться и внедряться зависимости. С точки зрения удобства сопровождения и расширения кода целесообразно использовать отдельный объект, называемый DI-контейнер [2]. DI-контейнер управляет жизненным циклом объектов, создавая их, внедряя необходимые зависимости, и, возможно, удаляя. Использование DI-контейнера для централизованного управления жизненным циклом объектов позволяет переиспользовать объекты, создавая их как синглтоны, что ведет к экономии вычислительных ресурсов.
В реальных приложениях распространен случай, когда классы образуют многослойную структуру и для какого-либо класса зависимостью является нижележащий класс. Таким образом образуется цепочка зависимостей. При использовании DI-контейнера эта цепочка описывается в коде контейнера и ее легко контролировать. Кроме того, в ряде случаев возникают т.н. «переносы зависимостей», когда какой-то объект передается по цепочке на нижний уровень иерархии. Использование DI-контейнера позволяет избавиться от переносов зависимостей между классами, передавая их вместо этого как синглтоны в контейнере.
Паттерн проектирования «внедрение зависимостей» был применен автором при реализации компонентов приложения осуществляющих загрузку файлов. В качестве хранилища файлов используется AWS S3-совместимое хранилище, развернутое на базе свободнораспространяемого ПО Minino [3]. Параметры конфигурации хранилища (S3_KEY, S3_SECRET, S3_BUCKET, S3_ENDPOINT) указываются в файле .env. Для работы с хранилищем используется библиотека AWS SDK for PHP [4]. Класс Container содержит только статические методы. Архитектура разработанных классов приведена на рисунке.
Рисунок 1. Архитектура классов, реализующих работу с файлами в приложении
Для загрузки файла компонент бизнес-логики приложения выполняет вызов:
$resource = Container::getFileUploader()->store($file, $filename);
Метод getFileUploader возвращает объект типа FileUploder – класс-интерфейс, который имплементируют все классы, занимающиеся загрузкой файлов. Это позволяет при необходимости легко заменить технологию работы с файлами, например, для сохранения их на локальный диск сервера. Для этого достаточно внести изменения в метод getFileUploader контейнера, возвращая объект другого класса, при этом вносить изменения в код бизнес-логики приложения не потребуется:
public static function getFileUploader(): FileUploader
{
return self::getS3FileUploader();
//Для изменения технологии работы с файлами поменять метод
//return self::getLocalFileUploader();
}
Собственно, внедрение зависимостей происходит при инициализации класса S3FileUploader:
public static function getS3FileUploader(): \S3FileUploader
{
return new \S3FileUploader(self::getS3Client(),self::getS3Config());
}
Описанная архитектура была реализована при разработке web-приложения «Персональный менеджер задач на PHP и MySQL с аутентификацией пользователя» на языке PHP. Код приложения размещен в открытом репозитории ан GitHub [5].
Список литературы:
- Dependency Injection [Электронный ресурс] / Jakob Jenkov. — Электрон. текстовые дан. — 2015. — Режим доступа: http://tutorials.jenkov.com/dependency-injection/index.html, свободный
- Контейнеры внедрения зависимостей и выгоды от их использования [Электронный ресурс] / Jakob Jenkov. — Электрон. текстовые дан. — 2018. — Режим доступа: https://habr.com/ru/post/350708/, свободный
- MinIO Quickstart Guide [Электронный ресурс] / MinIO, Inc. — Электрон. текстовые дан. — Режим доступа: https://docs.min.io/docs/, свободный
- AWS SDK for PHP - Version 3 [Электронный ресурс] / Official repository of the AWS SDK for PHP (@awsforphp). — Электрон. текстовые дан. — Режим доступа: https://github.com/aws/aws-sdk-php, свободный
- Кузин, Д.А. ToDoList. Персональный менеджер задач на PHP и MySQL с аутентификацией пользователя [Электронный ресурс] / Д.А. Кузин. — Электрон. текстовые дан. — 2022. — Режим доступа: https://github.com/2repby/ToDoList, свободный. — Репозиторий
дипломов
Оставить комментарий