脱・シェル芸!Taskで始めるイマドキ? Go開発
by
ageha734
×
Copy
Open
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Slide 1
Slide 1 text
@ageha734 脱・シェル芸! Taskで始めるイマドキ? Go開発
Slide 2
Slide 2 text
名前:日比 恵多(ひび けいた) 所属:プラットフォーム開発本部 認可チーム 登壇者 2
Slide 3
Slide 3 text
⚠ はじめに:注意事項 この発表は、Makefile を批判するものではありません! Makefile は、非常に優れたツールです。 その歴史と実績に敬意を表します! この発表では、日々の開発タスク(ビルド、テスト、 Lint など)を管理する 汎用タスクランナーという文脈 で、Task という、もう一つの快適な選択肢を 知ることを目的としています! 「適材適所」でツールを使い分けるための一つの提案 としてお聞きください!
Slide 4
Slide 4 text
このパートの目的 4 ● Makefile での「あるある」を共有し、その解決策として Task を知ってもらう ● ほんの僅かでも、「プロジェクトで使ってみたい! 」と思ってもらう
Slide 5
Slide 5 text
このパートで説明するもの 5 ● Task の基本的な概念と、Makefile との違い ● Task を導入してみての知見の共有
Slide 6
Slide 6 text
目次 6 ● その Makefile では、もう限界かも? ● Hello Task ● Task の"私的お推し"ポイント! ● 結局、何を使えばいいの? ● まとめ 07p 09p 16p 40p 43p
Slide 7
Slide 7 text
その Makefile では、も う限界かも? 7
Slide 8
Slide 8 text
こんな「つらみ」、ありませんか? 8 😭 どのコマンドが何をするのか、もう誰も分からない秘伝のタレ化した Makefile … 😭 新しいメンバーにコマンド体系を説明するのが大変 … 😭 「make 使い方」でググっても、コマンドばかりで公式ドキュメントにたどり着けない … 😭 タブとスペースを間違えて、謎のエラーと格闘 … 😭 Linux (GNU make) では動くのに、Mac (BSD make) だと微妙に動かない … 😭 そもそも Windows だと追加インストールが必要で環境構築が面倒 … そんな悩みを解決してくれる イケてるツール をご紹介します!
Slide 9
Slide 9 text
Hello Task 9
Slide 10
Slide 10 text
一言で言うと、Go言語で作られたビルドツール です。 ❤ YAML でシンプルに書ける! ❤ クロスプラットフォーム対応している! ❤ Gopher と相性がいい! Task って何? 10
Slide 11
Slide 11 text
Discord で直接聞いてみました。 【質問内容】 1. Task を開発したきっかけや動機は? 2. 具体的にどのような問題や課題を 解決しようとしていましたか? なぜ生まれたの? 11
Slide 12
Slide 12 text
Discord で直接聞いてみました。 【質問内容】 1. Task を開発したきっかけや動機は? 2. 具体的にどのような問題や課題を 解決しようとしていましたか? なぜ生まれたの? 12
Slide 13
Slide 13 text
Discord で直接聞いてみました。 【質問内容】 1. Task を開発したきっかけや動機は? 2. 具体的にどのような問題や課題を 解決しようとしていましたか? なぜ生まれたの? 13
Slide 14
Slide 14 text
【動機】 Windows での make は面倒... 💡 依存関係なしで単一バイナリで、簡単に導入できるツールが欲しいな〜 💡 YAML ファイルを読み込んでコマンドをいくつか実行できるものないかな〜 その当時探してみても、気に入ったものは見つからない 😭 そんなに難しいことなのだろうか? 開発者はこう思ってた! 14
Slide 15
Slide 15 text
【開発】 休暇中の2日間で作成した。 【リリース】 2017年に最初の PoC を動作に Reddit の /r/golang に投稿し v1.0.0 がリリースされました だからTaskを作った! 15
Slide 16
Slide 16 text
Task の"私的お推し" ポイント! 16
Slide 17
Slide 17 text
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
Slide 18
Slide 18 text
推しポイント②:設定ファイルのような明快さ 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}}
Slide 19
Slide 19 text
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}}
Slide 20
Slide 20 text
推しポイント③: 防御力マシマシのタスクが作れる 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 ./...
Slide 21
Slide 21 text
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 ./...
Slide 22
Slide 22 text
推しポイント④:ホットリロードができる 22 ● watch:true この一行で ホットリロードが有効化! ● sources にソースファイルを generates に生成物ファイルを 書くだけでファイルの変更を 監視できる! ● exclude で監視対象から 除外できる! tasks: build: watch: true method: timestamp sources: - ./**/*.go - exclude: ./**/*_test.go cmds: - go build ./... generates: - app
Slide 23
Slide 23 text
# 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
Slide 24
Slide 24 text
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
Slide 25
Slide 25 text
(おまけ②)テンプレート ここがスゴい!テンプレート機能 🎁 動的な変数 {{.TIMESTAMP}} や {{.CLI_ARGS}} を利用して 実行時の情報を使って変数を動的に生成できる。 🎁 環境依存の自動化 {{.OS}} (linux, darwin...) や {{.ARCH}} (amd64, arm64...) を利用して クロスコンパイルのコマンドを OS ごとに書く必要がなくなる。 🎁 組み込み関数 upper (大文字化) や split (文字列分割) などが用意されており、 シェルスクリプトで書いていたような文字列操作を Task 内だけで完結できる。
Slide 26
Slide 26 text
(おまけ②)テンプレート 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
Slide 27
Slide 27 text
推しポイント⑤:実はコスパも良い! 27 もちろん導入コスト(学習・移行)はかかりますが … それ以上に、こんな人件費を削減できます! 💹 削減① (実行待機 ) Go製で高速に動作するので CI の待ち時間を短縮 💹 削減② (学習) ドキュメントもしっかりしているので理解しやすい 💹 削減③ (オンボーディング ) 新しいメンバーも task --list を見れば何があるのかがひと目で見れる
Slide 28
Slide 28 text
同じ一連の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
Slide 29
Slide 29 text
数値で見る(ローカル環境: E2E) 29 【2回目実行時】 7秒ほど 早くなっている 【1回目実行時】 実行時間に変わり あまり見受けられない
Slide 30
Slide 30 text
数値で見る(ローカル環境: E2E) 30 【2回目実行時】 7秒ほど 早くなっている 【1回目実行時】 実行時間に変わり あまり見受けられない
Slide 31
Slide 31 text
数値で見る(ローカル環境: E2E) 31 【2回目実行時】 7秒ほど 早くなっている 【1回目実行時】 実行時間に変わり あまり見受けられない
Slide 32
Slide 32 text
10回の実施検証結果では、 Task が最も速いという結果になりました 数値で見る(GitHub Actions: CI) 32
Slide 33
Slide 33 text
10回の実施検証結果では、 Task が最も速いという結果になりました 【実行内容】 💹 Dockerでのサービス起動 💹 DBセットアップ 💹 APIテスト 数値で見る(GitHub Actions: E2E Test) 33
Slide 34
Slide 34 text
で、結局どれくらいおトクなの? 34 💰 チリツモが効く! --parallel で並列実行するだけで、 毎日の小さな待ち時間がごっそりなくなる! 一回数秒の差が、一年経てば大きなリターンになる。 💰 待ちガチな重い処理が爆速に!( E2E Test) Deps による依存関係の解決で、 一番ボトルネックだった処理が半分以下の時間に! もうコーヒーを淹れにいく必要はありません。
Slide 35
Slide 35 text
つまり、1年でこれだけの「おトク」が! 35 (※ すべての実行時間が 1日30分と仮定) ● 時間: 年間 約90時間 GET! (だいたい11日分の労働時間に相当!) (※ 時給5000円と仮定) ● お金: 年間 約450,000円 浮く計算に! (MacBook M4 Pro 48GB、買えちゃいますね) これ、たった1人のエンジニアの話です。チームなら … 🤔
Slide 36
Slide 36 text
【状況:Go言語研修での出来事】 新卒研修で提供された神リポジトリは Makefile でタスクが管理されていました。 【課題:増殖するG】 ❓ カスタムコマンドの追加が必要になり、 Makefile やシェルを編集する。 しかし、どんどん複雑化していく、どこに何があるか分からなる。 ❓ コマンド生成を Gemini に頼ると、一見動くものの、自分では理解できない おまじない のようなコマンドが増殖 …。 「もう無理!ちゃんと自分で管理できる仕組みにしたい! 」 なぜ導入に至ったのか 36
Slide 37
Slide 37 text
移行プロセスの3ステップ 🤖 既存のコードを丸投げ 複雑化した Makefile と複数のシェルスクリプトの中身を全部コピーして Gemini に贈呈 🤖 魔法の言葉をお願いする。 「これを Task の作法に則って、読みやすく書き換えてください」と依頼 🤖 出力結果を微調整 Gemini が生成した Task をレビューし、細かい部分を修正して完成! どのように導入していったのか 37
Slide 38
Slide 38 text
① LLMの惜しい間違い Makefile の変数 $(VAR) と Task の変数 {{.VAR}} を混同するなど、 一見動くけど実は違う、 微妙なシンタックスミス が生成されることがありました。 デバッグする過程で、 Task の正しいお作法を学ぶ必要 ② 翻訳するだけではダメな場面 Makefile の書き方をそのまま Task に移植しても、 Task の良さ(deps や status)を活かせないことに気づきました。 単なる「翻訳」ではなく、 Taskならどう設計するか?という「再設計」の視点が必要 もちろん、つまずいた点も… 38
Slide 39
Slide 39 text
とにかく管理がめちゃくちゃ楽 になった 🙌 コマンドが一つの YAML ファイルに集約 され、見通しが最高! 🙌 実行時間の待ち時間が短縮できた! 🙌 task --listで一覧できるので、もう「あのコマンドどこだっけ?」と探さなくなる 🙌 自分が理解・管理できるコマンドが増え、自信を持ってタスクを実行できる それでも、移行して本当に良かったこと 39
Slide 40
Slide 40 text
結局、 何を使えばいいの? 40
Slide 41
Slide 41 text
用途で使い分けるのが賢い選択肢 41 比較要素 Task が得意なこと Makefile が得意なこと 主な目的 ビルド・テスト・開発全般 C/C++ コンパイラ 開発体験 watch によるホットリロード、 preconditions での事前チェックなど、開発を支援する 機能が豊富。 主要な Linux/macOS や CIランナーに標 準インストール済みが多い。 依存関係 キャッシュ機能があり、 depsでタスク間の 依存を定義。並列実行も簡単。 ファイルのタイムスタンプ を元にした厳 密な依存関係解決が得意。 ドキュメント 公式ドキュメント が非常に探しやすい。 機能がまとまっている。 記事や事例がネット上に膨大に存在す る。歴史が長い分、情報量は圧倒的。
Slide 42
Slide 42 text
💡 無理に置き換えない。共存の選択 Makefile から Task のコマンドを呼び出すことで、段階的な移行。 チーム内での併用が可能です。 💡 LLMに「壁打ち」してみる 既存の Makefile をどう Task に変換すれば良いか、 LLM に相談してみるのも良い方法 プロジェクトに合った Task の書き方を学ぶ良いキッカケになります。 【最終的な判断基準はこれ!】 「コスト削減」と「可読性」を最優先するなら ... ➡ Task を試す価値オオアリ 「環境の普遍性」と「既存資産」を最優先するなら ... ➡ Makefile を使い続けるのが合理的 明日から使えるTips & 判断基準 42
Slide 43
Slide 43 text
まとめ 43
Slide 44
Slide 44 text
今日から task --init しよう! 44 ✅ YAML で宣言的に書けるため、誰でも読みやすくメンテナンスが容易! 👉 秘伝のタレになりやすい独自構文から脱却しよう。 ✅ 差分ビルドや並列実行で、CI の実行時間を客観的に短縮! 👉 無駄な待ち時間を削減し、コストを節約。 task --init から始める快適な開発ライフ、あなたもいかがですか? 😉
Slide 45
Slide 45 text
No content
Slide 46
Slide 46 text
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