Skip to content

Instantly share code, notes, and snippets.

@Suor
Created June 7, 2012 07:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Suor/2887191 to your computer and use it in GitHub Desktop.
Save Suor/2887191 to your computer and use it in GitHub Desktop.
Примеры использования AOP

Задача: нужно при активации услуги продлять жизнь объявления. Как не писать одинаковый код в каждом обработчике активации? Примеры возможного аспектно-ориентированного кода на разных языках. Код на перле рабочий с библиотекой Aspect, на остальных языках просто возможные варианты.

Первый вариант использует простые обёртки - перед вызовом AdvertService.activate() навешивает обёртку на метод .save() отдельного объявления, которая уже его продляет. Второй вариант комбинирует два среза: вызов AbstractAdvert.save() и нахождение в потоке управления AdvertService.activate(), и накладывает обработчик на комбинированный срез.

Интересно как недостаточный синтаксис и семантика разных языков делают подобные операции неуклюжими.

P.S. Другой вариант - использование событий, но он более многословный.

# В Coffeescript-e и Javascript-e нет типа "метод", поэтому отдельно передаём класс/объект, отдельно имя метода
before AdvertService, 'activate', (service) ->
before service.advert, 'save', (advert) ->
advert.time_life_started = timezone.now()
# Также тут нет перегрузки операций, поэтому используем цепочку вызовов для соединения срезов
aspect.call(AbstractAdvert, 'save').cflow(AdvertService, 'activate').before (advert) ->
advert.time_life_started = timezone.now()
before(AbstractAdvert, 'save', function (service) {
before(service.advert, 'save', function (advert) {
advert.time_life_started = timezone.now();
});
});
aspect.call(AbstractAdvert, 'save').cflow(AdvertService, 'activate').before(function (advert) {
advert.time_life_started = timezone.now();
});
before {
$_->self->time_life_started = timezone->now;
} call 'AbstractAdvert::save' & cflow 'AdvertService::activate';
class AdvertService(AbstractService):
...
# Наследование - приходится переименовывать метод, возможны проблемы с транзакциями и множественным наследованием
# К тому же объявление может и сохранено-то не будет, а мы тут суетимся.
def activate(self):
self.advert.time_life_started = timezone.now()
self._activate()
# В питоне нет анонимных многострочных функций, поэтому так неуклюже
@before(AdvertService.activate)
def schedule_prolong(service):
@before(service.advert.save)
def prolong(advert):
advert.time_life_started = timezone.now()
@before(call(AbstractAdvert.save) & cflow(AdvertService.activate))
def prolong(advert):
advert.time_life_started = timezone.now()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment