Post on 02-Jul-2015
Несоциалочка на рельсах
Сергей Укустов
Провектус, Казань
2014-09-20Web Expert Day
1 / 20
Большой проект
• 30 человек• 4 года• ≥ 330 000 строк кода• ≥ 20 репозиториев• сложная предметная область• технические решения на границе экосистемыRuby
• рядом аналитический стек наHadoop/Java/Python
2 / 20
Сложность предметной области
• Управление спросом (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
Rails — говно
• Покрывает 95% случаев• Культура необразованных упорков• Мантры как мины• MVC не масштабируется• «Всё уже написано до нас»
4 / 20
Виджет — проблема• Автономный встраиваемый кусокфункциональности
• Имеет независимый от «большой» страницыпоток управления
• Плохо ложится на ReST и рельсовый MVC• Пример: создание и редактирование событияуправления спросом
5 / 20
Виджет — решениеApotomo: https://github.com/apotonick/apotomoclass ParentController < ActionController::Basehas_widget do |root|root << widget(:event)end# ...
end
class EventWidget < Apotomo::Widgetdef new(args = {}); render; enddef edit(args = {}); render; enddef create(event); end # event — внутреннее дляApotomo событие
end
# Внутри шаблона= render_widget :event, :new
6 / 20
Event sourcing внутри приложения• Легкое горизонтальное масштабирование• Несколько действий на один сигнал
7 / 20
Базовое идеологическое про события
• Что-то произошло ⇒ что-то надо делать• Началось ⇒ что-то надо делать• Закончилось ⇒ что-то надо делать• На одно событие может быть 100500 действий
8 / 20
Event sourcing vs Resque
За Resque:• тот же «запустил и забыл»• та же легковесность запуска• то же масштабирование — воркеры можноразнести по разным машинам
Против Resque:• один сигнал — одно действие
9 / 20
Общая шина сообщенийМожно использовать лучшее из обоих подходов:
• очередь сообщений — для сообщений,• Resque — для действий.
10 / 20
Сообщения vs HTTP APIК рассмотрению:
• Тяни или толкай• Объём даннных
Очевидно:• малый объём оповещения — сообщения• большой объём данных — стягиваем через HTTPAPI
11 / 20
EventMachine vs Resque
12 / 20
Observers
Против:• не входят в Rails 4• непрозрачны, слишком много магии
За:• SRP: шлём сообщения
Против:• есть выход и получше
13 / 20
Request/Operation• Уточнённый кусок DDD: Boundary и Service• https://github.com/apotonick/trailblazer:Contract/Operation
• Request — контракт:▶ первичная валидация, что параметры ок▶ удобство доступа к объектам предметнойобласти
▶ иммутабельный FormObject или ParameterObjectclass EventsController::Create::Requestattr_reader :start_timedef initialize(params)@device_uid = params[:device_uid]@start_time = params[:start_time]
enddef device@device ||= Device.find_by_uid(@device_uid)
endend
14 / 20
Request/Operation• Operation — кусок бизнес-логики AKA Service(DDD) AKA Command (CQRS).
• В простейшем случае отвечает только наидемпотентный вызов #success?
• Есть проблема с пространством имён —некрасиво
class EventsControllerdef createoperation = Create::Operation.new(Create::Request.new(params))if operation.success?# ...
else# ...
endend
end
15 / 20
Ограниченные контексты и разныеязыки
• Главная система со своим сложившимсялексиконом
• Smart Energy Profile 2• OpenADR 2.0b• Разные языки — разные серверы• Антикоррупционный слой через HTTP API
▶ Хозяин и раб▶ Адаптер на стороне хозяина: переименование икомбинация
▶ Декоратор на стороне раба: сложно▶ Срезаем углы: ActiveAdmin как JSON API▶ Углы могут кусать: id vs uid
16 / 20
Разделение на гемы
• Горизонтальное — по слоям — ок• Вертикальное — самоубийство• Связанные жизненные циклы — зло• Корпоративное пространство имён — ок, еслиготовить правильно
• Помни о близнецовой связи (connascence)
17 / 20
Кодерские мелочи
• Декораторы убивают хелперы, и это хорошо• FormObjects вместо accepts_nested_attributes_for• Иммутабельность FTW• Щепотка ФП: #flat_map, #inject, #take• Если появляется QueryObject, что-то сдохло вконсерватории
• Yardoc
18 / 20
Бог не фраер
Ибо очи Его над путями человека, и Он видит всешаги его
• Абстракции• Границы• Асинхронность• SOLID• Документация• Рациональность
19 / 20
Вопросы?
20 / 20