38
Корпоративное приложение на Rails. Отчет после года разработки Андрей Колешко @ka8725

Корпоративное приложение на Rails

  • Upload
    -

  • View
    187

  • Download
    0

Embed Size (px)

DESCRIPTION

Проблемы, которые возникают в Rails приложении при создании корпоративного приложения.

Citation preview

Page 1: Корпоративное приложение на Rails

Корпоративное приложение на Rails. Отчет после года разработки

Андрей Колешко @ka8725

Page 2: Корпоративное приложение на Rails

Что представляет из себя наше приложение

• Полно бизнес логики

• Работа с деньгами клиентов

• Общение со сторонними системами

• Очереди обработки данных (sidekiq)

• Асинхронность

• Поддержка плагинов через Rails engines

• Звездолет

Page 3: Корпоративное приложение на Rails

Приблизительное состояние кода в проекте

Page 4: Корпоративное приложение на Rails

Быть или не быть?

• Посмотрим с какими проблемами мы столкнулись и как с ними боролись

• Какие проблемы не решены

• Попробуем сделать выводы, можно ли использовать Rails в коммерческих приложениях

Page 5: Корпоративное приложение на Rails

Модульность

• Ruby modules

• Rails engines

Page 6: Корпоративное приложение на Rails

Ruby modules• Многие гемы просто не готовы к тому, что мы будем использовать Ruby модули

• DataGrid - не было возможности изменить шаблоны для client и admin области

• Draper - для работы декоратора в пространстве имен приходится писать магические строчки

• InheritedResources - поиск ресурса (AR модельки) в модуле не был реализован

• Rails - polymorphic routes генерировали неправильные helper-методы

Page 7: Корпоративное приложение на Rails

Rails Engines• Нельзя использовать разные версии gems в ядре и плагине

• В Ruby нет интерфейсов. Нельзя заставить плагины реализовать все методы, которые нам нужны

• Тестирование Rails Engines в контексте ядра - болезненный процесс

• rake railties:install:migrations постоянно генерирует новые файлы

• Установленный Rails Engine может поломать все приложение. У него есть доступ ко всему

Page 8: Корпоративное приложение на Rails

Имеем дело со всеми известными проблемами модульного приложения

Page 9: Корпоративное приложение на Rails

Как мы преодолеваем проблемы сейчас

• Pull request’ы в гемы, которые не готовы к использованию Ruby модулей

• Для плагинов предоставляем миксины

• Общение с плагинами стараемся выстраивать через самописный Pub-Sub, основанный на ActiveSupport::Notifications-

• Тестируются плагины вручную-

• Собственный регистратор плагинов

Page 10: Корпоративное приложение на Rails

Пример Pub-Sub# Core Publisher.broadcast_event('user.created', {user_id: 1}) !# Plugin Subscriber.subscribe('user.created') do |event| payload = event.payload puts payload[:user_id] end

http://goo.gl/QJxujy

Page 11: Корпоративное приложение на Rails

Особенности нашего Pub-Sub

• Однопоточный

• Нет обратной связи. Сообщения однонаправленные

Page 12: Корпоративное приложение на Rails

Собственный регистратор плагинов

• Дает простую установку копированием плагина в нужную папку

• Контролируемый процесс подключения плагина к системе

• Плагин - Rails engine

Page 13: Корпоративное приложение на Rails

Преимущества Rails engines как модулей

• В плагинах можно изменить все. View, Routes, Controllers, Models, Helpers…

• Быстро работает (нет сторонних вызовов)

Page 14: Корпоративное приложение на Rails

ActiveRecord• Избегаем nested_attributes

• Используем FormObjects, ServiceObjects, QueryObjects, PolicyObjects

• В моделе остается только отображение данных и самые необходимые валидации, ассоциации

• Избегаем Observers и Callbacks

Page 15: Корпоративное приложение на Rails

Исключение для использования callbacks

• Отправка сообщения в очередь для фоновой обработки

• Не изменяет состояние объектов

Page 16: Корпоративное приложение на Rails

Observers

• Правила использования не отличаются от callbacks

• Ведут к более запутанному коду чем callbacks

• Лучше никогда не использовать

Page 17: Корпоративное приложение на Rails

Завязались окончательно?

Page 18: Корпоративное приложение на Rails

Возможноcть развязать узлы в тестах

!

• Отключаем все колбэки в моделях

• Включаем колбэки в тестах в тех местах, где их вызов необходим

• Не используйте этот подход в новых приложениях!

Page 19: Корпоративное приложение на Rails

Возможность оставить тесты рабочими

class ActiveRecord::Base cattr_accessor :skip_callbacks-end !class User < ActiveRecord::Base after_create :send_invitation, unless: :skip_callbacks def send_invitation puts 'hello' end end !ActiveRecord::Base.skip_callbacks = true User.create # => ActiveRecord::Base.skip_callbacks = false User.create # => 'hello'

Page 20: Корпоративное приложение на Rails

Слой View• Проблема с длинными именами helper-методов

• Использование instance переменных (@var) во view

• Рендеринг таблиц

• fields_for и nested_attributes

• Фарш AngularJS

Page 21: Корпоративное приложение на Rails

Длинные имена helper-методов

plugin_exchange_client_account_application_contact_contact_distribution_group_path(parent.account, parent.core_application, parent, resource) !

Всего 141 символ!

Page 22: Корпоративное приложение на Rails

Решение# Controllers class SomeController < ApplicationController helper_method :submit_path helper_method :cancel_path ! private ! def submit_path any_size_of_helper_method_you_want_submit_path( arg1, arg2, … ) end ! def cancel_path any_size_of_helper_method_you_want_cancel_path( arg1, arg2, … ) end !end

Page 23: Корпоративное приложение на Rails

Решение

# Views != form_tag submit_path do = link_to 'Cancel', cancel_path

Page 24: Корпоративное приложение на Rails

Преимущества решения

• “Чистый”, читабельный и более надежный код во view

• HAML вам сважет спасибо !

PS. Не используйте HAML! Есть более удачный шаблонизатор - SLIM.

Page 25: Корпоративное приложение на Rails

Helper-методы вместо @var

• Ошибка рендеринга более адекватная (undefined method my_helper_method вместо undefined_method “…” for nil class)

Page 26: Корпоративное приложение на Rails

Рендеринг таблиц• DataGrid-

• Сортировка и фильтрация из коробки

• Беспроблемная интеграция с пагинаторами и полнотектовыми движками (через свои scopes)

• Возможность изменять шаблоны таблицы

• view занимают всего 3 (!!!) строчки кода

• и другое - https://github.com/bogdan/datagrid

Page 27: Корпоративное приложение на Rails

fields_for и nested_attributes

• В FormObjects сложно обрабатывать магические хеши nested_attributes

• В большинстве случаев необходимо использовать свой primary key для поиска записи на обновление в базе. А не id, который зашит в rails хардкором

• Огромные имена переменных ассоциаций

Page 28: Корпоративное приложение на Rails

fields_for и nested_attributes

- form_object.locations.each do |location|

= f.fields_for 'locations[]', location, include_id: false, index: nil do |ff|

# include_id: false - предотвращает генерацию hidden field c id, т.к. нас это не устраивает

# index: nil - не включать index в название сгенерированного аттрибута

Page 29: Корпоративное приложение на Rails

Преимущества данного подхода

• Имена параметров чистые и понятные

• Возможность передавать на сервер свой primary ключ для поиска модели на обновление

• Проще обработка в FormObjects

Page 30: Корпоративное приложение на Rails

Фарш AngularJS• Т.к. состояние объектов хранится на сервере необходимо вручную вызывать ng-init

• В каждый input необходимо передать ng-model атрибут

• Если в ng-init забыт атрибут, который связан с ng-model, то получим некорректное отображение объекта на форме

• Что делать при успешном сохранении формы? Reload страницы? - Теряем flash сообщения

Page 31: Корпоративное приложение на Rails

Разработка на Rails быстрая?

• Только для небольших приложений

• Огромное количество кода препятствует быстрой разработке

Page 32: Корпоративное приложение на Rails

Rails way Enterprise way

Page 33: Корпоративное приложение на Rails

Выводы• Rails отлично подходит для создания прототипов-

• К модульности и огромным приложениям Rails не готов

• В сложных приложениях приходится отказываться от многих магических палочек Rails-

• Это ведет к увелечению собственного кода

• Код требует ухода. Знание шаблонов проектирования, принципов проектирования классов (SOLID) здесь просто необходимо

Page 34: Корпоративное приложение на Rails

Что в Ruby хорошо?

• Писать DSL

• Сам язык очень выразительный

• Код приятно писать и читать

• И на этом все :(

Page 35: Корпоративное приложение на Rails

Решились писать Enterprise на Rails?

• Нужен ли Вам Rails? Может, достаточно взять Sinatra + Grape, если у вас будет SPA (Single Page Application)?

• Тщательно обрабатывайте требования. Выясняйте Use Cases-

• На основании UseCases стройте доменную модель (набор классов и их взаимодействия).

• Не привязывайтесь к ActiveRecord. ActiveRecord - только для представления данных!

• Тщательно выбирайте гемы. Подумайте 100500 раз прежде чем выбрать InheritedResources, например.

• Следуйте принципам SOLID, не нарушайте закон Деметры

Page 36: Корпоративное приложение на Rails

Литература1. http://goo.gl/GyqjXg - 7 steps to get started with Clean

Architecture in Ruby

2. http://goo.gl/g0VA1 - 7 Patterns to Refactor Fat ActiveRecord Models

3. http://goo.gl/lz1fEX - Ruby Midwest 2011 - Keynote: Architecture the Lost Years by Robert Martin

4. http://goo.gl/MP6L7Z - High-Low Testing

5. http://goo.gl/aI3kdc - Growing Rails Applications in Practice

6. http://goo.gl/9KsmM - Принципы проектирования классов (S.O.L.I.D.)

Page 37: Корпоративное приложение на Rails

На правах рекламы

!

Основы Rake

Простые примеры применения в реальном мире

Сравнение с конкурентом - Thor

Page 38: Корпоративное приложение на Rails

Вопросы?

Андрей Колешко

@ka8725-

[email protected]