最近の記事

Terraformコードのリソース名はスネークケースを使用する

ルール

Use snake_case for resource names in terraform code (e.g., web_server).

(Terraformコードのリソース名はスネークケースを使用する)

解説

Terraformのリソース名には通常スネークケースが用いられます。

AWS公式のベストプラクティスでもスネークケースの使用が推奨されています。

サンプルコード

# リソース名にスネークケースを使用
resource "aws_instance" "web_server" {
  instance_type = "t3.micro"
  ami           = var.ami_id
}

参考リンク

Infrastructure 開発ガイドライン Coding Standards

リソース名に複数形を使用しない

ルール

Do not use plural forms in resource names.

(リソース名に複数形を使用しない)

解説

特にこだわる所ではないため、素直にAWSの推奨に従っています。

なぜこのようになっているかは存じませんが、リソースによって複数形だったり単数形だったりするよりは、片方だけに統一されているほうが好ましいと考えます。

サンプルコード

# 良い例: 単数形を使用
resource "aws_instance" "web_server" {
  count         = 3
  instance_type = "t3.micro"
  ami           = var.ami_id
}

参考リンク

Infrastructure 開発ガイドライン Coding Standards

リソース名にリソースタイプ名を含めない

ルール

Do not include the resource type name in the resource name (e.g., avoid aws_instance.ec2_instance).

(リソース名にリソースタイプ名を含めない)

解説

二つの理由により、リソース名にリソースタイプ名を含めるべきではありません。

  1. リソースタイプを見ればわかることは書くべきでない
  2. 命名が雑になりやすい

悪い例としてはaws_instance.ec2_instance のような命名が該当します。

AWS公式のベストプラクティスでもこの命名規則が推奨されています。

サンプルコード

# 良い例: リソースタイプを重複させない
resource "aws_instance" "web_server" {
  instance_type = "t3.micro"
  ami           = var.ami_id
}

resource "aws_security_group" "api" {
  name   = "${var.environment}-${var.project}-api"
  vpc_id = aws_vpc.main.id
}

参考リンク

Infrastructure 開発ガイドライン Coding Standards

モジュール内の単一リソースは main と命名する

ルール

A single resource within a module should be named main (e.g., resource "aws_vpc" "main").

(モジュール内の単一リソースは main と命名する)

解説

モジュール内に特定のリソースタイプが一つしかない場合はリソース名を main とします。

採用の理由は「それがAWS推奨の手法だから」ですが、モジュール内の主要なリソース、またはそのリソースのための補助的な宣言であることが理解しやすいため従っておけばよいと考えます。

サンプルコード

# modules/vpc/main.tf
# VPCリソースが一つだけの場合は main と命名
resource "aws_vpc" "main" {
  cidr_block           = var.cidr_block
  enable_dns_hostnames = true
  enable_dns_support   = true
}

参考リンク

Infrastructure 開発ガイドライン Coding Standards

真偽値変数は肯定形で命名する

ルール

Name boolean variables affirmatively (e.g., enable_external_access).

(真偽値変数は肯定形で命名する)

解説

コードの可読性を向上させるため、変数は肯定形で記載します。

否定形を使用した二重否定(e.g., disable_logging = false) は読みづらいため避けます。

サンプルコード

variable "enable_external_access" {
  type        = bool
  description = "Enable external access to the resource"
}

参考リンク

Infrastructure 開発ガイドライン Coding Standards

AWSリソース名は環境名-プロジェクト名の形式で命名する

ルール

Name AWS resource names (Name tags) in the format [environment]-[project]([-additional_info_if_any]) (e.g., production-practitioner-api). In HCL, use variables like ${var.environment}-${var.project}-api. ‘api’ is just an example, so be sure to replace it appropriately.

(AWSリソース名(Nameタグ)は[環境名]-[プロジェクト名][-追加情報]の形式で命名する)

解説

これはプロジェクト独自の命名規則です。

環境名を先頭に配置することですぐにどの環境のリソースかわかるようにし、環境の取り違えを防止します。

またどのリソース名でも同一の命名規則を徹底することで、スクリプトなどを使った一括処理を行いやすくします。

サンプルコード

resource "aws_instance" "api" {
  ami           = "ami-12345678"
  instance_type = "t3.micro"

  tags = {
    Name = "${var.environment}-${var.project}-api"
  }
}

参考リンク

Infrastructure 開発ガイドライン Coding Standards

サブモジュールにproviderやterraformブロックを含めない

ルール

Do not include provider or terraform in submodules.

(サブモジュールにproviderterraformブロックを含めない)

解説

プロバイダー設定はルートモジュールで一括管理します。そのためサブモジュールでproviderやterraformブロックを利用してはいけません。

Terraformの公式ベストプラクティスでも推奨されている設計原則です。

サンプルコード

# production/providers.tf(ルートモジュールで定義)
terraform {
  required_version = ">= 1.5.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

Infrastructure 開発ガイドライン Coding Standards

Spec Driven(仕様駆動開発)をspec-kitで試してみる 1

github/spec-kitが公開されました。AI駆動開発の本命であろう仕様駆動開発の標準化に貢献するであろうこのプロジェクトにはとても注目しています。

論理的帰結としての仕様駆動開発

かつて私も仕様書を元にAIに作成させる方法を自著の同人誌で提案したことがあります。やはり有利なのです。

まず大前提として、生成AIに作業をさせるためにはプロンプトが必要です。そのプロンプトは明確かつ必要十分の情報を保有していることが望ましいです。

そして開発プロジェクトにおいて「明確かつ必要十分の情報を保有している」プロンプトすなわちテキストとは、つまるところ仕様書です。仕様書とは設計やコーディングに必要な情報を明確かつ必要十分に記載したテキストなのですから。――常に実現できているとは限りませんが、目指してはいます。

である以上、

「いっそプロンプトとして仕様書を渡してしまえばいい

という発想に至るのは自然な帰結でしょう。

AIに渡すプロンプトを毎回作るのは大変ですし、再現性も低いという問題があります。これはバイブコーディングの泣き所でもあります。ですが仕様書を渡すスタイルなら何度でも書き終えた仕様書を渡せば済むわけです。再利用も簡単、追跡性もばっちりです。

Go言語を用いた開発プロジェクトに仕様駆動開発を導入することの課題とソリューションの登場

さて、前述の技術同人ではIaCを仕様駆動開発(と言う名前ではありませんでしたが)で実用にたるレベルで実行することができていました。これには下記の要因があります。

  1. コードの規模が小さく単純 : Terraform用コードの生成であったためコードの規模がさほど大きくなく、また分岐等のロジックもごくわずかでした
  2. ベストプラクティスが豊富に用意されている : Terraformのコーディングは公式やAWSがベストプラクティスを用意しており、これをそのまま使うことで高品質の成果物を作成することが可能です。
  3. 単独開発者 : 想定が私一人でも回る規模であったため、チーム内教育のことを考えなくて済みました。

ところがこの成功体験をもとにGoプロジェクトで仕様駆動開発を実践しようとすると問題が生じました。上の条件の逆で、コードの規模が大きく複雑、取りうるアーキテクチャ・ライブラリ・ツールの数も多く、またチーム開発を想定する必要があったのです。これは必要なプロンプト(=ドキュメント)の量を増やし、開発体制の整備にかかる時間をIaCだけのケースよりはるかに大きなものとし、しかもチーム内教育への考慮まで要求されることとなりました。

これらの課題を地力で頑張って乗り切ることは、不可能ではないまでも多大な時間を要し、かつそこまでしても普及させられると思えず、ありていに言ってあまり割に合わない作業になりそうに思えました。

そのような状況で登場したのがKiroや今回のSpec Kit等、大手が提示するツールやプロジェクトです。まだ実験的な性格も強いようですが、おそらく開発体制の充実度合いや運用保守の強固さなどから、このタイプの提示する仕様駆動開発の採用が堅い選択になるのではないかと考えられます。

個別に最適化したほうがプロジェクトにフィットさせられるのでしょうが、現実的には、多くのプロジェクトでは人の入れ替わりや開発リソースの限界などの要因によってそう簡単ではありません。技術的な理想ではなくとも、運用や教育などの面まで含めた総合的判断においては、既存のソリューションを利用するほうがベストとなるケースが多いことでしょう。

かなり前置きが長くなりましたが、このようなわけで、独自開発ではなく既存プロジェクトに乗る方向で仕様駆動開発を試していきます。spec-kitです。

AI駆動開発

Spec Driven(仕様駆動開発)をspec-kitで試してみる 2

前回は「仕様駆動開発が本命。でも自前実装は大変だから既存ソリューションのSpec Kitを利用することにした」と言うところまでお話しました。

早速Spec Kitの基本から見ていきます。

インストールと初期設定

uvxをインストールし、

curl -LsSf https://astral.sh/uv/install.sh | sh

spec-kitのインストールと初期設定。既存プロジェクトに導入するためここではプロジェクト指定を--hereとしています。

cd cognito-example/
uvx --from git+https://github.com/github/spec-kit.git specify init  --here

下記のような状態になりました

~/repositories/cognito-example$ tree -a
.
├── .claude
│   └── commands
│       ├── constitution.md
│       ├── implement.md
│       ├── plan.md
│       ├── specify.md
│       └── tasks.md
├── .specify
│   ├── memory
│   │   └── constitution.md
│   ├── scripts
│   │   └── bash
│   │       ├── check-implementation-prerequisites.sh
│   │       ├── check-task-prerequisites.sh
│   │       ├── common.sh
│   │       ├── create-new-feature.sh
│   │       ├── get-feature-paths.sh
│   │       ├── setup-plan.sh
│   │       └── update-agent-context.sh
│   └── templates
│       ├── agent-file-template.md
│       ├── plan-template.md
│       ├── spec-template.md
│       └── tasks-template.md
└── cognito-example.code-workspace

基本のワークフロー

Spec Kitのコマンドは2025/09/21時点で5つ。READMEからそのまま引き写しますが、下記のようになっています。

AI駆動開発

Goを用いたAI駆動開発のための開発環境整備: gofumpt 編

Goのフォーマッター「gofumpt」について解説します。

生成されたコードのチェックを自動化しよう

生成AIを使ってコーディングを自動化すると開発作業を大きく効率化することができます。しかし一方で、レビューの負担という新たな問題も生じています。 生成されたコードの品質は一般にまちまちで、差があるものです。これらを全て人力で修正していたのでは多大な時間がかかってしまい、せっかくAIで効率化した意味が減殺されてしまいます。チェックと修正自体も自動化しないといけないわけです。

コードスタイル(フォーマット)を機械的にチェック・修正できるフォーマッタは、生成AIが活躍するようになった現在においても大いに威力を発揮します。コードスタイルの些細な違いは動作に影響しませんが、可読性や保守性の観点からぜひ統一したいものです。

「フォーマッタが正しい」で割り切る簡便さ

また開発プロジェクトからはまだまだ人が完全にいなくなったわけではありません。チーム開発となると複数名の開発者が参加します。このときコードスタイルをどのように決めるかは悩ましい課題となりがちです。

コードスタイルには個々の好みが出ます。括弧の位置や空行の入れ方程度のことですら個々の「こうしたい」があるのです。プロジェクトの都度合意を得るために何度もやりとりするのも大変です。それらをそれぞれが譲らず自分の好みで書き始めると収拾がつかなくなってしまいます(そしてそうなったのであろうコードを見ることも時折あります)。

その点「フォーマッタが正しい。以上」で決めてしまえば公正です。あらかじめ決まったルールを使えばいいため議論の必要もありません。しかも自動でコードスタイルを整えてくれるため、レビューの際に些細な改行の違いなどを見つけるために目を皿のようにする必要もなくなります。ただCIでフォーマッタの実行を保証すればよいだけになるのです。

標準を超えた整形ルールを提供するgofumpt

そのようなわけで、Goの開発環境を整えるための施策の一つとして、フォーマッタ「gofumpt」を導入します。これはよりリッチになったgofmtと考えればよく、より厳格で豊富なフォーマットルールを適用します。例えば次のような処理をしてくれます。

  • 括弧位置の統一
  • 不要な空行の削除
  • コメントの余白の修正

詳細は公式に紹介されているため、気になる方はそちらをご参照ください。

シンプルな導入手順と基本的な使い方

gofumptのインストールは以下のコマンドで行えます。ここでは簡単なlatestで紹介していますが、プロダクト用途なら意図せぬ動作変更がないようバージョンを指定したほうが安定します。

# プロダクト用途ならバージョン指定を推奨
go install mvdan.cc/gofumpt@latest

以下のコマンドでファイルをフォーマットできます。

# 単一ファイルのフォーマット
gofumpt -w main.go

# ディレクトリ内の全Goファイルをフォーマット
gofumpt -w .

ワークフローを記したファイルにコマンドを記載しておけば、AIエージェントがよろしくやってくれるはずです。ただし確実に行われることを保証するためCIにも組み込むほうがよいです。

実行例

どのようなフォーマットが行われるのかご紹介します。まずこちらはgofumptを適用する前のコード。

整形前のコード(sample_before.go):

package main

var V interface {
} = 3

type T struct {
}

func foo() (any, error) {

	return nil, nil

}

func bar() {

	_, err := foo()

	if err != nil {

		return err
	}

}

それが処理をかけるとこのようになりました。

Go開発環境