Паттерны проектирования в Ruby

Не будем утомлять вас долгим вступлением и сразу же сделаем сакраментальное заявление: паттерны (шаблоны) программирования — это отличная вещь. Ну как минимум — по задумке. В первую очередь, они должны помогать при работе в команде. Представьте: все разработчики используют паттерны, код стандартизирован. Для того чтобы быстро в нем разобраться, достаточно лишь узнать паттерн. Волки сыты, овцы целы и все счастливы.

Однако на практике этот подход дает больше минусов, чем плюсов. В чем они заключаются?

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

А теперь все плохо — не правда ли? Не расстраивайтесь, зачастую паттерны здорово упрощают жизнь.

Задача

Перед нами возникла задача посчитать коэффициент “дружбы” между двумя пользователями на основе их взаимодействия в социальных сетях. Мы не будем приводить алгоритм расчета — он выходит за рамки этой статьи. Гораздо важнее идея и постановка задачи.

Итак, есть две таблицы. К примеру: values и values_maximums. Алгоритм расчетов состоит в обработке данных из двух таблиц (обратим ваше внимание на то, что они пересекаются).

Например, в таблице values есть столбцы a1, a2, a3, a4, b1, b2, c1.
В наблице values_maximums есть столбцы am, bm, cm.

Смысл расчета в следующем:

  • На основе 100 строк из таблицы values и столбцов a1, a2, a3 рассчитывается одна строка таблицы values_maximums — колонка am.
  • В таблице values на основе столбцов a1, a2, a3 и полученного значения am — пересчитываем строки и получаем b1, b2.
  • На основе 100 строк и столбцов b1, b2 — считаем bm для values_maximums.
  • Производим аналогичные действия для столбцов “c”.

Кроме того, мы выделили еще 4 случая:

  • Первоначальный расчет;
  • Расчет на основе готовых данных;
  • Рекуррентный расчет;
  • Расчет по запросу.

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

Итак, постановка задачи состоялась. Мы располагаем данными, требующими четырехшаговой обработки. Кроме того, у нас есть три типа запросов, в зависимости от которых меняется либо алгоритм расчета данных, либо вызов следующего шага (inline или async).

Builder pattern — общие сведения

Builder pattern — это паттерн, применяемый, когда известны этапы производства чего-либо, но его реализация на каждом конкретном этапе отличается. Для примера возьмем автомобильное производство. Этапы: сборка кузова, установка двигателя, установка колес, отделка салона, подключение электроники.

Перед вами — схема. На ее основе можно собирать кабриолеты, седаны, грузовики и даже мотоциклы. Различаться будет лишь техника реализации (количество и/или размер колес, форма кузова, комплект электроники и т.д.). Однако этапы производства останутся неизменными.

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

Реализация

Начнем с конца. Именно так выглядит код в итоге:


Как видите, у нас есть два класса. В каждом из них описаны одни и те же шаги. А внутри каждого шага — метод perform, описывающий логику его работы. ReccurentProcessing наследуется от DedicatedProcessing, потому что логика шагов одинакова, но передача управления между ними должна быть асинхронной (через Sidekiq worker).

Код выглядит читаемым. Осталось лишь разобраться, как эта магия работает. Оказывается, что все реализуется за счет двух небольших классов.

Класс, описывающий логику шага. Он достаточно прост — принимает входные данные и возвращает результат. То есть, чтобы обратиться к входным данным внутри шага, мы используем options, а чтобы вернуть результат — кладем его в results.

Рассмотрим второй класс. Именно он приводит магию в действие.

Шаги, которые нужно выполнить и их последовательность:

Это — переменная класса, в которой хранятся блоки для обработки каждого шага.

Самый важный момент — построение класса обработки:

Class.new(Step, &block) — мы создаем класс на основе Step и полученного блока. В итоге метод perform, описанный внутри блока, будет помещен в этот класс. Т.е. для каждого типа расчета у нас получится своя структура steps. И она будет выглядеть примерно так:

и так далее

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

Перед вами метод класса. Поэтому он не будет пересекаться с методом внутри описания шага. Мы инициализируем нужный нам класс. Заполняем его входными данными и вызываем perform. Тот самый perform, который описывается внутри каждого шага.

При наличии следующего шага, вызываем метод perform_next_step, который передает ему управление:

Метод предельно прост. По умолчанию он сразу же выполняет следующий шаг.

В завершение мы переписали этот метод для рекуррентных расчетов:

Выводы

  1. Мы получили довольно простой и вполне читаемый код. Он достаточно четко описывает необходимые шаги, передачу управления между ними и регулируется отдельным механизмом, полностью подконтрольным программисту.
  2. Описание каждого шага по отдельности — это очень удобно и вдобавок — читаемо. А читаемость (напомним!) является одним из главных требований к разработке. Особенно, когда речь идет о проведении сложных расчетов.

Будьте в курсе всех агро новостей

Ищи больше интересной информации в нашем TG-канале Подписаться

Похожие статьи

Заполните форму или свяжитесь
удобным для Вас способом

Контакты

г. Севастополь, ул. Руднева, д.41, 4 этаж технопарк ИТ-Крым +7 978 679-76-353 agro@crimeadigital.ru

Социальные сети

Нажимая на кнопку, вы даете согласие на обработку персональных данных и соглашаетесь c политикой конфиденциальности

Крым Диджитал приняла участие в стратегической сессии

Руководители Крым Диджитал приняли участие в стратегической сессии, которая прошла на базе СевГУ 10 июня. Вместе с Правительством Севастополя, Институтом информационных технологий и управления в технических системах СевГУ и приглашенными ИТ-компаниями города обсудили перспективу развития системы высшего образования в Севастополе.Представители бизнеса, власти и образовательной системы выступали со своим видением будущих потребностей региона в кадрах, поднимали насущные вопросы обучения студентов, прохождения практики и дальнейшего трудоустройства. Крым Диджитал является амбассадором идеи образования и взращивания молодых кадров, развивает образовательные проекты и на протяжении 5 последних лет ведет активную работу в направлении поддержки и развития молодых специалистов ИТ-отрасли Крыма.

Руководители Крым Диджитал приняли участие в стратегической сессии, которая прошла на базе СевГУ 10 июня.

Вместе с Правительством Севастополя, Институтом информационных технологий и управления в технических системах СевГУ и приглашенными ИТ-компаниями города обсудили перспективу развития системы высшего образования в Севастополе.
Представители бизнеса, власти и образовательной системы выступали со своим видением будущих потребностей региона в кадрах, поднимали насущные вопросы обучения студентов, прохождения практики и дальнейшего трудоустройства.

Крым Диджитал является амбассадором идеи образования и взращивания молодых кадров, развивает образовательные проекты и на протяжении 5 последних лет ведет активную работу в направлении поддержки и развития молодых специалистов ИТ-отрасли Крыма.

Выпуск курса Software Testing

Мы поздравляем выпускников нашего первого в этом году курса Крым Диджитал Академии по Software Testing! Всего курс успешно завершили 13 человек. В течение 2 месяцев несмотря на теплую погоду и манящее море ребята ответственно посещали занятия 2 раза в неделю, делали домашние задания и проверочные работы. Трое начинающих специалистов теперь стажеры нашей компании. Следующий курс намечен на август. Не пропусти анонс записи!

Мы поздравляем выпускников нашего первого в этом году курса Крым Диджитал Академии по Software Testing!

Всего курс успешно завершили 13 человек. В течение 2 месяцев несмотря на теплую погоду и манящее море ребята ответственно посещали занятия 2 раза в неделю, делали домашние задания и проверочные работы. Трое начинающих специалистов теперь стажеры нашей компании.

Следующий курс намечен на август. Не пропусти анонс записи!

Лицензия на образовательную деятельность

В 2022 году мы получили лицензию на образовательную деятельность по программам дополнительного профессионального образования! Теперь мы можем обучать специалистов по направлениям Ruby on Rails, ReactJS и Software Testing и выдавать удостоверения о повышении квалификации государственного образца.
В 2022 году мы получили лицензию на образовательную деятельность по программам дополнительного профессионального образования! Теперь мы можем обучать специалистов по направлениям Ruby on Rails, ReactJS и Software Testing и выдавать удостоверения о повышении квалификации государственного образца.

Мы вошли в Реестр эффективно и социально значимых предприятий.

По результатам ежегодной финансово-экономической аналитики Межотраслевой рейтинговой компании Крым Диджитал включена в Реестр эффективных и социально значимых предприятий. По итогу аналитики, в рамках отрасли (ОКВЭД 62.01) и региона Крым, CDG вошло в 4% лучших компаний страны, с результатом – 92 балла!
По результатам ежегодной финансово-экономической аналитики Межотраслевой рейтинговой компании Крым Диджитал включена в Реестр эффективных и социально значимых предприятий. По итогу аналитики, в рамках отрасли (ОКВЭД 62.01) и региона Крым, CDG вошло в 4% лучших компаний страны, с результатом – 92 балла!