小山氏が自作、CLIツールのケーススタディを紹介
ここからは、ケーススタディとして小山氏の自作CLIツールを紹介する。
1例目は、さまざまなメトリクスを取得し、調査するためのツール「sheer-heart-attack」だ。「よく分からないがCPU利用率が上昇するタイミングがある。今度CPU利用率が80%を超えた時にtopコマンドの結果をとりたい」のような場合に使える。実行するとバックグラウンドプロセスを起動し、指定時間だけサーバのメトリクスを監視する。また、事前に設定した条件に数値が達すると任意のコマンド実行やSlack通知も行える。このような機能は頻繁に使うものではないため、「sheer-heart-attack launch」だけを覚えて、後はインタラクティブモードで「○○を入力してください」などと入力を促すようにした。これにより、ユーザは複雑なコマンドを覚えなくて済む。
2例目は、ログの中から特定のキーワードだけ目立つように着色する「colr」だ。これは文字を「目立たせたい」という目的を考慮し、あえて色を指定する機能は作らず、引数で色付けしたい単語を列挙してもらう形にした。
3例目は「octocov」でコードメトリクスの計測ツールだ。主にCI(GitHub Actions)のAPIで使用されるが、ローカルで使うことも可能だ。機械のユースケースをメインにしつつ、人も使えるように環境変数で挙動を変更できるようにしている。
CLIツールはどう設計する?──Webアプリケーションの原則パターンをCLIに応用
ここで、CLIツールとWebアプリケーションを比較してみよう。Webアプリケーションの入出力はHTTPであり、CLIツールもほとんどの場合、入出力が決まっている。どちらも目的に合わせた機能を備えているが、CLIツールにはWebアプリケーションと異なる特性もある。例えば、CLIツールは実行場所が不特定多数で、実行完了とともにプロセスが終了する。また、不特定多数のユーザからの入力を同時に受け付けることはない。Web-DBのように影響が閉じた構成になることはなく、外部の要素へ作用することが多い点も特徴だ。
入出力が決まっていて、実装すべきビジネスロジックも定義できる点では、CLIツールはWebアプリケーションと同じである。したがって小山氏は、「CLIツールでもWebアプリケーションのプラクティスをそのまま使える」と話す。
ただし実際のところ、CLIツールはUNIX哲学に従い「1つのことをうまくやる」ように実装されている。そのためEntitiesやUse Casesは小さくなりがちだ。しかしPresentersとなるコマンドは自明なので、だいたい同じ構成になる。「また、Gatewaysは外部要素へ作用する機能を持つことが多いため、多様性が生まれやすい」と小山氏は説明する。
そのため、ツールとしての実装デザインについて、小山氏は「CLIツールの特性により、重点的に実装を考えるレイヤーが変わることがよくありますが、Webアプリケーションと同じアーキテクチャパターンや原則はそのまま活用できます。これは断言できます。パターンや原則に則れば問題ありません」と言う。
ここで、実装デザインのケーススタディを見ていこう。1点目は「tbls」だ。これは多種多様なデータベースに接続して、データベーススキーマドキュメントを生成するツールである。どのデータベースでも同じスキーマドキュメントを生成する必要があるため、Gatewaysが大活躍する。
「Webアプリケーション議論でよくある『DBを置き換えるなんてアプリケーションの寿命から見ても存在しない』ということにはならず、むしろ増えていく。ちゃんとレイヤー分けして整備してよかった」(小山氏)
2点目は先述したコードメトリクスの計測・収集ツール「octocov」だ。収集したメトリクスをGitHubのプルリクエストにコメントする以外にも、AWS S3やGoogle Cloud Storageなどさまざまなデータストアにレポートできるため、1つのレポジトリで閉じることなく事業やプロジェクトを横断して集計できることがメリットだ。「レポート」で抽象化した上で、多くのAPIに対応させている。ここでもGatewaysは大盛況だ。
3点目は「evry」だ。これは流れるログを時間や行で区切るためのツールである。絶え間なくストリームで流れてくるログを手早く見たい場合に、例えば「3秒間隔でカウントしたい」「1000行ごとに統計を取りたい」などの要望を実現する。ログはストリーム形式であるため、標準入力の計算コストをできるだけ小さくしてリアルタイムで処理できるよう、入力から出力までのパイプライン式のデータ構造になっている。他にも、データベースに接続しているパケットをキャプチャするなど、流量の多いデータを処理する時に有効だ。
このツールは「標準入力でうけとって標準出力に結果を返す」という動きだけをみるとシンプルだが、リアルタイムに処理をしていく必要がある。下図では、青の矢印の流れを止めない実装が必要だ。これを実現するため、「入力と出力」というイメージよりも、「入力から出力」というパイプラインを組むようなデザインになっている。このようなアーキテクチャは、CLIツールのユースケースではよく見られるそうだ。
最後に小山氏は「CLIツールは画面のない単純なプログラムと思われがちですが、自分でデザインする際に考慮すべき点は多いです。より良いユーザ体験を提供するため、Webアプリケーションに勝るとも劣らないデザイン設計が必要なんです。今回紹介した事例が、皆さんがCLIツールを開発する時の助けになれば幸いです」と述べ、セッションを締めくくった。