Азбука переносимости: именование проектов

Удивительно, но можно насоздавать проблем для переносимости и пакетирования ПО проекта даже не написав ни строчки кода, а просто неудачно его назвав.

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

TL;DR

  • Будьте изобретательны выбирая название проекту, и проверяйте его уникальность во избежание конфликтов имён сейчас и в будущем. Не используйте короткие названия и названия из одного простого слова.
  • Выбирайте название совместимое с используемыми в большинстве пакетных систем ограничениями - [a-z0-9-]+ (в нижнем регистре), не слишком длинное, используйте префикс lib для библиотек.
  • Используйте единственное написание названия в разных частях проекта - в названии репозитория, именах дистрибутивов, системе сборке, документации и устанавливаемых в систему файлах и каталогах чтобы никого не запутать.

Выбирайте уникальное название

Так сложилось, что в *никс мире имена программ обычно попадают в единое пространство имён в пакетном репозитории и на файловой системе (т.е. исполняемые файлы всего установленного ПО в один каталог bin/, то же касается библиотек и конфигурационных файлов).

С одной стороны, это удобно, потому что к софту можно обратиться просто по названию, без указания каких-то уточняющих квалификаторов. Например, установить просто firefox без указания что это какой-нибудь org.firefox.firefox, или запустить просто firefox без указания полного пути. С другой стороны, в такой схеме не исключаются конфликты имён, когда никак не связанные проекты носят одно название.

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

Чтобы избежать конфликтов, проверьте что выбранное для проекта название уже кем-то не используется хотя бы в следующих сервисах:

  • Repology, которая ведёт мониторинг большинства пакетных систем, а поэтому знает почти все используемые названия пакетов. Отдельно можно проверить https://repology.org/project/<name> - там будут видны названия удалённых пакетов, которых не видно в обычном поиске.
  • Репозитории, каталоги и магазины приложений не покрытые Repology, такие как, например, Google Play или App Store.
  • GitHub на тему используемых названий репозиториев.
  • Других хостинги кода, в том числе и те где остались в основном заброшенные проекты (которые, тем не менее, могут в какой-то момент продолжить развитие): Launchpad, Savannah, SourceForge. В Debian есть не очень поддерживаемый скрипт который проверяет их автоматически. Есть также расширенный список источников для него.
  • Обычные поисковики. Ведь в идеале имеет смысл обеспечить уникальность названия не только среди программных продуктов, но и вообще, с тем чтобы пользователи по одному лишь названию могли сразу найти ваш проект.

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

  • не использовать короткие названия из 5 или менее символов;
  • не использовать имена из одного простого слова (ski, slack, slice, slim, slime, smack…).

А вот примеры конфликтов названий (от Repology, которой известны сотни их).

  • clementine (музыкальный проигрыватель, оконный менеджер)
  • clog (утилита управления changelog, утилита просмотра логов, библиотека для логгирования, tcp логгер)
  • et (eternal terminal, egg timer, enemy territory)
  • grip (cd ripper, markdown previewer, gambas previewer, поисковый движок, движок компьютерного зрения)
  • kup (утилита для бэкапа из KDE, kernel.org upload tool)
  • lux (две различных утилиты управления яркостью, движок полнотекстового поиска, утилита обновления ядра)
  • mars (две различных игры, MIPS Assembler and Runtime Simulator, ПО для органической химии, некая runtime system)
  • nomad (конфигуратор беспроводных соединений, кластерный оркестратор, браузер, утилита для Active Directory)
  • pcl (библиотека корутин, point cloud library)
  • sdb (игра, встраиваемая БД, клиент некоего демона sdbd в tizen, библиотека хэш-таблиц, клиент отладчика для mono)

Выбирайте название совместимое с пакетами

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

  • Не использовать верхний регистр.

  • Использовать - как разделитель слов в названии.

    Package names SHOULD be in lower case and use dashes in preference to underscores.
    Fedora Naming Guidelines

  • Не использовать символы помимо алфавитно-цифровых и минуса ([a-z0-9-]+)

    When naming packages for Fedora, the maintainer MUST use the dash ‘-’ as the delimiter for name parts. The maintainer MUST NOT use an underscore ‘_’, a plus ‘+’, or a period ‘.’ as a delimiter
    Fedora Naming Guidelines

  • Если вы пишете библиотеку, имеет смысл добавить префикс lib в официальное название.

    Пакет должен иметь название lib%name%abiversion
    Alt Linux Shared Libs Policy (Russian)

  • Не добавлять название языка программирования к имени проекта (как, например, в python-twitter).

    В этом случае возможность конфликта имён появляется уже среди модулей этого языка (здесь: с модулем twitter). Помимо этого, большинство репозиториев добавляют свой префикс для модулей (как-то py-, python-, py39- и т.д.) из-за чего python-twitter-dateutil может стать либо странным python-python-twitter (мантейнер сохранил оригинальное название, добавив обязательный префикс), либо исказиться до, например, py3-twitter (двойной префикс схлопнут, оригинальное название искажено). В последнем случае всё ещё сильнее усложняется если в репозиторий попытаться добавить И пакет модуля twitter.

Примеры искажений названий проектов для соответствия политикам именования пакетов:

  • libc++libcxx
  • freetypelibfreetype
  • python-dateutilpython-python-dateutil, py-dateutil

Используйте единообразное написание названия

Другая частая ошибка - неконсистентное написание названия в разных контекстах (название репозитория; файл дистрибутива; упоминания внутри проекта, в системе сборки, в документации; имя исполняемого файла или файла библиотеки, каталога с заголовочными файлами; имя пакета с учётом ограничений перечисленных в предыдущей главе).

Ошибка может проявляться в использовании различающийся капитализации (ddnet vs. DDNet), разделителей (dd-rescue, dd_rescue, ddrescue), использования сокращений (garden-of-coloured-lights vs. garden, speech-dispatcher vs. speechd, src-highlite vs. source-highlight), упоминания эпох развития проекта (mandelbulber vs. mandelbulber2), и ведёт всё к тем же неожиданным и неконсистентным именованиям в репозиториях.

Примеры на которые можно равняться:

  • diff-so-fancy, репозиторий https://github.com/so-fancy/diff-so-fancy, распространяется как diff-so-fancy и устанавливает исполняемый файл diff-so-fancy.
  • libvirt, репозиторий https://gitlab.com/libvirt/libvirt, сайт https://libvirt.org/, устанавливает библиотеку libvirt.so и заголовочные файлы include/libvirt/*.h.

Ссылки