Создавайте продуманные интерфейсы командной строки
Интерфейс командной строки имеет тенденцию усложняться со временем, вбирая в себя новые опции по мере того, как Вы добавляете новые возможности в приложение. К сожалению, редко эти интерфейсы разрабатываются с учётом их развития, развитие их не контролируется. Таким образом новые флаги, опции и аргументы, принимаемые приложением добавляются для конкретного случая (ad hoc) и не согласованы между собой.
Это также означает, что флаги, опции и аргументы разных приложений, написанных Вами, не похожи друг на друга. Результатом неизбежно будет набор программ, каждая из которых управляется особым и не похожим ни на что образом. Например:
> orchestrate source.txt -to interim.orc
> remonstrate +interim.rem -interim.orc
> fenestrate --src=interim.rem --dest=final.wdw Invalid input format
> fenestrate --help Unknown option: --help. Type 'fenestrate -hmo' for help
Здесь утилита orchestrate ожидает имя входного файла в качестве первого аргумента, а с помощью флага -to указывается выходной файл. Другой инструмент из того же набора, remonstrate
в отличие от предыдущей программы, использует опции -infile и +outfile. А программа fenestrate, похоже, требует "длинные опции" в GNU-стиле: --src=infile и --dest=outfile, кроме, очевидно, странно обозначенного флага для получения помощи. В конце концов, это просто беспорядок!
Когда Вы предоставляете комплект программ, все они должны иметь сходный интерфейс -- предоставлять те же флаги, опции и те же стандартные возможности. Это позволяет пользователям Ваших программ извлечь преимущество из уже имеющихся знаний, вместо того, чтобы постоянно задавать Вам вопросы.
Эти три программы должны работать, например, так:
> orchestrate -i source.txt -o dest.orc
> remonstrate -i source.orc -o dest.rem
> fenestrate -i source.rem -o dest.wdw Input file ('source.rem') not a valid Remora file (type "fenestrate --help" for help)
> fenestrate --help fenestrate - convert Remora .rem files to Windows .wdw format Usage: fenestrate [-i <infile>] [-o <outfile>] [-cstq] [-h|-v] Options: -i <infile> Specify input source [default: STDIN] -o <outfile> Specify output destination [default: STDOUT] -c Attempt to produce a more compact representation -h Use horizontal (landscape) layout -v Use vertical (portrait) layout -s Be strict regarding input -t Be extra tolerant regarding input -q Run silent --version Вывести информацию о версии --usage Вывести краткую инструкцию по запуску --help Получить эту справку --man Вывести подробное руководство
Здесь каждое приложение, которому требуется входной и выходной файл, использует для этого одинаковые флаги. Пользователь, который хочет использовать утилиту substrate utility (для конвертации .wdw-файла в процедуру) вероятно сможет угадать корректный синтаксис требуемой команды:
> substrate -i dest.wdw -o dest.sub
Те, кто не сможет этого угадать, вероятно могут догадаться использовать команду
> substrate --help
для получения помощи.
Существенная часть работы по проектированию интерфейсов состоит в том, чтобы придать единообразие различным компонентам этого интерфейса. Вот некоторые соглашения, которые могут помочь Вам в проектировании последовательного и предсказуемого интерфейса:
Требуйте наличие флага перед каждым элементом данных командной строки, исключая, возможно, имена файлов
Пользователи не настроены запоминать, что Ваше приложение требует указания "входного файла, выходного файла, размера блока, вида операции, стратегии обработки ошибок", причём указания всех этих данных в строгом порядке:
> lustrate sample_data proc_data 1000 normalize log
Они хотят иметь возможность явно указать то, что они хотят, причём в удобном для них порядке::
> lustrate sample_data proc_data -op=normalize -b1000 --fallback=log
Предоставьте также флаги для каждого имени файла, особенно если файлы это могут использоваться программой для различных целей.
Пользователи также могут быть не в восторге от того, что им нужно помнить в каком порядке указываются различные имена файлов. Так что позвольте им также добавлять метки для этих аргументов и указывать их в том порядке, в котором они предпочитают:
> lustrate -i sample_data -op normalize -b1000 --fallback log -o proc_data
Используйте одиночный дефиса (-) в качестве префикса для флагов, заданных в сокращённой форме, до трёх символов включительно (-v, -i, -rw, -in, -out).
Опытные пользователи ценят сокращённые флаги, т.к. нужно меньше набирать на клавиатуре. Не используйте двойной дефис для этих сокращённых флагов.
Используйте двойной дефис (--) в качестве префикса для длинных наименований флагов (--verbose, --interactive, --readwrite, --input, --output).
Флаги, являющиеся полными словами улучшают читаемость команд (например, в shell-скриптах). Двойные дефисы также помогают отличить длинные имен флагов от расположенных рядом имён файлов.
Если флаг ожидает ассоциированное с ним значение, предоставьте опциональный знак = между именем флага и его значением.
Одни люди предпочитают визуально ассоциировать значение с предшествующим ему флагом::
> lustrate -i=sample_data -op=normalize -b=1000 --fallback=log -o=proc_data
Другие нет:
> lustrate -i sample_data -op normalize -b1000 --fallback log -o proc_data
А некоторые могут предпочитать смешивать эти два стиля:
> lustrate -i sample_data -o proc_data -op=normalize -b=1000 --fallback=log
Предоставьте им возможность выбора.
Предусмотрите возможность "компоновки" нескольких однобуквенных флагов в один (используя один дефис).
Иногда раздражает печатать дефисы для целой серии флагов:
> lustrate -i sample_data -v -l -x
Разрешите опытным пользователям также писать:
> lustrate -i sample_data -vlx
предоставляйте многобуквенную версию для каждого однобуквенного флага.
Сокращённые формы флагов хороши для опытных пользователей, но они могут вызывать затруднения у новичков: тяжело запомнить и ещё труднее понять. Не вынуждайте людей напрягаться. Дайте им более понятную многословную альтернативу для сокращённого флага; полные слова легче запомнить и легче понять, т.к. они сами себя документируют в shell-скриптах.
Всегда допускайте - в качестве специального имени файла.
Широко используемое соглашение состоит в том, чтобы указывать дефис (-) на месте имени входного файла, что означает "считать со стандартного ввода", и дефис на месте имени выходного файла, что означает "вывести на стандартный вывод".
Всегда допускайте -- в качестве ограничителя перед именами файлов.
Другое широко используемое соглашение состоит в том, что использование двойного дефиса (--) в командной строке означает конец указание любых флагов / опций и означает, что все оставшиеся аргументы являются именами файлов, даже если некоторые из них выглядят как флаги.