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

У меня есть старый проект Codeigniter, над которым я работаю, и я пытаюсь улучшить кодовую базу. В основном я пытаюсь отделить Codeigiter, где я могу, и внедрить модульные тесты в процессе.

В настоящее время я работаю над рефакторингом рабочего процесса пользователя: в частности, добавлением или обновлением пользователя. В его нынешнем виде есть метод контроллера под названием «save», который обрабатывает все, включая следующее:

  • проверьте, существует ли имя пользователя
  • подтвердить пароль
  • обновить или вставить пользователя
  • создать запись разрешения (пользователь может иметь много разрешений)
  • сохранить загруженное пользователем изображение во временную папку
  • обрезать загруженное пользователем изображение и сохранить его во временную папку
  • загрузить обрезанное изображение пользователя в корзину S3
  • обновить пользователя с изображением
  • перенаправить обратно на индекс пользователя

Как вы можете себе представить, этот контроллер ОГРОМНЫЙ (и это один из самых простых рабочих процессов в приложении).

Моя самая большая проблема в настоящее время — неспособность проверить это из-за всей связи. Я просто не знаю, с чего начать. За последние несколько недель я много читал, и вот мои нынешние мысли:

  • Создайте объект службы, который обрабатывает весь процесс под названием UserSaveService. Это позволило бы контроллеру просто вызывать метод службы и обрабатывать перенаправления и флэш-ошибки / успехи. Этот сервис будет обрабатывать обновление / вставку пользователя с использованием моделей Codeigniter ActiveRecord.
  • Создать объекты (объект команды?) Для каждого основного компонента
  • UploadImage: принимает имя формы -> обрабатывает загрузку изображения во временную папку -> возвращает путь к загруженному изображению
  • CropImage: принимает путь и размеры обрезки -> обрезает изображение и сохраняет его во временной папке -> возвращает путь обрезанного изображения
  • UploadToS3: принимает путь к файлу (в данном случае обрезанное изображение) и идентификатор корзины -> загружает файл в S3 -> возвращает URL S3

Моя структура в настоящее время выглядит так:

application (codeigniter)
src
-- services
---- SaveUserService.php
-- commands
---- UploadImage.php
---- CropImage.php
---- UploadToS3.php

У кого-нибудь есть рекомендации? Я хотел бы знать, какие шаблоны могут быть использованы здесь! Я понимаю, что это широкий вопрос, поэтому я надеюсь, что он не закроется, я просто не знаю, где еще провести такого рода обсуждения. Спасибо вам большое!

1

Решение

Вы не можете уйти от огромной точки входа в приложение (Save User). Я бы не беспокоился о размере (с точки зрения функциональности и того, что он делает), я бы беспокоился о том, как он связан для тестирования, как вы сказали.

Разделение по модулям

Я бы работал над разделением кода на сервисы (как говорит Грег Янг, это, вероятно, самый перегруженный термин в программном обеспечении!), Который может вызывать основное приложение (Save User), как вы перечислили:

  • ImageUploader
  • ImageCropper

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

Затем вы можете использовать контейнер внедрения зависимостей / инверсии управления, чтобы свести все вместе (для более простых программ вам может не понадобиться контейнер IoC), это будет инициализировано во время загрузки приложения (или в начале теста, где вы будет указывать на использование фиктивных реализаций). Вы можете найти эту ссылку интересной Зачем мне контейнер IoC, а не простой DI-код?

Разделение сообщениями

Если вы обнаружили, что столкнулись с необходимостью справиться с бизнес-риском, связанным со сбоем сервисов (т. Е. Загрузкой изображений на удаленный файловый сервер, что если бы это было не так, как бы вы справились с этим?), Что привело бы к разрыву всего потока, то вы могли бы Подумайте о разъединении с помощью сообщений (сообщение NewUser, прикрепление изображения в этом сообщении, запуск на служебной шине, где слушатель слушает) … это будет разъединять вещи во времени, но это может привести к дополнительным издержкам в инфраструктуре и вашей системе станет в конечном итоге последовательным.

Твердые принципы

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

От Википедия на ТВЕРДЫХ принципах Вы хотите рассмотреть следующее:

S — принцип единой ответственности
класс должен иметь только одну ответственность (то есть только одно потенциальное изменение в спецификации программного обеспечения должно влиять на спецификацию класса)

O — открытый / закрытый принцип
«Программные объекты… должны быть открыты для расширения, но закрыты для модификации».

L — принцип замещения Лискова
«Объекты в программе должны заменяться экземплярами их подтипов без изменения правильности этой программы». См. Также проектирование по контракту.

I — Принцип разделения интерфейса
«Многие клиентские интерфейсы лучше, чем один универсальный интерфейс».

D — Принцип инверсии зависимостей
нужно «зависеть от абстракций. Не зависит от конкрементов ».
Внедрение зависимостей является одним из методов следования этому принципу.

Рекомендуемые книги

Несколько хороших книг от дяди Боба действительно помогли мне с этим, хороший поиск в Google нашел бы много подобных материалов:

  • Чистый код: руководство по гибкому программному обеспечению
  • Гибкая разработка программного обеспечения, принципы, шаблоны и практики
  • Чистый кодер: кодекс поведения для профессиональных программистов
2

Другие решения

Других решений пока нет …