Scala: Где я должен размещать заявления импорта?
Scala позволяет импортировать практически все, что угодно, где угодно, и это здорово. Но есть ли какие-либо соображения, которые я должен учитывать при импорте чего-либо внутри класса, метода или всего лишь одного блока? Как это относится к производительности, стилю, поддерживаемости кода и т.д.
В общем, я стараюсь подчиняться этим правилам (составленный мною):
- Если я импортирую что-то внешнее из другого пакета, я всегда помещаю его вверху сразу после "пакета".
- Если я использую что-то более одного раза в одном файле, я также импортирую его вверху.
- В противном случае я помещаю свой импорт вверху соответствующего класса/свойства/объекта.
- Я не могу импортировать вещи в методы и блоки.
- Я пытаюсь избежать импорта содержимого объектов экземпляра, если у меня нет повода для этого.
- Я бы избегал переименования и "скрытия", если только не разрешать конфликты имен, но мне это еще не нужно.
Имеют ли эти "правила" смысл? Я слишком сильно ограничиваю себя?
Ответы
Ответ 1
Как правило, имеет смысл ограничить объем чего-либо (например, переменной или метода) до "наименее", насколько это возможно. Например, используйте внутренний def, а не один на уровне класса. Почему импортные заявления должны быть разными? Зачем загрязнять класс с импортом, который используется только в одном блоке?
Мне нравится объявлять импорт как можно ближе к тому, где они используются!
Таким образом, общие утилиты, такие как scalaz и мои собственные, как правило, импортируются один раз на верхнем уровне (потому что они используются во всем классе). В то время как такие вещи, как I/O, импортируются локально, только там, где они используются
Ответ 2
Нет.
Я не могу импортировать вещи в методы и блоки.
Почему?
Ответ 3
Вы должны помнить, что Scala все еще скомпилирован, и все правила, применимые к Java как язык компиляции, также применимы к Scala. Компилятор должен знать, какой символ вы имеете в виду, когда говорите List
или Function
.
Вы можете использовать операторы импорта внутри блока, но тщательно их использовать. Излишние могут привести к непоследовательному пониманию исходных файлов другими людьми. Было бы неудобно, если граница одного класса будет использовать два разных определения List
, зависящих от контекста.
Ответ 4
правила импорта в Эффективном Scala говорят:
Поместите импорт в верхнюю часть файла
Читатель может обращаться ко всем импортам в одном месте.
В некоторых базовых кодах, с которыми я работал, была тенденция импортировать одно и то же несколько раз в несколько мест в одном файле, потому что разработчик не проверял это. Было бы неплохо, если бы IDE могли автоматически продвигать импорт блоков, если они обнаруживают несколько экземпляров из них, но AFAIK тот, который я использую (IntelliJ), не делает этого.
При работе с большими файлами многие люди обычно смотрят только на свой локальный фрагмент кода, поэтому они могут локально импортировать что-то, что конфликтует с другими частями пакета (например, в одном классе Promise
импортируется из scala.concurrent
, а в другом - от akka.dispatch
), и это сложнее обнаружить, когда у вас есть импорт, посыпанный повсеместно.
Это может быть или не быть релевантным для вашей конкретной базы кода, но я лично склонен пессимистично относиться к коду, который я поддерживаю (энтропия и все такое), и поэтому стараюсь с самого начала вводить правила, которые гарантировали бы поддержку в длинных работать.
Изменить: удалено ссылка на ScalaStyle правило BlockImportChecker, которое не связано.
Ответ 5
Поместите импорт в верхнюю часть файла.
Наличие их разбросанных по всему файлу затрудняет чтение кода:
- Они не имеют никакого логического смысла, они просто псевдоним; таким образом, они "загрязняют" код, который отражает логический аспект программы.
- Нельзя ожидать, где их найти (для чего предназначены соглашения).
- В файлах с несколькими ссылками на объекты с тем же именем, но с другим пространством имен, трудно отслеживать, что это имя ссылается в каждой области.
Я не вижу преимущества в размещении их рядом с их ближайшей областью. Собственно, с учетом этих рассуждений никогда нельзя использовать их вообще; вместо этого всегда следует использовать полное пространство имен для каждого объекта, на который делается ссылка. Имеет ли это смысл? ИМХО, нет.