Здравствуйте, hi_octane, Вы писали:
BFE>>Бросить исключение просто, но вот поймать... _>Если в языке программирования сложно поймать исключения — он не годится для продакшн-разработки Основано на личном опыте и опыте тех дедов, которые эти самые исключения изобрели. Деды от души наработались на языках без исключений, "заплатили за них железную цену", и получили такие же железные аргументы за их нужность.
Исключения нужны, когда разрабатывается многоуровневая система в которой есть альтернативный способ работы при многокомпонентной системе, а не когда нужно два файла сравнить.
BFE>>Ну и к тому же, отсутствие файла может вовсе не являться исключительной ситуацией, если это так, то исключение бросать — это вести себя странно. _>We need to go deeper Вот ты проверил по File.Exists, а при чтении файла сетевой диск целиком отвалился (или флэшку вытащили). Теперь надо решить — этот файл пропал, но раз он пропал то его нет — а мы как раз решили не бросать исключение если файла нет. Или вот такое "файла нет" уже совсем другое, и оно уже настоящая проблема?
Нет, обнаруживать проблемы такого рода — это вне функциональности данной функции.
_>Нужно ли дать вызывающей стороне понять что проблема не просто в "нет файла", а в том что всего сетевого диска больше нет?
Нет. Это обнаружится либо на следующем этапе работы, либо вообще не важно.
_>А вдруг вызывающей стороне надо отличать таймаут чтения файла от исчезновения сетевого адаптера?
Мы всё ещё говорим о функции сравнения двух файлов?
_>Попытка взять на себя кусочек чужой ответственности всегда плохо заканчивается.
Именно!
_> Ты не предусмотришь в своей функции всех проблем с тем, что, случается, подсовывают под видом файла. Того что файл есть, но открыть его нельзя из-за прав доступа, и ещё кучи нюансов. И точно также не предусмотришь всех нюансов вызывающей стороны.
Правильно. Именно поэтому все ошибочные ситуации надо рассматривать одинаково, независимо от их природы. Нет доступа? Нет файла? А какая разница? Почему бы в обоих случаях не вернуть false — файлы разные. Что не так?
Здравствуйте, kov_serg, Вы писали:
_>>>Когда файлы имеют одинаковую длинну но доступ к одному или к обоим файлам запрещен или ошибки чтения и невозможно вычислить hash за разумное время или без внешнего вмешательства BFE>>Смотрите: если к одному файлу доступ разрешён, а к другому нет — то файлы разные, так как у них разные права доступа. _>Нет. Файлы могут быть одинаковые и разные. Но это пока невозможно определить => данный вопрос должен быть отложен до решения проблем с доступом.
Не-а. Даже если содержимое файлов одинаковое, то это не значит что файлы одинаковые — ведь их атрибуты различаются.
BFE>>Смотрите: если доступ к обоим файлам запрещен или же ошибки чтения, то как будет выглядеть их обработка? _>Элементарно. Они заносятся в список проблем и обрабатываем остальные файлы.
И как потом обрабатывается этот список проблемных файлов?
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, kov_serg, Вы писали:
_>>>>Когда файлы имеют одинаковую длинну но доступ к одному или к обоим файлам запрещен или ошибки чтения и невозможно вычислить hash за разумное время или без внешнего вмешательства BFE>>>Смотрите: если к одному файлу доступ разрешён, а к другому нет — то файлы разные, так как у них разные права доступа. _>>Нет. Файлы могут быть одинаковые и разные. Но это пока невозможно определить => данный вопрос должен быть отложен до решения проблем с доступом. BFE>Не-а. Даже если содержимое файлов одинаковое, то это не значит что файлы одинаковые — ведь их атрибуты различаются.
Ага не скрепные файлы? Или лежат не не освещенном носителе. Может у вас еще и имя файла должно совпадать?
BFE>>>Смотрите: если доступ к обоим файлам запрещен или же ошибки чтения, то как будет выглядеть их обработка? _>>Элементарно. Они заносятся в список проблем и обрабатываем остальные файлы. BFE>И как потом обрабатывается этот список проблемных файлов?
Очень просто он обрабатывается потом. Например у вас 100500 файлов и только 2 проблемных. Вы же не будете останавливать весь споцесс из-за такой мелочи, особенно если порядок файлов не определён.
Просто уведомить того кто поставил задачу о наличии проблем и это уже его задача устранить проблему и запустить повторную обработку.
Здравствуйте, B0FEE664, Вы писали:
BFE>Ну вот я и спрашиваю, есть ли такие задачи, где action4 отличается от action0,1,2 ?
Я ж тебе уже привёл пример выше.
Или ещё вот: "периодически проверяем, нужно ли начать процесс бэкапа?":
Если первого файла нет (action0 | action1) или оба файла есть, но они равны (action3), то ничего не делаем.
Если оба файла есть, но они неравны (action4), то начинаем процесс бэкапа.
Ещё раз. Ты решаешь задачу "как упаковать 5 разных значений в один бит". В общем случае такое не решается. А наличие конкретных частных условий, когда это возможно — не позволяет тебе выдать универсальное решение.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, B0FEE664, Вы писали:
ЕМ>>Если она не умеет в исключения, то долг за те проблемы, которые может породить.
BFE>Какие, например?
Э-э-э... Типичное понимание термина "файл" — это не математическая абстракция над которой операция сравнения определяется произвольно, а контейнер, с содержимым которого работает операция сравнения. Если контейнер не существует, то с чем работает операция, чтоб она не стала математической абстракцией?
BFE>Да, я видел такой подход. Такой подход ведёт к тому, что при всех подобных вызовах (и это не обязательно работа с файлами), код поимки исключения добавляется при каждом вызове функции и обрабатывается одинаково. Как если бы это было просто третье значение возвращаемое функцией.Выглядит нечитаемо и приводит к дублированию кода по всему проекту.
Если ситуация отсутствия хотя бы одного из файлов ПРЕДУСМАТРИВАЕТСЯ общей задачей, то логичнее проверить их наличие ДО вызова функции сравнения и соответственно среагировать (и это будет ветвление, а не обработка исключения). Если не предусматривается — то дефолтный обработчик всех необработанных никем исключений — как раз адекватное место для реакции на НЕпредусмотренные ситуации.
BFE>Предположим, что вы пишите ТЗ. Какое уточнение вы добавите?
Возможна масса вариантов, зависящих от общей задачи:
а) ситуация отсутствия файлов предусматривается, является ошибкой конфигурации/интеграции/пользователя и должна быть обработана ДО сравнения — тогда не обрабатывать исключения в сравнении, пусть они сигнализируют об ошибке ПРОГРАММИСТА (забывшего заранее обработать ситуацию)
б) ситуация отсутствия файлов НЕ предусматривается (невозможна/невероятна) — опять же не обрабатывать исключения в сравнении, пусть они сигнализируют об ИСКЛЮЧИТЕЛЬНОЙ ситуации
в) ситуация отсутствия файлов предусматривается, при этом отсутствующий файл можно рассматривать как неотсутствующий (пустой и т.п.) — эту ситуацию другие комментаторы уже рассмотрели, не буду углубляться, т.к. вариантов всё равно больше одного.
г) никакой общей задачи нет, наше ТЗ — на шарообразную функцию в вакууме — тогда для УНИВЕРСАЛЬНОСТИ придется ввести третий входной параметр, в котором будет enum из всех возможных вариантов обработки ситуации несуществования файлов, и все эти варианты реализовать. (Если ЯП позволяет — можно задать дефолтное значение для параметра и можно будет его не прописывать в вызове.)
BFE>Я не следую принципу YAGNI, так как этот принцип ведёт к написанию исключительно ситуативного кода и как следствие к нулевому переиспользованию. Мне просто не интересно писать такой код.
Принцип YAGNI призван экономить время программиста (ну не получается заранее ВСЁ предугадать и написать УНИВЕРСАЛЬНЫЙ код; попытки его таки написать отнимают кучу времени сейчас и вовсе не гарантируют экономии времени в будущем). Сделать программирование интересным — это другая задача, с задачей экономии времени она слабо пересекается.
Здравствуйте, kov_serg, Вы писали:
BFE>>Не-а. Даже если содержимое файлов одинаковое, то это не значит что файлы одинаковые — ведь их атрибуты различаются. _>Ага не скрепные файлы? Или лежат не не освещенном носителе.
Нет, просто файлы разные.
_>Может у вас еще и имя файла должно совпадать?
проверка имён — это другая функция.
_>Очень просто он обрабатывается потом. Например у вас 100500 файлов и только 2 проблемных. Вы же не будете останавливать весь споцесс из-за такой мелочи, особенно если порядок файлов не определён.
Где-то тут рядом кто-то в таких ситуациях предлагает исключение бросать...
_>Просто уведомить того кто поставил задачу о наличии проблем и это уже его задача устранить проблему и запустить повторную обработку.
Фактически это отсутствие обработки и игнорирование проблем. Если со списком потом никто не работает, то зачем он вообще нужен? Ерунда какая-то... У меня в коде есть ситуация, где ведётся список проблемных файлов, но совершенно с другой целью — игнорировать их при последующей обработке...
Здравствуйте, B0FEE664, Вы писали:
_>>Может у вас еще и имя файла должно совпадать? BFE>проверка имён — это другая функция.
Хорошо, но уже лучше. И ещё надо не забывать, что:
Если имена не совпали, то это всё равно может быть один и тот же файл (симлинки, хардлинки, сетевые пути, UNC-пути).
Если имена совпали, то при открытии одного того же имени — это могут быть разные файлы.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, L_G, Вы писали:
BFE>>Да, я видел такой подход. Такой подход ведёт к тому, что при всех подобных вызовах (и это не обязательно работа с файлами), код поимки исключения добавляется при каждом вызове функции и обрабатывается одинаково. Как если бы это было просто третье значение возвращаемое функцией.Выглядит нечитаемо и приводит к дублированию кода по всему проекту.
L_G>Если ситуация отсутствия хотя бы одного из файлов ПРЕДУСМАТРИВАЕТСЯ общей задачей, то логичнее проверить их наличие ДО вызова функции сравнения и соответственно среагировать (и это будет ветвление, а не обработка исключения). Если не предусматривается — то дефолтный обработчик всех необработанных никем исключений — как раз адекватное место для реакции на НЕпредусмотренные ситуации.
Это ошибочный подход из-за "многопоточности". Файл в любой момент может быть удалён кем-то ещё, поэтому проверка что-либо до вызова функции не гарантирует, что в момент вызова функции файл всё ещё будет существовать.
BFE>>Предположим, что вы пишите ТЗ. Какое уточнение вы добавите?
L_G>Возможна масса вариантов, зависящих от общей задачи: L_G>а) ситуация отсутствия файлов предусматривается, является ошибкой конфигурации/интеграции/пользователя и должна быть обработана ДО сравнения — тогда не обрабатывать исключения в сравнении, пусть они сигнализируют об ошибке ПРОГРАММИСТА (забывшего заранее обработать ситуацию)
см. выше.
L_G>б) ситуация отсутствия файлов НЕ предусматривается (невозможна/невероятна) — опять же не обрабатывать исключения в сравнении, пусть они сигнализируют об ИСКЛЮЧИТЕЛЬНОЙ ситуации
С трудом, но наверное такое можно себе представить.
L_G>Принцип YAGNI призван экономить время программиста (ну не получается заранее ВСЁ предугадать и написать УНИВЕРСАЛЬНЫЙ код; попытки его таки написать отнимают кучу времени сейчас и вовсе не гарантируют экономии времени в будущем). Сделать программирование интересным — это другая задача, с задачей экономии времени она слабо пересекается.
Ага, я такую "экономию" не один год уже наблюдаю: коллектив переписывает одну и ту же функциональность в который раз. И каждый раз с ошибками отличными от предыдущей реализации. На каждом конкретном месяце экономия есть, а в целом — упущенная выгода. Впрочем это проблемы работодателя, а не работников.
Кстати! Добавление исключения в функцию — это ведь как раз попытка написать универсальный код, особенно если эти исключения не будут задействованы.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Э-э-э... Типичное понимание термина "файл" — это не математическая абстракция над которой операция сравнения определяется произвольно, а контейнер, с содержимым которого работает операция сравнения. Если контейнер не существует, то с чем работает операция, чтоб она не стала математической абстракцией?
Это как со строкой: пустая строка и NULL строка могут рассматриваться как одинаковыми, так и различными. Зависит от задачи. Обычно, однако, пустую строку и NULL строку можно рассматривать равными.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, ·, Вы писали:
BFE>·>Если имена совпали, то при открытии одного того же имени — это могут быть разные файлы. BFE>А это как?
Это pipes или псевдо файл из procfs или просто постоянно обновляемый временный файл
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, kov_serg, Вы писали:
BFE>>>Не-а. Даже если содержимое файлов одинаковое, то это не значит что файлы одинаковые — ведь их атрибуты различаются. _>>Ага не скрепные файлы? Или лежат не не освещенном носителе. BFE>Нет, просто файлы разные.
Вы уже определитесь. Разные это значит только разное содержимое, любые метаданные туда не входят ни права ни атрибуты ни владелец ни дата на расположение на диске и т.п.
_>>Может у вас еще и имя файла должно совпадать? BFE>проверка имён — это другая функция.
Это был сарказм.
_>>Очень просто он обрабатывается потом. Например у вас 100500 файлов и только 2 проблемных. Вы же не будете останавливать весь споцесс из-за такой мелочи, особенно если порядок файлов не определён. BFE>Где-то тут рядом кто-то в таких ситуациях предлагает исключение бросать...
Нинужно никаких исключений они нарушают прямую исполнения. И она превращается в ужос нах. Особенно когда данные обрабатываются малыми группами по 2 — 3 млн шт
_>>Просто уведомить того кто поставил задачу о наличии проблем и это уже его задача устранить проблему и запустить повторную обработку. BFE>Фактически это отсутствие обработки и игнорирование проблем. Если со списком потом никто не работает, то зачем он вообще нужен? Ерунда какая-то... У меня в коде есть ситуация, где ведётся список проблемных файлов, но совершенно с другой целью — игнорировать их при последующей обработке...
Нет это разнесение ответственности. Эта не задача функции сравнивающей идентичность файлов принимать решение что делать в сложных ситуациях. Её задача просто сообщить о проблемме, а не пытаться решать её или игнорировать втихоря.
BFE>Это ошибочный подход из-за "многопоточности". Файл в любой момент может быть удалён кем-то ещё, поэтому проверка что-либо до вызова функции не гарантирует, что в момент вызова функции файл всё ещё будет существовать.
"Ошибочность" вряд ли есть в предварительной проверке того, существовал ли файл вообще (или его "забыли" создать, или записали в другую папку и т.п. — т.е. в проверке на ошибки пользователя/интеграции/конфигурации/забывчивого программиста).
"Файл в любой момент может быть удалён кем-то ещё" больше походит на описание как раз исключительной (обрабатываемой исключениями) ситуации. Если это ожидаемая ситуация — тогда эти исключения придется либо (так себе вариант) ловить на КАЖДОЙ файловой операции отдельно (в т.ч. и после нашего сравнения, если предусмотрены дальнейшие действия над уже сравнёнными файлами), либо (проще и логичнее) завернуть в один try...catch всю группу операций (более широкую, чем наше сравнение) — и для второго варианта как раз лучше, чтобы в операции сравнения своей обработки исключений (ситуации отсутствия файлов) не было.
Из предложенных вариантов, попробую угадать, (г) (со ВСЕМИ заранее реализованными вариантами реакции на отсутствие файлов) оказывается более приемлемым?
BFE>Ага, я такую "экономию" не один год уже наблюдаю: коллектив переписывает одну и ту же функциональность в который раз. И каждый раз с ошибками отличными от предыдущей реализации. На каждом конкретном месяце экономия есть, а в целом — упущенная выгода. Впрочем это проблемы работодателя, а не работников.
Всегда остаётся вероятность, что YAGNI придумали идиоты и применение этого принципа в массовом индустриальном/энтерпрайзном программировании неоправдано. Но я в этот принцип почему-то поверил и даже широко применяю (видимо, потому, что я очень ленивый программист).
BTW, рационально мыслящие программисты обычно практикуют не переписывание с нуля, а дописывание нового с одновременным рефакторингом старого (рефакторинга в рамках необходимого для того, чтобы новое вписалось органично, а не в виде костылей). Думается, тем коллективом двигало как раз то самое хорошо знакомое тебе стремление сделать программирование интересным.
BFE>Кстати! Добавление исключения в функцию — это ведь как раз попытка написать универсальный код, особенно если эти исключения не будут задействованы.
На всякий случай: у меня о ДОБАВЛЕНИИ исключения в функцию речь не шла, проброска исключений из вызываемых функций выше (в вызывающую) не требует кода.
Здравствуйте, B0FEE664, Вы писали:
BFE>·>Если имена совпали, то при открытии одного того же имени — это могут быть разные файлы. BFE>А это как?
Когда между открытиями меняется линк или заменяется файл.
Поэтому придумали во всяких less, tail специальный ключик --follow-name.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, B0FEE664, Вы писали:
BFE>Зависит от задачи.
Вот именно. Но Вы-то поставили вопрос о некой всеобщей функции, которая умеет возвращать только true/false.
BFE>Обычно, однако, пустую строку и NULL строку можно рассматривать равными.
Обычно их как раз нельзя полагать равными. Если объект, связываемый со строкой, равен NULL, это может означать как то, что связь объекта со строкой не установлена или удалена, так и то, что где-то что-то испортилось, и в объект, который должен быть постоянно связан со строкой, попал NULL, и объект попросту не валиден. А если он связан с пустой строкой, то объект валиден, а в строке ничего нет.
В этом смысле языки, не приравнивающие null/nil к пустой строке, исключительно правильны.
Здравствуйте, B0FEE664, Вы писали:
BFE>Вот если мы сравниваем два нулевых указателя, то получаем true. BFE>А вот если мы сравниваем два несуществующих файла, то функция их сравнения должна возвращать true или false?
Надо как в БД реализовано. Если что-то сравниваешь с null, то получаешь не true/false, а null
Здравствуйте, kov_serg, Вы писали:
BFE>>·>Если имена совпали, то при открытии одного того же имени — это могут быть разные файлы. BFE>>А это как?
_>Это pipes или псевдо файл из procfs или просто постоянно обновляемый временный файл
Это не настоящие файлы. Вот как сравнивать содержимое таких файлов? Так что их можно даже не рассматривать, тем более, что они редки о часто не поддерживаются файловой системой.
Здравствуйте, ·, Вы писали:
BFE>>·>Если имена совпали, то при открытии одного того же имени — это могут быть разные файлы. BFE>>А это как? ·>Когда между открытиями меняется линк или заменяется файл. ·>Поэтому придумали во всяких less, tail специальный ключик --follow-name.
Такая ситуация ничем не отличается от той, когда файл удалили сразу после завершения выполнения функции, так что это можно выкинуть из рассмотрения.
Здравствуйте, Евгений Музыченко, Вы писали:
BFE>>Зависит от задачи. ЕМ>Вот именно. Но Вы-то поставили вопрос о некой всеобщей функции, которая умеет возвращать только true/false.
Речь про строки, то есть аналогия. Не факт, что для файлов должен быть такой же подход.
BFE>>Обычно, однако, пустую строку и NULL строку можно рассматривать равными. ЕМ>Обычно их как раз нельзя полагать равными. Если объект, связываемый со строкой, равен NULL, это может означать как то, что связь объекта со строкой не установлена или удалена, так и то, что где-то что-то испортилось, и в объект, который должен быть постоянно связан со строкой, попал NULL, и объект попросту не валиден. А если он связан с пустой строкой, то объект валиден, а в строке ничего нет.
Не согласен. NULL строка — это такая строка, у которой нет значения. Например это строковое поле в базе данных у которого нет никакого значения.
ЕМ>В этом смысле языки, не приравнивающие null/nil к пустой строке, исключительно правильны.
Впрочем, если это так, то мы возвращаемся к изначальной формулировке. Файл — контейнер и строка — контейнер. NULL строка равна другой NULL строке. Значит два отсутствующих файла равны между собой?