LINUX.ORG.RU

История изменений

Исправление den73, (текущая версия) :

В общем-то, тут уже напрашивающееся решение:

1. Пишем всё же N-1 ветвей - по числу переходов между версиями. Пусть это будут функции migrate-to-i-c1, где i - номер версии, куда мигрируем.

2. Добавляем поле «версия». К сожалению, это должно быть инициализуемое поле экземпляра. В качестве небольшого смягчения наказания, можно условиться, что отсутствие поля «версия» - это версия 0.

3. Метод для update-instance-for-redefined-class сначала по параметрам ориентируется, откуда и куда мы движемся.

4. Далее везде в теле метода вместо slot-value используем slot-or-externally-stored-value

(setf slot-or-externally-stored-value) пишет в слот, если он есть. Если слота нет, то в локальную переменную, определённую внутри нашего метода. Например, это может быть alist, где ключ - имя слота, а value - значение. И особый случай для unbound.

При чтении всё аналогично - если есть слот, читаем из него, если нет - из локальной переменной.

5. Выполняем все ветви от начальной до конечной версии.

Пока не вижу тут изъянов. Вот теперь уже вопрос: адекватно ли то, что я придумал и какие в нём могут быть дыры? Одну дыру сразу скажу - если скрипт может выполняться с ошибками, то эти ошибки откладываются на неопределённое будущее - на момент, когда мы обратимся к экземпляру. Единственный вариант этого избежать - вести реестр всех объектов данного класса и принудительно менять все экземпляры при каждом переопределении класса. Но это тоже стоит своих денег.

Исправление den73, :

В общем-то, тут уже напрашивающееся решение:

1. Пишем всё же N-1 ветвей - по числу переходов между версиями. Пусть это будут функции migrate-to-i-c1, где i - номер версии, куда мигрируем.

2. Добавляем поле «версия». К сожалению, это должно быть инициализуемое поле экземпляра. В качестве небольшого смягчения наказания, можно условиться, что отсутствие поля «версия» - это версия 0.

3. Метод для update-instance-for-redefined-class сначала по параметрам ориентируется, откуда и куда мы движемся.

4. Далее везде в теле метода вместо slot-value используем slot-or-externally-stored-value

(setf slot-or-externally-stored-value) пишет в слот, если он есть. Если слота нет, то в локальную переменную, определённую внутри нашего метода. Например, это может быть alist, где ключ - имя слота, а value - значение. И особый случай для unbound.

При чтении всё аналогично - если есть слот, читаем из него, если нет - из локальной переменной.

5. Выполняем все ветви от начальной до конечной версии.

Пока не вижу тут изъянов. Вот теперь уже вопрос: адекватно ли то, что я придумал и какие в нём могут быть дыры? Одну дыру сразу скажу - если скрипт выполняется с ошибками, то эти ошибки откладываются на неопределённое будущее. Единственный вариант этого избежать - вести реестр всех объектов данного класса. Тогда вообще можно принудительно менять все экземпляры при каждом переопределении класса. Но это тоже стоит своих денег.

Исправление den73, :

В общем-то, тут уже напрашивающееся решение:

1. Пишем всё же N-1 ветвей - по числу переходов между версиями. Пусть это будут функции migrate-to-i-c1, где i - номер версии, куда мигрируем.

2. Добавляем поле «версия». К сожалению, это должно быть инициализуемое поле экземпляра. В качестве небольшого смягчения наказания, можно условиться, что отсутствие поля «версия» - это версия 0.

3. Метод для update-instance-for-redefined-class сначала по параметрам ориентируется, откуда и куда мы движемся.

4. Далее везде в теле метода вместо slot-value используем slot-or-externally-stored-value

(setf slot-or-externally-stored-value) пишет в слот, если он есть. Если слота нет, то в локальную переменную, определённую внутри нашего метода. Например, это может быть alist, где ключ - имя слота, а value - значение. И особый случая для unbound.

При чтении всё аналогично - если есть слот, читаем из него, если нет - из локальной переменной.

5. Выполняем все ветви от начальной до конечной версии.

Пока не вижу тут изъянов. Вот теперь уже вопрос: адекватно ли то, что я придумал и какие в нём могут быть дыры? Одну дыру сразу скажу - если скрипт выполняется с ошибками, то эти ошибки откладываются на неопределённое будущее. Единственный вариант этого избежать - вести реестр всех объектов данного класса. Тогда вообще можно принудительно менять все экземпляры при каждом переопределении класса. Но это тоже стоит своих денег.

Исходная версия den73, :

Конечно, тут уже есть напрашивающееся решение: 1. Пишем всё же N-1 ветвей - по числу переходов между версиями. Пусть это будут функции migrate-to-i-c1, где i - номер версии, куда мигрируем.

2. Добавляем поле «версия». К сожалению, это должно быть инициализуемое поле экземпляра. В качестве небольшого смягчения наказания, можно условиться, что отсутствие поля «версия» - это версия 0.

3. Метод для update-instance-for-redefined-class сначала по параметрам ориентируется, откуда и куда мы движемся.

4. Далее везде в теле метода вместо slot-value используем slot-or-externally-stored-value

(setf slot-or-externally-stored-value) пишет в слот, если он есть. Если слота нет, то в локальную переменную, определённую внутри нашего метода. Например, это может быть alist, где ключ - имя слота, а value - значение. И особый случая для unbound.

При чтении всё аналогично - если есть слот, читаем из него, если нет - из локальной переменной.

5. Выполняем все ветви от начальной до конечной версии.

Пока не вижу тут изъянов. Вот теперь уже вопрос: адекватно ли то, что я придумал и какие в нём могут быть дыры? Одну дыру сразу скажу - если скрипт выполняется с ошибками, то эти ошибки откладываются на неопределённое будущее. Единственный вариант этого избежать - вести реестр всех объектов данного класса. Тогда вообще можно принудительно менять все экземпляры при каждом переопределении класса. Но это тоже стоит своих денег.