Почему такие языки, как Java, используют иерархические имена пакетов, а Python - нет?

Я не занимался корпоративной работой на Java, но часто вижу соглашение об именах имен доменов с обратным доменом. Например, для пакета Qaru Java вы поместите свой код под пакетом com.stackoverflow.

Я просто столкнулся с пакетом Python, который использует Java-подобное соглашение, и я не был уверен, что это за аргументы и против него, или применимы ли они к Python так же, как Java. Каковы причины, по которым вы предпочитаете друг друга? Имеют ли эти причины разные языки?

Ответы

Ответ 1

Если сам Гвидо объявил, что следует придерживаться соглашения об обратном домене, он не будет принят, если не будут существенные изменения в реализации import в python.

Рассмотрим: python ищет путь импорта во время выполнения с отказоустойчивым алгоритмом; java ищет путь с исчерпывающим алгоритмом как во время компиляции, так и во время выполнения. Вперед, попробуйте упорядочить свои каталоги следующим образом:

folder_on_path/
    com/
        __init__.py
        domain1/
            module.py
            __init__.py


other_folder_on_path/
    com/
        __init__.py
        domain2/
            module.py
            __init__.py

Затем попробуйте:

from com.domain1 import module
from com.domain2 import module

Именно одно из этих утверждений будет успешным. Зачем? Потому что либо folder_on_path, либо other_folder_on_path выше на пути поиска. Когда python видит from com., он захватывает первый com пакет, который он может. Если это будет содержать domain1, то первый import будет успешным; если нет, он выбрасывает ImportError и отказывается. Зачем? Поскольку import должен выполняться во время выполнения, потенциально в любой момент потока кода (хотя чаще всего в начале). Никто не хочет, чтобы в этот момент была исчерпывающая древовидная прогулка, чтобы проверить, нет ли возможного соответствия. Предполагается, что если он найдет пакет с именем com, это пакет com.

Кроме того, python не различает следующие утверждения:

from com import domain1
from com.domain1 import module
from com.domain1.module import variable

Понятие о том, что com является com, будет различным в каждом случае. В java вам действительно нужно иметь дело со вторым случаем, и это можно сделать, пройдя через файловую систему (я предполагаю, что преимущество классов и файлов имен одинаково). В python, если вы попытались выполнить импорт только с помощью файловой системы, первый случай мог (почти) быть прозрачным одинаковым ( init.py не запускался), второй случай может быть выполнен, но вы потеряете первоначальный запуск module.py, но третий случай полностью недостижим. Код должен быть доступен для variable. И это еще один важный момент: import делает больше, чем разрешает пространства имен, он выполняет код.

Теперь вы можете избежать этого, если каждый пакет python, когда-либо распространенный, потребовал установки, которая искала папку com, а затем domain и т.д. и т.д., но это делает упаковку значительно сложнее, разрушает возможности перетаскивания и делает упаковку и всевозможную неприятность.

Ответ 2

Python не делает этого, потому что у вас заканчивается проблема - кому принадлежит пакет com, который почти все остальное является подпапкой? Метод Python для создания иерархии пакетов (через иерархию файловой системы) не совсем хорошо сочетается с этим соглашением. Java может уйти от него, потому что иерархия пакетов определяется структурой строковых литералов, поданных в оператор "package", поэтому нет необходимости в явном пакете "com".

Также возникает вопрос, что делать, если вы хотите публично выпустить пакет, но не владеете доменным именем, подходящим для привязки к имени пакета, или если вы в конечном итоге меняете (или теряете) свое доменное имя для некоторая причина. (У более поздних обновлений требуется другое имя пакета? Откуда вы знаете, что com.nifty_consultants.nifty_utility - это более новая версия com.joe_blow_software.nifty_utility? Или, наоборот, откуда вы знаете, что это не более новая версия? продление домена и имя получает захват домена кемпер, а кто-то покупает у них имя, и они хотят публично выпускать пакеты программного обеспечения, должны ли они использовать то же имя, которое вы уже использовали?)

Имена доменов и имена пакетов программ, как мне кажется, затрагивают две совершенно разные проблемы и имеют совершенно разные усложняющие факторы. Мне лично не нравится Java-конвенция, потому что (IMHO) он нарушает разделение проблем. Устранение конфликтов пространства имен приятно и все, но я ненавижу мысль о том, что пространство имен программного обеспечения определяется (и зависит от) взаимодействие отдела маркетинга с какой-то сторонней бюрократией.

Чтобы пояснить мою точку зрения, в ответ на комментарий JeeBee: в Python пакет представляет собой каталог, содержащий файл __init__.py (и предположительно один или несколько файлов модулей). Иерархия пакетов требует, чтобы каждый пакет более высокого уровня был полным, законным пакетом. Если два пакета (особенно из разных поставщиков, но даже не связанных напрямую с ним пакетов от одного и того же поставщика) используют имя пакета верхнего уровня, является ли это имя "com" ​​или "web" или "utils" или что-то еще, должен предоставить __init__.py для этого пакета верхнего уровня. Мы также должны предположить, что эти пакеты, вероятно, будут установлены в одном и том же месте в дереве каталогов, т.е. Site-packages/[pkg]/[subpkg]. Таким образом, файловая система гарантирует, что есть только один [pkg]/__init__.py - так какой выигрывает? На этот вопрос нет (и не может быть) правильного ответа на общий случай. Мы также не можем разумно объединить два файла вместе. Поскольку мы не можем знать, что может потребоваться в другом пакете __init__.py, подпакеты, совместно использующие пакет верхнего уровня, не могут считаться работающими, когда они установлены, если они специально не написаны, чтобы быть совместимыми друг с другом (по крайней мере, в этот один файл). Это будет кошмар распределения и в значительной степени аннулирует всю точку вложенности пакетов. Это не относится к иерархиям пакетов обратного домена, хотя они являются наиболее очевидным плохим примером, и (ИМО) являются философски сомнительными - это действительно практическая проблема общих пакетов верхнего уровня, а не философских вопросов, которые моя главная забота здесь.

(С другой стороны, один большой пакет с использованием подпакетов для лучшей организации себя - отличная идея, поскольку эти подпакеты специально разработаны для совместной работы и совместной работы. Однако это не так распространено в Python, поскольку один концептуальный пакет не требует большого количества файлов, требующих дополнительного уровня организации.)

Ответ 3

"Каковы причины, по которым вы предпочитаете друг друга?"

Стиль Python проще. Стиль Java позволяет использовать одноименные продукты из разных организаций.

"Применяются ли эти причины на разных языках?"

Да. Вы можете легко получить пакеты Python верхнего уровня с именами "com", "org", "mil", "net", "edu" и "gov" и поместить ваши пакеты в качестве подпакетов в них.

Edit. У вас есть определенная сложность, когда вы это делаете, потому что каждый человек должен сотрудничать и не загрязнять эти пакеты верхнего уровня своей собственной рывкой.

Python не начал этого делать, потому что столкновение пространства имен - как практическое дело - оказывается довольно редким.

Java начала это делать, потому что люди, которые разработали Java, предвидели много людей, которые невольно выбрали одно и то же имя для своих пакетов и нуждались в том, чтобы разобраться в столкновениях и проблемах с владением.

Java-люди не предвидели, что сообщество Open Source выбрало странные уникальные имена, чтобы избежать конфликтов имен. Интересно, что каждый, кто пишет XML-парсер, не называет его "парсером". Кажется, они называют это "саксонский" или "Xalan" или что-то совершенно странное.

Ответ 4

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

Отменив имя домена, он также дает ему иерархическую структуру, которая удобна. Таким образом, вы можете иметь подпакеты в конце.

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

Почему, например, не делают библиотеки JavaScript? Их глобальное пространство имен является большой проблемой, но библиотеки Javascript используют простые глобальные идентификаторы, такие как "$", которые сталкиваются с другими библиотеками Javascript.

Ответ 5

Где-то в Joel on Software Джоэл сравнивает два метода выращивания компании: метод Бен и Джерри, который начинается небольшим и растет органично, и метод Amazon для привлечения большого количества денег и подачи очень широких требований с самого начала.

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

ОК, это не получилось так, как надеялось Sun, но они планировали, как будто они преуспеют. Лично я презираю проекты, которые могут быть подорваны успехом.

Первоначально Python был проектом Гвидо ван Россума, и довольно давно было уверенно, что он выживет, если ван Россум попадет в автобус. По-моему, не было никаких первоначальных планов захватить мир, и он не был предназначен как язык веб-апплетов.

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

Ответ 6

Идея состоит в том, чтобы избежать конфликтов в пространстве имен. Вместо нечитаемых UUID и т.п. Обратное доменное имя вряд ли попадет кому-то другим способом. Очень просто, но прагматично. Более того, при использовании сторонних библиотек он может дать вам представление о том, откуда они пришли (для обновлений, поддержки и т.д.).

Ответ 7

У Python есть это, это просто более плоская иерархия. Посмотрите os.path, например. И там ничто не останавливает разработчиков библиотеки, делающих гораздо более глубокие, например. Джанго.

В принципе, я думаю, что Python разработан по идее, что вы хотите получить материал без необходимости указывать или вводить слишком много заранее. Это очень помогает при использовании сценариев и командной строки. Есть несколько частей "The Zen of Python", в которых говорится об этом:

  • Простой лучше, чем сложный.
  • Плоский лучше, чем вложенный.
  • Красивая лучше, чем уродливая. (Система Java выглядит уродливо для меня.)

С другой стороны, есть:

  • Пространства имен - одна хорошая идея - позвольте сделать еще больше!

Ответ 8

Java может сделать это так, так как это рекомендуемая стандартная практика Java и почти универсально принятая сообществом Java. У Python dos нет этого соглашения.