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

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

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

Ответы [ 8 ]

18 голосов
/ 02 апреля 2009

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

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

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

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

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

13 голосов
/ 03 апреля 2009

Если бы сам Гвидо объявил, что следует придерживаться соглашения об обратном домене, он не будет принят, если только не произойдут существенные изменения в реализации 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, и так далее, и так далее, но это значительно усложняет упаковку, устраняет возможность перетаскивания и создает неудобства при упаковке.

12 голосов
/ 02 апреля 2009

«По каким причинам вы бы предпочли одно другому?»

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

«Применимы ли эти причины к языкам?»

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

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

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

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

Java-люди не предвидели, что сообщество Open Source выберет необычные уникальные имена, чтобы избежать коллизий имен. Любопытно, что каждый, кто пишет парсер xml, не называет это парсером. Кажется, они называют это «саксонским» или «ксаланским» или что-то совершенно странное.

11 голосов
/ 03 апреля 2009

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

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

Хорошо, все получилось не совсем так, как надеялся Сун, но они планировали так, как будто добьются успеха. Лично я презираю проекты, которые могут быть подорваны успехом.

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

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

11 голосов
/ 02 апреля 2009

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

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

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

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

6 голосов
/ 02 апреля 2009

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

2 голосов
/ 02 апреля 2009

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

По сути, я думаю, что Python разработан для идеи, что вы хотите сделать что-то без необходимости задавать или вводить слишком много заранее. Это очень помогает при использовании сценариев и командной строки. Существует несколько разделов «Дзен Питона», которые объясняют это:

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

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

  • Пространства имен - одна из замечательных идей - давайте сделаем больше таких!
0 голосов
/ 02 апреля 2009

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

...