Политика невмешательства

Содержание

Слайд 2

Постановка задачи

Состояние системы
Модель А
+ Модель B
+ Модель C

Постановка задачи Состояние системы Модель А + Модель B + Модель C
Требуется просматривать
состояние "до" изменения
состояние "после" изменения
служебную информацию (кто, когда, ...)

Слайд 3

Варианты решения

Inline code
Callback
before_save, after_save
Observer
paper_trail, act_as_versioned
Decorator
method_decorators
Aspect
aspectr, aquarium

Варианты решения Inline code Callback before_save, after_save Observer paper_trail, act_as_versioned Decorator method_decorators Aspect aspectr, aquarium

Слайд 4

Inline code
save_before( a, b, c );
change( a, b, c );
save_after( a, b,

Inline code save_before( a, b, c ); change( a, b, c );
c );
Загрязняется основная логика
Необходимо поддерживать изменения
(не катит)

Слайд 5

Callback

before_save :save_state_before
after_save :save_state_after
Сохранение состояния 1 модели (не группы)
Дополнительный код в моделях

Callback before_save :save_state_before after_save :save_state_after Сохранение состояния 1 модели (не группы) Дополнительный код в моделях

Слайд 6

AR::Observer: обычная реализация

class UserObserver < ActiveRecord::Observer
def after_save(user)

end
end
Сохранение состояния 1 модели (не

AR::Observer: обычная реализация class UserObserver def after_save(user) … end end Сохранение состояния 1 модели (не группы)
группы)

Слайд 7

AR::Observer: реализация через gem

class User < ActiveRecord::Base
# команда подключения функционала гема

AR::Observer: реализация через gem class User # команда подключения функционала гема has_paper_trail
has_paper_trail
# acts_as_versioned
end
Сохранение состояния 1 модели (не группы)
Дополнительный код в моделях

Слайд 8

Decorator

class UserService < MethodDecorators
+Log_user_state
def approve(user_id)
User.find(user_id).approve()
Billing.add_user(user_id)
Complaint.scope_user(user_id).each(&:close)
save!
end
end
Нужно много

Decorator class UserService +Log_user_state def approve(user_id) User.find(user_id).approve() Billing.add_user(user_id) Complaint.scope_user(user_id).each(&:close) save! end end
различных декораторов
В коде есть следы (хоть и приемлемо мало)

gem install method_decorator

Слайд 9

Aspect

Кто знает, что такое АОП?

Aspect Кто знает, что такое АОП?

Слайд 10

Aspect

AOP
Aspect
Advice
Join Point

Программа


user.set_role("admin")


Aspect
class UserAspect < AOP
advice User, :set_role, options
end

Aspect AOP Aspect Advice Join Point Программа … … user.set_role("admin") … …

Слайд 11

Aspect

class Changelog
watch UserService, [:approve, :disapprove], {
state_before: lambda{ |user_id| … },
state_after:

Aspect class Changelog watch UserService, [:approve, :disapprove], { state_before: lambda{ |user_id| …
lambda{ … },
state_error: lambda{ … }
}
end
Нет ни единой строчки в моделях/сервисах/etc
Все настройки – в одном месте

Слайд 12

Выбор

AspectR (2002)
Aquarium - gem install aquarium

Выбор AspectR (2002) Aquarium - gem install aquarium

Слайд 13

Практика

Aquarium
мощный
слишком
Упрощение интерфейса
более жёсткие требования
обработка ошибок
спокойный сон после release

Практика Aquarium мощный слишком Упрощение интерфейса более жёсткие требования обработка ошибок спокойный сон после release

Слайд 14

Откат в жизни модератора

Детальная трассировка изменений
У меня все ходы записаны (с) 12ст
Легко

Откат в жизни модератора Детальная трассировка изменений У меня все ходы записаны
откатить изменения
Долой коррупцию, распил и откаты!

Слайд 15

Ссылки

http://bit.ly/cR400e - AOP @ wikipedia
http://bit.ly/15q8bT - Decorator @ wikipedia
http://bit.ly/It8d7l - method_decorators
http://bit.ly/KXu9ZA - aquarium

Ссылки http://bit.ly/cR400e - AOP @ wikipedia http://bit.ly/15q8bT - Decorator @ wikipedia http://bit.ly/It8d7l
@ github
http://bit.ly/rUyqf - aquarium @ rubyforge