metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2009-08-30 09:39 pm

Безумие

Есть такой волшебный паттерн - RAII, и его всякие модификации в языках без автоматического вызова деструкторов(try-finally, using(чего-нибудь IDisposable)) и т.д.
В общем, его применение соответствует тому, что мы создаем/открываем ресурс при входе в блок кода и гарантированно закрываем/разрушаем его при выходе из блока. Причем при любом выходе(в дельфях, например break, continue, exit, выкидывание исключения - все вызывают finally). Но в итоге можно считать, что вход и выход производятся таки вокруг линейного потока выполнения.

А мне нужно такое же, но для ситуации, когда ресурс живет внутри сложного workflow с ожиданием действий от пользователя. Т.е. например - при логине в систему создается некий объект, и при логауте или при закрытии программы - разрушается. Тут еще не так сложно, а вот в случае, когда состояний штук пять, и в двух из них ресурс не нужен, а в трех нужен, а переходы могут быть какие попало - вручную создавать-разрушать и следить за временем жизни ресурса становится занудно.

Вот сижу, думаю, как и чем бы это кошерно описать на c#. Пока ничего толкового в голову не пришло, кроме описания состояний как объектов с полями для каждого нужного ресурса, помеченных специально назначенным атрибутом.
Переход между состояниями это будет хитрая функция, преобразующая объект текущего состояния в объект нового состояния(хотя на самом деле тут есть зло в том, что на самом деле удобнее было бы состояние представить как mix-in из нескольких объектов, и функцию перехода разбить на несколько более простых), перед ее применением будет проверяться не нужно ли разрушить ресурсы из старого состояния, а после применения - не нужно ли создать ресурсов для нового. В большинстве случаев, переход по своей сути и представляет уничтожение старых ресурсов и создание новых, с их инициализацией. Т.е. в функции перехода ничего писать, в общем-то, кроме инициализации ресурсов и не нужно будет - остальное будет выполнено автоматически.

А еще блин обработка ошибок для всего этого - переход между состояниями может не произойти, т.е. нужно будет корректно откатиться назад к старому состоянию, чтобы гуй не оказался в промежуточном.


Кстати, еще во всем этом меня сильно напрягает идея класса, у которого всегда существует не более одного объекта-экземпляра. Чем-то это противоречит смыслу ООП, по моему.

PS: Кстати, в последнее время все идеи "чего не хватает в языках программирования" сводятся к тому, что линейная одномерная структура текста-кода не всегда адекватно соответствует задаче. Например в ней описывать реляционные таблицы - напряжно, в отличие от их естественного вида-гридов. Про графы вообще речи нет, их удобный для восприятия вид - картинка - дико не удобен для редактирования. Что-нибудь еще более сложное из структур, сложнее графов, бывает?:)

[identity profile] metaclass.livejournal.com 2009-08-30 07:18 pm (UTC)(link)
Ресурс "внешний". Файл в 100 мег размером скачанный с сервера при входе и который обязательно грохнуть при выходе. Ручка к бинарному потоку на железяку, которую нужно открывать и закрывать.

Для оных вещей строгое управление временем жизни обязательно. А то может оказаться, что, например, мы вышли из состояния где ресурс нужен в состояние где не нужен, забыли его, но сборщик мусора до него еще не добрался, а мы уже зашли в новое состояние, где он опять нужен, но открыть его можно только один раз, и все грохнулось.

В принципе, можно было бы его вообще не закрывать в таком случае, а хранить в каком-то глобальном пуле в течение некоторого времени и активировать повторно при надобности. Но что-то меня повторная активация и глобальные состояния напрягают - я предпочитаю все закрыть и начать с чистого листа в следующий раз, так оно надежнее.

[identity profile] mend0za.livejournal.com 2009-08-30 07:27 pm (UTC)(link)
В голову приходит только использование деструкторов и явная пристрелка сущностей по истечении времени жизни + reflection чтобы доступаться до него из других ветвей выполнения.

Была в чём-то пересекающаяся задача - по прилёту сигнала (SIGHUP) - зачистить кэши и переоткрыть все файлы. В итоге даже не стали возиться с глобальной регистрацией всего и вся, находили все объекты типа кэш с помощью Object#kind_of? и дёргали найденное за сиську с табличкой flush().
Сами кэши хранились как переменные класса и разделялись соотвественно всеми объектами класса.

[identity profile] metaclass.livejournal.com 2009-08-30 07:38 pm (UTC)(link)
Да, примерно так оно и у меня выходит.
Перебрать поля рефлекшеном, выбрать отмеченные атрибутом "ресурс", грохнуть ненужные, создать новые, инициализировать их.