Lex Kravetski (lex_kravetski) wrote,
Lex Kravetski
lex_kravetski

Categories:
  • Music:

Правильная файловая система

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

Итак, проблема в файловой системе. И в той части ОС, которая с этой файловой системой работает. Причём, даже не одна проблема, а сразу много, и при попытках решить одни из них — другие усугубляются.

В общем, так. Первая из множества проблема: хранение деталей приложения — запускных файлов, библиотек и настроек. На мой взгляд, самый удобный вариант — хранить их в все в папке приложения. Тогда приложение легко переносится с одного места на другое (в том числе, на другой компьютер), легко бэкапится (да-да, можно забэкапить только настройки, однако никто вам не гарантирует, что когда вы захотите переустановить приложение, то по месту его получения — на сайте или в репозитории — будет лежать та же версия; новая ведь может и не быть совместима с вашими настройками и, что ещё хуже, — с документами тоже). С другой стороны, граждане, сидящие под Линуксом, точнее, некоторые из них, уверены, что настройки следует хранить в отдельном месте, дабы перенести можно было все сразу. Все сразу их всё равно перенести на деле нельзя, но здравое зерно тут есть. Разработчики же Майкрософт, в свою очередь, рекомендуют запись в реестр — типа, чтобы другим программам было проще найти ваше приложение и чтобы настройки сохранились даже если вы удалите приложение. И в их словах тоже есть здравое зерно.

Однако эти три подхода противоречат друг другу, а временами и сами себе. При хранении всего в одной папке в современных реализациях ОС возникает проблема с разделением настроек разных пользователей. Оно понятно, что настройки при этом подходе раскладываются по разным папкам внутри одной главной. И попытавшийся переписать главную папку, перепишет и чужие настройки тоже. На мой взгляд, это — наименьшее зло: сейчас место на винте уже дешевле затрачиваемого времени, поэтому унесённые чужие настройки, буде они даже займут лишний мегабайт, не могут рассматриваться как суровый отжиратель пространства.

Равно как и библиотеки — ведь разнесение файлов приложения по разным местам вдохновлено в том числе надеждой сохранить единственный экземпляр каждой библиотеки. Это наверно когда-то здорово экономило место, но сейчас оно не менее здорово портит нервы: перенести программу просто копированием не получается — на новой машине (или на старой после сноса системы) нужных приложению библиотек может и не оказаться. Поэтому перенос не состоится. Ну и настройки из реестра ровно по той же причине крайне плохо поддаются переносу и бэкапу. Из отдельных Линуксовых папок — тоже плохо. Что из реестра экспорт делать, что в десятке папок всё связанное с приложением искать, один хрен, долго и вероятность что-то не углядеть весьма высока. Однако вдобавок приложение в отдельной папке затрудняет перенос всех настроек всех приложений…

Реестр в состоянии сохранить настройки в рамках одной системы, но существенно усложняет их сохранение даже при переустановке этой систем, не говоря уже об установке другой или их экспорте на другой компьютер. Наличие многих папок (типа, «Program Files» и «Documents and Settings», у которой внутри тоже туева хуча подпапок) чревато утерей полезной информации — часть ведь по сути пользовательских документов неожиданно обнаруживается не там, где сохранён основной, а в совсем других местах (характерный пример — кисти Иллюстратора). Разнесение же по разным папкам одного и того же приложения чревато не только утерей, но и проблемами с удалением старых версий приложения. И затруднением переносимости тоже.

Как ни поверни, иными словами, всё хреново: разные папки — хреново (в Винде они, к слову, тоже разные. Одни приложения калят в Документс энд Сеттингс, другие — в системную директорию Винды, третьи, так вообще свои настройки в «Моих документах» сохраняют), реестр — хреново, одна папка чуть менее хреново, но тоже хреново.

Тут вот я что подумал: засмотрим попристальнее на ссылки. Ссылки на файлы и папки сейчас ведь повсеместно используются. И в общем-то, ссылка в ряде случаев является заменителем файла. В ряде, но не в главном для поднятой темы: при копировании ссылки копируется ссылка, а не файл. Ну и новый такой же файл, скопированный на тот же диск, остаётся вторым таким же файлом, никак не влияя на ссылки. Надо бы как-то углу́бить и усугу́бить поведение ссылок, дабы они решили все вопросы сразу.

И надо это сделать вот как:

Файлов вообще быть не должно, должны быть только ссылки на файлы.

Ну, как мы понимаем, совсем устранить файлы вроде как не получится. Однако файловая система вполне может скрыть реальные, физические файлы ото всех, кроме ссылок. И, возможно, ОС. Но от пользователя с любыми правами файлы следует скрыть. Видны должны быть только ссылки. Типа, как в Java — нет переменной, представляющей собой объект. Все переменные хранят только ссылки на объекты. И, как в Java удаление всех ссылок означает удаление объекта, файлы должны удалять только тогда, когда на них не осталось ссылок.

На каждом девайсе (физическом, логическом, архиве — не важно; скажем так, девайс в данном случае — это то, что имеет свою собственную файловую систему) присутствует единственный экземпляр файла. При копировании ссылки с одного девайса на другой, автоматически копируется сам файл. Если на втором девайсе такой файл уже есть, то в указанное копировщиком место копируется толко ссылка. Довольно простые правила.

Поскольку «тот же файл» понятие не совсем определённое, в частности, собранная разными компиляторами из одних и тех же исходников библиотека физически может оказаться совсем другой, имеет ввести некие идентификаторы сходства. Например, GUID для библиотек. Но, в принципе, можно и без этого — сейчас ведь разные сборки одной и той же библиотеки вообще в лучшем случае по имени файла считаются сходными. В общем, для определения сходств и различий вполне можно и существующими методами воспользоваться — работать будет.

От внедрения описанной концепции мы получаем кучу ништяков. Ссылка на файл настроек теперь спокойно может храниться прямо в папке приложения. И при копировании папки файл настроек тоже скопируется — ссылкой, если на тот же девайс, или же физически файлом, если на другой. Одновременно можно все настройки сложить в отдельную папку и переносить все настройки всех приложений разом.

Библиотеки, как и мечталось, всегда присутствуют в единственном экземпляре, при этом они «хранятся» в виде ссылок вместе с приложением, которое их использует. При копировании приложения копируются и нужные ему библиотеки.

Разграничение доступа достигается просто сокрытием ссылок (или запретом на изменение физических файлов, на которые они ссылаются) от пользователя, не имеющего на них прав. Ровно тем же способом можно сокрыть ссылки на физические каталоги и воспрепятствовать копированию в них.

Документ может инкапсулировать в себя ссылки на другие документы с файлами и при копировании его, всё с ним связанное тоже скопируется — шрифты, кисти, текстуры, картинки, что угодно. Забэкапленный документ будет означать, что всё это тоже забэкаплено. Причём, совершенно без напряжения со стороны пользователя — просто по факту копирования документа на другой девайс.

Тут есть одна тонкость: неизменность ссылки не означает неизменности файла. А файлы сейчас зачастую копируют с целью не просто получить точную копию имеющегося, а с целью сохранить слепок состояния оригинала на тот случай, если он поменяется. Понятно, что копирование ссылки на файл этому не способствует — ведь файл остаётся одним и тем же, изменив его по одной ссылке, мы изменим его и для другой то же. Соответственно, нужна некая система версий, позволяющая не просто сделать копию ссылки, но и физическую копию состояния.

Оное тоже можно встроить прямо в файловую систему (что, к слову, кое-где уже сделано). А именно: файл по умолчанию хранит не только последнее состояние, но и предыдущие свои версии тоже. Изменённая версия файла при записи не перетирает предыдущую, а дописывается к ней. Имеющий ссылку на файл, автоматически получает и ссылку на его версии тоже. При копировании ссылки на другой носитель по умолчанию копируются все его версии, однако есть возможность и скопировать только некоторые из них, например, последнюю. Ну и в самой операционной системе должен иметься некий менеджер версий, позволяющий по крайней мере удалить ненужные версии и, заодно, дать посмотреть, кто ещё ссылается на файл — дабы можно было добиться его физического удаления.

Фактически это — система контроля версий, сразу встроенная в файловую.

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

Ровно тем же способом организуется корзина — в неё просто копируется ссылка на файл. И удаление ссылки на файл из «Моих документов» в этом случае не приведёт к физическому удалению самого файла. При очищении корзины — если там лежит последняя на устройстве ссылка на файл — файл удалится физически.

На первый взгляд описанная схема выглядит странной. Я даже поначалу принял её за эдакую программистскую шутку. Однако она непротиворечива, работоспособна и удобна в использовании. И её странности — сродни мнимым странностям языков вида Java. В них ведь тоже поначалу кажется, что отсутствие возможности хранить в переменной сам объект, а не ссылку на него — чревато. А потом оказывается, что ни фига не чревато. Наоборот, удобно даже.

Для примера рассмотрим мнимое противоречие: есть исходники, из которых компилируется запускаемый файл. Поскольку процесс разработки в полном разгаре, оный процесс проделывается много раз подряд. Кажется, что предложенная система приводит к неудобству: скомпилированный файл ведь кладётся на то же место, где лежал его предшественник. Что происходит с предшественником? Создаётся ли версия, которая в данном процессе совершенно не нужна? Освобождается ли место? Получаются ли два файла или же один?

Ответ довольно прост и для его постижения достаточно посмотреть, что произойдёт при выполнении вот этих двух строк java-программы:

A a = new A();

a = new A();

Процесс компилирования из исходников концептуально тождественен этим двум строкам. Действительно, при первой компиляции компилятор запросил у системы новый файл (new A()) и сохранил на него ссылку в новой переменной а. При второй компиляции компилятор снова запросил новый файл, но ссылку на него сохранил уже в существующей переменной. Не смотря на сохранение названия переменной, ссылки на самом деле разные — они на разные объекты. Ссылка на первый объект утрачена, на него ссылок больше нет и он удаляется. Теперь мы имеем ссылку с тем же названием, но на другой объект. С файлами ровно так же: ссылка — неизменяема. Изменяема только переменная — имя файла, — которая её хранит. Итак, создастся новый файл и он будет связан с именем предыдущего. Предыдущий же лишится последней ссылки на себя и будет физически удалён. Никакого противоречия. Внешне система ведёт себя ровно так же, как ныне существующие.

C исходниками при этом происходит иное — они «не создаются через new», а просто сохраняются в изменённом состоянии. То есть, файлы с исходниками хранят не только последнюю свою версию, но и предыдущие тоже. Аналогом сего может быть код на Java:

A a = new A();

a.setX(10);

a.setX(20);

при том условии, что внутри «setX» предыдущие значения как-то запоминаются. И снова никакого противоречия.

Считаю, срочно надо внедрять.

Tags: программирование, философия
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 254 comments
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →
Previous
← Ctrl ← Alt
Next
Ctrl → Alt →