56355


# 背景

PythonでCLIツールを作成しています。  
[aws-cli](https://github.com/aws/aws-
cli)のような、外部サービスにアクセスするCLIツールです。以下のようにコマンドを実行します。

[code]

    # ユーザusr1を登録
    $ mycli register_user --user_id usr1 --user_info "{'name': 'alice`}"
    
    # usr1,usr2,usr3に関する詳細情報を出力する
    $ mycli print_users --user_id usr1 usr2 usr3
    
[/code]

コマンドライン引数のパースには、[argparser](https://docs.python.org/ja/3/library/argparse.html)モジュールを利用しています。

# 悩んでいること

CLIツールのサブコマンドやオプションの設計に悩んでいます。  
例えば、以下のような内容です。

### サブコマンド名やオプション名の命名規則

  * アンダースコア区切り？ハイフン区切り？
  * 複数の値を受け取ることができる（1個でもOK）オプション名は単数形？複数形？ `--user alice bob` or `--users alice bob`

### オプション

  * 使わない方が良い（競合しやすい）オプション名（`-h`?）

### その他

  * 標準入力の使いどころ。ファイルで渡すか標準入力で渡すか
  * 引数の順番（例：コピー元、コピー先の順）

# 質問

CLIツールに関して、ベターパターンやアンチパターン、標準や慣習が記載されているサイトがありましたら、教えていただきたいです。  
「command line interface design pattern」で検索してみましが、私が期待するサイトが見つかりませんでした。


CC BY-SA 4.0
2019-07-03T01:56:17.310
56335
2019-07-04T01:38:12.760
2019-07-04T01:36:19.250
19524
19524
question
python command-line
CLIツールのベターパターン/アンチパターンを教えてください


アンチ(ベター)パターンがあるのか分かりませんが、Linuxでよく使われるオプション名などは  
「linux command long option」などで検索すると参考になるかもしれません。

以下はあくまで個人的な意見として

>   * アンダースコア区切り？ハイフン区切り？
>   * 複数の値を受け取ることができる（1個でもOK）オプション名は単数形？複数形？
>

少しでもキーボードのタイプ数を減らしたいので、(Shiftキーを押しながらの)アンダースコアより **ハイフン区切り** 、複数の値を取りうる場合も
**単数形** を使いたいです。  
ただし後者は「1個または複数」の値を取りうる場合で、「常に複数」の値を取るなら複数形でもいいのかもしれません。

> 使わない方が良い（競合しやすい）オプション名（-h?）

オプションはそれぞれのコマンドが解釈するものなはずなので、「競合」という状態がよく分からないです。そのコマンドで必要なオプションが自然と説明できる名前を付ければいいのではないでしょうか。

おっしゃる通り`-h`はヘルプ表示によく使われますが、他にも「引数なしでコマンド実行」や「manマニュアル」などでヘルプを提供する場合もあり、`-h
HOSTNAME`のように他の意味に割り当てているコマンドもあります。

> 標準入力の使いどころ。ファイルで渡すか標準入力で渡すか

**そのコマンドがどのように振る舞うのか次第** ではないでしょうか (パイプラインで繋いで他のコマンドから入力を受け取りたいのか否か)。

> 引数の順番（例：コピー元、コピー先の順）

例に挙げられた「コピー」などの例は「元、先」の順がほとんどなので、似た動作を行うコマンドを想定しているなら、既存のコマンドに習うべきでしょう。  
利用するユーザーも既存の知識をベースにコマンドが振る舞うことを期待すると思うので、ここで齟齬があると実行するコマンドによっては取り返しのつかない不幸が簡単に起きます。


CC BY-SA 4.0
2019-07-03T12:33:38.257
56355
2019-07-03T12:33:38.257
3060
56335
answer


最初に考えることは、どれくらいのオプションの数になるのかです。
オプション数が少ないのであれば、デザインを深く考える必要はありません。(不必要に一文字オプションと、自己説明的なオプションで同じ意味を持たせるのは、個人的にはオーバーエンジニアリングだと思います。)

ツールが多機能でもっと複雑になる場合は、全体のデザインを考えて、全体を通して一貫したコマンド体系にする必要があります。唯一の例外は "help".

まず、コマンドの基本的なパターンが、

[code]

    CLI-command action [sub-action] parameters
    
[/code]

だとします。 action が最初にきて、sub-action
がある場合があり、残りは全てactionで使うパラメタです。コマンドの動作は最初の引き数で決定します。例えば、二つのファイルを取り、何かを変換して出力するとします。

[code]

    your-command convert -input in-file-1 -input in-file-2 -output out-file
    
[/code]

この例で、 help を表示する場合、

[code]

    your-command help convert
    your-command convert help
    
[/code]

は、同じヘルプメッセージを表示するように、全体を設計します。
コマンドラインだけでなく、それぞれのアクション、サブアクションがプログラムの中で自然に構成できるように書き、ヘルプもそれに従うように作ります。Linux
のパッケージマネジャーなどがよく使うパターンです。action は - を使わず、パラメタは -を付けることをお勧めします。

コマンドを、

[code]

    your-command [parameter] action
    
[/code]

の形にすると、一つのアクションが、複数のターゲットに適用する場合にコマンド入力するのが非常に不便なので、避けます。基本的に一つのターゲットを取るのは、特殊な場合と考えるようにします。

[code]

    your-command convert -input in-file-1 -input in-file-2 -output out-file-1 -- -input in-file-3 -input in-file-4 -output out-file-2
    
[/code]

のようなコマンドが書けると、コマンドの有用性が上がります。 (例： curl）

入力、出力がファイルの場合、できるだけ stdin/stdout を使えるようにすることをお勧めします。 '-' を指定された場合、stdin/stdout
を使います。


CC BY-SA 4.0
2019-07-03T13:36:59.053
56358
2019-07-04T01:38:12.760
2019-07-04T01:38:12.760
19524
34969
56335
answer