# 命名規則

## 一般的な規則

{% hint style="info" %}
少なくともこれらの規則には従うべきですよ :)
{% endhint %}

{% hint style="info" %}
クラウドリソースの実際の名前には、多くの場合、使用可能な名前に制限があることに注意してください。例えば、一部のリソースではダッシュ（-）を含めることができなかったり、キャメルケースでなければならなかったりします。本書で説明する規則は、Terraform自体の名前に関するものです。
{% endhint %}

1. リソース名、データソース名、変数名、出力など、すべての場所で `-`（ダッシュ）の代わりに `_`（アンダースコア）を使用してください。
2. UTF-8がサポートされていても、小文字とアルファベットを使用することを推奨します。

リソースとデータソースの引数

1. リソース名にリソースタイプを（部分的にも、完全にも）繰り返さないでください：

{% hint style="success" %}

```
`resource "aws_route_table" "public" {}`
```

{% endhint %}

{% hint style="danger" %}

```
`resource "aws_route_table" "public_route_table" {}`
```

{% endhint %}

{% hint style="danger" %}

```
`resource "aws_route_table" "public_aws_route_table" {}`
```

{% endhint %}

2. より説明的で一般的な名前が利用できない場合、またはリソースモジュールがこのタイプのリソースを1つだけ作成する場合（例えば、[AWS VPCモジュール](https://github.com/terraform-aws-modules/terraform-aws-vpc)では `aws_nat_gateway` タイプのリソースは1つだけで、`aws_route_table` タイプのリソースは複数あるため、`aws_nat_gateway` は `this` という名前にし、`aws_route_table` には `private`、`public`、`database` のようなより説明的な名前をつけるべき）、リソース名は `this` にすべきです。
3. 名前には常に単数名詞を使用してください。
4. 引数の値の中や、人が目にする場所（例：RDSインスタンスのDNS名）では、`-`（ハイフン）を使用してください。
5. リソースまたはデータソースのブロック内で、`count`/`for_each`引数を最初の引数として一番上に記述し、その後に改行を入れて区切ってください。
6. リソースでサポートされている場合は`tags`引数を実質的な最後の引数として記述し、必要に応じてその後に`depends_on`と`lifecycle`を続けてください。これらはすべて空行1行で区切ってください。
7. `count`/`for_each`引数で条件を使用する場合は、`length`やその他の式を使用するのではなく、ブール値を使用することを推奨します。

## `resource`のコード例

### `count`と`for_each`の使用方法

{% hint style="success" %}
{% code title="main.tf" %}

```hcl
resource "aws_route_table" "public" {
  count = 2

  vpc_id = "vpc-12345678"
  # ... 残りの引数は省略
}

resource "aws_route_table" "private" {
  for_each = toset(["one", "two"])

  vpc_id = "vpc-12345678"
  # ... 残りの引数は省略
}
```

{% endcode %}
{% endhint %}

{% hint style="danger" %}
{% code title="main.tf" %}

```hcl
resource "aws_route_table" "public" {
  vpc_id = "vpc-12345678"
  count  = 2

  # ... 残りの引数は省略
}
```

{% endcode %}
{% endhint %}

### `tags` の配置

{% hint style="success" %}
{% code title="main.tf" %}

```hcl
resource "aws_nat_gateway" "this" {
  count = 2

  allocation_id = "..."
  subnet_id     = "..."

  tags = {
    Name = "..."
  }

  depends_on = [aws_internet_gateway.this]

  lifecycle {
    create_before_destroy = true
  }
}   
```

{% endcode %}
{% endhint %}

{% hint style="danger" %}
{% code title="main.tf" %}

```hcl
resource "aws_nat_gateway" "this" {
  count = 2

  tags = "..."

  depends_on = [aws_internet_gateway.this]

  lifecycle {
    create_before_destroy = true
  }

  allocation_id = "..."
  subnet_id     = "..."
}
```

{% endcode %}
{% endhint %}

### `count`内の条件

{% hint style="success" %}
{% code title="outputs.tf" %}

```hcl
resource "aws_nat_gateway" "that" {    # 最適
  count = var.create_public_subnets ? 1 : 0
}

resource "aws_nat_gateway" "this" {    # 良い
  count = length(var.public_subnets) > 0 ? 1 : 0
}
```

{% endcode %}
{% endhint %}

## 変数

1. リソースモジュールで車輪の再発明をしないでください：作業しているリソースの "Argument Reference" セクションで定義されている通りに、変数の`name`、`description`、`default`値を使用してください。
2. 変数のバリデーションサポートはかなり限定的です（例：他の変数へのアクセスや参照ができません）。多くの場合この機能は役に立たないので、それを考慮して計画してください。
3. 型が`list(...)`または`map(...)`の場合は、変数名に複数形を使用してください。
4. 変数ブロック内のキーは次の順序で並べてください：description、type、default、validation
5. 明白だと思える場合でも、将来必要になるので、すべての変数に必ずdescriptionを含めてください。
6. 各キーに厳密な制約が必要な場合を除き、`object()`のような特定の型よりも、シンプルな型（`number`、`string`、`list(...)`、`map(...)`、`any`）の使用を推奨します。
7. マップのすべての要素が同じ型（例：`string`）を持つ場合、または変換可能な場合（例：`number`型は`string`に変換可能）は、`map(map(string))`のような特定の型を使用してください。
8. 特定の深さから型バリデーションを無効にする場合や、複数の型をサポートする必要がある場合は、`any`型を使用してください。
9. 値`{}`は時にマップであり、時にオブジェクトです。オブジェクトを作成する方法がないため、マップを作成するには`tomap(...)`を使用してください。

## 出力

出力はスコープ外でも一貫性があり理解しやすいものにしてください（モジュールを使用するユーザーにとって、返される値の型と属性が明らかであるべきです）。

1. 出力名は、含まれるプロパティを説明するものであり、通常望むよりも自由度は低くすべきです。
2. 出力名の良い構造は`{name}_{type}_{attribute}`のようになります。ここで：
   1. `{name}`はリソースまたはデータソース名です
      * `data "aws_subnet" "private"`の`{name}`は`private`です
      * `resource "aws_vpc_endpoint_policy" "test"`の`{name}`は`test`です
   2. `{type}`はプロバイダーのプレフィックスを除いたリソースまたはデータソースの型です
      * `data "aws_subnet" "private"`の`{type}`は`subnet`です
      * `resource "aws_vpc_endpoint_policy" "test"`の`{type}`は`vpc_endpoint_policy`です
   3. `{attribute}`は出力によって返される属性です
   4. [例](#code-examples-of-output)を参照してください。
3. 出力が補間関数と複数のリソースを使用した値を返す場合、`{name}`と`{type}`はできるだけ一般的にすべきです（プレフィックスとしての`this`は省略すべき）。[例](#code-examples-of-output)を参照してください。
4. 返される値がリストの場合は、複数形の名前にすべきです。[例](#code-examples-of-output)を参照してください。
5. 明白だと思える場合でも、すべての出力に必ず`description`を含めてください。
6. すべてのモジュールのすべての場所でその出力の使用を完全に制御できない限り、`sensitive`引数の設定は避けてください。
7. （0.13以前のバージョンでの従来のアプローチである）`element(concat(...))`よりも（Terraform 0.13以降で利用可能な）`try()`を推奨します。

### `output`のコード例

セキュリティグループのIDを最大1つ返す場合：

{% hint style="success" %}
{% code title="outputs.tf" %}

```hcl
output "security_group_id" {
  description = "The ID of the security group"
  value       = try(aws_security_group.this[0].id, aws_security_group.name_prefix[0].id, "")
}
```

{% endcode %}
{% endhint %}

同じタイプの複数のリソースがある場合、出力名では`this`を省略すべきです：

{% hint style="danger" %}
{% code title="outputs.tf" %}

```hcl
output "this_security_group_id" {
  description = "The ID of the security group"
  value       = element(concat(coalescelist(aws_security_group.this.*.id, aws_security_group.web.*.id), [""]), 0)
}
```

{% endcode %}
{% endhint %}

### 返される値がリストの場合は、複数形の名前を使用してください

{% hint style="success" %}
{% code title="outputs.tf" %}

```hcl
output "rds_cluster_instance_endpoints" {
  description = "A list of all cluster instance endpoints"
  value       = aws_rds_cluster_instance.this.*.endpoint
}
```

{% endcode %}
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.terraform-best-practices.com/ja/naming.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
