Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Несоциалочка на Рельсах

Несоциалочка на Рельсах

Уроки, вынесенные из большого, старого и страшного проекта на Rails

Avatar for Sergey Ukustov

Sergey Ukustov

September 20, 2014

More Decks by Sergey Ukustov

Other Decks in Programming

Transcript

  1. Большой проект • 30 человек • 4 года • ≥

    330 000 строк кода • ≥ 20 репозиториев • сложная предметная область • технические решения на границе экосистемы Ruby • рядом аналитический стек на Hadoop/Java/Python 2 / 20
  2. Сложность предметной области • Управление спросом (Demand Response) ▶ N

    раз в год c XX:XX до YY:YY часов цены внезапно повышаются ▶ события сгруппированы в программы ▶ уведомление людей ▶ уведомление устройств • Тарифный план ▶ энергия: 0 — 100 кВч, 100 — 400 кВч,… ▶ время: 8:00 — 12:00, 12:00 — 16:00,… ▶ мощность: 10 кВ, 20кВ,… ▶ пиковые часы: 12:00 — 14:00 послезавтра ▶ время действия: июнь — август • Развитие стандартов: 2.0 и 1.0 — это две большие разницы 3 / 20
  3. Rails — говно • Покрывает 95% случаев • Культура необразованных

    упорков • Мантры как мины • MVC не масштабируется • «Всё уже написано до нас» 4 / 20
  4. Виджет — проблема • Автономный встраиваемый кусок функциональности • Имеет

    независимый от «большой» страницы поток управления • Плохо ложится на ReST и рельсовый MVC • Пример: создание и редактирование события управления спросом 5 / 20
  5. Виджет — решение Apotomo: https://github.com/apotonick/apotomo class ParentController < ActionController::Base has_widget

    do |root| root << widget(:event) end # ... end class EventWidget < Apotomo::Widget def new(args = {}); render; end def edit(args = {}); render; end def create(event); end # event — внутреннее для Apotomo событие end # Внутри шаблона = render_widget :event, :new 6 / 20
  6. Базовое идеологическое про события • Что-то произошло ⇒ что-то надо

    делать • Началось ⇒ что-то надо делать • Закончилось ⇒ что-то надо делать • На одно событие может быть 100500 действий 8 / 20
  7. Event sourcing vs Resque За Resque: • тот же «запустил

    и забыл» • та же легковесность запуска • то же масштабирование — воркеры можно разнести по разным машинам Против Resque: • один сигнал — одно действие 9 / 20
  8. Общая шина сообщений Можно использовать лучшее из обоих подходов: •

    очередь сообщений — для сообщений, • Resque — для действий. 10 / 20
  9. Сообщения vs HTTP API К рассмотрению: • Тяни или толкай

    • Объём даннных Очевидно: • малый объём оповещения — сообщения • большой объём данных — стягиваем через HTTP API 11 / 20
  10. Observers Против: • не входят в Rails 4 • непрозрачны,

    слишком много магии За: • SRP: шлём сообщения Против: • есть выход и получше 13 / 20
  11. Request/Operation • Уточнённый кусок DDD: Boundary и Service • https://github.com/apotonick/trailblazer:

    Contract/Operation • Request — контракт: ▶ первичная валидация, что параметры ок ▶ удобство доступа к объектам предметной области ▶ иммутабельный FormObject или ParameterObject class EventsController::Create::Request attr_reader :start_time def initialize(params) @device_uid = params[:device_uid] @start_time = params[:start_time] end def device @device ||= Device.find_by_uid(@device_uid) end end 14 / 20
  12. Request/Operation • Operation — кусок бизнес-логики AKA Service (DDD) AKA

    Command (CQRS). • В простейшем случае отвечает только на идемпотентный вызов #success? • Есть проблема с пространством имён — некрасиво class EventsController def create operation = Create::Operation.new(Create::Request. new(params)) if operation.success? # ... else # ... end end end 15 / 20
  13. Ограниченные контексты и разные языки • Главная система со своим

    сложившимся лексиконом • Smart Energy Profile 2 • OpenADR 2.0b • Разные языки — разные серверы • Антикоррупционный слой через HTTP API ▶ Хозяин и раб ▶ Адаптер на стороне хозяина: переименование и комбинация ▶ Декоратор на стороне раба: сложно ▶ Срезаем углы: ActiveAdmin как JSON API ▶ Углы могут кусать: id vs uid 16 / 20
  14. Разделение на гемы • Горизонтальное — по слоям — ок

    • Вертикальное — самоубийство • Связанные жизненные циклы — зло • Корпоративное пространство имён — ок, если готовить правильно • Помни о близнецовой связи (connascence) 17 / 20
  15. Кодерские мелочи • Декораторы убивают хелперы, и это хорошо •

    FormObjects вместо accepts_nested_attributes_for • Иммутабельность FTW • Щепотка ФП: #flat_map, #inject, #take • Если появляется QueryObject, что-то сдохло в консерватории • Yardoc 18 / 20
  16. Бог не фраер Ибо очи Его над путями человека, и

    Он видит все шаги его • Абстракции • Границы • Асинхронность • SOLID • Документация • Рациональность 19 / 20