Недавно я прочёл запись в блоге одного парня, который жаловался, что на интервью его попросили написать функцию, которая должна скопировать файл. Нет, я понимаю, как можно взъесться на такое задание, но если бы в подобной ситуации оказался я… уж я бы оторвался по полной:
Кандидат: Что конкретно Вы имеете в виду, говоря «скопировать»?
Интервьюер: Ну… создать новый файл, содержимое которого является копией содержимого исходного файла.
К: Нужно ли скопировать также и метаданные о времени создания и модификации оригинального файла?
И: Нет, не нужно.
К: Должен ли файл-копия иметь то же имя, что и исходный файл?
И: Нет.
К: Может ли файл-копия иметь то же имя, что и исходный файл?
И: Хммм… нет.
К: Должен ли я предусмотреть защиту от атаки через подмену букв со сходными начертаниями (например, турецкой I)?
И: Не беспокойтесь об этом.
К: Должен ли файл-копия находиться в том же каталоге, что и исходный файл? Хочу отметить, что если да — то он, вероятно, не может иметь то же самое имя. Если только речь не идёт о копировании файла самого в себя (это тоже интересный вопрос...)
И: Да.
К: Как насчёт атрибутов файла?
И: Скопируйте их тоже.
К: Должен ли я модифицировать атрибуты исходного файла? Если функция копирования, которую Вы просите меня написать, является частью операции резервного копирования или архивирования, то я должен сбросить архивный атрибут у исходного файла.
И: Нет, оставьте их в покое.
К: Вы сказали, что я должен тупо скопировать атрибуты исходного файла на файл-копию. Но если архивный атрибут у исходного файла сброшен, а я его «тупо скопирую» на файл назначения, то это может ввести в заблуждение программы резервного копирования, которые могут использоваться на этом компьютере.
И: Просто скопируйте атрибуты. Меня не волнует, как там у пользователя организовано резервное копирование.
К: Ну, мне кажется, что это не самый разумный подход при разработке программного обеспечения, которым всё-таки будут люди пользоваться, но раз Вы так настаиваете…
И:…
К: Как насчёт атрибута «сжатый»? Ведь может оказаться, что файловая система, на которой находится каталог назначения, не поддерживает сжатие.
И: Делайте копию несжатой.
К: Даже если исходный файл — сжатый, а в каталоге назначения поддерживается сжатие?
И: ДА.
К: А как насчёт атрибута «зашифрованный»? Что, если исходный файл зашифрован, а в каталоге назначения не поддерживается шифрование?
И: В этом случае не шифруйте копию.
К: Не хочу отклоняться от темы, но мне кажется, что такое поведение создаст серьёзную дырку в безопасности. Особенно в случае если файловая система, на которую мы копируем файл, поддерживает произвольные атрибуты (прямо или косвенно).
И: Послушайте, просто скопируйте чёртов файл!
К: Как насчёт информации о создателе файла?
И: Плевать!
К: Как насчёт информации о владельце файла?
И: Плевать!
К: А как насчёт прав доступа? Должен ли я по-разному обрабатывать унаследованные и назначенные права?
И: К чёрту права!
К: На какой ОС должна работать моя функция?
И: Windows XP.
К: Home, Pro, Media Center, или какой-то их комбинации?
И: Pro.
К: На какой пакет обновлений я могу рассчитывать?
И: Service Pack 2.
К: То есть я могу не поддерживать предыдущие уровни обновлений?
И: Верно.
К: Каким образом мне будет передано имя исходного файла?
И: Как параметр.
К: Будет ли оно передано как строка, завершённая нулевым байтом, строка с длиной, или как объект?
И: Строка, завершённая нулевым байтом.
К: Предусматривать ли ситуацию с передачей мне пустого указателя?
И: Нет.
К: Предусматривать ли ситуацию с передачей мне пустой строки?
И: Нет.
К: Предусматривать ли ситуацию с передачей мне неправильно сформированной строки (например, без завершающего нулевого байта)?
И: Нет.
К: В какой кодировке будет переданное мне имя?
И: Unicode.
К: Простите, но Unicode — это вообще-то не кодировка. Unicode-данные должны быть в какой-то конкретной кодировке — например, UTF-8, UCS-2, UTF-16…
И: Ладно, пусть будет UTF-8.
К: Хорошо, но смею заметить, что тогда для передачи в вызов Windows API мне придётся перекодировать в UTF-16, а это несколько геморройно…
И: Тогда UTF-16!
К: С каким порядком байтов?
И: Ррррр… с каким хотите!
К: Предусматривать ли обработку относительных путей, или только абсолютных?
И: Только абсолютных.
К: Есть ли какие-то особенности у передаваемых мне путей, по которыми я должен их фильтровать?
И: Нет. Считайте, что вызывающая программа это уже сделала.
К: Как будет формироваться (или передаваться) имя файла назначения?
[… текли минуты, превращаясь в часы...]
К: Должен ли я поддерживать (или допускать) асинхронное копирование?
И: Нет.
К: Как я должен сообщать об аварийных ситуациях — исключением или кодом возврата?
И: Без разницы.
К: Должен ли я обрабатывать исключения, приходящие из вызываемых мною функций, или просто пропускать их к вызвавшему меня коду?
И: Пропускайте.
К: Что, если файл назначения уже существует?
И: Мамой клянусь, что нет.
К: То есть вызывающая программа это гарантирует?
И: Вот именно.
К: То есть если всё-таки окажется, что он уже существует, то это значит, что гарантии нарушены, и мне следовало бы обрушить программу — что-то явно пошло не так, и мало ли что ещё она там сейчас наделает?
И: Как хотите.
К: А как насчёт вторичных потоков данных у файла?
И: Да делайте что хотите, чёрт бы Вас побрал!
К: Послушайте, Вам может показаться, что я на Вас давлю, и мне очень жаль — но мне крайне важно уяснить все детали Вашего задания. Очевидно, раз Вы хотите, чтобы я написал Вам новую функцию копирования файла, — вместо того, чтобы воспользоваться одной из множества уже реализованных во всевозможных библиотеках и фреймворках — то у Вас имеются какие-то очень-очень специфические требования, которым библиотечные функции не удовлетворяют, и я намереваюсь эти требования из Вас вытянуть. Конечно, я уже могу быстренько набросать что-нибудь подходящее, но должен отметить, что у нас ещё целая куча не до конца выясненных деталей…
И: ААААААААААААААААААААААААААААААААААААААААААА!!!
Дело сделано.
Кандидат: Что конкретно Вы имеете в виду, говоря «скопировать»?
Интервьюер: Ну… создать новый файл, содержимое которого является копией содержимого исходного файла.
К: Нужно ли скопировать также и метаданные о времени создания и модификации оригинального файла?
И: Нет, не нужно.
К: Должен ли файл-копия иметь то же имя, что и исходный файл?
И: Нет.
К: Может ли файл-копия иметь то же имя, что и исходный файл?
И: Хммм… нет.
К: Должен ли я предусмотреть защиту от атаки через подмену букв со сходными начертаниями (например, турецкой I)?
И: Не беспокойтесь об этом.
К: Должен ли файл-копия находиться в том же каталоге, что и исходный файл? Хочу отметить, что если да — то он, вероятно, не может иметь то же самое имя. Если только речь не идёт о копировании файла самого в себя (это тоже интересный вопрос...)
И: Да.
К: Как насчёт атрибутов файла?
И: Скопируйте их тоже.
К: Должен ли я модифицировать атрибуты исходного файла? Если функция копирования, которую Вы просите меня написать, является частью операции резервного копирования или архивирования, то я должен сбросить архивный атрибут у исходного файла.
И: Нет, оставьте их в покое.
К: Вы сказали, что я должен тупо скопировать атрибуты исходного файла на файл-копию. Но если архивный атрибут у исходного файла сброшен, а я его «тупо скопирую» на файл назначения, то это может ввести в заблуждение программы резервного копирования, которые могут использоваться на этом компьютере.
И: Просто скопируйте атрибуты. Меня не волнует, как там у пользователя организовано резервное копирование.
К: Ну, мне кажется, что это не самый разумный подход при разработке программного обеспечения, которым всё-таки будут люди пользоваться, но раз Вы так настаиваете…
И:…
К: Как насчёт атрибута «сжатый»? Ведь может оказаться, что файловая система, на которой находится каталог назначения, не поддерживает сжатие.
И: Делайте копию несжатой.
К: Даже если исходный файл — сжатый, а в каталоге назначения поддерживается сжатие?
И: ДА.
К: А как насчёт атрибута «зашифрованный»? Что, если исходный файл зашифрован, а в каталоге назначения не поддерживается шифрование?
И: В этом случае не шифруйте копию.
К: Не хочу отклоняться от темы, но мне кажется, что такое поведение создаст серьёзную дырку в безопасности. Особенно в случае если файловая система, на которую мы копируем файл, поддерживает произвольные атрибуты (прямо или косвенно).
И: Послушайте, просто скопируйте чёртов файл!
К: Как насчёт информации о создателе файла?
И: Плевать!
К: Как насчёт информации о владельце файла?
И: Плевать!
К: А как насчёт прав доступа? Должен ли я по-разному обрабатывать унаследованные и назначенные права?
И: К чёрту права!
К: На какой ОС должна работать моя функция?
И: Windows XP.
К: Home, Pro, Media Center, или какой-то их комбинации?
И: Pro.
К: На какой пакет обновлений я могу рассчитывать?
И: Service Pack 2.
К: То есть я могу не поддерживать предыдущие уровни обновлений?
И: Верно.
К: Каким образом мне будет передано имя исходного файла?
И: Как параметр.
К: Будет ли оно передано как строка, завершённая нулевым байтом, строка с длиной, или как объект?
И: Строка, завершённая нулевым байтом.
К: Предусматривать ли ситуацию с передачей мне пустого указателя?
И: Нет.
К: Предусматривать ли ситуацию с передачей мне пустой строки?
И: Нет.
К: Предусматривать ли ситуацию с передачей мне неправильно сформированной строки (например, без завершающего нулевого байта)?
И: Нет.
К: В какой кодировке будет переданное мне имя?
И: Unicode.
К: Простите, но Unicode — это вообще-то не кодировка. Unicode-данные должны быть в какой-то конкретной кодировке — например, UTF-8, UCS-2, UTF-16…
И: Ладно, пусть будет UTF-8.
К: Хорошо, но смею заметить, что тогда для передачи в вызов Windows API мне придётся перекодировать в UTF-16, а это несколько геморройно…
И: Тогда UTF-16!
К: С каким порядком байтов?
И: Ррррр… с каким хотите!
К: Предусматривать ли обработку относительных путей, или только абсолютных?
И: Только абсолютных.
К: Есть ли какие-то особенности у передаваемых мне путей, по которыми я должен их фильтровать?
И: Нет. Считайте, что вызывающая программа это уже сделала.
К: Как будет формироваться (или передаваться) имя файла назначения?
[… текли минуты, превращаясь в часы...]
К: Должен ли я поддерживать (или допускать) асинхронное копирование?
И: Нет.
К: Как я должен сообщать об аварийных ситуациях — исключением или кодом возврата?
И: Без разницы.
К: Должен ли я обрабатывать исключения, приходящие из вызываемых мною функций, или просто пропускать их к вызвавшему меня коду?
И: Пропускайте.
К: Что, если файл назначения уже существует?
И: Мамой клянусь, что нет.
К: То есть вызывающая программа это гарантирует?
И: Вот именно.
К: То есть если всё-таки окажется, что он уже существует, то это значит, что гарантии нарушены, и мне следовало бы обрушить программу — что-то явно пошло не так, и мало ли что ещё она там сейчас наделает?
И: Как хотите.
К: А как насчёт вторичных потоков данных у файла?
И: Да делайте что хотите, чёрт бы Вас побрал!
К: Послушайте, Вам может показаться, что я на Вас давлю, и мне очень жаль — но мне крайне важно уяснить все детали Вашего задания. Очевидно, раз Вы хотите, чтобы я написал Вам новую функцию копирования файла, — вместо того, чтобы воспользоваться одной из множества уже реализованных во всевозможных библиотеках и фреймворках — то у Вас имеются какие-то очень-очень специфические требования, которым библиотечные функции не удовлетворяют, и я намереваюсь эти требования из Вас вытянуть. Конечно, я уже могу быстренько набросать что-нибудь подходящее, но должен отметить, что у нас ещё целая куча не до конца выясненных деталей…
И: ААААААААААААААААААААААААААААААААААААААААААА!!!
Дело сделано.