интерфейс `Files` в BBCB плохой! не спорьте, я всегда прав.
поясняю за базар. довольно очевидно, что `Files` делался с прицелом на один унифицированый драйвер FS — потому что никакого другого в ETHOS не было и не планировалось. поэтому любые драйвера-навески там выглядят как хаки. и префиксы тоже хаки, которые пришлось гвоздями вбить в основной драйвер. с этой точки зрения (одна FS без наворотов) дизайн адекватен. но вот если перейти к ситуации, когда драйверов в системе может быть много и очень разных — вот тут всё становится плохо.
если вы ещё не убеждены — давайте просто посмотрим на Locator. локаторы настолько отвязаны от всего остального, что совершенно очевидно: локаторы для всех FS предполагались одинаковые, и свободно используемые любым драйвером. что явно не так в любом реалистичном сценарии, где FS больше одной.
а теперь давайте посмотрим с другой стороны: локатор не только знает некий путь в своей FS — он ещё и совершенно точно знает, к какой FS принадлежит. это логично, потому что в общем случае «бесшовный» перескок с FS на FS невозможен: надо просто делать новый локатор на новый путь.
отсюда получается, что все методы `dir` — это на самом деле методы локатора. собственно, не зря `dir` получает оный локатор аргументом. делаем ещё шаг — и избавляемся от посредника. остаются только локаторы.
so far, so good. но. локаторы надо как-то производить. вот тут и вступает в игру «фабрика локаторов». тот самый `dir`, но по факту с одним методом: `This()`. причём метод этот лимитированый. почему? а потому что интерфейс `Files` расширяется списком префиксов. к каждому префиксу можно прикрепить фабрику. умолчательно у нас будет пустой префикс и одна фабрика, плюс механизмы регистрации новых. точнее, правило, которое назначает фабрику для пустого префикса.
таким образом мы получаем нормальный механизм для реализации FS любой заморочености, и возможность эти FS комбинировать любым удобным способом. при этом нам не нужно писать некоего «арбитра» и полагаться на его наличие. а локаторы превращаются в полноценные объекты, которых достаточно для любых файловых операций (кроме одной, о ней ниже).
конечно, подобную механику возможно реализовать поверх существующего `Files` — но какой смысл? проще поменять интерфейс.
одна операция, которую сложно привязать к локатору — это `Files.dir.Temp()`. вот здесь нужна совсем отдельная фабрика. просто потому, что в общем случае временные файлы даже имени не имеют (и в LC на никсах они действительно не имеют имени). обычно в системе существует один штатный способ создавать временные файлы, и он нуждается в отдельном интерфейсе.
далее. вместо двух операций получения сразу всего списка существующих файлов и путей (которые вообще больше похожи на ad-hoc решение) — вводим Reader, который можно попросить у локатора. и который обычным образом используется для чтения каталога поэлементно. он возвращает как имена файлов, так и имена подкаталогов; отличаются они битом в атрибутах. а будет ли такой Reader сразу читать весь каталог и кэшировать, или честно итерировать — совершенно неважно. также Reader можно создать не только для всего каталога, но и для конкретного имени в каталоге: `NewReader (IN name: STRING; old: Reader): Reader`. если `name` пустой — читаем весь каталог. если не пустой — получаем информацию об одном конкретном элементе каталога. (нужна ли микрооптимизация с `old` — я не уверен. но она не мешает, так что пусть будет.)
в Oberon/Ur вместо пустой строки можно передать `NIL` (пустая строка и есть `NIL` на самом деле), так что в общем случае вызов выглядит как `NewReader(NIL, NIL)`.
и, кстати, мы получили схему, в которую отлично ложатся URL: "scheme:path". вы же в курсе, что "//" в URL — это часть пути для конкретной схемы, а не обязательный компонент?
в общем, я собираюсь передизайнить файловый интерфейс в Oberon/Ur именно так. а потом, скорее всего, перетащу это в LC (оставив `FilesOld` для легаси кода).
p.s.: локаторы-фильтры в новой схеме тоже выглядят проще, чем в существующей. они действительно просто фильтры, которые могут некоторые запросы перекидывать локатору другой FS, а некоторые обрабатывать сами. соответственно, та же PackFS (которая пристёгнута к бинарнику) — просто перехватывает все открытия дисковых файлов, и возвращает или свой локатор (если файл в PackFS), или сигнализирует, что она в это не умеет, и основной prefix resolver пробует предыдущую зарегистрированую фабрику для того же префикса. дёшево, сердито, удобно. небольшие проблемы будут с Reader'ом каталогов — но они и в существующей схеме есть, и на них просто все забили.
|