Служебный метод - передать файл или строку?

Вот пример вспомогательного метода:

public static Long getFileSize(String fileString) {

    File file = new File(fileString);

    if (file == null || !file.isFile())
        return null;

    return file.length();
}

Является ли хорошей практикой передавать строку, а не файл в метод, подобный этому? Вообще, какие рассуждения следует применять при создании утилитарных методов этого стиля?

9 ответов

Решение

Это мое предпочтительное решение:

public static Long getFileSize(String path) {
    return getFileSize(new File(path));
}

public static Long getFileSize(File file) {
    return (!file.isFile()) ? -1L : file.length();
}

Обратите внимание, что он возвращает -1L, а не 0L, что позволяет вызывающей стороне различать пустой файл и "файл", длина которого по какой-либо причине не может быть определена. file.length() вернет ноль в некоторых случаях, когда у вас нет файла нулевой длины; например

  • когда file не существует
  • когда file это каталог
  • когда file это специальный файл (например, файл устройства, канал и т. д.), и ОС не может определить его длину.

file.isFile() колл занимается этими делами. Тем не менее, это спорно ли метод (ы) должен возвращать -1L или выбросить исключение. Ответ на эту дискуссию зависит от того, -1L случаи являются "нормальными" или "исключительными", и это может быть определено только со ссылкой на контексты, в которых метод предназначен для использования,

Я бы пошел с файлом. Мне кажется, что ООП корректен: более безопасен (строковые "общие" в Java...) и семантически выразительные: если вы имеете дело с файлами, тогда передайте объект File.

Напомним, что в Java объект File представляет собой не сам файл (его содержимое), а скорее его путь: " Абстрактное представление путей к файлам и каталогам " (это может быть даже путь к несуществующему файлу), и это почти именно то, что вам нужно здесь.

Это может быть ограничением только в нескольких случаях: если "файл" на самом деле является неким псевдофайлом или ресурсом, например, внутри файла JAR. Альтернатива, которую я нашел полезной, - это URI, который (концептуально) включает в себя файл в качестве особого случая, но также и другие ресурсы.

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

Моя рекомендация будет иметь оба:

public static Long getFileSize(String path) {
    return getFileSize(new File(path));
}

public static Long getFileSize(File file) {
    return (file == null || !file.isFile()) ? 0L : file.length();
}

и пусть ваши пользователи выбирают в зависимости от типа объекта, который они используют для представления путей в файловой системе. Как упомянул @Nikita, ни один из вариантов не ошибается.

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

Мой подход к этому, когда я не уверен, состоит в том, чтобы создать два метода, один для String, другой для File. Затем пусть String one создаст файл и вызовет файл один.

public static long getFileSize (final String fileString) {
  return getFileSIze (new File (fileString)); 
}

public static long getFileSize (File file) {
   if (file == null || !file.isFile()) return null;
   return file.length();
}

Перегрузка метода - лучшая практика в таких случаях.

На мой взгляд, эта функция полезна только со строковым параметром. Что оно делает?

  • Создает объект файла.
  • Проверяет, что это может быть создано.
  • Проверяет, что это файл
  • Возвращает длину

Если вы передали ему файл, первое, что не нужно, вероятно, следует предположить следующие два, а длина - это функция-член файла. Если вы передадите этот файл, эта функция станет слишком тривиальной для написания:)

(Кроме того, я думаю, что возвращать null из функции, которая возвращает long, странно)

Если у вас уже есть объект File, используйте:

length = file.isFile() ? file.length() : -1;

Если ваш код имеет дело с файлами, а не с именами файлов, вы можете самостоятельно сохранить файл, если вы повторно используете указатели файлов. В этом случае это может привести к их использованию поверх имени файла.

Есть ряд соображений:

  1. Существуют служебные методы, позволяющие уменьшить количество повторяющихся кодов паролей в вашем приложении, что делает код более читабельным и уменьшает количество потенциальных ошибок. Имеет смысл обслуживать наиболее распространенные шаблоны использования, т. Е. Если в большинстве случаев у вас есть строка, описывающая файл, - передайте строку. Преимущество заключается в том, что в первую очередь нужно использовать служебный метод, а не получать оптимальную подпись, которая на 100% ориентирована на будущее.

  2. Передача файла вместо строки обеспечивает более строгую типизацию, то есть во время компиляции можно проверить больше кода, защищая от опечаток. Заставьте компилятор сделать работу за вас, используйте преимущества строгой типизации.

  3. Передача файла означает, что вы можете передать любой тип объекта File, возможно, сделанный на заказ объект файла в памяти, не изменяя служебный метод для обработки дескриптора файла на заказ.

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

  5. В конце вы можете иметь несколько перегруженных утилитарных методов по очень низкой цене. Этот сценарий как раз и является причиной существования перегрузки методов в качестве языковой функции. Посмотрите, что естественно работает в вашей кодовой базе. Код податлив, и это не одно из таких дизайнерских решений, с которым вам придется жить вечно, если только вы не создаете API для использования другими людьми.

  6. Вы могли бы также хотеть изменить имя, чтобы быть немного более информативным, например

    • long sizeFromFile(Файл f) и
    • long sizeFromFileName (имя строки)

    используя соглашение, первоначально предложенное Джоэлем Спольски.

Это зависит от полезности, ожидаемой со стороны клиента. В случае, если на стороне клиента уже есть файловый объект и он хочет получить размер файла, разработчик на стороне клиента вынужден извлечь путь к файлу и передать его служебному методу. Чтобы избежать этого, я бы предоставил перегруженные методы 1) с File 2) File Path String

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

Единственное, что имеет значение, это то, как вы собираетесь использовать этот метод. Другими словами, если ваше приложение работает с объектами File, вы можете передать их и удалить некоторые ненужные операции. Если вы работаете с путями к файлам, строковый параметр может быть более удобным.

Но, в конечном счете, ни один из вариантов не является неправильным: ни одно из них не сделает ваше приложение хуже

Другие вопросы по тегам