Upgrade to Pro — share decks privately, control downloads, hide ads and more …

脱・シェル芸!Taskで始めるイマドキ? Go開発

Avatar for ageha734 ageha734
September 25, 2025

脱・シェル芸!Taskで始めるイマドキ? Go開発

2025 年 9 月 17 日から公開されている DMM.go #11 のオンデマンドセッションにて登壇した「脱・シェル芸!Taskで始めるイマドキ? Go開発」の講演資料です。
詳細はこちらをご覧ください。(https://dmm.connpass.com/event/363839/

Avatar for ageha734

ageha734

September 25, 2025

Other Decks in Business

Transcript

  1. ⚠ はじめに:注意事項 この発表は、Makefile を批判するものではありません! Makefile は、非常に優れたツールです。 その歴史と実績に敬意を表します! この発表では、日々の開発タスク(ビルド、テスト、 Lint など)を管理する

    汎用タスクランナーという文脈 で、Task という、もう一つの快適な選択肢を 知ることを目的としています! 「適材適所」でツールを使い分けるための一つの提案 としてお聞きください!
  2. 目次 6 • その Makefile では、もう限界かも?  • Hello Task •

    Task の"私的お推し"ポイント! • 結局、何を使えばいいの? • まとめ 07p 09p 16p 40p 43p
  3. こんな「つらみ」、ありませんか? 8 😭 どのコマンドが何をするのか、もう誰も分からない秘伝のタレ化した Makefile … 😭 新しいメンバーにコマンド体系を説明するのが大変 … 😭

    「make 使い方」でググっても、コマンドばかりで公式ドキュメントにたどり着けない … 😭 タブとスペースを間違えて、謎のエラーと格闘 … 😭 Linux (GNU make) では動くのに、Mac (BSD make) だと微妙に動かない … 😭 そもそも Windows だと追加インストールが必要で環境構築が面倒 … そんな悩みを解決してくれる イケてるツール をご紹介します!
  4. 【動機】 Windows での make は面倒... 💡 依存関係なしで単一バイナリで、簡単に導入できるツールが欲しいな〜 💡 YAML ファイルを読み込んでコマンドをいくつか実行できるものないかな〜

    その当時探してみても、気に入ったものは見つからない 😭 そんなに難しいことなのだろうか? 開発者はこう思ってた! 14
  5. Task には様々なインストール方法があります! のほかに! 📦 brew install go-task/tap/go-task 📦 winget install

    Task.Task 📦 npm install @go-task/cli 📦 pip install go-task-bin 推しポイント①:マルチプラットフォーム 17 go install github.com/go-task/task/v3/cmd/task@latest
  6. 推しポイント②:設定ファイルのような明快さ 18 • YAMLで書ける! • GoDotEnv が内包されている! • vars で変数を宣言できる!

    • 記述後は task run で実行! • task --list でタスク一覧 説明( desc )を表示できる! version: '3' dotenv: ['.env'] vars: BINARY: bin/$APP_NAME/app tasks: run: desc: "アプリを動かす" cmds: - go run {{.BINARY}}
  7. Makefile と Task の比較してみると? 19 # Makefile -include .env export

    BINARY ?= bin/$APP_NAME/app .PHONY: run run: ## アプリを動かす go run {{.BINARY}} # Taskfile.yml dotenv: ['.env'] vars: BINARY: bin/$APP_NAME/app tasks: run: desc: "アプリを動かす" cmds: - go run {{.BINARY}}
  8. 推しポイント③: 防御力マシマシのタスクが作れる 20 • aliases で短いタスクで 実行できる! • preconditions コマンド実行前に

    前提条件をチェック 満たさなければエラーで 止めてくれる! • status で条件をチェック 満たしていればタスクを スキップしてくれる! tasks: generate: aliases: ['g'] preconditions: - sh: "[ -f go.mod ]" msg: "go.mod not found" - sh: "[ command -v mockgen ]" msg: "mockgen not command" status: - test -d test/mock cmds: - go generate ./...
  9. Makefile と Task の比較してみると? 21 # Makefile .PHONY: generate g

    generate: @[ -f go.mod ] || exit 1 @command -v mockgen >/dev/null 2>&1 || exit 1 @[ -d test/mock ] && exit 0 @go generate ./... g: generate # Taskfile.yml tasks: generate: aliases: ['g'] preconditions: - sh: "[ -f go.mod ]" msg: "go.mod not found" - sh: "[ command -v mockgen ]" msg: "mockgen not command" status: - test -d test/mock cmds: - go generate ./...
  10. 推しポイント④:ホットリロードができる 22 • watch:true この一行で ホットリロードが有効化! • sources にソースファイルを generates

    に生成物ファイルを 書くだけでファイルの変更を 監視できる! • exclude で監視対象から 除外できる! tasks: build: watch: true method: timestamp sources: - ./**/*.go - exclude: ./**/*_test.go cmds: - go build ./... generates: - app
  11. # Taskfile.yml tasks: build: watch: true method: timestamp sources: -

    ./**/*.go - exclude: ./**/*_test.go cmds: - go build ./... generates: - app Makefile と Task の比較してみると? 23 # Makefile TARGET_APP := app GO_FILES := $(shell find . -name '*.go' | grep -v '_test.go$$') .PHONY: build watch build: $(TARGET_APP) $(TARGET_APP): $(GO_FILES) go build -o $(TARGET_APP) main.go watch: @find . -name '*.go' | grep -v '_test.go$$' | entr -c make build
  12. includes で設定を分割・再利用! ルートの Taskfile.yml で 各サービスの Task を読み込める! 下記のコマンドで一括ビルド! (おまけ①)マイクロサービスでも活躍

    24 includes: user-api: ./services/user-api tasks: mod: desc: "依存関係を整理" cmds: - go mod tidy build:all: desc: "全サービスをビルドする " deps: mod cmds: - task: user-api:build task build:all
  13. (おまけ②)テンプレート ここがスゴい!テンプレート機能 🎁 動的な変数 {{.TIMESTAMP}} や {{.CLI_ARGS}} を利用して 実行時の情報を使って変数を動的に生成できる。 🎁

    環境依存の自動化 {{.OS}} (linux, darwin...) や {{.ARCH}} (amd64, arm64...) を利用して クロスコンパイルのコマンドを OS ごとに書く必要がなくなる。 🎁 組み込み関数 upper (大文字化) や split (文字列分割) などが用意されており、 シェルスクリプトで書いていたような文字列操作を Task 内だけで完結できる。
  14. (おまけ②)テンプレート dotenv: ['.env'] vars: PRODUCTION: $PRODUCTION VERSION: "1.2.3" FILENAME: {{.OS

    | trim}}-{{.ARCH}}-{{printf "v%s" .VERSION}}-$APP_NAME tasks: build: method: checksum sources: ['**/*.go'] status: - echo "{{.CHECKSUM}}" | cmp -s - bin/{{.FILENAME}}.checksum cmds: - go build -o bin/{{.FILENAME}} {{if .PRODUCTION}}-ldflags="-X main.revision={{.VERSION}}"{{end}} . - echo "{{.CHECKSUM}}" > bin/{{.FILENAME}}.checksum generates: - bin/{{.FILENAME}} - bin/{{.FILENAME}}.checksum
  15. 推しポイント⑤:実はコスパも良い! 27 もちろん導入コスト(学習・移行)はかかりますが … それ以上に、こんな人件費を削減できます! 💹 削減① (実行待機 ) Go製で高速に動作するので

    CI の待ち時間を短縮 💹 削減② (学習) ドキュメントもしっかりしているので理解しやすい 💹 削減③ (オンボーディング ) 新しいメンバーも task --list を見れば何があるのかがひと目で見れる
  16. 同じ一連のGoコマンド(lint, test, build, e2e)を、 💹 MacBook M4 16GB 💹 GitHub

    Actions(ubuntu-latest) Task と Makefile、シンプルシェルスクリプト各方法で実行し、 ジョブ全体の完了時間を比較しました。 https://github.com/ageha734/dmm-go-2025-09-17-go-task 実行時間を比較してみた 28
  17. つまり、1年でこれだけの「おトク」が! 35 (※ すべての実行時間が 1日30分と仮定) • 時間: 年間 約90時間 GET!

    (だいたい11日分の労働時間に相当!) (※ 時給5000円と仮定) • お金: 年間 約450,000円 浮く計算に! (MacBook M4 Pro 48GB、買えちゃいますね) これ、たった1人のエンジニアの話です。チームなら … 🤔
  18. 【状況:Go言語研修での出来事】 新卒研修で提供された神リポジトリは Makefile でタスクが管理されていました。 【課題:増殖するG】 ❓ カスタムコマンドの追加が必要になり、 Makefile やシェルを編集する。 しかし、どんどん複雑化していく、どこに何があるか分からなる。

    ❓ コマンド生成を Gemini に頼ると、一見動くものの、自分では理解できない おまじない のようなコマンドが増殖 …。 「もう無理!ちゃんと自分で管理できる仕組みにしたい! 」 なぜ導入に至ったのか 36
  19. 移行プロセスの3ステップ 🤖 既存のコードを丸投げ 複雑化した Makefile と複数のシェルスクリプトの中身を全部コピーして Gemini に贈呈 🤖 魔法の言葉をお願いする。

    「これを Task の作法に則って、読みやすく書き換えてください」と依頼 🤖 出力結果を微調整 Gemini が生成した Task をレビューし、細かい部分を修正して完成! どのように導入していったのか 37
  20. ① LLMの惜しい間違い Makefile の変数 $(VAR) と Task の変数 {{.VAR}} を混同するなど、

    一見動くけど実は違う、 微妙なシンタックスミス が生成されることがありました。 デバッグする過程で、 Task の正しいお作法を学ぶ必要 ② 翻訳するだけではダメな場面 Makefile の書き方をそのまま Task に移植しても、 Task の良さ(deps や status)を活かせないことに気づきました。 単なる「翻訳」ではなく、 Taskならどう設計するか?という「再設計」の視点が必要 もちろん、つまずいた点も… 38
  21. とにかく管理がめちゃくちゃ楽 になった 🙌 コマンドが一つの YAML ファイルに集約 され、見通しが最高! 🙌 実行時間の待ち時間が短縮できた! 🙌

    task --listで一覧できるので、もう「あのコマンドどこだっけ?」と探さなくなる 🙌 自分が理解・管理できるコマンドが増え、自信を持ってタスクを実行できる それでも、移行して本当に良かったこと 39
  22. 用途で使い分けるのが賢い選択肢 41 比較要素 Task が得意なこと Makefile が得意なこと 主な目的 ビルド・テスト・開発全般 C/C++

    コンパイラ 開発体験 watch によるホットリロード、 preconditions での事前チェックなど、開発を支援する 機能が豊富。 主要な Linux/macOS や CIランナーに標 準インストール済みが多い。 依存関係 キャッシュ機能があり、 depsでタスク間の 依存を定義。並列実行も簡単。 ファイルのタイムスタンプ を元にした厳 密な依存関係解決が得意。 ドキュメント 公式ドキュメント が非常に探しやすい。 機能がまとまっている。 記事や事例がネット上に膨大に存在す る。歴史が長い分、情報量は圧倒的。
  23. 💡 無理に置き換えない。共存の選択 Makefile から Task のコマンドを呼び出すことで、段階的な移行。 チーム内での併用が可能です。 💡 LLMに「壁打ち」してみる 既存の

    Makefile をどう Task に変換すれば良いか、 LLM に相談してみるのも良い方法 プロジェクトに合った Task の書き方を学ぶ良いキッカケになります。 【最終的な判断基準はこれ!】 「コスト削減」と「可読性」を最優先するなら ... ➡ Task を試す価値オオアリ 「環境の普遍性」と「既存資産」を最優先するなら ... ➡ Makefile を使い続けるのが合理的 明日から使えるTips & 判断基準 42
  24. 今日から task --init しよう! 44 ✅ YAML で宣言的に書けるため、誰でも読みやすくメンテナンスが容易! 👉 秘伝のタレになりやすい独自構文から脱却しよう。

    ✅ 差分ビルドや並列実行で、CI の実行時間を客観的に短縮! 👉 無駄な待ち時間を削減し、コストを節約。 task --init から始める快適な開発ライフ、あなたもいかがですか? 😉
  25. Task • Documentation ( https://taskfile.dev/ ) • GitHub ( https://github.com/go-task/task

    ) 比較・関連ツール • GNU Make ( https://www.gnu.org/software/make/manual/make.html ) • golangci-lint ( https://github.com/golangci/golangci-lint ) • gomock ( https://github.com/uber-go/mock ) 参考文献 46