1 ポイント 投稿者 GN⁺ 2026-02-02 | 1件のコメント | WhatsAppで共有
  • レポート生成アプリケーションの開発過程で --dry-run オプションを追加し、実行結果をシミュレーションできるようにした事例
  • このオプションは実際の変更を行わずにどのような処理が実行されるかを出力し、安全なテストと迅速なフィードバックを可能にする
  • 開発者はこれにより設定やアクセス可否、システム状態を即座に確認し、日常的な検証ツールとして活用できる
  • コード内で dryRun フラグを確認しなければならない多少の複雑さの増加が欠点として挙げられている
  • 命令型アプリケーションでは --dry-run 機能が非常に有用であり、プロジェクト初期に導入するほど開発効率が高まる

背景

  • 新たに開発中の レポート生成アプリケーションは、平日ごとに毎日レポートを生成し、それを圧縮して sftp サーバーにアップロードし、エラー応答を確認して通知メールを送信する構成
    • 各段階で生成されたファイルとフィードバックファイルは、段階ごとに異なるディレクトリへ移動される
  • 開発初期に、Subversion と複数の Linux コマンドの --dry-run オプションを思い出し、同じ機能を追加
    • このオプションは実際の変更を行わずに、実行時に何が起こるかを出力する
  • --dry-run 実行時には、生成されるレポートと除外されるレポート、圧縮および移動されるファイル、sftp でアップロードおよびダウンロードされる対象ファイルを段階ごとに出力

活用と利点

  • 開発およびテストの過程で毎日使うほど有用な機能
  • 実行前の状態確認用として使うと、設定やアクセス可否、システム状態を即座に確認できる
    • 実際の変更がないため、安全に実行できる
  • レポート状態ファイルの日付を変更した後、そのレポートが生成されるかどうかを 即座に確認できる
    • 実際のレポート生成には時間がかかるが、dry-run は迅速なフィードバックを提供する
  • システム全体のテスト時にも 高速な検証ループを提供

欠点

  • コード内で dryRun フラグを繰り返し確認しなければならないため、多少コードが汚れる
    • 主な段階ごとにフラグを検査し、実際の実行の代わりにログだけを出力する
  • ただしこの確認は深い階層には及ばず、レポート生成ロジック内部では別途の処理は不要
    • 実行可否を決める上位段階でのみ確認する

結論

  • 命令的に実行され結果を生成するアプリケーションは --dry-run オプションと相性が良い
    • 一方で、メッセージを待つ反応型アプリケーションには適していない
  • プロジェクト初期に追加したことが 開発効率の向上に大きく役立った
  • あらゆる状況で必要な機能ではないが、適切な場合には非常に有用なツールと評価される

1件のコメント

 
GN⁺ 2026-02-02
Hacker Newsのコメント
  • 状態を持つシステムとやり取りする場合、--dry-run にも 競合状態(race condition) が起こりうる
    現在の状態でツールが「何をするか」を示しても、実際の実行時には状況が変わっている可能性がある
    そのため私は Terraform の plan モード方式を好む。このモードでは実行可能な計画を作成しておき、計画時点の前提が変わっていたら中断またはロールバックできる
    また、コード中のあちこちに if dry_run: を入れずに済み、計画と実行を分離して execute(plan()) の形に単純化できる

    • 以前あった AWS DNS 障害の事例 も、これに近い競合状態が原因だった
      DNS Planner と Enactor の間のタイミング問題により、古い計画が最新の計画を上書きしてしまった
      関連する話は 以前の HN スレッド でも扱われていた
    • こうなると結局、コンパイラ(仕様→計画)仮想マシン(計画→実行) を実装することになる
    • Terraform や Ansible のようなインフラツールには理想的だが、単純なレポートツールには 過剰な複雑さ を招くことがある
      計画モードを作るにはドメイン固有言語やデータ構造が必要だからだ
    • 私も機密性の高いファイルを編集するスクリプトを作っていて、この方式を適用している
      (1) ファイルシステムの状態をキャプチャして計画を保存 → (2) 状態が変わっていないことを確認してから実行し、ログを記録 → (3) 以前の状態と比較してデータ損失がないか検証
      この 3 段階をそれぞれ別のスクリプトやフラグとして分離して使っている
    • だとすると、rm コマンドにこうした計画モードをどう適用できるのか気になる
  • あるツールに --dry-run がないときは、自分で作って使うこともある
    たとえば複雑な sed コマンドを実行する前に、diff を使って変更内容をあらかじめ比較する
    diff -u <(echo "hello") <(echo "hello" | sed "s/hello/hi/g") のように差分を確認できる
    関連する内容は 私のブログ にまとめてある

  • --dry-run パターンは好きだが、ドライラン経路のコードが実際の経路と同じように動作する 必要がある
    単に「何をするか」を出力して実際のロジックを飛ばしてしまうと、本番実行時のバグを見逃す可能性がある
    データベース書き込みや API 呼び出しの直前までは同じように実行されるべきだ

    • ただ、これを 統合テストとドライランの混同 だと見る人もいる
      ドライランは「何が起こるか」を示すものであり、実際のテストは別の領域だ
  • 私は逆に --commit--execute フラグを用意して、デフォルト実行を 読み取り専用(dry) にしておく方式を好む
    こうすると、誤って実際の変更を起こしてしまう可能性が減る

    • この方式を過去 8 年使ってきたが、変更は --commit を明示したときだけ起こるので安全だった
      一方で --dry-run を付け忘れて実行し、事故になったことは何度もあった
    • 私の ディレクトリ重複排除ツール もこのパターンに従っている
      デフォルトでは比較だけを行い、--execute を使って初めて実際にハードリンクへ置き換える
    • 以前使っていたツールの中には、実行前に特定の文言を入力させるものもあった
      こうした確認手順はミスを減らすのに効果的だ
    • 個人的には --wet-run のようなフラグも好きだ。状況によっては、反対の意味を持つフラグのほうが直感的なこともある
    • 最近作ったスクリプトはデフォルトが読み取り専用で、実際に削除するには DELETE-ACCOUNT を手入力しなければならない
      今のところ、一度も誤ってアカウントを削除したことはない
  • コード汚染を防ぐには、永続化(persistence) を注入可能な戦略として分離すべきだ
    あちこちに if dry_run: を入れるのはよくない
    むしろ本番実行を --wet-run で明示するほうが安全だ

    • アプリケーションの 振る舞いを明示的にモデル化 し、それを中央で処理するようにするとよい
      そうすればドライランかどうかの判定を 1 か所だけに集約できる — いわゆる “functional core, imperative shell” スタイルだ
    • ただし、毎回 rm --wet-run tempfile.tmp のように入力するのは面倒だ
      デフォルトは実行ありにして、その代わり --undo オプションで最後の操作を取り消せるほうがよいかもしれない
    • --wet-run という名前は気に入らないが、デフォルトを dry-run にして、--no-dry-run を明示しないと変更が起きない方式も使ったことがある
      サービスなら、実行環境(dev/prod)に応じて自動的に安全モードを選ぶのが理想的だ
    • こういう場合は デザインパターン を活用すると構造をきれいに保てる
  • 記事では「初期に --dry-run を追加したら意外と有用だった」と書かれていたが、
    実際にはこうしたフラグは AI コーディングエージェント(例: Claude) が自動提案することも多い
    最近多くの CLI ツールが似たパターンを持つのは、こうした エージェント主導のコード収束現象 のせいかもしれない

    • ただし筆者は Subversion の --dry-run に触発されたと明言していたので、十分に納得できる理由だと思う
  • 私は CLI ユーティリティに --really フラグを追加して、デフォルトを読み取り専用にすることがある
    ミス防止のため、意図的な確認手順 を要求するわけだ

    • 以前には --i-meant-that フラグを持つコマンドもあった
      リモートマシンを削除するコマンドで、デフォルトでは 10 秒待機してキャンセルの機会を与える
      幸い、このフラグが誤って使われたことはなかった
  • PowerShell の優れた点の 1 つは、[CmdletBinding(SupportsShouldProcess)] を 1 行追加するだけで
    自動的に -WhatIf ドライラン機能が使えるようになることだ。非常に 便利な機能

    • さらに -Confirm も同時に有効になり、ShouldProcess 関数を通してユーザーの 確認しきい値 と連携できる。本当に見事な設計だ
  • 私が管理している社内 CLI では、if not dry_run:REST API 呼び出し部分 の中に置いている
    こうすると実際の呼び出しの代わりに CURL コマンドのログ を残せるので、どんなリクエストが送られるか確認できる
    ただし API 間連携が複雑になるとシミュレーションは難しくなり、単純な if not dry_run: よりはるかに複雑になってしまう

    • できるだけ 実際の動作を 1 か所だけで行う ように構造化すれば、コード汚染を防げる
      私も自動化パイプライン向け CLI を多数保守しているが、このパターンをほぼすべてのツールに適用している
    • ただし、コンソールツールで REST を多用しすぎるのは非効率だという意見もある
      まずはローカルツールをきちんと作るべきだ、という主張だ
  • --dry-run フラグがコード全体に散らばっているなら、状態機械パターン を適用して各段階を明確に分離するのがよい