Стратегия передачи аргументов-переменные среды против командной строки
большинство приложений, которые пишут разработчики, должны быть внешне параметризованы при запуске. Мы проходим пути к файлам, имена трубу, протокол TCP/IP-адресов и т. д. До сих пор я использовал командная строка чтобы передать их в запущенное приложение. Мне пришлось разобрать командную строку main
и направьте аргументы туда, где они нужны, что, конечно, a хороший дизайн, но это трудно поддерживать для большого количества аргументов. Недавно я решил чтобы использовать переменные среды механизм. Они глобальны и доступны из любой точки мира, что менее элегантных С архитектурной точки зрения, но ограничивает размер кода.
Это мои первые (и, возможно, довольно поверхностные) впечатления от обеих стратегий, но я хотел бы услышать мнения более опытных разработчиков -- каковы взлеты и падения использования переменных среды и аргументов командной строки для передачи аргументов к процессу? Я хотел бы принять во внимание следующие вопросы:
- качество конструкции (гибкость / ремонтопригодность),
- ограничения памяти,
- переносимости раствора.
Примечания:
Ad. 1. Это главный аспект, который меня интересует.
Ad. 2. Это немного прагматично. Я знаю о некоторых ограничениях на Windows, которые в настоящее время огромный (более 32 Кб для командной строки и блока среды). Я думаю, это не проблема, так как вы просто должны использовать файл, чтобы передать тонны аргументов, если вам нужно.
Ad. 3. Я почти ничего не знаю о Unix, поэтому я не уверен, что обе стратегии так же полезны, как и в Windows. Уточните это, пожалуйста.
3 ответа:
1) я бы рекомендовал избегать переменных окружения как можно больше.
плюсы переменных окружения
- простота в использовании, потому что они видны из любого места. Если много независимых программ нуждаются в части информации, этот подход намного удобнее.
минусы переменных окружения
- трудно использовать правильно, потому что они видны (удалить-в состоянии, установить состоянии) из любой точки мира. Если я установлю новую программу, которая опирается на переменные среды, они будут топтать мои существующие? Я случайно не испортил свои переменные окружения, когда вчера дурачился?
мое мнение
- используйте аргументы командной строки для тех аргументов, которые, скорее всего, будут отличаться для каждого отдельного вызова программы (т. е. n для программы, которая вычисляет Н!)
- используйте конфигурационные файлы для аргументов, которые пользователь может разумно захотеть изменить, но не очень часто (т. е. размер дисплея, когда появляется окно)
- используйте переменные среды экономно-предпочтительно только для аргументов, которые, как ожидается, не изменятся (т. е. расположение интерпретатора Python)
- ваша точка
They are global and accessible from anywhere, which is less elegant from architectural point of view, but limits the amount of code
напоминает мне об обоснованиях для использования глобальных переменных ;)мои шрамы от переживания из первых рук ужасы чрезмерного использования переменной окружающей среды
- две программы нам нужны при работе, которые не могут работать на одном компьютере в то же время из-за экологических столкновения
- несколько версий программ с одинаковым именем, но разными ошибками-привели целую мастерскую на колени в течение нескольких часов, потому что местоположение программы было вытащено из окружающей среды и было (тихо, тонко) неправильно.
2) ограничения
Если бы я нажимал пределы либо того, что может содержать командная строка, либо того, что может обрабатывать среда, я бы немедленно рефакторинговал.
я использовал JSON в прошлом для приложения командной строки, которое требовало много параметров. Это было очень удобно, чтобы иметь возможность использовать словари и списки, а также строки и цифры. Приложение заняло всего несколько командных строк, одной из которых было расположение файла JSON.
преимущества такого подхода
- не нужно было писать много (болезненного) кода для взаимодействия с библиотекой CLI - это может быть боль, чтобы заставить многие из общих библиотек применять сложные ограничения (под "сложными" я имею в виду более сложные, чем проверка конкретного ключа или чередование между набором ключей)
- не нужно беспокоиться о требованиях библиотек CLI для порядка аргументов - просто используйте JSON объект!
- легко представлять сложные данные (отвечая
What won't fit into command line parameters?
), такие как списки- простота использования данных из других приложений - как для создания, так и для анализа программно
- легко для того чтобы приспособить будущие расширения
Примечание: Я хочу отличить это от того .подход к конфигурационному файлу -- это не для хранения конфигурации пользователя. Возможно, мне следует назвать это подходом "параметр-файл командной строки", потому что я использую это для программы, которая нуждается в большом количестве значений, которые не подходят хорошо в командной строке.
3) переносимость решения: я не знаю много о различиях между Mac, ПК и Linux в отношении переменных среды и аргументов командной строки, но я могу сказать вам:
- все три имеют поддержку переменных окружения
- все они поддерживают аргументы командной строки
Да, я знаю-это не очень полезно. Извините. Но ключевым моментом является то, что вы можете ожидайте, что разумное решение будет портативным, хотя вы определенно захотите проверить это для своих программ (например, чувствительны ли args командной строки к регистру на любых платформах? на всех платформах? Я не знаю).
последний вопрос:
Как упоминал Томаш, это не должно иметь значения для большинства приложений, откуда пришли параметры.
вы должны абстрактные параметры чтения с помощью стратегия узор. Создайте абстракцию с именем
ConfigurationSource
сreadConfig(key) -> value
метод (или возвращения некоторыхConfiguration
объект/структуру) со следующими реализациями:
CommandLineConfigurationSource
EnvironmentVariableConfigurationSource
WindowsFileConfigurationSource
- загрузка из конфигурационного файла изC:/Document and settings...
WindowsRegistryConfigurationSource
NetworkConfigrationSource
UnixFileConfigurationSource
- - загрузка из файла конфигурации от/home/user/...
DefaultConfigurationSource
по умолчанию- ...
вы также можете использовать цепи ответственности шаблон для цепочек источников в различных конфигурациях, таких как: если аргумент командной строки не указан, попробуйте переменную среды, а если все остальное не удается, верните дефолты.
Ad 1. Такой подход позволяет не только абстрагировать конфигурацию чтения, но и легко изменять базовый механизм без какого-либо влияния на клиентском коде. Также вы можете использовать несколько источников одновременно, отступая или собирая конфигурацию из разных источников.
Ad 2. Просто выберите, какая реализация подходит. Конечно, некоторые записи конфигурации не будут вписываться, например, в аргументы командной строки.
Ad 3. Если некоторые реализации не переносятся, есть два, один молча игнорируется / пропускается, когда он не подходит для данной системы.
Я думаю, что на этот вопрос уже достаточно хорошо ответили, но я чувствую, что он заслуживает обновления 2018 года. Я чувствую, что не упомянутое преимущество переменных окружающей среды заключается в том, что они обычно требуют меньше кода котельной плиты для работы. Это делает для более чистого более читаемого кода. Однако основным недостатком является то, что они удаляют слои изоляции из разных приложений, работающих на одной машине. Я думаю, что именно здесь Докер действительно сияет. Мой любимый шаблон дизайна используйте исключительно переменные среды и запустите приложение внутри контейнера Docker. Это устраняет проблему изоляции.