QR code

File.exists or Files.fileExists?

  • Translated by to

Как бы вы разработали класс, который абстрагирует, скажем, файл на диске с определенными свойствами? Допустим, вам нужно иметь возможность проверить, существует ли файл на диске или он уже был удален. Вы бы создали объект сначала и затем вызвали бы метод exists() на нем, или бы вызвали Disk.fileExists() сначала, и только после этого, если возвращается TRUE, создали экземпляр класса File и продолжали работать с ним? Это может показаться вопросом вкуса, но дело не настолько просто.

Давайте посмотрим, как можно проверить, существует ли файл на диске или нет, в разных языках программирования и их SDK:

Существует два различных проектировочных решения: сначала создать объект File, а затем запросить его существование на диске, или спросить диск, есть ли файл, и только после этого создать экземпляр класса File. Какое проектирование лучше? Давайте на минуту забудем, что статические методы - это зло, и представим, что Files не является утилитарным классом, а абстракцией диска. Как бы вы разработали метод exists(), если бы вы были разработчиком нового SDK для нового языка программирования?

Чтобы ответить на этот вопрос, мы должны ответить на более фундаментальный: какое сообщение SDK будет отправлять программисту, размещая метод exists() либо на File, либо на Disk?

Это может показаться тривиальным и косметическим вопросом опытному программисту, но позвольте убедить вас в обратном. Подумайте о дизайне списка платёжных счетов в базе данных. Счёт может быть либо “оплачен”, либо “ещё не оплачен”, что программист может проверить через метод paid(). Первый вариант дизайна выглядит так (это Java):

Вторым вариантом было бы следующее:

Какое сообщение передается в первом отрывке? Я считаю, что это следующее: “Счёт может быть оплачен или нет.” Какое сообщение содержится во втором варианте дизайна? Это: “Если счёт существует, он оплачен.” Другими словами, в первом отрывке два качества счёта (“Я существую” и “Я оплачен”) сосуществуют, в то время как во втором они объединяются в одно (“Я оплачен”).

В слое постоянства это дихотомия качеств может означать либо столбец paid в таблице SQL-базы данных, который может принимать значение NULL, либо столбец с ограничением NOT NULL. Первый отрывок может возвращать объект bill, который существует в базе данных как строка, но столбец paid установлен в NULL. Программист, использующий ваш дизайн, легко поймет идею статуса “оплачено” счёта: это не то же самое, что статус его существования. Программист должен сначала получить счёт, а затем проверить его статус оплаты. Программист также ожидает две возможные точки отказа—счёта может и не быть, или счёт может быть не оплачен—что может вызывать разные исключения или возвращать разные типы результатов.

Как видите, эта проблема не косметическая, а очень существенная: дизайн методов Bill или Bills помогает программистам понять, на каких условиях существуют счета.

Теперь ответ на исходный вопрос о методе exists() файла легко найти. Нахождение файла на диске - это первая задача, которая проверяет, является ли имя файла правильным, и может ли файл потенциально существовать на диске:

Затем проверяется существование файла на диске в данный момент:

Мы можем теперь прийти к выводу, что то, как Python, JS, Ruby и многие другие позволяют нам проверять существование файла на диске, неверно. JDK 6 был прав, но изобретатели JDK 8 испортили это (скорее всего во имя производительности).

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

Translated by ChatGPT gpt-3.5-turbo/42 on 2024-07-08 at 05:14

sixnines availability badge   GitHub stars