Вопрос по архитектуре.

ekulikova

Новичок
Задача.
Написать инструмент для ресайза изображений. Который может ресайзить как одно изображение, так и рекурсивно все изображения в папке.

Путем долгих размышления я пришла к такой структуре.
1. Три класса: класс для работы с одним изображением, класс для рекурсивного обхода директории и класс аля фабрика, который создает объект в зависимости от того передан файл или дириктория.
2. Класс для работы с изображением ресайзит его разными способами и может либо сохрать результат в файл либо вывести в поток вывода.
3. Класс для директории имеет один метод __call, который рекурсивно обходит директорию и применяет тот метод, который был задан пользователем к каждому изображению. Новое изображение либо переписывает существуещее либо пишеться в новую папку, заданную пользователем при вызове функции.

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

grigori

( ͡° ͜ʖ ͡°)
Команда форума
мы вчера 5 часов сидели рисовали UML низкоуровневой архитектуры кода сервиса обработки изображений :)

1. эти классы называются контроллером
2. этот класс надо разбить на несколько
3. это просто один из классов контроллера, не отдельный слой

4. класс, который обрабатывает открытие файлов изображений - есть ли пермиссия на чтение, изображение ли в файле, проверка на нулевой размер файла

5. класс, в котором прописана логика ресайза в зависимости от целевых и исходных параметров изображения
Пример: в файле картинка разрешением 400 ширины на 800 высоты (вертикальная фотка), а целевая картинка - 300х200 пикселей
Ресайзить можно четырьмя способами:
а) отресайзить по ширине с 400 до 300 и обрезать по центру для соблюдения целевого размера
б) отресайзить по высоте с 800 до 200, а ширина получится 75 - ничего не разглядеть, зато не обрезано
в) отресайзить по ширине с 400 до 300 и оставить высоту 600 - бывает нормально, если верстка позволяет разную высоту
г) вывести юзеру рамку, чтобы сам мышкой выбирал как кропнуть фотку под нужный формат

А что если исходная фотка размером 200 на 300? Непонятно.

6. классы отображения, которые определяют формат вывода: jpg, webp, jpeg2000, png, svg, вывод, запись в файл
7. логгер
8. обработчик ошибок
 
Последнее редактирование:

AnrDaemon

Продвинутый новичок
Вот уж воистину: многия знания - многия печали…
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
а причины есть

Года два назад я засел и изучил все доступные готовые пакеты для ресайза фотографий:
  • Есть пакет на питоне с навороченным функционалом, который что-то делает с фотками по запросу, в основном для AI
  • Есть 2 расширения для 3х библиотек в PHP, и ворох фантиков для обертки
  • то же под Ruby
  • Есть пакет на golang, который работает не очень хорошо
  • есть семейство утилит-библиотек libjpeg -> turbojpeg -> mozjpeg, и Мозилла не просто так сделала свой форк
Решений для обработки и хранения фотографий для веб-сайта с оптимизацией под web нет. Совсем. А еще кеширование и раздача.

Работа с изображениями для web отличается от GUI: фотки не надо ресайзить на лету много раз, их можно закешировать. Не надо оптимизировать проц - можно поставить еще серверов. Можно пригрузить проц ради оптимизации размера каждой фотки.

Я прочел статьи Badоо про эволюцию их системы работы с фотографиями. Они переделывали ее раза три.
Читал и слушал истории Чистякова на DevConf, как они пробовали для фотографий хранилище то в NFS, то в Postgres.

В поза-прошлом году ситуация с фотками изменилась. Смартфоны стали пополярны, фоток стало много, и разрешения стали больше. Где 5 лет назад было 50 гб фоток, и пофиг, сейчас 500 гб, и это уже другая история. Сейчас поддержка srcset, и одного URL в теге <img уже недостаточно - на одну фотку нужно несколько вариантов разного разрешения.
А еще есть два оптимизированных формата - WEBP для хромиум, и Jpeg2000 для iOS.

Раньше делали субдомен для фоток, и вперед. Сейчас есть HTTP/2, которому нужен один канал, и вместо поддомена я все отправляю через центральный роутер.

Когда у меня миллион файлов на S3, какие-то файлики теряются - все в пределах SLA. Эту потерю надо отследить, и отреагировать - поправить записи в базе данных.

Могу продолжать про upload по ajax и хранение в облаках - ceph, амазоны, GDPR, РКН :)
 
Последнее редактирование:

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Я могу написать еще десяток ссылок на подобные обертки вокруг image magic и gd.

to have a place to store high quality original images and to use the API to fetch variations of the images. Imbo will resize, rotate and crop (amongst other transformations) images on the fly so you won’t have to store all the different variations
С этой "идеей" на практике есть 5 ключевых проблем:
1. Latency при генерации фоток на лету на 2 порядка больше, чем при отдаче nginx-ом файла с диска.
2. Ужатые до 1920, "оригиналы" занимают в 5 раз больше места на диске, чем все 10 thumbnail-ов, которые выводятся на страницах.
3. Оригиналы пользовательских фотографий формата фотоаппарата или iPhone в web не нужны. Максимальное востребованное разрешение сейчас порядка 1920px. При работе с оригиналами 60% ресурсов сервера будут потрачены бесцельно.
4. На лету ресайз fullhd-изображения требует 1920*1080*24 = 47 мегабайт оперативки только открыть этот файл, а ресайз полностью забьет ядро на пол-секунды. 20 одновременных запросов заткнут средний сервер.
5. Диски умирают. Бекап-репликация-восстановление даже нескольких сотен гигабайт файлов - нетривиальная задача. Хранение - намного более важный вопрос, чем resize, но о нем ни слова. Зато они сделали sepia, sharpen и прочую мишуру.

Баду решает эту ситуацию так: они хранят 3 "опорных" разрешения каждой фотки в 2-уровневом файловом кеше ssd/hdd, и общий железный storage. Оригиналы не хранятся.

Поисковики считают скорость сайта по onDocumentLoad по официальной документации. Если важны позиции в поисковиках, скорость отдачи картинок влияет на посещаемость. Еще поисковики просят оптимизировать изображения на сайте. Авторы Imba не знают про webp, судя по всему.
 
Последнее редактирование:

Yoskaldyr

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

grigori

( ͡° ͜ʖ ͡°)
Команда форума
ну, я вплотную подошел к написанию такого сервиса, который будет решать задачи документированными способами

думаю, можно ли на этом построить какой-нибудь saas
 

Фанат

oncle terrible
Команда форума
@ekulikova, повторю свой коммент с codereview:

у второго класса нарушен single responsibility principle.

Я бы сделал такой финт ушами:

1. класс ресайза одной фотки
2. класс который по переданному ему пути возвращаем массив. если это ссылка на 1 файл. то в массиве 1 элемент. если ссылка на каталог - то пути ко всем файлам рекурсивно.
Возможно, в качество этого класса подойдет RecursiveDirectoryIterator из коробки
3. Класс который вызывает (2) и в цикле обходит возвращаемый массив.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Вот тот класс, который в пункте 3, он будет решать, картинка в переданном списке, или нет? А будет решать, валидная картинка, или нет? А будет решать, умеет ли класс из п.1 этот формат изображений? А если класс из п.1 может поддерживать разные форматы в зависимости от конфигурации сервера? А если ошибка встретилась, он будет пропускать обработку этого файла или выкидывать исключение? А будет знать куда сохранить результат? Сохраняя структуру папок, или все в одну папку? А поверх оригинала писать? А если это ридонли NFS шара была? А на S3 грузить сможет?

У класса из п3 100% признаки что это userland код, которому нечего делать в библиотеке.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
А будет знать куда сохранить результат? Сохраняя структуру папок, или все в одну папку? А поверх оригинала писать? А если это ридонли NFS шара была? А на S3 грузить сможет?

У класса из п3 100% признаки что это userland код, которому нечего делать в библиотеке.
если мы говорим про web, результат - на вывод, кеширование - отдельная задача и отдельное решение, а S3 заблокировали :D

в общем, это не userland код, а конфиг по конечному списку вариантов
 

Adelf

Administrator
Команда форума
ajax upload делается через динамически создаваемый iframe
года 3 назад Redjik нашел какую-то битую мэйлурную либу, и мы допилили ее
Эт неинтересно. через iframe загружали с незапамятных времен. С обрезанием фотки видимо ничего интересного пока не придумали.
 
Сверху