Об анинсталлерах

Одно из самых жутких, заброшенных и тоскливых мест Windows – это управление приложениями. Целиком мне сейчас о нём говорить не хочется, скажу только об одном аспекте: об анинсталле. Как он устроен – это дичайший бред. Попробуйте удалить несколько случайных продуктов на системе, которая проработала пару лет!

Не найден msi-файл установки, удаление невозможно.
Пропал компонент приложения, удаление невозможно.
Кто-то перезаписал мою регистрацию, удаление невозможно.
Кто-то вручную удалил с диска файлы, удаление невозможно.

(далее)

Это бред сумасшедшего. Как это удаление может быть невозможно?! Мне нужно не установить, а удалить! Слышите – удалить! Программу. Просто взять и удалить. Неужели это так сложно? Неужели для удаления файлов действительно требуется, чтобы они все до единого были на месте, чтобы сохранился пакет установки программы?
Да нет конечно же! Это лентяи-программисты заставляют пользователей плясать под свою дудку. Вместо того, чтобы подумать головой и написать нормальный деинсталлятор, они предпочитают переваливать все проблемы на плечи пользователя. Нет уверенности, что мы удалим всё? Ну так не будем удалять ничего! Пусть пользователь сам разбирается.

Удаление, уничтожение, очистка – это операции, которые должны выполняться “наилучшим возможным образом”. Т.е. в каждой ситуации должен удаляться абсолютный максимум того, что можно удалить. Если каких-то файлов уже нет – удаляем те, что остались. Если установочного пакета нет – ладно, удаляем хотя бы то, о чём сохранились записи. Не сохранилось записей – удаляем хотя бы то, о чём можно догадаться без них.

Ошибок в этих операциях не должно существовать в принципе. Они должны выполняться всегда.

В качестве бонуса: этот же принцип относится и к деструкторам объектов в программировании. Деструктор должен работать всегда. В каком бы состоянии не находился объект, деструкция, деинициализация, и вообще всё, что угодно, с приставкой “де-“, должно игнорировать ошибки и удалять всё возможное.

Это не значит, что надо ловить в деструкторе все ошибки и затыкать им рты. Если ошибка уже случилась, её, как обычно, нужно вывести пользователю. Просто деструктор должен быть написан так, чтобы выполнять максимум без ошибок даже в неизвестных обстоятельствах. Например, даже если деструктор у вас вызывается единожды, и lpMyObject всегда существует, нужно писать:
if (lpMyObject != NULL) {
FreeMyObject(lpMyObject);
lpMyObject = NULL;
}

Хорошая практика – это чтобы ваш деструктор можно было вызвать на любом этапе жизни объекта, и он успешно выполнился бы. Даже в середине конструктора. Даже в процессе выполнения какой-то критической функции. Потому, что деструктор не может позволить себе вызывать исключения: его самого, вероятно, вам придётся вызывать, если вы надеетесь программно обработать какие-то исключения. Следовательно, деструктор уже должен быть готов обрабатывать исключительные ситуации.

Напишите комментарий:

Если хотите, можно залогиниться.

*